prober.py 4.1 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# NIFTy
# Copyright (C) 2017  Theo Steininger
#
# Author: Theo Steininger
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
Theo Steininger's avatar
Theo Steininger committed
18
19
20

import abc

21
22
import numpy as np

Theo Steininger's avatar
Theo Steininger committed
23
from nifty.field import Field
24
25
26
import nifty.nifty_utilities as utilities

from nifty import nifty_configuration as nc
Theo Steininger's avatar
Theo Steininger committed
27
28
29
30

from d2o import STRATEGIES as DISTRIBUTION_STRATEGIES


31
class Prober(object):
Theo Steininger's avatar
Theo Steininger committed
32
    """
33
34
35
36
37
38
    See the following webpages for the principles behind the usage of
    mixin-classes

    https://www.python.org/download/releases/2.2.3/descrintro/#cooperation
    https://rhettinger.wordpress.com/2011/05/26/super-considered-super/

Theo Steininger's avatar
Theo Steininger committed
39
40
    """

41
    __metaclass__ = abc.ABCMeta
Theo Steininger's avatar
Theo Steininger committed
42

43
    def __init__(self, domain=None, distribution_strategy=None, probe_count=8,
44
                 random_type='pm1', compute_variance=False):
45

46
        self._domain = utilities.parse_domain(domain)
Theo Steininger's avatar
Theo Steininger committed
47
48
        self._distribution_strategy = \
            self._parse_distribution_strategy(distribution_strategy)
49
50
        self._probe_count = self._parse_probe_count(probe_count)
        self._random_type = self._parse_random_type(random_type)
Theo Steininger's avatar
Theo Steininger committed
51
52
        self.compute_variance = bool(compute_variance)

53
    # ---Properties---
54

55
    @property
Theo Steininger's avatar
Theo Steininger committed
56
    def domain(self):
57
58
59
        return self._domain

    @property
Theo Steininger's avatar
Theo Steininger committed
60
    def distribution_strategy(self):
61
        return self._distribution_strategy
Theo Steininger's avatar
Theo Steininger committed
62

Theo Steininger's avatar
Theo Steininger committed
63
    def _parse_distribution_strategy(self, distribution_strategy):
64
65
66
67
        if distribution_strategy is None:
            distribution_strategy = nc['default_distribution_strategy']
        else:
            distribution_strategy = str(distribution_strategy)
68
        if distribution_strategy not in DISTRIBUTION_STRATEGIES['global']:
69
70
            raise ValueError("distribution_strategy must be a global-type "
                             "strategy.")
71
        self._distribution_strategy = distribution_strategy
72

Theo Steininger's avatar
Theo Steininger committed
73
    @property
74
75
    def probe_count(self):
        return self._probe_count
Theo Steininger's avatar
Theo Steininger committed
76

77
78
    def _parse_probe_count(self, probe_count):
        return int(probe_count)
79
80
81
82
83

    @property
    def random_type(self):
        return self._random_type

84
    def _parse_random_type(self, random_type):
85
        if random_type not in ["pm1", "normal"]:
86
87
            raise ValueError(
                "unsupported random type: '" + str(random_type) + "'.")
88
        return random_type
89
90
91

    # ---Probing methods---

92
    def probing_run(self, callee):
93
        """ controls the generation, evaluation and finalization of probes """
94
        self.reset()
95
96
        for index in xrange(self.probe_count):
            current_probe = self.get_probe(index)
97
            pre_result = self.process_probe(callee, current_probe, index)
98
            self.finish_probe(current_probe, pre_result)
99

100
    def reset(self):
101
        pass
102
103
104
105

    def get_probe(self, index):
        """ layer of abstraction for potential probe-caching """
        return self.generate_probe()
Theo Steininger's avatar
Theo Steininger committed
106

Theo Steininger's avatar
Theo Steininger committed
107
108
    def generate_probe(self):
        """ a random-probe generator """
109
        f = Field.from_random(random_type=self.random_type,
Theo Steininger's avatar
Theo Steininger committed
110
                              domain=self.domain,
Theo Steininger's avatar
Theo Steininger committed
111
                              distribution_strategy=self.distribution_strategy)
112
113
        uid = np.random.randint(1e18)
        return (uid, f)
Theo Steininger's avatar
Theo Steininger committed
114

115
116
117
    def process_probe(self, callee, probe, index):
        """ layer of abstraction for potential result-caching/recycling """
        return self.evaluate_probe(callee, probe[1])
118

119
    def evaluate_probe(self, callee, probe, **kwargs):
120
        """ processes a probe """
121
        return callee(probe, **kwargs)
122

Theo Steininger's avatar
Theo Steininger committed
123
    def finish_probe(self, probe, pre_result):
124
        pass
Theo Steininger's avatar
Theo Steininger committed
125

126
127
    def __call__(self, callee):
        return self.probing_run(callee)