Ejemplo n.º 1
0
    def test_negative_selfloops(self):
        """Negative selfloops should cause an exception if uncapacitated and
        always be saturated otherwise.
        """
        G = nx.DiGraph()
        G.add_edge(1, 1, weight=-1)
        assert_raises(nx.NetworkXUnbounded, nx.network_simplex, G)
        assert_raises(nx.NetworkXUnbounded, nx.capacity_scaling, G)
        G[1][1]['capacity'] = 2
        flowCost, H = nx.network_simplex(G)
        assert_equal(flowCost, -2)
        assert_equal(H, {1: {1: 2}})
        flowCost, H = nx.capacity_scaling(G)
        assert_equal(flowCost, -2)
        assert_equal(H, {1: {1: 2}})

        G = nx.MultiDiGraph()
        G.add_edge(1, 1, 'x', weight=-1)
        G.add_edge(1, 1, 'y', weight=1)
        assert_raises(nx.NetworkXUnbounded, nx.network_simplex, G)
        assert_raises(nx.NetworkXUnbounded, nx.capacity_scaling, G)
        G[1][1]['x']['capacity'] = 2
        flowCost, H = nx.network_simplex(G)
        assert_equal(flowCost, -2)
        assert_equal(H, {1: {1: {'x': 2, 'y': 0}}})
        flowCost, H = nx.capacity_scaling(G)
        assert_equal(flowCost, -2)
        assert_equal(H, {1: {1: {'x': 2, 'y': 0}}})
Ejemplo n.º 2
0
    def test_digraph1(self):
        # From Bradley, S. P., Hax, A. C. and Magnanti, T. L. Applied
        # Mathematical Programming. Addison-Wesley, 1977.
        G = nx.DiGraph()
        G.add_node(1, demand=-20)
        G.add_node(4, demand=5)
        G.add_node(5, demand=15)
        G.add_edges_from([(1, 2, {'capacity': 15, 'weight': 4}),
                          (1, 3, {'capacity': 8, 'weight': 4}),
                          (2, 3, {'weight': 2}),
                          (2, 4, {'capacity': 4, 'weight': 2}),
                          (2, 5, {'capacity': 10, 'weight': 6}),
                          (3, 4, {'capacity': 15, 'weight': 1}),
                          (3, 5, {'capacity': 5, 'weight': 3}),
                          (4, 5, {'weight': 2}),
                          (5, 3, {'capacity': 4, 'weight': 1})])
        flowCost, H = nx.network_simplex(G)
        soln = {1: {2: 12, 3: 8},
                2: {3: 8, 4: 4, 5: 0},
                3: {4: 11, 5: 5},
                4: {5: 10},
                5: {3: 0}}
        assert_equal(flowCost, 150)
        assert_equal(nx.min_cost_flow_cost(G), 150)
        assert_equal(H, soln)
        assert_equal(nx.min_cost_flow(G), soln)
        assert_equal(nx.cost_of_flow(G, H), 150)

        flowCost, H = nx.capacity_scaling(G)
        assert_equal(flowCost, 150)
        assert_equal(H, soln)
        assert_equal(nx.cost_of_flow(G, H), 150)
Ejemplo n.º 3
0
    def test_zero_capacity_edges(self):
        """Address issue raised in ticket #617 by arv."""
        G = nx.DiGraph()
        G.add_edges_from([(1, 2, {'capacity': 1, 'weight': 1}),
                          (1, 5, {'capacity': 1, 'weight': 1}),
                          (2, 3, {'capacity': 0, 'weight': 1}),
                          (2, 5, {'capacity': 1, 'weight': 1}),
                          (5, 3, {'capacity': 2, 'weight': 1}),
                          (5, 4, {'capacity': 0, 'weight': 1}),
                          (3, 4, {'capacity': 2, 'weight': 1})])
        G.nodes[1]['demand'] = -1
        G.nodes[2]['demand'] = -1
        G.nodes[4]['demand'] = 2

        flowCost, H = nx.network_simplex(G)
        soln = {1: {2: 0, 5: 1},
                2: {3: 0, 5: 1},
                3: {4: 2},
                4: {},
                5: {3: 2, 4: 0}}
        assert_equal(flowCost, 6)
        assert_equal(nx.min_cost_flow_cost(G), 6)
        assert_equal(H, soln)
        assert_equal(nx.min_cost_flow(G), soln)
        assert_equal(nx.cost_of_flow(G, H), 6)

        flowCost, H = nx.capacity_scaling(G)
        assert_equal(flowCost, 6)
        assert_equal(H, soln)
        assert_equal(nx.cost_of_flow(G, H), 6)
Ejemplo n.º 4
0
    def test_digon(self):
        """Check if digons are handled properly. Taken from ticket
        #618 by arv."""
        nodes = [(1, {}),
                 (2, {'demand': -4}),
                 (3, {'demand': 4}),
                 ]
        edges = [(1, 2, {'capacity': 3, 'weight': 600000}),
                 (2, 1, {'capacity': 2, 'weight': 0}),
                 (2, 3, {'capacity': 5, 'weight': 714285}),
                 (3, 2, {'capacity': 2, 'weight': 0}),
                 ]
        G = nx.DiGraph(edges)
        G.add_nodes_from(nodes)
        flowCost, H = nx.network_simplex(G)
        soln = {1: {2: 0},
                2: {1: 0, 3: 4},
                3: {2: 0}}
        assert_equal(flowCost, 2857140)
        assert_equal(nx.min_cost_flow_cost(G), 2857140)
        assert_equal(H, soln)
        assert_equal(nx.min_cost_flow(G), soln)
        assert_equal(nx.cost_of_flow(G, H), 2857140)

        flowCost, H = nx.capacity_scaling(G)
        assert_equal(flowCost, 2857140)
        assert_equal(H, soln)
        assert_equal(nx.cost_of_flow(G, H), 2857140)
Ejemplo n.º 5
0
    def run_random_trial(self):
        G = nx.MultiDiGraph()
        nodes = range(1, 10)
        edges = generate_edges(nodes, 50)
        G.add_edges_from(edges)
        source = random.choice(G.nodes())
        while True:
            target = random.choice(G.nodes())
            if target != source:
                break
        amount = random.randint(1, 10)
        G.node[source]['demand'] = -amount
        G.node[target]['demand'] = amount

        cost, flow_dict, exception = None, None, None
        try:
            cost, flow_dict = min_cost_flow(G)
        except nx.NetworkXException as e:
            exception = e

        H = unmulti(G)
        try:
            cost2, flow_dict2 = nx.network_simplex(H)
        except nx.NetworkXException as e:
            self.assertEquals(type(e) != type(exception))
            self.assertEquals(cost, None)
        else:
            self.assertEquals(cost, cost2)
            self.assertEquals(exception, None)
Ejemplo n.º 6
0
 def test_large(self):
     fname = os.path.join(os.path.dirname(__file__), 'netgen-2.gpickle.bz2')
     G = nx.read_gpickle(fname)
     flowCost, flowDict = nx.network_simplex(G)
     assert_equal(6749969302, flowCost)
     assert_equal(6749969302, nx.cost_of_flow(G, flowDict))
     flowCost, flowDict = nx.capacity_scaling(G)
     assert_equal(6749969302, flowCost)
     assert_equal(6749969302, nx.cost_of_flow(G, flowDict))
Ejemplo n.º 7
0
    def test_multidigraph(self):
        """Multidigraphs are acceptable."""
        G = nx.MultiDiGraph()
        G.add_weighted_edges_from([(1, 2, 1), (2, 3, 2)], weight='capacity')
        flowCost, H = nx.network_simplex(G)
        assert_equal(flowCost, 0)
        assert_equal(H, {1: {2: {0: 0}}, 2: {3: {0: 0}}, 3: {}})

        flowCost, H = nx.capacity_scaling(G)
        assert_equal(flowCost, 0)
        assert_equal(H, {1: {2: {0: 0}}, 2: {3: {0: 0}}, 3: {}})
def processWiki(page, p=None, ignoreConditionalProbabilities=False):
    if p == None: p = readDict("data/wpairs")
    pe = readCounts("data/unigram-counts/" + page + ".en.tok.ucounts")
    pf = readCounts("data/unigram-counts/" + page + ".fr.tok.ucounts")

    G = nx.DiGraph()
    # 1 is source (F), 2 is sink (E)
    # 3 is F-null, 4 is E-null

    G.add_node(1, {'demand': -1, 'name': '*SOURCE*'})
    G.add_node(2, {'demand':  1, 'name': '*SINK*'})
    G.add_node(3, {'name': '*F-NULL*'})
    G.add_node(4, {'name': '*E-NULL*'})

    G.add_edge(1, 3, {'capacity': 1, 'weight': 100000})
    G.add_edge(4, 2, {'capacity': 1, 'weight': 100000})

    nCnt = 5

    fID = {}
    for f in pf.iterkeys():
        fID[f] = nCnt
        G.add_node(nCnt, {'name': f, 'lang': 'f'})
        G.add_edge(1, nCnt, {'capacity': pf[f], 'weight': 1})
        G.add_edge(nCnt, 4, {'capacity': 1, 'weight': 100000})
        nCnt += 1

    eID = {}
    for e in pe.iterkeys():
        eID[e] = nCnt
        G.add_node(nCnt, {'name': e, 'lang': 'e'})
        G.add_edge(nCnt, 2, {'capacity': pe[e], 'weight': 1})
        G.add_edge(3, nCnt, {'capacity': 1, 'weight': 100000})
        nCnt += 1

    for f in pf.iterkeys():
        nf = fID[f]
        if p.has_key(f):
            for e in p[f].iterkeys():
                if eID.has_key(e):
                    ne = eID[e]
                    cap = p[f][e]
                    if ignoreConditionalProbabilities: cap = 1
                    G.add_edge(nf, ne, {'capacity': cap, 'weight': 1})
                    
    flowCost,flowDict = nx.network_simplex(G)

    return G,flowDict
Ejemplo n.º 9
0
    def match(self, riders, ridees):
        graph = nx.DiGraph()
        for rider in riders:
            graph.add_node(rider.household_id, demand = - rider.capacity)

        for ridee in ridees:
            graph.add_node(ridee.household_id, demand = 1)

        for rider in riders:
            for ridee in ridees:
                distance = this._get_distance(rider.location, ridee.location)
                graph.add_edge(rider.household_id, ridee.household_id, weight = distance, capacity = 1)

        flowCost, flowDict = nx.network_simplex(graph)

        return flowDict
Ejemplo n.º 10
0
def nxMCF(startNodes, endNodes, capacities, costs, supplies):
    G = nx.DiGraph()
    for n, s in enumerate(supplies):
        G.add_node(n, demand=-s)

    for edgei in range(len(startNodes)):
        G.add_edge(startNodes[edgei],
                   endNodes[edgei],
                   weight=costs[edgei],
                   capacity=capacities[edgei])

    cost, flow = nx.network_simplex(G, demand='demand', capacity='capacity', weight='weight')
    totalFlow = 0
    for k1,v1 in flow.items():
        for k2,v2 in v1.items():
            totalFlow += v2
    return cost, totalFlow
Ejemplo n.º 11
0
    def test_transshipment(self):
        G = nx.DiGraph()
        G.add_node('a', demand=1)
        G.add_node('b', demand=-2)
        G.add_node('c', demand=-2)
        G.add_node('d', demand=3)
        G.add_node('e', demand=-4)
        G.add_node('f', demand=-4)
        G.add_node('g', demand=3)
        G.add_node('h', demand=2)
        G.add_node('r', demand=3)
        G.add_edge('a', 'c', weight=3)
        G.add_edge('r', 'a', weight=2)
        G.add_edge('b', 'a', weight=9)
        G.add_edge('r', 'c', weight=0)
        G.add_edge('b', 'r', weight=-6)
        G.add_edge('c', 'd', weight=5)
        G.add_edge('e', 'r', weight=4)
        G.add_edge('e', 'f', weight=3)
        G.add_edge('h', 'b', weight=4)
        G.add_edge('f', 'd', weight=7)
        G.add_edge('f', 'h', weight=12)
        G.add_edge('g', 'd', weight=12)
        G.add_edge('f', 'g', weight=-1)
        G.add_edge('h', 'g', weight=-10)
        flowCost, H = nx.network_simplex(G)
        soln = {'a': {'c': 0},
                'b': {'a': 0, 'r': 2},
                'c': {'d': 3},
                'd': {},
                'e': {'r': 3, 'f': 1},
                'f': {'d': 0, 'g': 3, 'h': 2},
                'g': {'d': 0},
                'h': {'b': 0, 'g': 0},
                'r': {'a': 1, 'c': 1}}
        assert_equal(flowCost, 41)
        assert_equal(nx.min_cost_flow_cost(G), 41)
        assert_equal(H, soln)
        assert_equal(nx.min_cost_flow(G), soln)
        assert_equal(nx.cost_of_flow(G, H), 41)

        flowCost, H = nx.capacity_scaling(G)
        assert_equal(flowCost, 41)
        assert_equal(nx.cost_of_flow(G, H), 41)
        assert_equal(H, soln)
Ejemplo n.º 12
0
 def test_simple_digraph(self):
     G = nx.DiGraph()
     G.add_node('a', demand = -5)
     G.add_node('d', demand = 5)
     G.add_edge('a', 'b', weight = 3, capacity = 4)
     G.add_edge('a', 'c', weight = 6, capacity = 10)
     G.add_edge('b', 'd', weight = 1, capacity = 9)
     G.add_edge('c', 'd', weight = 2, capacity = 5)
     flowCost, H = nx.network_simplex(G)
     soln = {'a': {'b': 4, 'c': 1},
             'b': {'d': 4},
             'c': {'d': 1},
             'd': {}}
     assert_equal(flowCost, 24)
     assert_equal(nx.min_cost_flow_cost(G), 24)
     assert_equal(H, soln)
     assert_equal(nx.min_cost_flow(G), soln)
     assert_equal(nx.cost_of_flow(G, H), 24)
Ejemplo n.º 13
0
 def test_bone_shaped(self):
     # From #1283
     G = nx.DiGraph()
     G.add_node(0, demand=-4)
     G.add_node(1, demand=2)
     G.add_node(2, demand=2)
     G.add_node(3, demand=4)
     G.add_node(4, demand=-2)
     G.add_node(5, demand=-2)
     G.add_edge(0, 1, capacity=4)
     G.add_edge(0, 2, capacity=4)
     G.add_edge(4, 3, capacity=4)
     G.add_edge(5, 3, capacity=4)
     G.add_edge(0, 3, capacity=0)
     flowCost, H = nx.network_simplex(G)
     assert_equal(flowCost, 0)
     assert_equal(
         H, {0: {1: 2, 2: 2, 3: 0}, 1: {}, 2: {}, 3: {}, 4: {3: 2}, 5: {3: 2}})
     flowCost, H = nx.capacity_scaling(G)
     assert_equal(flowCost, 0)
     assert_equal(
         H, {0: {1: 2, 2: 2, 3: 0}, 1: {}, 2: {}, 3: {}, 4: {3: 2}, 5: {3: 2}})
Ejemplo n.º 14
0
def network_simplex(play: dict):
    DG = nx.DiGraph(big_dimat_df(play))
    res = nx.network_simplex(DG)
    return res
Ejemplo n.º 15
0
def test_digraph1():
    # From Bradley, S. P., Hax, A. C. and Magnanti, T. L. Applied
    # Mathematical Programming. Addison-Wesley, 1977.
    G = nx.DiGraph()
    G.add_node(1, demand=-20)
    G.add_node(4, demand=5)
    G.add_node(5, demand=15)
    G.add_edges_from([
        (1, 2, {
            "capacity": 15,
            "weight": 4
        }),
        (1, 3, {
            "capacity": 8,
            "weight": 4
        }),
        (2, 3, {
            "weight": 2
        }),
        (2, 4, {
            "capacity": 4,
            "weight": 2
        }),
        (2, 5, {
            "capacity": 10,
            "weight": 6
        }),
        (3, 4, {
            "capacity": 15,
            "weight": 1
        }),
        (3, 5, {
            "capacity": 5,
            "weight": 3
        }),
        (4, 5, {
            "weight": 2
        }),
        (5, 3, {
            "capacity": 4,
            "weight": 1
        }),
    ])
    flowCost, H = nx.network_simplex(G)
    soln = {
        1: {
            2: 12,
            3: 8
        },
        2: {
            3: 8,
            4: 4,
            5: 0
        },
        3: {
            4: 11,
            5: 5
        },
        4: {
            5: 10
        },
        5: {
            3: 0
        },
    }
    assert flowCost == 150
    assert nx.min_cost_flow_cost(G) == 150
    assert H == soln
Ejemplo n.º 16
0
def route(PP, source=None, destination=None, view=False, debug=False):

    nPaths = len(PP)
    MainGraph = nx.DiGraph()
    tmp = []
    j = 0
    epsilon = 0.0000000001
    nodes = dict()
    all_edges = dict()
    G = [None] * nPaths
    for c, ip in zip(COLORS, xrange(nPaths)):
        Path = PP[ip]
        G[ip] = nx.DiGraph()

        k = j
        for x in Path:
            nodes[j] = x
            tmp.append([x, j])
            j += 1

        G[ip].add_nodes_from(nodes.keys())
        the_edges = [(i, i + 1) for i in xrange(k, j - 1)]
        all_edges[ip] = the_edges
        G[ip].add_edges_from(the_edges)

        # Add to Unified Graph
        MainGraph.add_nodes_from(nodes.keys())
        MainGraph.add_edges_from([(i, i + 1) for i in xrange(k, j - 1)])

    # Connecting the graph(s)
    for u in tmp:
        for v in tmp:
            if u != v:
                if u[0] == v[0]:
                    e = (u[1], v[1])
                    if e in MainGraph.edges():  # TODO add capacity here?
                        if debug: print ' %s already there.' % list(e)
                    else:
                        if debug: print ' Adding %s to graph.' % list(e)
                        MainGraph.add_edge(e[0], e[1])

    n = len(MainGraph.nodes())

    source_node = LatLngtoNode(source, nodes)
    destination_node = LatLngtoNode(destination, nodes)

    # Optimization Graph

    OG = nx.DiGraph()

    m = 3  # max capacity  TODO randomly?
    w = 1

    for e in MainGraph.edges():
        OG.add_edge(e[0], e[1], weight=w, capacity=m)

    OG.add_node(source_node, demand=-1)
    OG.add_node(destination_node, demand=1)

    try:

        flowCost, flowDict = nx.network_simplex(OG)
        print 'shortest_path_length? ', flowCost == nx.shortest_path_length(
            OG, source_node, destination_node, weight='weight')

    except Exception as e:
        print('Pick another option (%s)' % e)
        print("(Keep it, not congested)")

        return -1

    E = []
    print 'flowDict : '
    for u in flowDict:
        for v in flowDict[u]:
            if flowDict[u][v] != 0:
                print '\t', u, ' -> ', v, ' : ', flowDict[u][v]
                E.append((u, v))

    print("Optimum = %s" % flowCost)

    for e in E:
        print e

    print '----- leaving route() ---------------------------------'

    return E, flowCost
Ejemplo n.º 17
0
    nz_idx = pd.Series(np.nonzero(C_transfers.values)[0])
    for i in range(abs(dif)):
        C_transfers.iloc[nz_idx[i]] -= direct 

for i in CG.nodes():
    CG.node[i]['load'] = C_loads[i]
    CG.node[i]['gen'] = C_gen[i]
    CG.node[i]['trans'] = C_transfers[i]

for i in CG.nodes():
    CG.node[i]['MW_net'] = CG.node[i]['gen'] - CG.node[i]['load'] - CG.node[i]['trans']

DG = CG.to_directed()


NS = nx.network_simplex(DG, demand='MW_net', weight='R', capacity='tot_MW_cap')
#### EVERYTHING BELOW DOESN'T WORK!!!

for i in G.nodes():
    kv_list = [G.adj[i][j]['tot_kv'] for j in G.adj[i].keys() if isinstance(j, int)]
    kv_max, kv_min = max(kv_list), min(kv_list)
    G[i]['max_volt'] = kv_max
    G[i]['min_volt'] = kv_min

#### GET GRID VOLTAGES FROM EIA FORM DATA

mwkv = pd.DataFrame(np.zeros(len(G.nodes())), index=G.nodes())

for x in ['load', 'gen', 'trans', 'min_volt', 'max_volt']:
    mwkv_col = pd.DataFrame(np.vstack([tuple([i, G[i][x]]) for i in G.nodes() if x in G[i].keys()])).rename(columns={1 : x}).set_index(0)
    mwkv = pd.concat([mwkv, mwkv_col], axis=1)
Ejemplo n.º 18
0
    generator = [j]
    for i in range(7):
        hdi = energize_hood_neighbor(hdi)
    if largest_hdi < len(hdi):
        largest_hdi = len(hdi)
        best = generator
for i in range(7):
    plt.subplot(331 + i)
    plt.title(i)
    nx.draw(g, gpos, node_color=red_coloring(best), alph=0.7)
    best = energize_hood_neighbor(best)
print(best)
plt.show()

# Calculate a valid network flow.
nx.network_simplex(g)

plt.close()
# Graph with edge width determined by simplex flow
flowCost, flowDict = nx.network_simplex(g)
G = nx.Graph()
widths = []
for u in flowDict:
    for v in flowDict[u]:
        if flowDict[u][v] != 0:
            G.add_edge(u, v)
            widths.append(flowDict[u][v])
plt.figure(figsize=(10, 5))
gpos = nx.spring_layout(G)
nx.draw_networkx_nodes(G, gpos, node_size=700)
nx.draw_networkx_edges(G, gpos, width=widths)
Ejemplo n.º 19
0
def min_cost_flow_cost(G, demand='demand', capacity='capacity',
                       weight='weight'):
    r"""Find the cost of a minimum cost flow satisfying all demands in digraph G.

    G is a digraph with edge costs and capacities and in which nodes
    have demand, i.e., they want to send or receive some amount of
    flow. A negative demand means that the node wants to send flow, a
    positive demand means that the node want to receive flow. A flow on
    the digraph G satisfies all demand if the net flow into each node
    is equal to the demand of that node.

    Parameters
    ----------
    G : NetworkX graph
        DiGraph on which a minimum cost flow satisfying all demands is
        to be found.

    demand : string
        Nodes of the graph G are expected to have an attribute demand
        that indicates how much flow a node wants to send (negative
        demand) or receive (positive demand). Note that the sum of the
        demands should be 0 otherwise the problem in not feasible. If
        this attribute is not present, a node is considered to have 0
        demand. Default value: 'demand'.

    capacity : string
        Edges of the graph G are expected to have an attribute capacity
        that indicates how much flow the edge can support. If this
        attribute is not present, the edge is considered to have
        infinite capacity. Default value: 'capacity'.

    weight : string
        Edges of the graph G are expected to have an attribute weight
        that indicates the cost incurred by sending one unit of flow on
        that edge. If not present, the weight is considered to be 0.
        Default value: 'weight'.

    Returns
    -------
    flowCost : integer, float
        Cost of a minimum cost flow satisfying all demands.

    Raises
    ------
    NetworkXError
        This exception is raised if the input graph is not directed or
        not connected.

    NetworkXUnfeasible
        This exception is raised in the following situations:

            * The sum of the demands is not zero. Then, there is no
              flow satisfying all demands.
            * There is no flow satisfying all demand.

    NetworkXUnbounded
        This exception is raised if the digraph G has a cycle of
        negative cost and infinite capacity. Then, the cost of a flow
        satisfying all demands is unbounded below.

    See also
    --------
    cost_of_flow, max_flow_min_cost, min_cost_flow, network_simplex

    Notes
    -----
    This algorithm is not guaranteed to work if edge weights or demands
    are floating point numbers (overflows and roundoff errors can
    cause problems). As a workaround you can use integer numbers by
    multiplying the relevant edge attributes by a convenient
    constant factor (eg 100).

    Examples
    --------
    A simple example of a min cost flow problem.

    >>> import networkx as nx
    >>> G = nx.DiGraph()
    >>> G.add_node('a', demand = -5)
    >>> G.add_node('d', demand = 5)
    >>> G.add_edge('a', 'b', weight = 3, capacity = 4)
    >>> G.add_edge('a', 'c', weight = 6, capacity = 10)
    >>> G.add_edge('b', 'd', weight = 1, capacity = 9)
    >>> G.add_edge('c', 'd', weight = 2, capacity = 5)
    >>> flowCost = nx.min_cost_flow_cost(G)
    >>> flowCost
    24
    """
    return nx.network_simplex(G, demand=demand, capacity=capacity,
                              weight=weight)[0]
Ejemplo n.º 20
0
    def optimiseFlows(self, max_iter=500, bKLDivergence=False):

        iter = 0

        eLambda = (self.phi + self.DELTA) * self.lengths

        if bKLDivergence:
            NLL1 = self._KDivergence(eLambda, self.mask)
        else:
            NLL1 = self._FDivergence(eLambda, self.mask)

        print(str(iter) + "," + str(NLL1))

        for gene, biGraph in self.biGraphs.items():
            biGraph.addSourceSinkShunt()

        while iter < max_iter:

            #first compute phi gradient in matrix format

            eLambda = (self.phi + self.DELTA) * self.lengths

            R = self.X / eLambda

            if bKLDivergence:
                gradPhi = -R * self.mask + self.lengths
            else:

                gradPhi = (eLambda - self.X) * self.mask * self.lengths

            if self.bLasso:
                gradPhi += self.fLambda

            newPhi = np.copy(self.phi)

            for gene, biGraph in self.biGraphs.items():

                biGraph.updateCosts(gradPhi, self.mapGeneIdx[gene])

                residualGraph = ResidualBiGraph.createResidualGraph(
                    biGraph.diGraph)

                #residualGraph.add_edge('sink+','source+')
                #residualGraph.add_edge('source+','sink+')

                #for n1, d in residualGraph.nodes(data=True):
                #   d.pop('demand',None)

                #attrs = {'source+': {'demand': 0.01*INT_SCALE}, 'sink+': {'demand': -0.01*INT_SCALE}}

                #nx.set_node_attributes(residualGraph, attrs)

                flowCost, flowDict = nx.network_simplex(residualGraph)

                pflow = 0.01

                DeltaF = biGraph.deltaF(flowDict, pflow, self.X, eLambda,
                                        self.mapGeneIdx[gene], self.lengths,
                                        bKLDivergence, self.bLasso,
                                        self.fLambda)
                weight = biGraph.transformFlowCost(flowCost)

                i = 0
                while DeltaF > pflow * weight * BETA and i < 10:
                    pflow *= TAU

                    DeltaF = biGraph.deltaF(flowDict, pflow, self.X, eLambda,
                                            self.mapGeneIdx[gene],
                                            self.lengths, bKLDivergence,
                                            self.bLasso, self.fLambda)

                    i += 1

                if pflow > 0. and i < 10:
                    biGraph.updateFlows(flowDict, pflow)

                biGraph.updatePhi(newPhi, self.mapGeneIdx[gene])

            eLambda1 = (newPhi + self.DELTA) * self.lengths

            if bKLDivergence:
                NLL1 = self._KDivergence(eLambda1, self.mask)
            else:
                NLL1 = self._FDivergence(eLambda1, self.mask)

            if iter % 1 == 0:
                print(str(iter) + "," + str(NLL1))

                #print(str(iter) + "," + str(NLL3))

            self.phi = newPhi

            iter = iter + 1

        for gene, biGraph in self.biGraphs.items():
            biGraph.removeSourceSinkShunt()
    def decompose(self):
        """
		Calls the network simplex to run the MCF algorithm.
		Computes the fairlets and fairlet centers.

		Returns:
			fairlets (list) 
			fairlet_centers (list)
			costs (list)
		"""

        start_time = time.time()
        flow_cost, flow_dict = nx.network_simplex(self.G)
        print("Time taken to compute MCF solution - %.3f seconds." %
              (time.time() - start_time))

        fairlets = {}
        # Assumes mapping from blue nodes to the red nodes
        for i in flow_dict.keys():
            if 'B' in i and '_' in i:
                if sum(flow_dict[i].values()) == 1:
                    for j in flow_dict[i].keys():
                        if flow_dict[i][j] == 1:
                            if j.split('_')[0] not in fairlets:
                                fairlets[j.split('_')[0]] = [i.split('_')[0]]
                            else:
                                fairlets[j.split('_')[0]].append(
                                    i.split('_')[0])

        fairlets = [([a] + b) for a, b in fairlets.items()]

        fairlets2 = []
        for i in fairlets:
            curr_fairlet = []
            for j in i:
                if 'R' in j:
                    d = self.reds
                else:
                    d = self.blues
                curr_fairlet.append(d[int(j[1:]) - 1])
            fairlets2.append(curr_fairlet)
        fairlets = fairlets2
        del fairlets2

        # Choosing fairlet centers
        fairlet_centers = []
        fairlet_costs = []

        for f in fairlets:
            cost_list = [
                (i, max([distance(self.data[i], self.data[j]) for j in f]))
                for i in f
            ]
            cost_list = sorted(cost_list, key=lambda x: x[1], reverse=False)
            center, cost = cost_list[0][0], cost_list[0][1]
            fairlet_centers.append(center)
            fairlet_costs.append(cost)

        print("%d fairlets have been identified." % (len(fairlet_centers)))
        assert len(fairlets) == len(fairlet_centers)
        assert len(fairlet_centers) == len(fairlet_costs)

        return fairlets, fairlet_centers, fairlet_costs
import numpy as np
Ejemplo n.º 23
0
    def optimiseFlows(self, max_iter=100, minChange=1.0):

        iter = 0

        lNLL1 = self._devF()

        print(str(iter) + "," + str(lNLL1))

        #self.biGraph.addSourceSinkShunt()

        deltaF = minChange * 2.

        while iter < max_iter or deltaF > minChange:

            #first compute phi gradient in matrix format

            dNeta = 1. / ((1.0 - self.Eta + self.minDelta) *
                          (self.Eta + self.minDelta))

            gradEta = (self.Theta - self.thetaStar) * dNeta

            newNeta = np.copy(self.Eta)

            self.biGraph.updateCosts(gradEta, self.mapIdx)

            residualGraph = ResidualBiGraph.createResidualGraph(
                self.biGraph.diGraph)

            flowCost, flowDict = nx.network_simplex(residualGraph)

            pflow = 0.1

            DeltaF = self.biGraph.deltaFF(flowDict, pflow, self.thetaStar,
                                          self.Eta, self.Theta, self.mapIdx,
                                          self.minDelta)
            weight = self.biGraph.transformFlowCost(flowCost)

            i = 0
            while DeltaF > pflow * weight * BETA and i < 10:
                pflow *= TAU

                DeltaF = self.biGraph.deltaFF(flowDict, pflow, self.thetaStar,
                                              self.Eta, self.Theta,
                                              self.mapIdx, self.minDelta)

                i += 1

            if pflow > 0. and i < 10:
                self.biGraph.updateFlows(flowDict, pflow)

            self.biGraph.updatePhi(newNeta, self.mapIdx)

            self.Eta = newNeta

            self._updateTheta()

            NLL1 = self._devF()

            deltaF = abs(NLL1 - lNLL1)

            lNLL1 = NLL1

            if iter % 10 == 0:
                print(str(iter) + "," + str(NLL1) + "," + str(deltaF))

            iter = iter + 1
Ejemplo n.º 24
0
    def optimiseFlows(self, alpha=1.):

        iter = 0

        eLambda = (np.dot(self.phi, self.gamma) +
                   self.DELTA) * self.lengths[:, np.newaxis]
        NLL1 = np.sum(eLambda - self.X * np.log(eLambda))

        print(str(iter) + "," + str(NLL1))

        while iter < 200:

            #first compute phi gradient in matrix format

            eLambda = (np.dot(self.phi, self.gamma) +
                       self.DELTA) * self.lengths[:, np.newaxis]
            gSum = np.sum(self.gamma, axis=1)
            R = self.X / eLambda

            gradPhi = (-np.dot(R, self.gamma.transpose()) +
                       gSum[np.newaxis, :]) * self.lengths[:, np.newaxis]

            gradPhi += -(alpha - 1.) / (self.phi + self.PRECISION) + (
                alpha - 1.) / (1.0 - self.phi + self.PRECISION)

            newPhi = np.copy(self.phi)

            for g in range(self.G):
                self.biGraphs[g].updateCosts(gradPhi[:, g], self.mapIdx)

                residualGraph = ResidualBiGraph.createResidualGraph(
                    self.biGraphs[g].diGraph)

                flowCost, flowDict = nx.network_simplex(residualGraph)

                pflow = 0.1

                DeltaF = self.biGraphs[g].deltaF(flowDict, pflow, self.X,
                                                 eLambda, self.mapIdx,
                                                 self.lengths, g, self.gamma)

                weight = flowCost / float(INT_SCALE)

                i = 0
                while DeltaF > pflow * weight * BETA and i < 10:
                    pflow *= TAU

                    DeltaF = self.biGraphs[g].deltaF(flowDict, pflow, self.X,
                                                     eLambda, self.mapIdx,
                                                     self.lengths, g,
                                                     self.gamma)

                    #print(str(i) + "," + str(pflow) + "," + str(DeltaF) + "," + str(pflow*weight*BETA))
                    i += 1

                if pflow > 0. and i < 10:
                    self.biGraphs[g].updateFlows(flowDict, pflow)

                self.biGraphs[g].updatePhi(newPhi, g, self.mapIdx)

            eLambda1 = (np.dot(newPhi, self.gamma) +
                        self.DELTA) * self.lengths[:, np.newaxis]
            NLL1 = np.sum(eLambda1 - self.X * np.log(eLambda1))
            print(str(iter) + "," + str(NLL1))

            pL = self.phi * self.lengths[:, np.newaxis]
            pSum = np.sum(pL, axis=0)

            if self.bARD:
                pSum += self.lambda_g

            self.gamma = self.gamma * (np.dot(np.transpose(pL), R) /
                                       pSum[:, np.newaxis])

            #self.gamma[self.gamma < 0] = 0.

            eLambda3 = (np.dot(newPhi, self.gamma) +
                        self.DELTA) * self.lengths[:, np.newaxis]
            NLL3 = np.sum(eLambda3 - self.X * np.log(eLambda3))

            if self.bARD:
                self.alpha_g = self.alphaG + self.S

                self.beta_g = self.betaG + np.sum(self.gamma, axis=1)

                self.lambda_g = self.alpha_g / self.beta_g

            print(str(iter) + "," + str(NLL3))

            self.phi = newPhi

            iter = iter + 1
Ejemplo n.º 25
0
def test_large():
    fname = os.path.join(os.path.dirname(__file__), "netgen-2.gpickle.bz2")
    G = nx.read_gpickle(fname)
    flowCost, flowDict = nx.network_simplex(G)
    assert 6749969302 == flowCost
    assert 6749969302 == nx.cost_of_flow(G, flowDict)
Ejemplo n.º 26
0
def printError(n, n2):
    file_name = '-'.join([n, n2])
    file = open('data/output/' + file_name + '.txt', 'w')
    file.write('Optimal route:' + '\n')
    file.write('There`s no an optimal route between these stops')
    file.close()


# =======================================
# Main
# =======================================
if __name__ == "__main__":

    file = open('data/inputfile.txt', 'r')

    for line in file:
        data = line.split('-')
        name = data[0]
        name2 = data[1]
        time = int(data[2])

        graph = MGraph()

        try:
            graph.findStartNode(name, time)
            graph.G.add_node(name2, demand=1)
            flowCost, flowDict = nx.network_simplex(graph.G)
            printOptimalRoute(name + ' Start', name2, flowDict, flowCost)
        except:
            printError(name, name2)
Ejemplo n.º 27
0
def rig_component(G, x, y, maxW):
    """ Compute the RIG metric on a single component.

    Parameters
    ----------
    G : nx.Graph
       A connected graph of weighted edges
    x : pd.Series
       Vector of nodes and their abundance in sample x
       within the connected graph G
    y : pd.Series
       Vector of nodes and their abundance in sample y
       within the connected graph G
    maxW : float
       The cost of an insertion step

    Returns
    -------
    float :
       Distance between sample x and sample y

    Note
    ----
    If x or y is None, then 1 will be added to the total distance.
    If they are both None, then the distance will be zero.
    Also, the weights of the edges must be contained in `'weight'`.
    """

    # Both samples don't contain any metabolites
    if len(x) == 0 and len(y) == 0:
        return 0
    xtotal = int(max([x.sum(), 1]))
    ytotal = int(max([y.sum(), 1]))

    # Convert everything to fractions
    if x.sum() != 0:
        x = pd.Series([Fraction(i, xtotal) for i in np.ravel(x.values)], index=x.index)
    if y.sum() != 0:
        y = pd.Series([Fraction(i, ytotal) for i in np.ravel(y.values)], index=y.index)
    if x.equals(y):
        return 0

    # The component being analyzed has only 1 node.
    # So the networkx simplex algorithm cannot be run
    # since there are no edges.
    if len(list(G.nodes())) == 1:
        return maxW

    cost = 0
    edges = G.edges(data="weight")

    # If there one of the samples doesn't have any metabolites
    # on the component, arbituarily pick two metabolites
    # and append them to the set.  This to address the issue of
    # measuring distance between unshared components.
    if len(x) == 0 or x.sum() == 0:
        x = pd.Series({y.index[0]: Fraction(1, 1)})
        weight = maxW
    elif len(y) == 0 or y.sum() == 0:
        y = pd.Series({x.index[0]: Fraction(1, 1)})
        weight = maxW
    else:
        weight = 0
    _G = copy.deepcopy(G)

    xarr = pd.Series({n: (x[n] if n in x else 0) for n in G.nodes()})
    yarr = pd.Series({n: (y[n] if n in y else 0) for n in G.nodes()})

    d = 0
    maxxD = max(map(lambda k: k.denominator, x))
    maxyD = max(map(lambda k: k.denominator, y))

    for node in _G.nodes():
        dmd = int((xarr[node] - yarr[node]) * xtotal * ytotal)
        _G.node[node]["demand"] = dmd
        d += dmd

    W, _ = nx.network_simplex(_G.to_directed())
    cost += W + weight
    return cost
def generate_path(G, operations, directory):
    '''
    Generates optimal path/sub_graph using different strategies
    # Arguments
        G: networkx graph
        operations: Graph operations to be performed
            greedy: Generates path in a greedy way from a networkx graph generated by MultiChannelNet
            dag_longest: Generates path using networkx dag_longest_path using the architecture weights as cost of each edge
                https://networkx.github.io/documentation/stable/reference/algorithms/generated/networkx.algorithms.dag.dag_longest_path.html
            beam_search: Generates approximate longest path using beam search by computing a weighted degree of each node
                https://networkx.github.io/documentation/stable/reference/algorithms/generated/networkx.algorithms.traversal.beamsearch.bfs_beam_edges.html
            flow_with_demand: Generates a subgraph using networkx capacity_scaling with the demand parameter passed earlier
                https://networkx.github.io/documentation/stable/reference/algorithms/generated/networkx.algorithms.flow.capacity_scaling.html#networkx.algorithms.flow.capacity_scaling
            iterative_cost_search: Runs an iterative cost search using network_simplex from networkx with the demand scaling
                from 1 to the demand passed with each step being the parameter demand_step
                https://networkx.github.io/documentation/stable/reference/algorithms/generated/networkx.algorithms.flow.network_simplex.html#networkx.algorithms.flow.network_simplex

        directory: File directory for the output to be stored
    '''
    print('Optimal path: ')
    if 'greedy' in operations:
        bottom_up_greedy = gen_greedy_path(G, strategy="bottom_up")
        top_down_greedy = gen_greedy_path(G, strategy="top_down")

        print('Greedy: ')
        print('\tBottom up:')
        print('\t', bottom_up_greedy)
        print('\t', top_down_greedy)

    if 'dag_longest' in operations:
        dag_optimal_path = nx.algorithms.dag.dag_longest_path(G)
        print('DAG Longest Path: ')
        print(dag_optimal_path)

    if 'beam_search' in operations:
        # TODO test and save output
        weighted_degree = dict(list(G.degree(weight='weight')))
        beam_edges = nx.algorithms.traversal.beamsearch.bfs_beam_edges(
            G, 'Source', weighted_degree.get, width=args.beam_width)

    if 'flow_with_demand' in operations:
        G.nodes["Source"]['demand'] = -args.flow_demand
        G.nodes["Linear"]['demand'] = args.flow_demand
        fl_cost, fl_dict = nx.capacity_scaling(G,
                                               demand='demand',
                                               weight='capacity',
                                               capacity='weight_int')
        new_g = nx.DiGraph()
        new_path = new_g.add_edges_from(min_cost_flow_edge)
        nx.write_pickle(new_path,
                        os.path.join(directory_name, "capacity_scaled.graph"))
        print('Capacity Scaling: ')
        print(new_path.edges)

    elif 'iterative_cost_search' in operations:
        demand_cost_list = []
        for demand in range(1, args.flow_demand, args.demand_step):
            G.nodes["Source"]['demand'] = -args.flow_demand
            G.nodes["Linear"]['demand'] = args.flow_demand
            try:
                flow_cost, flow_dict = nx.network_simplex(
                    cnn_model.G, weight='capacity', capacity='weight_int')
            except nx.exception.NetworkXUnfeasible:
                print('There is no flow satisfying the demand ', demand)
                continue
            min_cost_flow_edges = [(u, v) for u in flow_dict
                                   for v in flow_dict[u]
                                   if flow_dict[u][v] > args.flow_cut]
            if len(min_cost_flow_edges) != 0:
                demand_cost_list.append(demand, fl_cost)

        print('Iterative cost search with demand', args.flow_demand,
              'demand_step', args.demand_step, ':')
        print(demand_cost_list)
        plt.xlabel('Demand')
        plt.ylabel('Cost')
        plt.scatter(*zip(*demand_cost_list))
        plt.savefig(
            os.path.join(directory_name, "iterative_cost_search_graph.png"))
Ejemplo n.º 29
0
def min_cost_flow(G, demand='demand', capacity='capacity', weight='weight'):
    r"""Return a minimum cost flow satisfying all demands in digraph G.

    G is a digraph with edge costs and capacities and in which nodes
    have demand, i.e., they want to send or receive some amount of
    flow. A negative demand means that the node wants to send flow, a
    positive demand means that the node want to receive flow. A flow on
    the digraph G satisfies all demand if the net flow into each node
    is equal to the demand of that node.

    Parameters
    ----------
    G : NetworkX graph
        DiGraph on which a minimum cost flow satisfying all demands is
        to be found.

    demand : string
        Nodes of the graph G are expected to have an attribute demand
        that indicates how much flow a node wants to send (negative
        demand) or receive (positive demand). Note that the sum of the
        demands should be 0 otherwise the problem in not feasible. If
        this attribute is not present, a node is considered to have 0
        demand. Default value: 'demand'.

    capacity : string
        Edges of the graph G are expected to have an attribute capacity
        that indicates how much flow the edge can support. If this
        attribute is not present, the edge is considered to have
        infinite capacity. Default value: 'capacity'.

    weight : string
        Edges of the graph G are expected to have an attribute weight
        that indicates the cost incurred by sending one unit of flow on
        that edge. If not present, the weight is considered to be 0.
        Default value: 'weight'.

    Returns
    -------
    flowDict : dictionary
        Dictionary of dictionaries keyed by nodes such that
        flowDict[u][v] is the flow edge (u, v).

    Raises
    ------
    NetworkXError
        This exception is raised if the input graph is not directed or
        not connected.

    NetworkXUnfeasible
        This exception is raised in the following situations:

            * The sum of the demands is not zero. Then, there is no
              flow satisfying all demands.
            * There is no flow satisfying all demand.

    NetworkXUnbounded
        This exception is raised if the digraph G has a cycle of
        negative cost and infinite capacity. Then, the cost of a flow
        satisfying all demands is unbounded below.

    See also
    --------
    cost_of_flow, max_flow_min_cost, min_cost_flow_cost, network_simplex

    Notes
    -----
    This algorithm is not guaranteed to work if edge weights or demands
    are floating point numbers (overflows and roundoff errors can
    cause problems). As a workaround you can use integer numbers by
    multiplying the relevant edge attributes by a convenient
    constant factor (eg 100).

    Examples
    --------
    A simple example of a min cost flow problem.

    >>> import networkx as nx
    >>> G = nx.DiGraph()
    >>> G.add_node('a', demand = -5)
    >>> G.add_node('d', demand = 5)
    >>> G.add_edge('a', 'b', weight = 3, capacity = 4)
    >>> G.add_edge('a', 'c', weight = 6, capacity = 10)
    >>> G.add_edge('b', 'd', weight = 1, capacity = 9)
    >>> G.add_edge('c', 'd', weight = 2, capacity = 5)
    >>> flowDict = nx.min_cost_flow(G)
    """
    return nx.network_simplex(G,
                              demand=demand,
                              capacity=capacity,
                              weight=weight)[1]
def flow_fail_sim(G, demand_value, capacity_factor, default_capacity,
                  trigger_edge, g_name, result_file_path, run,
                  adjust_capacities, net_name, set_edge_capacities_by_type,
                  select_supply_demand_at_random, trigger_until_cascading):

    ### variables for removing nodes and edges
    remove_nodes_over = False
    remove_edges_over = True

    ### variables for testing
    print_test_outputs = False
    find_alt_routes = False

    checking_flow_demand = True

    ### what to do on failure
    fail_print_nodes = False
    fail_print_edges = True

    ### what to do on completion
    print_nodes = False
    print_edges = False

    ## set result file path
    if run != None:
        result_file_path = result_file_path + '\\result_%s_run_%s.txt' % (
            g_name, run)
    else:
        result_file_path = result_file_path + '\\result_%s.txt' % g_name

    ### open results file
    results_file = open(result_file_path, 'w')

    ### set demand value based on the number of nodes in the network
    #demand_value = nx.number_of_nodes(G)/2.0
    #default_capacity = nx.number_of_nodes(G)/30.0
    #default_capacity = nx.number_of_edges(G)/100.0

    ### start of model

    #create containers to store removed edges and nodes
    graph_edges_removed = []
    graph_nodes_removed = []

    # add a random capacity value to all nodes and edges
    #G = maxflow_tools.set_random_capacities(G,3,8,'flow_capacity')

    if print_test_outputs == True: print '## Creating super nodes if needed'
    # create super nodes for supply and demand
    G, supply_nodes, demand_nodes, added_nodes, added_edges = maxflow_tools.topological_changes(
        G).check_for_demand_supply_nodes()

    if set_edge_capacities_by_type == True:
        #set edge capacities based on the network type (given the name)
        G = func_set_edge_capacities(G, net_name)
    else:
        #set flow capacity for edges
        for edge in G.edges():
            G[edge[0]][edge[1]]['flow_capacity'] = default_capacity
            #print G[edge[0]][edge[1]]['flow_capacity']
        for node in G.nodes():
            G.node[node]['flow_capacity'] = default_capacity

    if select_supply_demand_at_random == True:
        #select a single supply and demand node at random
        #reseats the roles of all other nodes adn edges as well
        G = set_single_supply_demand_randomly(G)

    # convert topology
    G, supply_nodes, demand_nodes, super_supply_node, super_demand_node = maxflow_tools.topological_changes(
        G).convert_topo('demand', 'supply', 'intermediate', 'flow_capacity')
    '''    
    print '--------------------------------'
    print 'Supply node(s):', supply_nodes
    print 'Demand node(s):', demand_nodes
    print '--------------------------------'
    '''

    #reset flow values to zero
    G = maxflow_tools.other(G).reset_flow_values()

    #set demand values
    # set value of zero for all nodes
    for nd in G.nodes():
        G.node[nd]['demand'] = 0

    #set demand values for demand node(s)
    if super_demand_node != False:
        G.node[super_demand_node]['demand'] = demand_value
    else:
        split_demand_value = demand_value / len(demand_nodes)
        for nd in demand_nodes:
            print 'Assigning a demand to node', nd, 'of', split_demand_value
            G.node[nd]['demand'] = split_demand_value

    # set demand values for supply node(s)
    if super_supply_node != False:
        supply_nd = super_demand_node
        G.node[super_supply_node]['demand'] = -demand_value
    else:
        split_demand_value = demand_value / len(supply_nodes)
        for nd in supply_nodes:
            print 'Assinging a demand to node', nd, 'of', -split_demand_value
            supply_nd = nd
            G.node[nd]['demand'] = -split_demand_value

    #set flow capacity for edges
    #set capacities as equal to the demand in the network for all nodes and egdes
    #for edge in G.edges(): G[edge[0]][edge[1]]['flow_capacity'] = default_capacity

    #print 'A supply of %s is available from node %s.' %(G.node[supply_nodes[0]]['demand'],supply_nodes[0])
    #print 'A demand of %s must be met for node %s.' %(G.node[demand_nodes[0]]['demand'],demand_nodes[0])

    #print 'Running network simplex'
    # run network simplex
    try:
        cost, edge_flows = nx.network_simplex(G,
                                              demand='demand',
                                              capacity='flow_capacity',
                                              weight='weight')
    except:
        print 'Probably no flow satisfying all demands'
        return
    print 'b'
    for edge in G.edges():
        if int(G[edge[0]][edge[1]]['flow_capacity']) != 4:
            print 'some edges have wrong capacity'
            break
    # assign flow values to network
    G = maxflow_tools.flow(G).assign_edge_node_flows(edge_flows)

    #print 'Setting capacities based on flows'
    if adjust_capacities == True:
        print '### Adjusting capacities based on flow values'
        # set capacities based on flow values
        G = maxflow_tools.other(G).set_capacity_values(supply_nd,
                                                       capacity_factor,
                                                       default_capacity,
                                                       'flow_capacity')

    # initiate cascading failure
    trigger_edges = []
    G, trigger_edges, graph_edges_removed = func_trigger_edge(
        G, trigger_edge, trigger_edges, super_supply_node, super_demand_node,
        supply_nodes, demand_nodes, added_nodes, results_file)

    print '## Running cascading failure'
    terminate = False
    step_count = 1
    trigger_step = 1
    graph_nodes_removed.append([])

    while terminate == False and step_count < 100 and trigger_step < 100:
        print '-------------------------------------'
        print 'Trigger step:', trigger_step
        print 'Step:', step_count
        results_file.write('\nCascading failure: step %s' % step_count)

        try:
            if print_test_outputs == True: print '### Calculate flows'

            G, cost, edge_flows, over_edges, demand_supplied, supply_used = func_calculate_edge_flows(
                G, demand_nodes, supply_nodes, super_supply_node,
                checking_flow_demand, fail_print_nodes, fail_print_edges)

            if print_test_outputs == True:
                print '### Resolved edge flows - (demand supplied: %s, supply_used: %s)' % (
                    demand_supplied, supply_used)

            #not 100% sure what this does
            G = maxflow_tools.other(G).track_flows(super_supply_node,
                                                   supply_nodes, demand_nodes)

            # check after the routing of flows that all demands are met
            G, terminate = func_check_demands_met(G, fail_print_nodes,
                                                  fail_print_edges, terminate)
            if terminate == True: break

            print '### Checking for edges over capacity'
            # check for edges over capacity
            edges_over, nodes_over = maxflow_tools.other(
                G).check_over_capacity(super_supply_node, super_demand_node,
                                       supply_nodes, demand_nodes)

            # this is optional at the moment until sure this is needed - need to check what this is doing
            if find_alt_routes == True:
                G = maxflow_tools.find_alternative_route(G)

            # if there is an edge over capacity, no longer need any trigger edges removed
            if len(edges_over) > 0:
                trigger_until_cascading = False
            else:
                # identify and remove the next trigger edge
                G, trigger_edges, trigger_edge = func_trigger_edge(
                    G, trigger_edge, trigger_edges, super_supply_node,
                    super_demand_node, supply_nodes, demand_nodes, added_nodes,
                    results_file)
                trigger_edge = []
                # iterate the trigger step
                trigger_step += 1
                # take one of step count - one added again at end
                step_count -= 1

            # remove any nodes over capacity if set to do so
            if remove_nodes_over == True and len(nodes_over) > 0:
                print '### Remove nodes over capacity'
                for u in nodes_over:
                    print 'Removed node: %s' % u
                    G.remove_node(u)
            # remove any edges over capacity if set to do so
            if remove_edges_over == True and len(edges_over) > 0:
                print '### Remove edges over capacity'
                # remove edges which are over capacity
                for u, v in edges_over:
                    print 'Removed edge: (%s,%s)' % (u, v)
                    G.remove_edge(u, v)

            # record the edges and nodes removed at each time step
            graph_edges_removed.append(
                edges_over)  # only really interested in this
            graph_nodes_removed.append(nodes_over)
            results_file.write('\nEdges removed: %s' % edges_over)
            results_file.write('\nNodes removed: %s' % nodes_over)

            # need to look at subgraph methods - this is where it breaParkRun Replacement - icyks at the moment
            # need to think about creating super demand and supply nodes for subgraphs
            if print_test_outputs == True:
                print '### Check subgraphs in network'

            # need to remove subgraphs which cannot be computed
            G, demand_nodes = maxflow_tools.flow(G).handle_subgraphs(
                supply_nodes, demand_nodes, super_supply_node,
                super_demand_node)

            if G == None:
                # no subgraph has both a supply and demand node so run terminated
                text = 'No graphs with both supply and demand nodes left'
                terminate = maxflow_tools.other(G).simulation_completed(
                    text, graph_edges_removed, print_edges, print_nodes)
                write_result_file_simulation_end(results_file, trigger_edges,
                                                 graph_edges_removed,
                                                 graph_nodes_removed)

            if print_test_outputs == True:
                print '### Check supply still left in network'

            # if the supply value now at zero, stop simulation
            demand_sum = sum(d['demand'] for v, d in G.nodes(data=True))
            if demand_sum != 0:
                raise error_classes.DemandError(
                    G,
                    'Demand across network does not equal zero as it should.',
                    fail_print_nodes, fail_print_edges)

            # check demand in the network has not reached 0 - if not a super supply node then must add up
            if super_supply_node != False and terminate == False:
                if G.node[super_supply_node]['demand'] == 0:
                    text = 'Supply in network is now zero'
                    terminate = maxflow_tools.other(G).simulation_completed(
                        text, graph_edges_removed, print_edges, print_nodes)
                    write_result_file_simulation_end(results_file,
                                                     trigger_edges,
                                                     graph_edges_removed,
                                                     graph_nodes_removed)

            elif terminate == False:
                supply_left = 0
                for nd in supply_nodes:
                    supply_left += -G.node[nd]['demand']
                if supply_left == 0:
                    text = 'Supply in network is now zero'
                    terminate = maxflow_tools.other(G).simulation_completed(
                        text, graph_edges_removed, print_edges, print_nodes)
                    write_result_file_simulation_end(results_file, text,
                                                     trigger_edges,
                                                     graph_edges_removed,
                                                     graph_nodes_removed)

        except nx.exception.NetworkXUnfeasible:
            text = 'No routes which allow demand(s) to be met'
            terminate = maxflow_tools.other(G).simulation_completed(
                text, graph_edges_removed, print_edges, print_nodes)
            write_result_file_simulation_end(results_file, text, trigger_edges,
                                             graph_edges_removed,
                                             graph_nodes_removed)

        #check if any changes since last step - if not terminate
        # this should only terminate if trigger untilc ascading is false - some cascading has occured
        if trigger_until_cascading == False and graph_edges_removed[
                step_count] == [] and graph_nodes_removed[
                    step_count] == [] and terminate == False:
            text = 'Network has reached an equilibrium'
            terminate = maxflow_tools.other(G).simulation_completed(
                text, graph_edges_removed, print_edges, print_nodes)
            write_result_file_simulation_end(results_file, text, trigger_edges,
                                             graph_edges_removed,
                                             graph_nodes_removed)

        #iterate the step counter based on what has happend thus far
        step_count += 1
Ejemplo n.º 31
0
def min_cost_flow_cost(G,
                       demand='demand',
                       capacity='capacity',
                       weight='weight'):
    """Find the cost of a minimum cost flow satisfying all demands in digraph G.

    G is a digraph with edge costs and capacities and in which nodes
    have demand, i.e., they want to send or receive some amount of
    flow. A negative demand means that the node wants to send flow, a
    positive demand means that the node want to receive flow. A flow on
    the digraph G satisfies all demand if the net flow into each node
    is equal to the demand of that node.

    Parameters
    ----------
    G : NetworkX graph
        DiGraph on which a minimum cost flow satisfying all demands is
        to be found.

    demand: string
        Nodes of the graph G are expected to have an attribute demand
        that indicates how much flow a node wants to send (negative
        demand) or receive (positive demand). Note that the sum of the
        demands should be 0 otherwise the problem in not feasible. If
        this attribute is not present, a node is considered to have 0
        demand. Default value: 'demand'.

    capacity: string
        Edges of the graph G are expected to have an attribute capacity
        that indicates how much flow the edge can support. If this
        attribute is not present, the edge is considered to have
        infinite capacity. Default value: 'capacity'.

    weight: string
        Edges of the graph G are expected to have an attribute weight
        that indicates the cost incurred by sending one unit of flow on
        that edge. If not present, the weight is considered to be 0.
        Default value: 'weight'.

    Returns
    -------
    flowCost: integer, float
        Cost of a minimum cost flow satisfying all demands.

    Raises
    ------
    NetworkXError
        This exception is raised if the input graph is not directed or
        not connected.

    NetworkXUnfeasible
        This exception is raised in the following situations:
            * The sum of the demands is not zero. Then, there is no
              flow satisfying all demands.
            * There is no flow satisfying all demand.

    NetworkXUnbounded
        This exception is raised if the digraph G has a cycle of
        negative cost and infinite capacity. Then, the cost of a flow
        satisfying all demands is unbounded below.

    See also
    --------
    cost_of_flow, max_flow_min_cost, min_cost_flow, network_simplex

    Examples
    --------
    A simple example of a min cost flow problem.

    >>> import networkx as nx
    >>> G = nx.DiGraph()
    >>> G.add_node('a', demand = -5)
    >>> G.add_node('d', demand = 5)
    >>> G.add_edge('a', 'b', weight = 3, capacity = 4)
    >>> G.add_edge('a', 'c', weight = 6, capacity = 10)
    >>> G.add_edge('b', 'd', weight = 1, capacity = 9)
    >>> G.add_edge('c', 'd', weight = 2, capacity = 5)
    >>> flowCost = nx.min_cost_flow_cost(G)
    >>> flowCost
    24
    """
    return nx.network_simplex(G,
                              demand=demand,
                              capacity=capacity,
                              weight=weight)[0]
Ejemplo n.º 32
0
    def test_transshipment(self):
        G = nx.DiGraph()
        G.add_node('a', demand=1)
        G.add_node('b', demand=-2)
        G.add_node('c', demand=-2)
        G.add_node('d', demand=3)
        G.add_node('e', demand=-4)
        G.add_node('f', demand=-4)
        G.add_node('g', demand=3)
        G.add_node('h', demand=2)
        G.add_node('r', demand=3)
        G.add_edge('a', 'c', weight=3)
        G.add_edge('r', 'a', weight=2)
        G.add_edge('b', 'a', weight=9)
        G.add_edge('r', 'c', weight=0)
        G.add_edge('b', 'r', weight=-6)
        G.add_edge('c', 'd', weight=5)
        G.add_edge('e', 'r', weight=4)
        G.add_edge('e', 'f', weight=3)
        G.add_edge('h', 'b', weight=4)
        G.add_edge('f', 'd', weight=7)
        G.add_edge('f', 'h', weight=12)
        G.add_edge('g', 'd', weight=12)
        G.add_edge('f', 'g', weight=-1)
        G.add_edge('h', 'g', weight=-10)
        flowCost, H = nx.network_simplex(G)
        soln = {
            'a': {
                'c': 0
            },
            'b': {
                'a': 0,
                'r': 2
            },
            'c': {
                'd': 3
            },
            'd': {},
            'e': {
                'r': 3,
                'f': 1
            },
            'f': {
                'd': 0,
                'g': 3,
                'h': 2
            },
            'g': {
                'd': 0
            },
            'h': {
                'b': 0,
                'g': 0
            },
            'r': {
                'a': 1,
                'c': 1
            }
        }
        assert_equal(flowCost, 41)
        assert_equal(nx.min_cost_flow_cost(G), 41)
        assert_equal(H, soln)
        assert_equal(nx.min_cost_flow(G), soln)
        assert_equal(nx.cost_of_flow(G, H), 41)

        flowCost, H = nx.capacity_scaling(G)
        assert_equal(flowCost, 41)
        assert_equal(nx.cost_of_flow(G, H), 41)
        assert_equal(H, soln)
Ejemplo n.º 33
0
def min_cost_flow(G, demand = 'demand', capacity = 'capacity',
                  weight = 'weight'):
    r"""Return a minimum cost flow satisfying all demands in digraph G.

    G is a digraph with edge costs and capacities and in which nodes
    have demand, i.e., they want to send or receive some amount of
    flow. A negative demand means that the node wants to send flow, a
    positive demand means that the node want to receive flow. A flow on
    the digraph G satisfies all demand if the net flow into each node
    is equal to the demand of that node.

    Parameters
    ----------
    G : NetworkX graph
        DiGraph on which a minimum cost flow satisfying all demands is
        to be found.

    demand : string
        Nodes of the graph G are expected to have an attribute demand
        that indicates how much flow a node wants to send (negative
        demand) or receive (positive demand). Note that the sum of the
        demands should be 0 otherwise the problem in not feasible. If
        this attribute is not present, a node is considered to have 0
        demand. Default value: 'demand'.

    capacity : string
        Edges of the graph G are expected to have an attribute capacity
        that indicates how much flow the edge can support. If this
        attribute is not present, the edge is considered to have
        infinite capacity. Default value: 'capacity'.

    weight : string
        Edges of the graph G are expected to have an attribute weight
        that indicates the cost incurred by sending one unit of flow on
        that edge. If not present, the weight is considered to be 0.
        Default value: 'weight'.

    Returns
    -------
    flowDict : dictionary
        Dictionary of dictionaries keyed by nodes such that
        flowDict[u][v] is the flow edge (u, v).

    Raises
    ------
    NetworkXError
        This exception is raised if the input graph is not directed or
        not connected.

    NetworkXUnfeasible
        This exception is raised in the following situations:

            * The sum of the demands is not zero. Then, there is no
              flow satisfying all demands.
            * There is no flow satisfying all demand.

    NetworkXUnbounded
        This exception is raised if the digraph G has a cycle of
        negative cost and infinite capacity. Then, the cost of a flow
        satisfying all demands is unbounded below.

    See also
    --------
    cost_of_flow, max_flow_min_cost, min_cost_flow_cost, network_simplex

    Examples
    --------
    A simple example of a min cost flow problem.

    >>> import networkx as nx
    >>> G = nx.DiGraph()
    >>> G.add_node('a', demand = -5)
    >>> G.add_node('d', demand = 5)
    >>> G.add_edge('a', 'b', weight = 3, capacity = 4)
    >>> G.add_edge('a', 'c', weight = 6, capacity = 10)
    >>> G.add_edge('b', 'd', weight = 1, capacity = 9)
    >>> G.add_edge('c', 'd', weight = 2, capacity = 5)
    >>> flowDict = nx.min_cost_flow(G)
    """
    return nx.network_simplex(G, demand = demand, capacity = capacity,
                              weight = weight)[1]
Ejemplo n.º 34
0
def mcf_sparse_nx(x, y, psi, capacity=None):
    points = np.vstack((x, y)).T
    num_points = points.shape[0]

    # Delaunay triangularization
    tri = Delaunay(points)
    simplex = tri.simplices
    simplex_neighbors = tri.neighbors
    num_simplex = simplex.shape[0]

    if capacity is None:
        cap_args = dict()
    else:
        cap_args = {'capacity': capacity}

    # get pseudo estimation of gradients and vertex edges
    psi_diff = W(psi[simplex] - psi[np.roll(simplex, 1, 1)])
    edges = np.stack((np.roll(simplex, 1, 1), simplex), axis=2).reshape(-1, 2)

    # get corresponding simplex's edges orthogonal to original vertex edges
    simplex_edges = np.stack((
        np.broadcast_to(np.arange(num_simplex)[:, None], simplex_neighbors.shape),
        np.roll(simplex_neighbors, -1, 1)), axis=2
    ).reshape(-1, 2)

    # get demands
    demands = np.round(-psi_diff.sum(1) * 0.5 / np.pi).astype(np.int)
    psi_diff = psi_diff.flatten()

    G = nx.Graph()
    G.add_nodes_from(zip(range(num_simplex),
                         [{'demand': d} for d in demands]))

    # set earth node index to -1, and its demand is the negative of the sum of all demands,
    # so the total demands is zero
    G.add_node(-1, demand=-demands.sum())

    # set the edge weight to 1 whenever one of its nodes has zero demand
    demands_dummy = np.concatenate((demands, [-demands.sum()]))
    weights = np.any(demands_dummy[simplex_edges] == 0, 1)
    G.add_weighted_edges_from(zip(simplex_edges[:, 0], simplex_edges[:, 1], weights), **cap_args)

    # make graph to directed graph, so we can distinguish positive and negative flow
    G = G.to_directed()

    # perform MCF
    cost, flowdict = nx.network_simplex(G)

    # construct K matrix with the same shape as the edges
    K = np.empty(edges.shape[0])

    # add the flow to their orthogonal edge
    for i, (u, v) in enumerate(simplex_edges):
        K[i] = -flowdict[u][v] + flowdict[v][u]

    # derive correct gradients
    psi_diff += K * 2 * np.pi

    # construct temporary dict that hold all edge gradients from different direction
    psi_dict = {i: {} for i in range(num_points)}
    for diff, (u, v) in zip(psi_diff, edges):
        psi_dict[u][v] = diff

    # integrate the gradients
    result = psi.copy()

    # choose an integration path, here let's use BFS
    traverse_G = nx.DiGraph(edges.tolist())
    for u, v in nx.algorithms.traversal.breadth_first_search.bfs_edges(traverse_G, 0):
        result[v] = result[u] + psi_dict[u][v]
    return result
Ejemplo n.º 35
0
    nz_idx = pd.Series(np.nonzero(C_transfers.values)[0])
    for i in range(abs(dif)):
        C_transfers.iloc[nz_idx[i]] -= direct

for i in CG.nodes():
    CG.node[i]['load'] = C_loads[i]
    CG.node[i]['gen'] = C_gen[i]
    CG.node[i]['trans'] = C_transfers[i]

for i in CG.nodes():
    CG.node[i]['MW_net'] = CG.node[i]['gen'] - CG.node[i]['load'] - CG.node[i][
        'trans']

DG = CG.to_directed()

NS = nx.network_simplex(DG, demand='MW_net', weight='R', capacity='tot_MW_cap')
#### EVERYTHING BELOW DOESN'T WORK!!!

for i in G.nodes():
    kv_list = [
        G.adj[i][j]['tot_kv'] for j in G.adj[i].keys() if isinstance(j, int)
    ]
    kv_max, kv_min = max(kv_list), min(kv_list)
    G[i]['max_volt'] = kv_max
    G[i]['min_volt'] = kv_min

#### GET GRID VOLTAGES FROM EIA FORM DATA

mwkv = pd.DataFrame(np.zeros(len(G.nodes())), index=G.nodes())

for x in ['load', 'gen', 'trans', 'min_volt', 'max_volt']:
Ejemplo n.º 36
0
def mcf_nx(x: np.ndarray, capacity=None):
    assert x.ndim == 2, "Input x should be a 2d array!"

    # construct index for each node
    N, M = x.shape
    index = np.arange(N * M).reshape(N, M)

    if capacity is None:
        cap_args = dict()
    else:
        cap_args = {'capacity': capacity}

    # get pseudo estimation of gradients along x and y axis
    psi1 = W(np.diff(x, axis=0))
    psi2 = W(np.diff(x, axis=1))

    G = nx.Graph()

    demands = np.round(-(psi1[:, 1:] - psi1[:, :-1] - psi2[1:, :] + psi2[:-1, :]) * 0.5 / np.pi).astype(np.int)
    # for convenience let's pad the demands so it match the shape of image
    # this add N + M - 1 dummy nodes with 0 demand
    demands = np.pad(demands, ((0, 1),) * 2, 'constant', constant_values=0)
    G.add_nodes_from(zip(index.ravel(), [{'demand': d} for d in demands.ravel()]))

    # set earth node index to -1, and its demand is the negative of the sum of all demands,
    # so the total demands is zero
    G.add_node(-1, demand=-demands.sum())

    # edges along x and y axis
    edges = np.vstack((
        np.vstack((index[:, :-1].ravel(), index[:, 1:].ravel())).T,
        np.vstack((index[:-1].ravel(), index[1:].ravel())).T)
    )

    # set the edge weight to 1 when its left (upper) node demands is equal to zero
    # I found it achieve very stable result
    weights = np.concatenate(((demands[:, :-1] == 0).ravel(), (demands[:-1] == 0).ravel()))
    G.add_weighted_edges_from(zip(edges[:, 0], edges[:, 1], weights), **cap_args)

    # add the remaining edges that connected to earth node
    G.add_edges_from(zip([-1] * M, range(M)), **cap_args)
    G.add_edges_from(zip([-1] * M, range((N - 1) * M, N * M)), **cap_args)
    G.add_edges_from(zip([-1] * N, range(0, N * M, M)), **cap_args)
    G.add_edges_from(zip([-1] * N, range(M - 1, N * M, M)), **cap_args)

    # make graph to directed graph, so we can distinguish positive and negative flow
    G = G.to_directed()

    # perform MCF
    cost, flowdict = nx.network_simplex(G)

    # construct K matrix with the same shape as the gradients
    K2 = np.empty((N, M - 1))
    K1 = np.empty((N - 1, M))

    # add the flow to their orthogonal edge
    # the sign of the flow depends on those 4 vectors direction (clockwise or counter-clockwise)
    # when calculating the demands
    for i in range(N - 1):
        for j in range(M):
            if j == 0:
                K1[i][0] = -flowdict[-1][i * M] + flowdict[i * M][-1]
            else:
                K1[i][j] = -flowdict[i * M + j - 1][i * M + j] + flowdict[i * M + j][i * M + j - 1]

    for i in range(N):
        for j in range(M - 1):
            if i == 0:
                K2[i][j] = flowdict[-1][j] - flowdict[j][-1]
            else:
                K2[i][j] = flowdict[(i - 1) * M + j][i * M + j] - flowdict[i * M + j][(i - 1) * M + j]

    # the boundary node with index = 0 have only one edge to earth node,
    # so set one of its edge's K to zero
    K2[0, 0] = 0

    # derive correct gradients
    psi1 += K1 * 2 * np.pi
    psi2 += K2 * 2 * np.pi

    # integrate the gradients
    y = np.full_like(x, x[0, 0])
    y[1:, 0] += np.cumsum(psi1[:, 0])
    y[:, 1:] = np.cumsum(psi2, axis=1) + y[:, :1]
    return y
Ejemplo n.º 37
0
def generalized_assignment_problem(node_demand,
                                   node_supply,
                                   connection_list,
                                   overload_supplies=False,
                                   overload_threshold=None,
                                   risky=False):
    """ 
    A solution to the unweighted generalized assignment problem.
    Uses the network simplex algorithm to get an LP relaxation.
    A 2-approximation (on supply overloads) is then used to recover a non-fractional assignment.
    Algorithm based on this theory:
    https://theory.stanford.edu/~jvondrak/CS369P/lec12.pdf
    but also deals with unassigned nodes.

    A heuristic of weighting edges by the supply value is used.
    Options exist to allocate demands by connecting to overloaded supplies

    Parameters
    ----------
    node_demand: dict
        The demand nodes (or jobs). Job i must be entirely assigned to one supply with amount node_demand[i]
        node_demand[i] assumed to be integer for convergence of network simplex

    node_supply: dict
        The supply nodes (or machines). Machine j can have any number of jobs attached with at most node_supply[j] allocated
        node_supply[i] assumed to be integer for convergence of network simplex

    connection_list: dict
        A dictionary that maps the supply nodes that demand i can be assigned to

    overload_supplies: float, optional
        A flag indicating whether supply nodes should be overloaded if there exist unassigned jobs

    overload_threshold: float, optional
        The amount that we're willing to overload supply nodes not assigned with the (worst case) 2-approximation ratio

    risky: bool, optional
        A flag to try removing multiple single or two degree supplies simultaneously.
        The correct approach is to resolve the LP each time to speed things up. 
        This may create incorrect solutions.
        However, with the heuristic used this is likely not a problem, since priority assigned to larger supplies
        (Proof required for that theory though...)
    """

    G = nx.DiGraph()
    for i in connection_list:
        for j in connection_list[i]:
            G.add_edge(
                i, j, weight=node_supply[j] * -1, capacity=node_demand[i]
            )  #A heuristic that may help get more integer solutions?

    for i in node_demand:
        G.add_node(i, demand=node_demand[i] * -1)

    for i in node_supply:
        G.add_node(i, demand=node_supply[i])

    original_supply = {i: v for i, v in node_supply.items()}
    original_demand = {i: v for i, v in node_demand.items()}
    closest_supply = {}
    closest_supply_amount = {}
    assignments = {}  #map demands to supplies

    while len(node_demand) > 0:
        total_demand = 0
        total_supply = 0
        max_supply = 0

        for i in node_demand:
            total_demand += node_demand[i]
        for i in node_supply:
            total_supply += node_supply[i]
            if node_supply[i] > max_supply:
                max_supply = node_supply[i]

        # Supply slack used if there is too much demand and not enough supply. Represents infeasibility
        # Demand slack used if there is more supply than demand. This does not constitue infeasibility, but availability in the supply nodes

        #Add total_demand + total_supply incase all nodes disconnected.
        #This means supply_slack is feeding all the supply nodes and demand_slack is feeding all the demand nodes
        if total_supply > total_demand:
            G.add_node('demand_slack',
                       demand=-1 * (total_demand + total_supply) +
                       total_demand - total_supply)
            G.add_node('supply_slack', demand=total_demand + total_supply)
        else:
            G.add_node('demand_slack',
                       demand=-1 * (total_demand + total_supply))
            G.add_node('supply_slack',
                       demand=(total_demand + total_supply) - total_supply +
                       total_demand)

        G.add_edge('demand_slack',
                   'supply_slack',
                   weight=-1 * max_supply,
                   capacity=total_demand +
                   total_supply)  #might this cause numerical issues?

        #Costs of all real edges are negative so only assigned if no other options
        for i in node_supply:
            G.add_edge('demand_slack', i, weight=10, capacity=node_supply[i])

        for j in node_demand:
            G.add_edge(j, 'supply_slack', weight=10, capacity=node_demand[j])

        # Network simplex algorithm used to do the LP relaxation. Should be fast in practice
        flow_cost, flow_dict = nx.network_simplex(G)
        demands_to_remove = []
        supplies_to_remove = []
        remove_supplies = True

        # Find closest fractional node assignment in case node is unassigned. Only used if overload_supplies flag is set
        if overload_supplies:
            for i in node_demand:
                for j in flow_dict[i]:
                    if j != "supply_slack":
                        if i not in closest_supply_amount or flow_dict[i][
                                j] > closest_supply_amount[i]:
                            closest_supply[i] = j
                            closest_supply_amount[i] = flow_dict[i][j]

        # Remove demand node if it's unassigned (i.e. connected to slack supply
        # Remove demand node and edges if it's fully allocated to a supply node
        # Remove edge if LP relaxation assigns it to 0 (not included in optimal
        for i in node_demand:
            for j in flow_dict[i]:
                if j == 'supply_slack' and flow_dict[i][j] > 0:
                    remove_supplies = False
                    assignments[i] = 'unassigned'
                    G.remove_node(i)
                    demands_to_remove.append(i)
                    break
                if flow_dict[i][j] == node_demand[i]:
                    remove_supplies = False
                    assignments[i] = j
                    node_supply[j] = node_supply[j] - node_demand[i]
                    G.node[j]['demand'] = G.node[j]['demand'] - node_demand[i]
                    G.remove_node(i)
                    demands_to_remove.append(i)
                    break
                if j != 'supply_slack' and flow_dict[i][
                        j] == 0:  #ignore empty edges to slack node
                    remove_supplies = False
                    G.remove_edge(i, j)

        # Only remove supplies if no edges have been removed already
        # Remove supply node if it has a degree of one (i.e. it won't be used since it wasn't fully assigned in the LP)
        # Remove supply node if it has a degree of two and inputs from connected nodes are overloaded
        if remove_supplies:
            # Since it's a digraph we need to specify nodes coming into j for the degree 2 case
            reverse_neighbors = {}
            for i in node_demand:
                for j in G.neighbors(i):
                    if j in reverse_neighbors:
                        reverse_neighbors[j].append(i)
                    else:
                        reverse_neighbors[j] = [i]
            for j in node_supply:
                if G.degree(
                        j
                ) <= 2:  # Degree needs to be <=1 but we've got a slack node connected to all supplies
                    G.remove_node(j)
                    supplies_to_remove.append(j)
                    if not risky:
                        break
                elif G.degree(
                        j
                ) == 3:  # Degree needs to be <=2 but we've got a slack node connected to all supplies
                    total_xin = 0
                    for i in reverse_neighbors[j]:
                        if node_demand[i] != 0:  #should always be the case
                            total_xin += flow_dict[i][j] / float(
                                node_demand[i])
                    if total_xin >= 1:
                        G.remove_node(j)
                        supplies_to_remove.apend(j)
                        if not risky:
                            break

        # Update supply and demand nodes and prepare for rerun.
        for i in demands_to_remove:
            node_demand.pop(i)
        for i in supplies_to_remove:
            node_supply.pop(i)
        G.remove_node('supply_slack')
        G.remove_node('demand_slack')

    allocation_amounts = {}
    for i in original_supply.keys():
        allocation_amounts[i] = 0

    print("Assigneed Demands:")
    for i in original_demand.keys():
        if assignments[i] == 'unassigned':
            pass
        else:
            allocation_amounts[assignments[i]] += original_demand[i]
            print(i + "-> " + assignments[i])
    print()
    print("Non-empty supplies:")
    for i in original_supply.keys():
        if original_supply[i] != 0 and allocation_amounts[i] != 0:
            print(i + " at " + str(allocation_amounts[i]) + " (" + str(
                round(100 * allocation_amounts[i] /
                      float(original_supply[i]), 3)) + "%)")

    print()
    print("Unassigned demands:")
    overloaded_allocation_amounts = {}
    for i in original_demand.keys():
        # closest_supply will only be non-empty if overload_supplies is True
        if assignments[i] == 'unassigned' and i in closest_supply:
            print(i + " not assigned - closest supply is " + closest_supply[i])
            if closest_supply[i] not in overloaded_allocation_amounts:
                if overload_threshold is None or allocation_amounts[
                        closest_supply[i]] + original_demand[
                            i] < overload_threshold * original_supply[
                                closest_supply[i]]:
                    overloaded_allocation_amounts[
                        closest_supply[i]] = allocation_amounts[
                            closest_supply[i]] + original_demand[i]
                    assignments[i] = closest_supply[i]
            else:
                if overload_threshold is None or overloaded_allocation_amounts[
                        closest_supply[i]] + original_demand[
                            i] < overload_threshold * original_supply[
                                closest_supply[i]]:
                    overloaded_allocation_amounts[
                        closest_supply[i]] = overloaded_allocation_amounts[
                            closest_supply[i]] + original_demand[i]
                    assignments[i] = closest_supply[i]

        # This is used if overload_supplies is False since closest_supply will be empty
        if assignments[i] == 'unassigned' and i not in closest_supply:
            print(i + " not assigned")

    if overload_supplies:
        print()
        print(
            "Supply loading if unassigned demands attached to best candidate within overload threshold {}:"
            .format(overload_threshold))
        for i in overloaded_allocation_amounts:
            print(i + " at " + str(overloaded_allocation_amounts[i]) + " (" +
                  str(
                      round(
                          100 * overloaded_allocation_amounts[i] /
                          float(original_supply[i]), 3)) + "%)")

    return assignments
Ejemplo n.º 38
0
G.add_node(1, demand=-2)
G.add_node(2, demand=-5)
# Adiciona nos de demanda
G.add_node(3, demand=1)
G.add_node(4, demand=3)
G.add_node(5, demand=3)
# Adiciona os arcos
G.add_edge(1, 3, weight=3)
G.add_edge(2, 3, weight=7)
# ###################################
G.add_edge(1, 4, weight=4)
G.add_edge(2, 4, weight=2)
# ###################################
G.add_edge(1, 5, weight=1)
G.add_edge(2, 5, weight=5)
flowCost, flowDict = nx.network_simplex(G)
print flowCost
# print flowDict
k,w = 0,0
mat = np.zeros([2,3])
cost = np.zeros([2,3])
total = 0
for i in flowDict:
    #print "i:%d\n"%i
    w = 0
    for j in flowDict[i]:
        # print flowDict[i][j],
        mat[k,w] = flowDict[i][j]
        cost[k,w] = G[i][j]["weight"]
        w += 1
        total += flowDict[i][j]*G[i][j]["weight"]
Ejemplo n.º 39
0
def distribute(G, requiredBikes, requiredDocks):
    url_status = 'https://api.bsmsa.eu/ext/api/bsm/gbfs/v2/en/station_status'
    bikes = pd.DataFrame.from_records(pd.read_json(url_status)['data']
                                      ['stations'], index='station_id')
    G_Di = nx.DiGraph()
    G_Di.add_node('TOP')  # The green node
    demand = 0
    for st in bikes.itertuples():
        idx = st.Index
        if idx not in index_graph_stations(G):
            continue
        stridx = str(idx)
        # The blue (s), black (g) and red (t) nodes of the graph
        s_idx, g_idx, t_idx = 's'+stridx, 'g'+stridx, 't'+stridx
        G_Di.add_node(g_idx)
        G_Di.add_node(s_idx)
        G_Di.add_node(t_idx)

        b, d = st.num_bikes_available, st.num_docks_available
        req_bikes = max(0, requiredBikes - b)
        req_docks = max(0, requiredDocks - d)

        G_Di.add_edge('TOP', s_idx)
        G_Di.add_edge(t_idx, 'TOP')
        G_Di.add_edge(s_idx, g_idx)
        G_Di.add_edge(g_idx, t_idx)

        if req_bikes > 0:
            demand += req_bikes
            G_Di.nodes[t_idx]['demand'] = req_bikes
            G_Di.edges[s_idx, g_idx]['capacity'] = 0

        elif req_docks > 0:
            demand -= req_docks
            G_Di.nodes[s_idx]['demand'] = -req_docks
            G_Di.edges[g_idx, t_idx]['capacity'] = 0
    G_Di.nodes['TOP']['demand'] = -demand
    # Selects the established edges in our graph
    # and introduces them onto the directed.
    for edge in G.edges():
        node1 = edge[0]
        node2 = edge[1]
        id1 = node1.Index
        id2 = node2.Index
        dist = G[node1][node2]['weight']*10
        G_Di.add_edge('g'+str(id1), 'g'+str(id2),
                      cost=int(1000*dist), weight=dist)
        G_Di.add_edge('g'+str(id2), 'g'+str(id1),
                      cost=int(1000*dist), weight=dist)
    err = False

    try:
        flowCost, flowDict = nx.network_simplex(G_Di, weight='cost')

    except nx.NetworkXUnfeasible:
        err = True
        return err, 0, 0
        # Error = No solution could be found for the parameters given"

    # The format error has been eliminated, because the graph provided to the
    # function is directed.

    if not err:

        total_cost = 0
        initial = True
        for src in flowDict:
            if src[0] != 'g':
                continue
            idx_src = int(src[1:])
            for dst, b in flowDict[src].items():
                if dst[0] == 'g' and b > 0:
                    idx_dst = int(dst[1:])
                    total_cost += G_Di.edges[src, dst]['weight']
                    # The cost is the distance traveled * num of bikes.
                    cost = (G_Di.edges[src, dst]['weight'] *
                            b, idx_src, idx_dst)
                    if initial:
                        initial = False
                        Biggest_move = cost
                    elif cost[0] > Biggest_move[0]:
                        Biggest_move = cost
        if total_cost == 0:
            return err, total_cost, 0
        return err, total_cost, Biggest_move
Ejemplo n.º 40
0
    def optimseFlows(self, logger, NLL_F, NLL_D, maxIter):

        self.initialiseFlows()

        dF = 0.
        F = 0.

        (dF, F) = self.evalDF(NLL_F, NLL_D)

        rho = 1.0e2

        i = 0

        ssedges = set(self.sEdges)

        init_pflow = 0.1 * max(self.X.items(), key=itemgetter(1))[1]
        logger.info("Performing %d iterations of graph normalisation: ",
                    maxIter)
        logger.info("Iter, dF, F")
        ChangeF = 1.0
        F = -1.
        while i < maxIter and abs(ChangeF) > 1.0e-3:

            self.setWeightsD(NLL_D)

            path = nx.bellman_ford_path(self.diGraph,
                                        'source+',
                                        'sink+',
                                        weight='dweight')

            weight = self.evalPathWeight(path, 'dweight')

            epath = [(u, v) for u, v in zip(path, path[1:])]

            spath = set(epath) & ssedges

            if i > 10 and i % 5 == 0:

                (fMax, rMax) = self.setResidualGraph()

                if fMax > 1.0e-6 and rMax > 1.0e-6:
                    ds = {'sink+': -MAX_REV_FLOW, 'source+': MAX_REV_FLOW}

                    nx.set_node_attributes(self.rGraph, ds, 'demand')

                    (mf, pf) = nx.network_simplex(self.rGraph,
                                                  demand='demand',
                                                  capacity='capacity',
                                                  weight='rweight')

                    fCost = (mf * rMax) / (MAX_INT_FLOW * MAX_REV_FLOW)
                else:
                    fCost = 1.0e6
            else:
                fCost = 1.0e6

            if weight < fCost and weight < 0.:
                pflow = init_pflow

                DeltaF = self.deltaF(spath, pflow, NLL_F)

                while DeltaF > pflow * weight * BETA:
                    pflow *= TAU

                    DeltaF = self.deltaF(spath, pflow, NLL_F)

                if pflow > 0.:
                    self.addFlowPath(path, pflow)

            else:
                if fCost < 0.:
                    epath = []

                    for k, v in pf.items():
                        for k2, v2 in v.items():
                            if int(v2) > 0:
                                epath.append((k2, k))

                    pflow = fMax * (MAX_REV_FLOW / MAX_INT_FLOW)

                    spath = set(epath) & ssedges

                    DeltaF = self.deltaF(spath, -pflow, NLL_F)

                    while DeltaF > pflow * fCost * BETA:
                        pflow *= TAU

                        DeltaF = self.deltaF(spath, -pflow, NLL_F)

                        #print(str(pflow) + ',' + str(DeltaF))

                    if pflow > 0.:
                        self.addEdgePath(epath, -pflow)

            lastF = F
            (dF, F) = self.evalDF(NLL_F, NLL_D)
            ChangeF = F - lastF
            if i % 10 == 0:
                logger.info("%d, %f, %f", i, dF, F)

            i += 1
Ejemplo n.º 41
0
    parser = argparse.ArgumentParser(
        description="Script which shows minimum flow in given graph")
    parser.add_argument("nodes_file",
                        help="File which contain nodes and their demands")
    parser.add_argument(
        "edges_file",
        help="File which contain edges with their weights and capacities")
    args = parser.parse_args()
    #we need directed graph
    G = nx.DiGraph()
    #load nodes[0] and their demands[1]
    with open(args.nodes_file) as nodes:
        for data in nodes:
            node_demand = data.split(" ")
            G.add_node(node_demand[0], demand=int(node_demand[1]))
    #load edges with their data
    with open(args.edges_file) as edges:
        for data in edges:
            edge_data = data.split(" ")
            G.add_edge(edge_data[0],
                       edge_data[1],
                       capacity=int(edge_data[2]),
                       weight=int(edge_data[3]))

    flow_cost, flow_dict = nx.network_simplex(G)
    print "Flow cost : " + str(flow_cost)

    for verticle, neighbours in flow_dict.iteritems():
        for neighbour, weight in neighbours.iteritems():
            print "From: %s to: %s weight: %s" % (verticle, neighbour, weight)
Ejemplo n.º 42
0
def test_transshipment():
    G = nx.DiGraph()
    G.add_node("a", demand=1)
    G.add_node("b", demand=-2)
    G.add_node("c", demand=-2)
    G.add_node("d", demand=3)
    G.add_node("e", demand=-4)
    G.add_node("f", demand=-4)
    G.add_node("g", demand=3)
    G.add_node("h", demand=2)
    G.add_node("r", demand=3)
    G.add_edge("a", "c", weight=3)
    G.add_edge("r", "a", weight=2)
    G.add_edge("b", "a", weight=9)
    G.add_edge("r", "c", weight=0)
    G.add_edge("b", "r", weight=-6)
    G.add_edge("c", "d", weight=5)
    G.add_edge("e", "r", weight=4)
    G.add_edge("e", "f", weight=3)
    G.add_edge("h", "b", weight=4)
    G.add_edge("f", "d", weight=7)
    G.add_edge("f", "h", weight=12)
    G.add_edge("g", "d", weight=12)
    G.add_edge("f", "g", weight=-1)
    G.add_edge("h", "g", weight=-10)
    flowCost, H = nx.network_simplex(G)
    soln = {
        "a": {
            "c": 0
        },
        "b": {
            "a": 0,
            "r": 2
        },
        "c": {
            "d": 3
        },
        "d": {},
        "e": {
            "r": 3,
            "f": 1
        },
        "f": {
            "d": 0,
            "g": 3,
            "h": 2
        },
        "g": {
            "d": 0
        },
        "h": {
            "b": 0,
            "g": 0
        },
        "r": {
            "a": 1,
            "c": 1
        },
    }
    assert flowCost == 41
    assert H == soln
Ejemplo n.º 43
0
    def test_digraph1(self):
        # From Bradley, S. P., Hax, A. C. and Magnanti, T. L. Applied
        # Mathematical Programming. Addison-Wesley, 1977.
        G = nx.DiGraph()
        G.add_node(1, demand=-20)
        G.add_node(4, demand=5)
        G.add_node(5, demand=15)
        G.add_edges_from([(1, 2, {
            'capacity': 15,
            'weight': 4
        }), (1, 3, {
            'capacity': 8,
            'weight': 4
        }), (2, 3, {
            'weight': 2
        }), (2, 4, {
            'capacity': 4,
            'weight': 2
        }), (2, 5, {
            'capacity': 10,
            'weight': 6
        }), (3, 4, {
            'capacity': 15,
            'weight': 1
        }), (3, 5, {
            'capacity': 5,
            'weight': 3
        }), (4, 5, {
            'weight': 2
        }), (5, 3, {
            'capacity': 4,
            'weight': 1
        })])
        flowCost, H = nx.network_simplex(G)
        soln = {
            1: {
                2: 12,
                3: 8
            },
            2: {
                3: 8,
                4: 4,
                5: 0
            },
            3: {
                4: 11,
                5: 5
            },
            4: {
                5: 10
            },
            5: {
                3: 0
            }
        }
        assert_equal(flowCost, 150)
        assert_equal(nx.min_cost_flow_cost(G), 150)
        assert_equal(H, soln)
        assert_equal(nx.min_cost_flow(G), soln)
        assert_equal(nx.cost_of_flow(G, H), 150)

        flowCost, H = nx.capacity_scaling(G)
        assert_equal(flowCost, 150)
        assert_equal(H, soln)
        assert_equal(nx.cost_of_flow(G, H), 150)
Ejemplo n.º 44
0
def flow(G, rb, rd):
    url_status = 'https://api.bsmsa.eu/ext/api/bsm/gbfs/v2/en/station_status'
    bikes = DataFrame.from_records(pd.read_json(url_status)
                                   ['data']['stations'], index='station_id')

    DG = nx.DiGraph()
    DG.add_node('TOP')  # The green node
    demand = 0

    for station in bikes.itertuples():
        idx = station.Index
        if idx not in Nodes_of_graf(G):
            continue
        stridx = str(idx)
        # The blue (s), black (g) and red (t) nodes of the graph
        s_idx, g_idx, t_idx = 's'+stridx, 'g'+stridx, 't'+stridx
        DG.add_node(g_idx)
        DG.add_node(s_idx)
        DG.add_node(t_idx)

        b, d = station.num_bikes_available, station.num_docks_available
        req_bikes = max(0, int(rb) - b)
        req_docks = max(0, int(rd) - d)

        DG.add_edge('TOP', s_idx)
        DG.add_edge(t_idx, 'TOP')
        DG.add_edge(s_idx, g_idx)
        DG.add_edge(g_idx, t_idx)

        if req_bikes > 0:
            demand += req_bikes
            DG.nodes[t_idx]['demand'] = req_bikes
            DG.edges[s_idx, g_idx]['offer'] = 0
        elif req_docks > 0:
            demand -= req_docks
            DG.nodes[s_idx]['demand'] = -req_docks
            DG.edges[g_idx, t_idx]['offer'] = 0

    DG.nodes['TOP']['demand'] = -demand

    for edge in G.edges():
        first = edge[0]
        second = edge[1]
        ID1 = first[0]
        ID2 = second[0]
        dist = G[first][second]['weight']*10
        DG.add_edge('g'+str(ID1), 'g'+str(ID2),
                    cost=int(1000*dist), weight=dist)
        DG.add_edge('g'+str(ID2), 'g'+str(ID1),
                    cost=int(1000*dist), weight=dist)

    # This variable will indicate if a solution can be found
    err = True

    try:
        Fc, Fd = nx.network_simplex(DG, weight='cost')

    except nx.NetworkXUnfeasible:
        err = False
        return err, 0, 0

    if err:
        total = 0
        first = True
        for sd in Fd:
            if sd[0] != 'g':
                continue
            sd_ID = int(sd[1:])
            for dst, a in Fd[sd].items():
                if dst[0] == 'g' and a > 0:
                    dt_ID = int(dst[1:])
                    total += DG.edges[sd, dst]['weight']
                    w_aresta = (DG.edges[sd, dst]['weight'] * a,
                                sd_ID, dt_ID)
                    if first:
                        first = False
                        maxim = w_aresta
                    elif w_aresta[0] > maxim[0]:
                        maxim = w_aresta
        if total == 0:
            return err, total, 0
        return err, str(int(total)), str(int(maxim[0]))