Package paramz :: Package core :: Module constrainable
[hide private]
[frames] | no frames]

Source Code for Module paramz.core.constrainable

  1  #=============================================================================== 
  2  # Copyright (c) 2015, Max Zwiessele 
  3  # All rights reserved. 
  4  # 
  5  # Redistribution and use in source and binary forms, with or without 
  6  # modification, are permitted provided that the following conditions are met: 
  7  # 
  8  # * Redistributions of source code must retain the above copyright notice, this 
  9  #   list of conditions and the following disclaimer. 
 10  # 
 11  # * Redistributions in binary form must reproduce the above copyright notice, 
 12  #   this list of conditions and the following disclaimer in the documentation 
 13  #   and/or other materials provided with the distribution. 
 14  # 
 15  # * Neither the name of paramz.core.constrainable nor the names of its 
 16  #   contributors may be used to endorse or promote products derived from 
 17  #   this software without specific prior written permission. 
 18  # 
 19  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
 20  # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
 21  # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
 22  # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 
 23  # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
 24  # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
 25  # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 26  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
 27  # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
 28  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 29  #=============================================================================== 
 30  import numpy as np 
 31  from .indexable import Indexable 
 32  from ..transformations import Transformation,Logexp, NegativeLogexp, Logistic, __fixed__, FIXED, UNFIXED 
33 34 -class Constrainable(Indexable):
35 - def __init__(self, name, default_constraint=None, *a, **kw):
36 super(Constrainable, self).__init__(name=name) 37 self._default_constraint_ = default_constraint 38 from .index_operations import ParameterIndexOperations 39 self.add_index_operation('constraints', ParameterIndexOperations()) 40 if self._default_constraint_ is not None: 41 self.constrain(self._default_constraint_)
42 43 # def __setstate__(self, state): 44 # super(Constrainable, self).__setstate__(state) 45 # #from .index_operations import ParameterIndexOperations 46 # #self.add_index_operation('constraints', ParameterIndexOperations()) 47 # #self._index_operations['constraints'] = self.constraints 48 49 #=========================================================================== 50 # Fixing Parameters: 51 #===========================================================================
52 - def constrain_fixed(self, value=None, warning=True, trigger_parent=True):
53 """ 54 Constrain this parameter to be fixed to the current value it carries. 55 56 This does not override the previous constraints, so unfixing will 57 restore the constraint set before fixing. 58 59 :param warning: print a warning for overwriting constraints. 60 """ 61 if value is not None: 62 self[:] = value 63 64 #index = self.unconstrain() 65 index = self._add_to_index_operations(self.constraints, np.empty(0), __fixed__, warning) 66 self._highest_parent_._set_fixed(self, index) 67 self.notify_observers(self, None if trigger_parent else -np.inf) 68 return index
69 fix = constrain_fixed 70
71 - def unconstrain_fixed(self):
72 """ 73 This parameter will no longer be fixed. 74 75 If there was a constraint on this parameter when fixing it, 76 it will be constraint with that previous constraint. 77 """ 78 unconstrained = self.unconstrain(__fixed__) 79 self._highest_parent_._set_unfixed(self, unconstrained) 80 #if self._default_constraint_ is not None: 81 # return self.constrain(self._default_constraint_) 82 return unconstrained
83 unfix = unconstrain_fixed 84
85 - def _ensure_fixes(self):
86 # Ensure that the fixes array is set: 87 # Parameterized: ones(self.size) 88 # Param: ones(self._realsize_ 89 if (not hasattr(self, "_fixes_")) or (self._fixes_ is None) or (self._fixes_.size != self.size): 90 self._fixes_ = np.ones(self.size, dtype=bool) 91 self._fixes_[self.constraints[__fixed__]] = FIXED
92 93
94 - def _set_fixed(self, param, index):
95 self._ensure_fixes() 96 offset = self._offset_for(param) 97 self._fixes_[index+offset] = FIXED 98 if np.all(self._fixes_): self._fixes_ = None # ==UNFIXED
99
100 - def _set_unfixed(self, param, index):
101 self._ensure_fixes() 102 offset = self._offset_for(param) 103 self._fixes_[index+offset] = UNFIXED 104 if np.all(self._fixes_): self._fixes_ = None # ==UNFIXED
105
106 - def _connect_fixes(self):
107 fixed_indices = self.constraints[__fixed__] 108 if fixed_indices.size > 0: 109 self._ensure_fixes() 110 self._fixes_[:] = UNFIXED 111 self._fixes_[fixed_indices] = FIXED 112 else: 113 self._fixes_ = None 114 del self.constraints[__fixed__]
115 116 #=========================================================================== 117 # Convenience for fixed 118 #===========================================================================
119 - def _has_fixes(self):
120 return self.constraints[__fixed__].size != 0
121 122 @property
123 - def is_fixed(self):
124 for p in self.parameters: 125 if not p.is_fixed: return False 126 return True
127
128 - def _get_original(self, param):
129 # if advanced indexing is activated it happens that the array is a copy 130 # you can retrieve the original param through this method, by passing 131 # the copy here 132 return self.parameters[param._parent_index_]
133 134 #=========================================================================== 135 # Constrain operations -> done 136 #=========================================================================== 137
138 - def constrain(self, transform, warning=True, trigger_parent=True):
139 """ 140 :param transform: the :py:class:`paramz.transformations.Transformation` 141 to constrain the this parameter to. 142 :param warning: print a warning if re-constraining parameters. 143 144 Constrain the parameter to the given 145 :py:class:`paramz.transformations.Transformation`. 146 """ 147 if isinstance(transform, Transformation): 148 self.param_array[...] = transform.initialize(self.param_array) 149 elif transform == __fixed__: 150 return self.fix(warning=warning, trigger_parent=trigger_parent) 151 else: 152 raise ValueError('Can only constrain with paramz.transformations.Transformation object') 153 reconstrained = self.unconstrain() 154 added = self._add_to_index_operations(self.constraints, reconstrained, transform, warning) 155 self.trigger_update(trigger_parent) 156 return added
157
158 - def unconstrain(self, *transforms):
159 """ 160 :param transforms: The transformations to unconstrain from. 161 162 remove all :py:class:`paramz.transformations.Transformation` 163 transformats of this parameter object. 164 """ 165 return self._remove_from_index_operations(self.constraints, transforms)
166
167 - def constrain_positive(self, warning=True, trigger_parent=True):
168 """ 169 :param warning: print a warning if re-constraining parameters. 170 171 Constrain this parameter to the default positive constraint. 172 """ 173 self.constrain(Logexp(), warning=warning, trigger_parent=trigger_parent)
174
175 - def constrain_negative(self, warning=True, trigger_parent=True):
176 """ 177 :param warning: print a warning if re-constraining parameters. 178 179 Constrain this parameter to the default negative constraint. 180 """ 181 self.constrain(NegativeLogexp(), warning=warning, trigger_parent=trigger_parent)
182
183 - def constrain_bounded(self, lower, upper, warning=True, trigger_parent=True):
184 """ 185 :param lower, upper: the limits to bound this parameter to 186 :param warning: print a warning if re-constraining parameters. 187 188 Constrain this parameter to lie within the given range. 189 """ 190 self.constrain(Logistic(lower, upper), warning=warning, trigger_parent=trigger_parent)
191
192 - def unconstrain_positive(self):
193 """ 194 Remove positive constraint of this parameter. 195 """ 196 self.unconstrain(Logexp())
197
198 - def unconstrain_negative(self):
199 """ 200 Remove negative constraint of this parameter. 201 """ 202 self.unconstrain(NegativeLogexp())
203
204 - def unconstrain_bounded(self, lower, upper):
205 """ 206 :param lower, upper: the limits to unbound this parameter from 207 208 Remove (lower, upper) bounded constrain from this parameter/ 209 """ 210 self.unconstrain(Logistic(lower, upper))
211