def calc_derivatives(self,
                         first=False,
                         second=False,
                         savebase=False,
                         required_inputs=None,
                         required_outputs=None):
        """ Calculate derivatives and save baseline states for all components
        in this workflow.
        """

        self._stop = False

        dgraph = self.derivative_graph(required_inputs, required_outputs)
        comps = dgraph.edge_dict_to_comp_list(
            edges_to_dict(dgraph.list_connections()))
        for compname, data in comps.iteritems():
            if '~' in compname:
                comp = self._derivative_graph.node[compname]['pa_object']
            elif compname.startswith('@'):
                continue
            else:
                comp = self.scope.get(compname)

            J = self._J_cache.get(compname)
            if compname not in self._shape_cache:
                self._shape_cache[compname] = {}
            if J is None:
                J = comp.calc_derivatives(first, second, savebase,
                                          data['inputs'], data['outputs'])
                if J is not None:
                    self._J_cache[compname] = J

            if self._stop:
                raise RunStopped('Stop requested')
    def calc_derivatives(self, first=False, second=False, savebase=False,
                         required_inputs=None, required_outputs=None):
        """ Calculate derivatives and save baseline states for all components
        in this workflow.
        """

        self._stop = False

        dgraph = self.derivative_graph(required_inputs, required_outputs)
        comps = dgraph.edge_dict_to_comp_list(edges_to_dict(dgraph.list_connections()))
        for compname, data in comps.iteritems():
            if '~' in compname:
                comp = self._derivative_graph.node[compname]['pa_object']
            elif compname.startswith('@'):
                continue
            else:
                comp = self.scope.get(compname)

            J = self._J_cache.get(compname)
            if compname not in self._shape_cache:
                self._shape_cache[compname] = {}
            if J is None:
                J = comp.calc_derivatives(first, second, savebase,
                                          data['inputs'], data['outputs'])
                if J is not None:
                    self._J_cache[compname] = J

            if self._stop:
                raise RunStopped('Stop requested')
    def edge_list(self):
        """ Return the list of edges for the derivatives of this workflow. """

        if self._edges is None:
            self._edges = edges_to_dict(self.derivative_graph().list_connections())

        return self._edges
    def edge_list(self):
        """ Return the list of edges for the derivatives of this workflow. """

        if self._edges is None:
            self._edges = edges_to_dict(
                self.derivative_graph().list_connections())

        return self._edges
def get_inner_edges(graph, srcs, dests, wflow):
    graph = graph.subgraph(graph.nodes())

    # add @in and @out nodes, rewire input srcs, etc.
    graph = mod_for_derivs(graph, srcs, dests, wflow)

    # sort edges by src so that basevars occur before subvars
    edges = sorted(graph.list_connections(), key=lambda e: e[0])
    return edges_to_dict(edges)
def get_inner_edges(graph, srcs, dests, wflow):

    graph = graph.subgraph(graph.nodes())

    # add @in and @out nodes, rewire input srcs, etc.
    graph = mod_for_derivs(graph, srcs, dests, wflow)

    # sort edges by src so that basevars occur before subvars
    edges = sorted(graph.list_connections(), key=lambda e: e[0])
    return edges_to_dict(edges)
    def test_get_inner_connections(self):
        self.assertEqual(len(_get_inner_connections(self.dep, ['b'], ['c'])),
                         6)
        self.assertEqual(
            set(_get_inner_connections(self.dep, ['b'], ['c'])),
            set([('b[3]', 'A.b'), ('A.d.z', 'B.b[4]'), ('A.c[2]', 'B.a.x.y'),
                 ('B.c', 'C.a'), ('B.d', 'C.b'), ('C.c', 'c')]))

        dep, scope = _make_graph(comps=['A', 'B'],
                                 connections=[('A.c', 'B.a'), ('A.d', 'B.b')],
                                 inputs=['a', 'b'],
                                 outputs=['c', 'd'])
        self.assertEqual(len(_get_inner_connections(dep, ['A.a'], ['B.c'])), 2)
        self.assertEqual(set(_get_inner_connections(dep, ['A.a'], ['B.c'])),
                         set([('A.c', 'B.a'), ('A.d', 'B.b')]))

        dep, scope = _make_graph(comps=['A', 'B', 'C'],
                                 connections=[('A.c', 'B.a'), ('A.d', 'B.b'),
                                              ('B.d', 'C.a')],
                                 inputs=['a', 'b'],
                                 outputs=['c', 'd'])
        self.assertEqual(set(_get_inner_connections(dep, ['A.a'], ['C.c'])),
                         set([('A.c', 'B.a'), ('A.d', 'B.b'), ('B.d', 'C.a')]))

        # same output feeding two inputs
        dep, scope = _make_graph(comps=['A', 'B', 'C'],
                                 connections=[('A.d', 'B.a'), ('A.d', 'B.b'),
                                              ('B.d', 'C.a')],
                                 inputs=['a', 'b'],
                                 outputs=['c', 'd'])
        edges = _get_inner_connections(dep, ['A.a'], ['C.c'])
        self.assertEqual(set(edges),
                         set([('A.d', 'B.a'), ('A.d', 'B.b'), ('B.d', 'C.a')]))
        edict = edges_to_dict(edges)
        self.assertEqual(len(edict), 2)
        self.assertEqual(set(edict['A.d']), set(['B.a', 'B.b']))
        self.assertEqual(edict['B.d'], ['C.a'])

        # loop
        dep, scope = _make_graph(comps=['A', 'B', 'C'],
                                 connections=[('A.d', 'B.a'), ('B.d', 'C.a'),
                                              ('C.d', 'A.a')],
                                 inputs=['a', 'b'],
                                 outputs=['c', 'd'])
        self.assertEqual(set(_get_inner_connections(dep, ['A.a'], ['C.d'])),
                         set([('A.d', 'B.a'), ('B.d', 'C.a'), ('C.d', 'A.a')]))
    def _pre_init(self, pa_name, group, dgraph, fd, boundary_params):
        """Return a tuple of the form (pa_inputs, pa_outputs, renames)
        for the PseudoAssembly that would be created given the nodes in
        group and the given graph.
        """

        # First, find our group boundary
        self._orig_group_nodes = list(group) + list(boundary_params)
        allnodes = dgraph.find_prefixed_nodes(self._orig_group_nodes)
        out_edges = nx.edge_boundary(dgraph, allnodes)
        in_edges = nx.edge_boundary(dgraph,
                                    set(dgraph.nodes()).difference(allnodes))
        solver_states = []
        if fd is False:
            for comp in group:

                # Keep any node marked 'solver_state'. Note, only inputs can
                # be solver_states.
                solver_states.extend([
                    node for node in dgraph.find_prefixed_nodes([comp])
                    if 'solver_state' in dgraph.node[node]
                ])

        pa_inputs = edges_to_dict(in_edges).values()
        pa_inputs.extend(solver_states)
        pa_outputs = set([a[0] for a in out_edges])

        renames = {}

        # Add pseudoassy inputs
        for varpath in list(flatten_list_of_iters(pa_inputs)) + \
                       list(pa_outputs):
            varname = to_PA_var(varpath, pa_name)
            if varpath in dgraph:
                renames[varpath] = varname
                old = dgraph.base_var(varpath)
                if old != varpath:
                    renames[old] = to_PA_var(old, pa_name)

        # make boundary params outputs of the PA
        pa_outputs.update(boundary_params)

        return pa_inputs, pa_outputs, renames
    def _pre_init(self, pa_name, group, dgraph, fd, boundary_params):
        """Return a tuple of the form (pa_inputs, pa_outputs, renames)
        for the PseudoAssembly that would be created given the nodes in
        group and the given graph.
        """

        # First, find our group boundary
        self._orig_group_nodes = list(group) + list(boundary_params)
        allnodes = dgraph.find_prefixed_nodes(self._orig_group_nodes)
        out_edges = nx.edge_boundary(dgraph, allnodes)
        in_edges = nx.edge_boundary(dgraph,
                                    set(dgraph.nodes()).difference(allnodes))
        solver_states = []
        if fd is False:
            for comp in group:

                # Keep any node marked 'solver_state'. Note, only inputs can
                # be solver_states.
                solver_states.extend([node for node in dgraph.find_prefixed_nodes([comp])
                                      if 'solver_state' in dgraph.node[node]])

        pa_inputs = edges_to_dict(in_edges).values()
        pa_inputs.extend(solver_states)
        pa_outputs = set([a[0] for a in out_edges])

        renames = {}

        # Add pseudoassy inputs
        for varpath in list(flatten_list_of_iters(pa_inputs)) + \
                       list(pa_outputs):
            varname = to_PA_var(varpath, pa_name)
            if varpath in dgraph:
                renames[varpath] = varname
                old = dgraph.base_var(varpath)
                if old != varpath:
                    renames[old] = to_PA_var(old, pa_name)

        # make boundary params outputs of the PA
        pa_outputs.update(boundary_params)

        return pa_inputs, pa_outputs, renames
    def test_get_inner_connections(self):
        self.assertEqual(len(_get_inner_connections(self.dep, ['b'], ['c'])), 6)
        self.assertEqual(set(_get_inner_connections(self.dep, ['b'], ['c'])),
                         set([('b[3]','A.b'),('A.d.z','B.b[4]'),('A.c[2]','B.a.x.y'),
                              ('B.c','C.a'),('B.d','C.b'),('C.c','c')]))

        dep, scope = _make_graph(comps=['A','B'],
                                 connections=[('A.c','B.a'),('A.d','B.b')],
                                 inputs=['a','b'],
                                 outputs=['c','d'])
        self.assertEqual(len(_get_inner_connections(dep, ['A.a'], ['B.c'])), 2)
        self.assertEqual(set(_get_inner_connections(dep, ['A.a'], ['B.c'])),
                         set([('A.c','B.a'),('A.d','B.b')]))
        
        dep, scope = _make_graph(comps=['A','B', 'C'],
                                 connections=[('A.c','B.a'),('A.d','B.b'),('B.d','C.a')],
                                 inputs=['a','b'],
                                 outputs=['c','d'])
        self.assertEqual(set(_get_inner_connections(dep, ['A.a'], ['C.c'])),
                         set([('A.c','B.a'),('A.d','B.b'),('B.d','C.a')]))

        # same output feeding two inputs
        dep, scope = _make_graph(comps=['A','B', 'C'],
                                 connections=[('A.d','B.a'),('A.d','B.b'),('B.d','C.a')],
                                 inputs=['a','b'],
                                 outputs=['c','d'])
        edges = _get_inner_connections(dep, ['A.a'], ['C.c'])
        self.assertEqual(set(edges), set([('A.d','B.a'),('A.d','B.b'),('B.d','C.a')]))
        edict = edges_to_dict(edges)
        self.assertEqual(len(edict), 2)
        self.assertEqual(set(edict['A.d']), set(['B.a','B.b']))
        self.assertEqual(edict['B.d'], ['C.a'])

        # loop
        dep, scope = _make_graph(comps=['A','B', 'C'],
                                 connections=[('A.d','B.a'),('B.d','C.a'),('C.d','A.a')],
                                 inputs=['a','b'],
                                 outputs=['c','d'])
        self.assertEqual(set(_get_inner_connections(dep, ['A.a'], ['C.d'])),
                         set([('A.d','B.a'),('B.d','C.a'),('C.d','A.a')]))