def restricted(self, inputs=None, outputs=None): """ Return an ExecutionModel which has been restricted to the given inputs and outputs. Parameters ---------- inputs : sequence of str, optional The names of the input variables which have changed. If not provided, then every possible input will be considered to have changed. outputs : sequence of str, optional The names of the output variables which are desired to recompute. Returns ------- model : ExecutionModel """ if inputs is not None: inputs = set(inputs) if outputs is not None: outputs = set(outputs) # Convert the names to the nodes which are directly related to them. input_nodes = set() output_nodes = set() for statement in self.statements: inbindings = set(iv.binding for iv in statement.inputs) if inputs is None or inputs.intersection(inbindings): input_nodes.add(statement) outbindings = set(ov.binding for ov in statement.outputs) if outputs is None or outputs.intersection(outbindings): output_nodes.add(statement) # Find the reachable subgraphs of both the inputs and outputs. dep_graph = self.dep_graph inreachable = graph.reverse(graph.reachable_graph( graph.reverse(dep_graph), input_nodes)) outreachable = graph.reachable_graph(dep_graph, output_nodes) # Our desired set of statements is the intersection of these two graphs. in_nodes = set() for node, deps in inreachable.iteritems(): in_nodes.add(node) for d in deps: in_nodes.add(d) intersection = set() for node, deps in outreachable.iteritems(): if node in in_nodes: intersection.add(node) for d in deps: if d in in_nodes: intersection.add(d) em = self.__class__( statements=list(intersection), ) return em
def _get_sorted_statements(self): """ self.statements in topologically sorted order. """ succ_graph = graph.reverse(self.dep_graph) sorted = graph.topological_sort(succ_graph) return sorted
def _base(self, graph, result, error=None): if error: self.assertRaises(error, lambda: self._base(graph, result)) else: self.assertEqual(G.reverse(graph), result)