Example #1
0
 def test_missing_scenario_name(self):
     G = networkx.DiGraph()
     G.add_node("R", name="Root")
     G.add_node("C")
     G.add_edge("R", "C", weight=1)
     with self.assertRaises(KeyError):
         ScenarioTreeModelFromNetworkX(G, scenario_name_attribute="name")
Example #2
0
 def test_bundles(self):
     G = networkx.DiGraph()
     G.add_node("r")
     for i in range(4):
         G.add_node("u" + str(i), bundle=i % 2)
         G.add_edge("r", "u" + str(i))
     model = ScenarioTreeModelFromNetworkX(G,
                                           edge_probability_attribute=None)
     self.assertEqual(sorted(list(model.Stages)),
                      sorted(["Stage1", "Stage2"]))
     self.assertEqual(sorted(list(model.Nodes)),
                      sorted(["r", "u0", "u1", "u2", "u3"]))
     self.assertEqual(sorted(list(model.Children["r"])),
                      sorted(["u0", "u1", "u2", "u3"]))
     for i in range(4):
         self.assertEqual(sorted(list(model.Children["u" + str(i)])),
                          sorted([]))
     self.assertEqual(sorted(list(model.Scenarios)),
                      sorted(["u0", "u1", "u2", "u3"]))
     self.assertEqual(value(model.ConditionalProbability["r"]), 1.0)
     for i in range(4):
         self.assertEqual(value(model.ConditionalProbability["u" + str(i)]),
                          0.25)
     self.assertEqual(model.Bundling.value, True)
     self.assertEqual(list(model.Bundles), [0, 1])
     for k, bundle_name in enumerate(model.Bundles):
         self.assertEqual(list(model.BundleScenarios[bundle_name]),
                          ["u" + str(i) for i in range(4) if i % 2 == k])
     model.StageCost["Stage1"] = "c1"
     model.StageCost["Stage2"] = "c2"
     model.StageVariables["Stage1"].add("x")
     ScenarioTree(scenariotreeinstance=model)
Example #3
0
 def test_two_stage(self):
     G = networkx.DiGraph()
     G.add_node("Root")
     G.add_node("Child1")
     G.add_edge("Root", "Child1", weight=0.8)
     G.add_node("Child2")
     G.add_edge("Root", "Child2", weight=0.2)
     model = ScenarioTreeModelFromNetworkX(G)
     self.assertEqual(sorted(list(model.Stages)),
                      sorted(["Stage1", "Stage2"]))
     self.assertEqual(sorted(list(model.Nodes)),
                      sorted(["Root", "Child1", "Child2"]))
     self.assertEqual(sorted(list(model.Children["Root"])),
                      sorted(["Child1", "Child2"]))
     self.assertEqual(sorted(list(model.Children["Child1"])), sorted([]))
     self.assertEqual(sorted(list(model.Children["Child2"])), sorted([]))
     self.assertEqual(sorted(list(model.Scenarios)),
                      sorted(["Child1", "Child2"]))
     self.assertEqual(value(model.ConditionalProbability["Root"]), 1.0)
     self.assertEqual(value(model.ConditionalProbability["Child1"]), 0.8)
     self.assertEqual(value(model.ConditionalProbability["Child2"]), 0.2)
     model.StageCost["Stage1"] = "c1"
     model.StageCost["Stage2"] = "c2"
     model.StageVariables["Stage1"].add("x")
     self.assertEqual(model.Bundling.value, False)
     self.assertEqual(list(model.Bundles), [])
     self.assertEqual(len(model.BundleScenarios), 0)
     ScenarioTree(scenariotreeinstance=model)
Example #4
0
 def test_two_stage_custom_names(self):
     G = networkx.DiGraph()
     G.add_node("R", label="Root")
     G.add_node("C1", label="Child1", scenario="S1")
     G.add_edge("R", "C1", probability=0.8)
     G.add_node("C2", label="Child2", scenario="S2")
     G.add_edge("R", "C2", probability=0.2)
     model = ScenarioTreeModelFromNetworkX(
         G,
         edge_probability_attribute="probability",
         node_name_attribute="label",
         stage_names=["T1", "T2"],
         scenario_name_attribute="scenario")
     self.assertEqual(sorted(list(model.Stages)), sorted(["T1", "T2"]))
     self.assertEqual(sorted(list(model.Nodes)),
                      sorted(["Root", "Child1", "Child2"]))
     self.assertEqual(sorted(list(model.Children["Root"])),
                      sorted(["Child1", "Child2"]))
     self.assertEqual(sorted(list(model.Children["Child1"])), sorted([]))
     self.assertEqual(sorted(list(model.Children["Child2"])), sorted([]))
     self.assertEqual(sorted(list(model.Scenarios)), sorted(["S1", "S2"]))
     self.assertEqual(value(model.ConditionalProbability["Root"]), 1.0)
     self.assertEqual(value(model.ConditionalProbability["Child1"]), 0.8)
     self.assertEqual(value(model.ConditionalProbability["Child2"]), 0.2)
     model.StageCost["T1"] = "c1"
     model.StageCost["T2"] = "c2"
     model.StageVariables["T1"].add("x")
     self.assertEqual(model.Bundling.value, False)
     self.assertEqual(list(model.Bundles), [])
     self.assertEqual(len(model.BundleScenarios), 0)
     ScenarioTree(scenariotreeinstance=model)
Example #5
0
 def test_bad_custom_stage_names2(self):
     G = networkx.DiGraph()
     G.add_node("R")
     G.add_node("C1")
     G.add_edge("R", "C1", weight=1.0)
     with self.assertRaises(ValueError):
         ScenarioTreeModelFromNetworkX(G, stage_names=["Stage1", "Stage1"])
Example #6
0
 def test_bad_weight1(self):
     G = networkx.DiGraph()
     G.add_node("R", )
     G.add_node("C", )
     G.add_edge("R", "C", weight=0.8)
     with self.assertRaises(ValueError):
         ScenarioTreeModelFromNetworkX(G)
Example #7
0
 def test_missing_weight(self):
     G = networkx.DiGraph()
     G.add_node("R", name="Root")
     G.add_node("C", name="Child")
     G.add_edge("R", "C")
     with self.assertRaises(KeyError):
         ScenarioTreeModelFromNetworkX(G)
Example #8
0
 def test_not_tree(self):
     G = networkx.DiGraph()
     G.add_node("1")
     G.add_node("2")
     G.add_edge("1", "2")
     G.add_edge("2", "1")
     with self.assertRaises(TypeError):
         ScenarioTreeModelFromNetworkX(G)
Example #9
0
    def test_two_stage_more_node_attributes(self):
        G = networkx.DiGraph()
        G.add_node("Root", cost="c1", variables=["x"], derived_variables=["y"])
        G.add_node("Child1",
                   cost="c2",
                   variables=["q"],
                   derived_variables=["z"])
        G.add_edge("Root", "Child1", weight=0.8)
        G.add_node("Child2",
                   cost="c2",
                   variables=["q"],
                   derived_variables=["z"])
        G.add_edge("Root", "Child2", weight=0.2)
        model = ScenarioTreeModelFromNetworkX(G)
        self.assertEqual(sorted(list(model.Stages)),
                         sorted(["Stage1", "Stage2"]))
        self.assertEqual(sorted(list(model.Nodes)),
                         sorted(["Root", "Child1", "Child2"]))
        self.assertEqual(sorted(list(model.Children["Root"])),
                         sorted(["Child1", "Child2"]))
        self.assertEqual(sorted(list(model.Children["Child1"])), sorted([]))
        self.assertEqual(sorted(list(model.Children["Child2"])), sorted([]))
        self.assertEqual(sorted(list(model.Scenarios)),
                         sorted(["Child1", "Child2"]))
        self.assertEqual(value(model.ConditionalProbability["Root"]), 1.0)
        self.assertEqual(value(model.ConditionalProbability["Child1"]), 0.8)
        self.assertEqual(value(model.ConditionalProbability["Child2"]), 0.2)

        self.assertEqual(model.StageCost["Stage1"].value, None)
        self.assertEqual(list(model.StageVariables["Stage1"]), [])
        self.assertEqual(list(model.StageDerivedVariables["Stage1"]), [])

        self.assertEqual(model.NodeCost["Root"].value, "c1")
        self.assertEqual(list(model.NodeVariables["Root"]), ["x"])
        self.assertEqual(list(model.NodeDerivedVariables["Root"]), ["y"])

        self.assertEqual(model.StageCost["Stage2"].value, None)
        self.assertEqual(list(model.StageVariables["Stage2"]), [])
        self.assertEqual(list(model.StageDerivedVariables["Stage2"]), [])

        self.assertEqual(model.NodeCost["Child1"].value, "c2")
        self.assertEqual(list(model.NodeVariables["Child1"]), ["q"])
        self.assertEqual(list(model.NodeDerivedVariables["Child1"]), ["z"])

        self.assertEqual(model.NodeCost["Child2"].value, "c2")
        self.assertEqual(list(model.NodeVariables["Child2"]), ["q"])
        self.assertEqual(list(model.NodeDerivedVariables["Child2"]), ["z"])
        self.assertEqual(model.Bundling.value, False)
        self.assertEqual(list(model.Bundles), [])
        self.assertEqual(len(model.BundleScenarios), 0)
        ScenarioTree(scenariotreeinstance=model)
Example #10
0
 def test_multi_stage(self):
     G = networkx.balanced_tree(3, 2, networkx.DiGraph())
     model = ScenarioTreeModelFromNetworkX(G,
                                           edge_probability_attribute=None)
     self.assertEqual(sorted(list(model.Stages)),
                      sorted(["Stage1", "Stage2", "Stage3"]))
     self.assertEqual(sorted(list(model.Nodes)),
                      sorted([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]))
     self.assertEqual(sorted(list(model.Children[0])), sorted([1, 2, 3]))
     self.assertEqual(sorted(list(model.Children[1])), sorted([4, 5, 6]))
     self.assertEqual(sorted(list(model.Children[2])), sorted([7, 8, 9]))
     self.assertEqual(sorted(list(model.Children[3])), sorted([10, 11, 12]))
     self.assertEqual(sorted(list(model.Children[4])), sorted([]))
     self.assertEqual(sorted(list(model.Children[5])), sorted([]))
     self.assertEqual(sorted(list(model.Children[6])), sorted([]))
     self.assertEqual(sorted(list(model.Children[7])), sorted([]))
     self.assertEqual(sorted(list(model.Children[8])), sorted([]))
     self.assertEqual(sorted(list(model.Children[9])), sorted([]))
     self.assertEqual(sorted(list(model.Children[10])), sorted([]))
     self.assertEqual(sorted(list(model.Children[11])), sorted([]))
     self.assertEqual(sorted(list(model.Children[12])), sorted([]))
     self.assertEqual(sorted(list(model.Scenarios)),
                      sorted([4, 5, 6, 7, 8, 9, 10, 11, 12]))
     self.assertEqual(value(model.ConditionalProbability[0]), 1.0)
     self.assertAlmostEqual(value(model.ConditionalProbability[1]), 1.0 / 3)
     self.assertAlmostEqual(value(model.ConditionalProbability[2]), 1.0 / 3)
     self.assertAlmostEqual(value(model.ConditionalProbability[3]), 1.0 / 3)
     self.assertAlmostEqual(value(model.ConditionalProbability[4]), 1.0 / 3)
     self.assertAlmostEqual(value(model.ConditionalProbability[5]), 1.0 / 3)
     self.assertAlmostEqual(value(model.ConditionalProbability[6]), 1.0 / 3)
     self.assertAlmostEqual(value(model.ConditionalProbability[7]), 1.0 / 3)
     self.assertAlmostEqual(value(model.ConditionalProbability[8]), 1.0 / 3)
     self.assertAlmostEqual(value(model.ConditionalProbability[9]), 1.0 / 3)
     self.assertAlmostEqual(value(model.ConditionalProbability[10]),
                            1.0 / 3)
     self.assertAlmostEqual(value(model.ConditionalProbability[11]),
                            1.0 / 3)
     self.assertAlmostEqual(value(model.ConditionalProbability[12]),
                            1.0 / 3)
     model.StageCost["Stage1"] = "c1"
     model.StageCost["Stage2"] = "c2"
     model.StageCost["Stage3"] = "c3"
     model.StageVariables["Stage1"].add("x")
     model.StageVariables["Stage2"].add("y")
     model.StageVariables["Stage3"].add("y")
     self.assertEqual(model.Bundling.value, False)
     self.assertEqual(list(model.Bundles), [])
     self.assertEqual(len(model.BundleScenarios), 0)
     ScenarioTree(scenariotreeinstance=model)
Example #11
0
 def test_bundles_incomplete(self):
     G = networkx.DiGraph()
     G.add_node("r")
     for i in range(4):
         G.add_node("u" + str(i), bundle="B")
         G.add_edge("r", "u" + str(i))
     model = ScenarioTreeModelFromNetworkX(G,
                                           edge_probability_attribute=None)
     self.assertEqual(model.Bundling.value, True)
     self.assertEqual(list(model.Bundles), ["B"])
     self.assertEqual(list(model.BundleScenarios["B"]),
                      ["u" + str(i) for i in range(4)])
     G.nodes["u0"]["bundle"] = None
     with self.assertRaises(ValueError):
         ScenarioTreeModelFromNetworkX(G, edge_probability_attribute=None)
     del G.nodes["u0"]["bundle"]
     with self.assertRaises(ValueError):
         ScenarioTreeModelFromNetworkX(G, edge_probability_attribute=None)
Example #12
0
 def test_unbalanced(self):
     G = networkx.DiGraph()
     G.add_node("R")
     G.add_node("0")
     G.add_node("1")
     G.add_edge("R", "0")
     G.add_edge("R", "1")
     G.add_node("00")
     G.add_node("01")
     G.add_edge("0", "00")
     G.add_edge("0", "01")
     model = ScenarioTreeModelFromNetworkX(G,
                                           edge_probability_attribute=None)
     self.assertEqual(sorted(list(model.Stages)),
                      sorted(["Stage1", "Stage2", "Stage3"]))
     self.assertEqual(sorted(list(model.Nodes)),
                      sorted(["R", "0", "1", "00", "01"]))
     self.assertEqual(sorted(list(model.Children["R"])), sorted(["0", "1"]))
     self.assertEqual(sorted(list(model.Children["0"])),
                      sorted(["00", "01"]))
     self.assertEqual(sorted(list(model.Children["1"])), sorted([]))
     self.assertEqual(sorted(list(model.Children["00"])), sorted([]))
     self.assertEqual(sorted(list(model.Children["01"])), sorted([]))
     self.assertEqual(sorted(list(model.Scenarios)),
                      sorted(["00", "01", "1"]))
     self.assertEqual(value(model.ConditionalProbability["R"]), 1.0)
     self.assertEqual(value(model.ConditionalProbability["0"]), 0.5)
     self.assertEqual(value(model.ConditionalProbability["1"]), 0.5)
     self.assertEqual(value(model.ConditionalProbability["00"]), 0.5)
     self.assertEqual(value(model.ConditionalProbability["01"]), 0.5)
     model.StageCost["Stage1"] = "c1"
     model.StageCost["Stage2"] = "c2"
     model.StageCost["Stage3"] = "c3"
     model.StageVariables["Stage1"].add("x")
     model.StageVariables["Stage2"].add("x")
     self.assertEqual(model.Bundling.value, False)
     self.assertEqual(list(model.Bundles), [])
     self.assertEqual(len(model.BundleScenarios), 0)
     ScenarioTree(scenariotreeinstance=model)
    def get_factory():
        tree = networkx.DiGraph()
        tree.add_node("r", variables=["x"], cost="t0_cost")
        for i in range(3):
            tree.add_node("s" + str(i),
                          variables=["Y", "stale", "fixed"],
                          cost="t1_cost",
                          bundle="b" + str(i))
            tree.add_edge("r", "s" + str(i), weight=1.0 / 3)

        model = aml.ConcreteModel()
        model.x = aml.Var()
        model.Y = aml.Var([1], bounds=(None, 1))
        model.stale = aml.Var(initialize=0.0)
        model.fixed = aml.Var(initialize=0.0)
        model.fixed.fix()
        model.p = aml.Param(mutable=True)
        model.t0_cost = aml.Expression(expr=model.x)
        model.t1_cost = aml.Expression(expr=model.Y[1])
        model.o = aml.Objective(expr=model.t0_cost + model.t1_cost)
        model.c = aml.ConstraintList()
        model.c.add(model.x >= 1)
        model.c.add(model.Y[1] >= model.p)

        def _create_model(scenario_name, node_names):
            m = model.clone()
            if scenario_name == "s0":
                m.p.value = 0.0
            elif scenario_name == "s1":
                m.p.value = 1.0
            else:
                assert (scenario_name == "s2")
                m.p.value = 2.0
            return m

        return ScenarioTreeInstanceFactory(model=_create_model,
                                           scenario_tree=tree)
Example #14
0
 def test_not_enough_stages(self):
     G = networkx.DiGraph()
     G.add_node("R")
     with self.assertRaises(ValueError):
         ScenarioTreeModelFromNetworkX(G)
Example #15
0
 def test_empty(self):
     G = networkx.DiGraph()
     with self.assertRaises(networkx.NetworkXPointlessConcept):
         ScenarioTreeModelFromNetworkX(G)
Example #16
0
def block_triangularize(matrix, matching=None):
    """
    Computes the necessary information to permute a matrix to block-lower
    triangular form, i.e. a partition of rows and columns into an ordered
    set of diagonal blocks in such a permutation.

    Arguments
    ---------
    matrix: A SciPy sparse matrix
    matching: A perfect matching of rows and columns, in the form of a dict
              mapping row indices to column indices

    Returns
    -------
    Two dicts. The first maps each row index to the index of its block in a
    block-lower triangular permutation of the matrix. The second maps each
    column index to the index of its block in a block-lower triangular
    permutation of the matrix.
    """
    nxb = nx.algorithms.bipartite
    nxc = nx.algorithms.components
    nxd = nx.algorithms.dag
    from_biadjacency_matrix = nxb.matrix.from_biadjacency_matrix

    M, N = matrix.shape
    if M != N:
        raise ValueError(
            "block_triangularize does not currently "
            "support non-square matrices. Got matrix with shape %s." %
            (matrix.shape, ))
    bg = from_biadjacency_matrix(matrix)

    if matching is None:
        matching = maximum_matching(matrix)

    len_matching = len(matching)
    if len_matching != M:
        raise ValueError("block_triangularize only supports matrices "
                         "that have a perfect matching of rows and columns. "
                         "Cardinality of maximal matching is %s" %
                         len_matching)

    # Construct directed graph of rows
    dg = nx.DiGraph()
    dg.add_nodes_from(range(M))
    for n in dg.nodes:
        col_idx = matching[n]
        col_node = col_idx + M
        # For all rows that share this column
        for neighbor in bg[col_node]:
            if neighbor != n:
                # Add an edge towards this column's matched row
                dg.add_edge(neighbor, n)

    # Partition the rows into strongly connected components (diagonal blocks)
    scc_list = list(nxc.strongly_connected_components(dg))
    node_scc_map = {n: idx for idx, scc in enumerate(scc_list) for n in scc}

    # Now we need to put the SCCs in the right order. We do this by performing
    # a topological sort on the DAG of SCCs.
    dag = nx.DiGraph()
    for i, c in enumerate(scc_list):
        dag.add_node(i)
    for n in dg.nodes:
        source_scc = node_scc_map[n]
        for neighbor in dg[n]:
            target_scc = node_scc_map[neighbor]
            if target_scc != source_scc:
                dag.add_edge(target_scc, source_scc)
                # Reverse direction of edge. This corresponds to creating
                # a block lower triangular matrix.

    scc_order = list(nxd.lexicographical_topological_sort(dag))

    scc_block_map = {c: i for i, c in enumerate(scc_order)}
    row_block_map = {n: scc_block_map[c] for n, c in node_scc_map.items()}
    # ^ This maps row indices to the blocks they belong to.

    # Invert the matching to map row indices to column indices
    col_row_map = {c: r for r, c in matching.items()}
    assert len(col_row_map) == M

    col_block_map = {c: row_block_map[col_row_map[c]] for c in range(N)}

    return row_block_map, col_block_map