diff --git a/GPy/core/parameterization/index_operations.py b/GPy/core/parameterization/index_operations.py index 7fc76d07..78c0d2b9 100644 --- a/GPy/core/parameterization/index_operations.py +++ b/GPy/core/parameterization/index_operations.py @@ -22,15 +22,44 @@ def extract_properties_to_index(index, props): class ParameterIndexOperations(object): - ''' - Index operations for storing param index _properties - This class enables index with slices retrieved from object.__getitem__ calls. - Adding an index will add the selected indexes by the slice of an indexarray - indexing a shape shaped array to the flattened index array. Remove will - remove the selected slice indices from the flattened array. - You can give an offset to set an offset for the given indices in the - index array, for multi-param handling. - ''' + """ + This object wraps a dictionary, whos keys are _operations_ that we'd like + to apply to a parameter array, and whose values are np integer arrays which + index the parameter array appropriately. + + A model instance will contain one instance of this class for each thing + that needs indexing (i.e. constraints, ties and priors). Parameters within + the model constain instances of the ParameterIndexOperationsView class, + which can map from a 'local' index (starting 0) to this global index. + + Here's an illustration: + + #======================================================================= + model : 0 1 2 3 4 5 6 7 8 9 + key1: 4 5 + key2: 7 8 + + param1: 0 1 2 3 4 5 + key1: 2 3 + key2: 5 + + param2: 0 1 2 3 4 + key1: 0 + key2: 2 3 + #======================================================================= + + The views of this global index have a subset of the keys in this global + (model) index. + + Adding a new key (e.g. a constraint) to a view will cause the view to pass + the new key to the global index, along with the local index and an offset. + This global index then stores the key and the appropriate global index + (which can be seen by the view). + + See also: + ParameterIndexOperationsView + + """ _offset = 0 def __init__(self, constraints=None): self._properties = IntArrayDict() diff --git a/GPy/core/parameterization/parameter_core.py b/GPy/core/parameterization/parameter_core.py index dab5c2d0..1f8b347d 100644 --- a/GPy/core/parameterization/parameter_core.py +++ b/GPy/core/parameterization/parameter_core.py @@ -495,6 +495,35 @@ class Indexable(Nameable, Observable): #=========================================================================== # Constrain operations -> done #=========================================================================== + + def tie(self, name): + #remove any constraints + old_const = self.constraints.properties()[:] + self.unconstrain() + + #set these parameters to be 'fixed' as in, not optimized + self._highest_parent_._set_fixed(self, self._raveled_index()) + + #see if a tie exists with that name + if name in self._highest_parent_.ties: + t = self._highest_parent_.ties[name] + else: + #create a tie object + value = np.atleast_1d(self.param_array)[0]*1 + import ties_and_remappings + t = ties_and_remappings.Tie(value=value, name=name) + + #add the new tie object to the global index + self._highest_parent_.ties[name] = t + self._highest_parent_.add_parameter(t) + + #constrain the tie as we were constrained + if len(old_const)==1: + t.constrain(old_const[0]) + + + self.constraints.add(t, self._raveled_index()) + t.add_tied_parameter(self) def constrain(self, transform, warning=True, trigger_parent=True): """ @@ -784,6 +813,7 @@ class Parameterizable(OptimizationHandlable): self._param_array_ = None self._added_names_ = set() self.__visited = False # for traversing in reverse order we need to know if we were here already + self.ties = {} @property def param_array(self):