1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 import numpy
32 from numpy.lib.function_base import vectorize
33 from .lists_and_dicts import IntArrayDict
34 from functools import reduce
37 prop_index = dict()
38 for i, cl in enumerate(props):
39 for c in cl:
40 ind = prop_index.get(c, list())
41 ind.append(index[i])
42 prop_index[c] = ind
43
44 for c, i in prop_index.items():
45 prop_index[c] = numpy.array(i, dtype=int)
46
47 return prop_index
48
51 """
52 This object wraps a dictionary, whos keys are _operations_ that we'd like
53 to apply to a parameter array, and whose values are np integer arrays which
54 index the parameter array appropriately.
55
56 A model instance will contain one instance of this class for each thing
57 that needs indexing (i.e. constraints, ties and priors). Parameters within
58 the model constain instances of the ParameterIndexOperationsView class,
59 which can map from a 'local' index (starting 0) to this global index.
60
61 Here's an illustration::
62
63 #=======================================================================
64 model : 0 1 2 3 4 5 6 7 8 9
65 key1: 4 5
66 key2: 7 8
67
68 param1: 0 1 2 3 4 5
69 key1: 2 3
70 key2: 5
71
72 param2: 0 1 2 3 4
73 key1: 0
74 key2: 2 3
75 #=======================================================================
76
77 The views of this global index have a subset of the keys in this global
78 (model) index.
79
80 Adding a new key (e.g. a constraint) to a view will cause the view to pass
81 the new key to the global index, along with the local index and an offset.
82 This global index then stores the key and the appropriate global index
83 (which can be seen by the view).
84
85 See also:
86 ParameterIndexOperationsView
87
88 """
89 _offset = 0
91 self._properties = IntArrayDict()
92 if constraints is not None:
93
94 for t, i in constraints.items():
95 self.add(t, i)
96
98 for i, ind in self._properties.items():
99 if ind.size > 0:
100 yield i, ind
101
103 return [i[0] for i in self.items()]
104
106 return [i[1] for i in self.items()]
107
109 for ind in self.indices():
110 toshift = ind>=start
111 ind[toshift] += size
112
114 for v, ind in list(self.items()):
115 todelete = (ind>=start) * (ind<start+size)
116 if todelete.sum() != 0:
117 ind = ind[~todelete]
118 toshift = ind>=start
119 if toshift.size != 0:
120 ind[toshift] -= size
121 if ind.size != 0: self._properties[v] = ind
122 else: del self._properties[v]
123
125 self._properties.clear()
126
127 @property
130
131
133 """
134 Returns a list of properties, such that each entry in the list corresponds
135 to the element of the index given.
136
137 Example:
138 let properties: 'one':[1,2,3,4], 'two':[3,5,6]
139
140 >>> properties_for([2,3,5])
141 [['one'], ['one', 'two'], ['two']]
142 """
143 return vectorize(lambda i: [prop for prop in self.properties() if i in self[prop]], otypes=[list])(index)
144
146 """
147 Return a dictionary, containing properties as keys and indices as index
148 Thus, the indices for each constraint, which is contained will be collected as
149 one dictionary
150
151 Example:
152 let properties: 'one':[1,2,3,4], 'two':[3,5,6]
153
154 >>> properties_dict_for([2,3,5])
155 {'one':[2,3], 'two':[3,5]}
156 """
157 props = self.properties_for(index)
158 prop_index = extract_properties_to_index(index, props)
159 return prop_index
160
161 - def add(self, prop, indices):
163
164 - def remove(self, prop, indices):
165 if prop in self._properties:
166 diff = remove_indices(self[prop], indices)
167 removed = numpy.intersect1d(self[prop], indices, True)
168 if not index_empty(diff):
169 self._properties[prop] = diff
170 else:
171 del self._properties[prop]
172 return removed.astype(int)
173 return numpy.array([]).astype(int)
174
175 - def update(self, parameter_index_view, offset=0):
176
177 for i, v in parameter_index_view.items():
178 self.add(i, v+offset)
179
182
186
188 return self._properties[prop]
189
191 del self._properties[prop]
192
193 - def __str__(self, *args, **kwargs):
194 import pprint
195 return pprint.pformat(dict(self._properties))
196
198 return numpy.union1d(arr1, arr2)
199
201 return numpy.setdiff1d(arr, to_remove, True)
202
205
207 - def __init__(self, param_index_operations, offset, size):
208 self._param_index_ops = param_index_operations
209 self._offset = offset
210 self._size = size
211
213 return [self._param_index_ops, self._offset, self._size]
214
216 self._param_index_ops = state[0]
217 self._offset = state[1]
218 self._size = state[2]
219
222
224 _items_list = self._param_index_ops.items()
225 for i, ind in _items_list:
226 ind2 = self._filter_index(ind)
227 if ind2.size > 0:
228 yield i, ind2
229
231 return [i[0] for i in self.items()]
232
234 return [i[1] for i in self.items()]
235
238
241
243 for i, ind in list(self.items()):
244 self._param_index_ops.remove(i, ind+self._offset)
245
246 @property
249
251 """
252 Returns a list of properties, such that each entry in the list corresponds
253 to the element of the index given.
254
255 Example:
256 let properties: 'one':[1,2,3,4], 'two':[3,5,6]
257
258 >>> properties_for([2,3,5])
259 [['one'], ['one', 'two'], ['two']]
260 """
261 return vectorize(lambda i: [prop for prop in self.properties() if i in self[prop]], otypes=[list])(index)
262
264 """
265 Return a dictionary, containing properties as keys and indices as index
266 Thus, the indices for each constraint, which is contained will be collected as
267 one dictionary
268
269 Example:
270 let properties: 'one':[1,2,3,4], 'two':[3,5,6]
271
272 >>> property_dict_for([2,3,5])
273 {'one':[2,3], 'two':[3,5]}
274 """
275 return extract_properties_to_index(index, self.properties_for(index))
276
277
278 - def add(self, prop, indices):
280
281
282 - def remove(self, prop, indices):
283 removed = self._param_index_ops.remove(prop, numpy.array(indices)+self._offset)
284 if removed.size > 0:
285 return removed-self._offset
286 return removed
287
288
290 ind = self._filter_index(self._param_index_ops[prop])
291 return ind
292
294 self.remove(prop, self[prop])
295
296 - def __str__(self, *args, **kwargs):
297 import pprint
298
299 return pprint.pformat(dict(self.items()))
300
301 - def update(self, parameter_index_view, offset=0):
302
303 for i, v in parameter_index_view.items():
304 self.add(i, v+offset)
305
306
309
313 pass
314