def test_tracegraph(simplemodel): def get_predec(node): return simplemodel._impl.tracegraph.predecessors(node) def get_succ(node): return simplemodel._impl.tracegraph.successors(node) space = simplemodel.spaces["Space1"] space.fibo[10] for x in range(10): fibo = get_node(space.fibo._impl, (x, ), {}) fibo_prev1 = get_node(space.fibo._impl, (x - 1, ), {}) fibo_prev2 = get_node(space.fibo._impl, (x - 2, ), {}) fibo_next1 = get_node(space.fibo._impl, (x + 1, ), {}) fibo_next2 = get_node(space.fibo._impl, (x + 2, ), {}) if x == 0 or x == 1: assert list(get_predec(fibo)) == [] assert fibo_next2 in get_succ(fibo) elif x < 9: assert fibo_prev1 in get_predec(fibo) assert fibo_prev2 in get_predec(fibo) assert fibo_next1 in get_succ(fibo) assert fibo_next2 in get_succ(fibo)
def clear_value(self, *args, **kwargs): if args == () and kwargs == {} and not self.is_scalar(): self.clear_all_values() else: node = get_node(self, *convert_args(args, kwargs)) if self.has_cell(node[KEY]): self._model.clear_descendants(node)
def test_tracegraph_informula_assignment(): model, space = new_model(), new_space() @defcells(space=space) def bar(x): bar[x] = x bar(1) nodes = model.tracegraph.nodes() assert get_node(bar._impl, (1, ), {}) in nodes
def test_tracegraph_standalone(): model, space = new_model(), new_space() @defcells(space=space) def foo(x): return x foo(1) nodes = model.tracegraph.nodes() assert get_node(foo._impl, (1, ), {}) in nodes
def clear_at(self, *args, **kwargs): """Clear value for given arguments. Clear the value associated with the given arguments. .. versionadded:: 0.1.0 See Also: :meth:`celar`, :meth:`clear_all` """ node = get_node(self._impl, args, kwargs) return self._impl.clear_value_at(node[KEY])
def set_value(self, args, value): node = get_node(self, *convert_args(args, {})) key = node[KEY] if self.system.callstack: if node == self.system.callstack.last(): self._store_value(key, value, False) else: raise KeyError("Assignment in cells other than %s" % key) else: self._store_value(key, value, True) self._model.cellgraph.add_node(node)
def restore_state(self, system): """Called after unpickling to restore some attributes manually.""" Impl.restore_state(self, system) BaseSpaceContainerImpl.restore_state(self, system) mapping = {} for node in self.cellgraph: if isinstance(node, tuple): name, key = node else: name, key = node, None cells = self.get_object(name) mapping[node] = get_node(cells, key, None) self.cellgraph = nx.relabel_nodes(self.cellgraph, mapping)
def is_input(self, *args, **kwargs): """``True`` if this is input. Return ``True`` if this cell is input, ``False`` if calculated. Raise an error if there is no value. .. versionadded:: 0.1.0 """ node = get_node(self._impl, args, kwargs) if self._impl.has_node(node[KEY]): return node[KEY] in self._impl.input_keys else: raise ValueError("Value not found")
def _store_value(self, key, value): if isinstance(value, Cells): if value._impl.is_scalar(): value = value._impl.single_value if value is not None: self.data[key] = value elif self.get_property("allow_none"): self.data[key] = value else: tracemsg = self.system.callstack.tracemessage() raise NoneReturnedError(get_node(self, key, None), tracemsg) return value
def get_value(self, args, kwargs=None): node = get_node(self, *convert_args(args, kwargs)) key = node[KEY] if self.has_cell(key): value = self.data[key] else: value = self.system.execution.eval_cell(node) graph = self._model.cellgraph if self.system.callstack: graph.add_path([node, self.system.callstack.last()]) else: graph.add_node(node) return value
def restore_state(self, datapath=None): """Called after unpickling to restore some attributes manually.""" BaseSpaceContainerImpl.restore_state(self) for client in self.datarefmgr.clients: self.system.iomanager.register_client(client, model=self.interface, datapath=datapath) mapping = {} for node in self.tracegraph: if isinstance(node, tuple): name, key = node else: name, key = node, None cells = self.get_impl_from_name(name) mapping[node] = get_node(cells, key, None) self.tracegraph = nx.relabel_nodes(self.tracegraph, mapping)
def find_match(self, args, kwargs): node = get_node(self, args, kwargs) key = node[KEY] keylen = len(key) if not self.get_property("allow_none"): raise NoneReturnedError(get_node_repr(node)) for match_len in range(keylen, -1, -1): for idxs in combinations(range(keylen), match_len): masked = [None] * keylen for idx in idxs: masked[idx] = key[idx] value = self.get_value(masked) if value is not None: return ArgsValuePair(tuple(masked), value) return ArgsValuePair(None, None)
def set_value(self, args, value): node = get_node(self, args, {}) key = node[KEY] if self.system.callstack: if node == self.system.callstack[-1]: self._store_value(key, value) else: raise KeyError("Assignment in cells other than %s" % key) else: if self.system._recalc_dependents: targets = self.model.tracegraph.get_startnodes_from(node) self.clear_value_at(key) self._store_value(key, value) self.model.tracegraph.add_node(node) self.input_keys.add(key) if self.system._recalc_dependents: for trg in targets: trg[OBJ].get_value_from_key(trg[KEY])
def get_dynspace(self, args, kwargs=None): """Create a dynamic root space Called from interface methods """ node = get_node(self, *convert_args(args, kwargs)) key = node[KEY] if key in self.param_spaces: return self.param_spaces[key] else: last_self = self.system.self self.system.self = self try: space_args = self.eval_formula(node) finally: self.system.self = last_self if space_args is None: space_args = {"bases": [self]} # Default else: if "bases" in space_args: bases = get_impls(space_args["bases"]) if isinstance(bases, StaticSpaceImpl): space_args["bases"] = [bases] elif bases is None: space_args["bases"] = [self] # Default else: space_args["bases"] = bases else: space_args["bases"] = [self] space_args["arguments"] = node_get_args(node) space = self._new_dynspace(**space_args) self.param_spaces[key] = space space.inherit(clear_value=False) return space
def find_match(self, args, kwargs): node = get_node(self, *convert_args(args, kwargs)) key = node[KEY] keylen = len(key) if not self.get_property("allow_none"): # raise ValueError('Cells %s cannot return None' % self.name) tracemsg = self.system.callstack.tracemessage() raise NoneReturnedError(node, tracemsg) for match_len in range(keylen, -1, -1): for idxs in combinations(range(keylen), match_len): masked = [None] * keylen for idx in idxs: masked[idx] = key[idx] value = self.get_value(masked) if value is not None: return ArgsValuePair(tuple(masked), value) return ArgsValuePair(None, None)
def _store_value(self, key, value, overwrite=False): if isinstance(value, Cells): if value._impl.is_scalar(): value = value._impl.single_value if not self.has_cell(key) or overwrite: if overwrite: self.clear_value(*key) if value is not None: self.data[key] = value elif self.get_property("allow_none"): self.data[key] = value else: tracemsg = self.system.callstack.tracemessage() raise NoneReturnedError(get_node(self, key, None), tracemsg) else: raise ValueError("Value already exists for %s" % key) return value
def node(self, *args, **kwargs): """Return a :class:`CellNode` object for the given arguments.""" return CellNode(get_node(self._impl, *convert_args(args, kwargs)))
def to_node(self): return ReferenceNode(get_node(self, None, None))
def predecessors(self, args, kwargs): node = get_node(self, *convert_args(args, kwargs)) preds = self._model.cellgraph.predecessors(node) return [CellNode(n) for n in preds]
def successors(self, args, kwargs): node = get_node(self, *convert_args(args, kwargs)) succs = self._model.cellgraph.successors(node) return [CellNode(n) for n in succs]
def get_value(self, args, kwargs=None): node = get_node(self, args, kwargs) return self.system.executor.eval_node(node)