1
2 """
3 The :mod:`parsimony.algorithms.bases` module includes several base classes
4 for using and creating algorithms.
5
6 Algorithms may not store states. I.e., if they are classes, do not keep
7 references to objects with state in the algorithm objects. It should be
8 possible to copy and share algorithms between e.g. estimators, and thus they
9 should not depend on any state.
10
11 Created on Thu Feb 20 17:42:16 2014
12
13 Copyright (c) 2013-2014, CEA/DSV/I2BM/Neurospin. All rights reserved.
14
15 @author: Tommy Löfstedt
16 @email: lofstedt.tommy@gmail.com
17 @license: BSD 3-clause.
18 """
19 import abc
20 import functools
21
22 import parsimony.utils.consts as consts
23 import parsimony.functions.properties as properties
24
25 __all__ = ["BaseAlgorithm", "check_compatibility",
26 "ImplicitAlgorithm", "ExplicitAlgorithm",
27 "IterativeAlgorithm", "InformationAlgorithm"]
31
32 __metaclass__ = abc.ABCMeta
33
34 @staticmethod
36 """Check if the function considered implements the given properties.
37 """
38 if not isinstance(function, (list, tuple)):
39 function = [function]
40
41 for f in function:
42 for prop in required_properties:
43 if isinstance(prop, properties.OR):
44 if not prop.evaluate(f):
45 raise ValueError("%s does not implement all " \
46 "properties %s" % (str(f), str(prop)))
47 elif not isinstance(f, prop):
48 raise ValueError("%s does not implement interface %s" %
49 (str(f), str(prop)))
50
52
53 for k in kwargs:
54 self.__setattr__(k, kwargs[k])
55
57 raise NotImplementedError('Method "get_params" has not been ' \
58 'implemented.')
59
63 """Automatically checks if a function implements a given set of properties.
64 """
65 @functools.wraps(f)
66 def wrapper(self, function, *args, **kwargs):
67
68 BaseAlgorithm.check_compatibility(function, self.INTERFACES)
69
70 return f(self, function, *args, **kwargs)
71
72 return wrapper
73
76 """Decorate run with this method to force a reset of your algorithm.
77
78 Automatically resets an algorithm by checking the implementing
79 classes and calling the appropriate reset methods.
80 """
81 @functools.wraps(f)
82 def wrapper(self, function, *args, **kwargs):
83
84
85 if isinstance(self, IterativeAlgorithm):
86 self.iter_reset()
87 if isinstance(self, InformationAlgorithm):
88 self.info_reset()
89
90 return f(self, function, *args, **kwargs)
91
92 return wrapper
93
96 """Implicit algorithms are algorithms that do not utilise a loss function.
97
98 Implicit algorithms instead minimise or maximise some underlying function
99 implicitly, usually from the data.
100
101 Parameters
102 ----------
103 X : One or more data matrices.
104 """
105 __metaclass__ = abc.ABCMeta
106
107 @abc.abstractmethod
108 - def run(X, **kwargs):
109 raise NotImplementedError('Abstract method "run" must be ' \
110 'specialised!')
111
114 """Explicit algorithms are algorithms that minimises a given function.
115
116 The function is explicitly minimised from properties of said function.
117
118 Implementing classes should update the INTERFACES class variable with
119 the properties that function must implement. Defauls to a list with one
120 element, the Function.
121 """
122 __metaclass__ = abc.ABCMeta
123
124 INTERFACES = [properties.Function]
125
126 @abc.abstractmethod
127 - def run(function, x, **kwargs):
128 """This function obtains a minimiser of a give function.
129
130 Parameters
131 ----------
132 function : The function to minimise.
133
134 x : A starting point.
135 """
136 raise NotImplementedError('Abstract method "run" must be ' \
137 'specialised!')
138
141 """Algorithms that require iterative steps to achieve the goal.
142
143 Fields
144 ------
145 max_iter : Non-negative integer. The maximum number of allowed iterations.
146
147 min_iter : Non-negative integer less than or equal to max_iter. The minimum
148 number of iterations that must be performed. Default is 1.
149
150 num_iter : Non-negative integer greater than or equal to min_iter. The
151 number of iterations performed by the iterative algorithm. All
152 algorithms that inherit from IterativeAlgortihm MUST call
153 iter_reset before every run.
154
155 Parameters
156 ----------
157 max_iter : Non-negative integer. The maximum number of allowed iterations.
158
159 min_iter : Non-negative integer. The minimum number of required iterations.
160 """
169
173
293
294 if __name__ == "__main__":
295 import doctest
296 doctest.testmod()
297