Convert networkx maximum_flow output into array - python

I am currently trying to model a network flow problem by applying a max-flow-min-cut algorithm to a directed graph. I managed to create the graph and solve for the maximum flow (and flows) by using
nx.maximum_flow(DG, s="S", t="T")
what follows is:
(11.0,
{'A1': {'A4': 1.0, 'A5': 0, 'T': 3.0},
'A2': {'A1': 4.0, 'A8': 2.0, 'T': 1.0},
'A3': {'A7': 3.0},
'A4': {'A3': 0, 'A8': 0, 'T': 1.0},
'A5': {'A3': 2.0, 'A8': 1.0},
'A6': {'A2': 7.0},
'A7': {'T': 3.0},
'A8': {'T': 3.0},
'S': {'A3': 1.0, 'A5': 3.0, 'A6': 7.0},
'T': {}})
which is a two value tuple (11, and the rest in one value). Now I want to create an array that has includes the flows for, say, A1 -> A4, A5 -> A8 and A6 -> A2.
However, I am failing to create any sort of list from this, since I am quite new to Python.
Ideally, I'd end up with something like this:
y = np.array([1.0, 1.0, 7.0]).reshape(3,1)
[[ 1.]
[ 1.]
[ 7.]]

I don't understand what is a problem.
import numpy as np
data = (
11.0,
{
'A1': {'A4': 1.0, 'A5': 0, 'T': 3.0},
'A2': {'A1': 4.0, 'A8': 2.0, 'T': 1.0},
'A3': {'A7': 3.0},
'A4': {'A3': 0, 'A8': 0, 'T': 1.0},
'A5': {'A3': 2.0, 'A8': 1.0},
'A6': {'A2': 7.0},
'A7': {'T': 3.0},
'A8': {'T': 3.0},
'S': {'A3': 1.0, 'A5': 3.0, 'A6': 7.0},
'T': {}
}
)
lst = [ data[1]['A1']['A4'], data[1]['A5']['A8'], data[1]['A6']['A2'] ]
y = np.array( lst ).reshape(3,1)
print(y)
Result:
[[ 1.]
[ 1.]
[ 7.]]

Related

Sum of values from nested dictionary [duplicate]

This question already has answers here:
How to sum values in multidimensional dictionary?
(6 answers)
Closed 1 year ago.
I have this nested dictionary:
{'rekless': {'C': 2.0, 'H': 4.0, 'J': 0.0}, 'bwipo': {'C': 3.0, 'D': 4.0, 'H': 0.0}, 'wunder': {'D': 10.0, 'G': 20.0, 'H': 0.50}, 'caps': {'D': 3.1, 'I': 2.0, '9J': 1.0, '10K': 2.0}, 'jankos': {'D': 3.2, 'I': 2.0, 'J': 1.0, 'K': 2.0} }
Want i want to do is to loop through it and sum all values of the "C, H, J,", etc...
So like, 'C' is going to be (2.0 + 3.0), 'D' is going to be (4.0 + 10.0 + 3.1 + 3.2).
So i can end up with something similar to this:
{ C: 'sum of values from c', D: 'sum of values from d', etc.. }
It doesnt need to be in a dictionary the final result.
Any ideias on how to start?
You need to loop through both dictionary and subdictionary:
d = {
'rekless': {'C': 2.0, 'H': 4.0, 'J': 0.0},
'bwipo': {'C': 3.0, 'D': 4.0, 'H': 0.0},
'wunder': {'D': 10.0, 'G': 20.0, 'H': 0.50},
'caps': {'D': 3.1, 'I': 2.0, '9J': 1.0, '10K': 2.0},
'jankos': {'D': 3.2, 'I': 2.0, 'J': 1.0, 'K': 2.0}
}
summary = dict()
for key, subdict in d.items():
for k, v in subdict.items():
summary[k] = summary.get(k, 0) + v
print(summary)
Assume d is:
d = {'rekless': {'C': 2.0, 'H': 4.0, 'J': 0.0}, 'bwipo': {'C': 3.0, 'D': 4.0, 'H': 0.0}, 'wunder': {'D': 10.0, 'G': 20.0, 'H': 0.50}, 'caps': {'D': 3.1, 'I': 2.0, '9J': 1.0, '10K': 2.0}, 'jankos': {'D': 3.2, 'I': 2.0, 'J': 1.0, 'K': 2.0} }
Try this:
vals ={}
for k in d:
sum_ = 0
for k_ in d[k]:
if k_ in vals:
vals[k_]+= int(d[k][k_])
else:
vals[k_]= int(d[k][k_])
for k__ in vals:
vals[k__]='sum of values from {} is: {}'.format(k__, vals[k__])
which results in vals to be:
{'C': 'sum of values from C is: 5',
'H': 'sum of values from H is: 4',
'J': 'sum of values from J is: 1',
'D': 'sum of values from D is: 20',
'G': 'sum of values from G is: 20',
'I': 'sum of values from I is: 4',
'9J': 'sum of values from 9J is: 1',
'10K': 'sum of values from 10K is: 2',
'K': 'sum of values from K is: 2'}

Extracting the values from nested dictionary in python

d= {0: {'Name': 'MN', 'volt': 1.0, 'an': 0.0},
1: {'Name': 'LT', 'volt': 1.0, 'an': 5.8},
2: {'Name': 'CK', 'volt': 1.0, 'an': 2.72},
3: {'Name': 'QL', 'volt': 1.0, 'an': 0.33}}
I am trying to create a matrix from the above nested dictionary that would result in the following output:
[MN 1.0 0.0
LT 1.0 5.8
CK 1.0 2.72
QL 1.0 0.33]
Using .values() function in python would result in the key names as well.
I guess you can them in a list like this
>>> d = {0: {'Name': 'MN', 'volt': 1.0, 'an': 0.0},
1: {'Name': 'LT', 'volt': 1.0, 'an': 5.8},
2: {'Name': 'CK', 'volt': 1.0, 'an': 2.72},
3: {'Name': 'QL', 'volt': 1.0, 'an': 0.33}}
>>> [list(i.values()) for i in d.values()]
[['MN', 1.0, 0.0],
['LT', 1.0, 5.8],
['CK', 1.0, 2.72],
['QL', 1.0, 0.33]]
You iterate over the values of the outer dictionary and then again, extract the values of interior dictionaries via i.values during iteration, store them in a list with list-comprehension.
If you want them flattened in a list
>>> sum([list(i.values()) for i in d.values()], [])
['MN', 1.0, 0.0, 'LT', 1.0, 5.8, 'CK', 1.0, 2.72, 'QL', 1.0, 0.33]

Compare 2 dictionary by value and drop some k, v python

I have 2 dictionary :
First = {'A': 0.0, 'B': 0.0, 'C': 0.0, 'D': 0.0, 'E': 0.0, 'F': 0.0, 'G': 0.0, 'H': 0.0, 'I': 0.0, 'J': 0.0, 'K': 0.47, 'L': 0.0, 'M': 0.0, 'N': 0.0, 'O': 0.0, 'P': 0.0, 'Q': 0.0, 'R': 0.0, 'S': 0.41, 'T': 0.0}
and
Second = {'A': 0.0, 'B': 0.0, 'C': 0.0, 'D': 0.0, 'E': 0.0, 'F': 0.0, 'G': 0.0, 'H': 0.0, 'I': 0.18, 'J': 0.0, 'K': 1.0, 'L': 0.0, 'M': 0.0, 'N': 0.0, 'O': 0.0, 'P': 0.0, 'Q': 0.0, 'R': 0.0, 'S': 0.32, 'T': 0.0}
I woud like to drop certain values in second dict with conditions :
1 - if value in second dict is < to value un first dict, drop the (k,v) to the second dict
2 - if value in second dict == 0.0 then drop the (k,v) to the second dict
Fanaly, we have result :
Second = {'I': 0.18,'K': 1.0, 'S': 0.32}
Here is my code :
for key, value in dict(Second).items():
for key, value in dict(First).items():
if Second[value] == First[value] :
del Second[key]
elif First[value]> Second[value]:
del Second[key]
Second
But dont work :
KeyError: 0.0
Can someone help me !
You can't lookup a value as a key to a dictionary. Also, your 2nd loop is causing you to loop through the Second dictionary after you've already cleared all the elements that you want to clear.
You're looking for something more like:
for key, value in dict(Second).items():
if Second[key] == First[key] :
del Second[key]
elif First[key]> Second[key]:
del Second[key]
or even better
for key, value in Second.items():
if Second[key] <= First[key]:
del Second[key]
though your second condition, specifies it should be something more like:
for key, value in Second.items():
if Second[key] < First[key] or Second[key] == 0.0:
del Second[key]
Iterate through the first dict, since it won't be the one changing, and based on your conditions filter stuff out
for k,v in First.iteritems():
if Second[k] < v or Second[k] == 0.0:
del Second[k]
output:
{'I': 0.18, 'K': 1.0}
You are mistakenly using the item value rather than the key in an attempt to access the value. Also, you will run into problems if you attempt to mutate the dict while iterating over it. Instead, you could use dict comprehension.
For example:
d1 = {'A': 0.0, 'B': 0.0, 'C': 0.0, 'D': 0.0, 'E': 0.0, 'F': 0.0, 'G': 0.0, 'H': 0.0, 'I': 0.0, 'J': 0.0, 'K': 0.47, 'L': 0.0, 'M': 0.0, 'N': 0.0, 'O': 0.0, 'P': 0.0, 'Q': 0.0, 'R': 0.0, 'S': 0.41, 'T': 0.0}
d2 = {'A': 0.0, 'B': 0.0, 'C': 0.0, 'D': 0.0, 'E': 0.0, 'F': 0.0, 'G': 0.0, 'H': 0.0, 'I': 0.18, 'J': 0.0, 'K': 1.0, 'L': 0.0, 'M': 0.0, 'N': 0.0, 'O': 0.0, 'P': 0.0, 'Q': 0.0, 'R': 0.0, 'S': 0.32, 'T': 0.0}
d2 = {k: v for k, v in d2.items() if v != 0 and v != d1[k]}
print(d2)
# {'I': 0.18, 'K': 1.0, 'S': 0.32}

Extracting dictionary items embedded in a list

Let's say I have the following list of dict
t = [{'a': 1.0, 'b': 2.0},
{'a': 3.0, 'b': 4.0},
{'a': 5.0, 'b': 6.0},
{'a': 7.0, 'b': 9.0},
{'a': 9.0, 'b': 0.0}]
Is there an efficient way to extract all the values contained in the dictionaries with a dictionary key value of a?
So far I have come up with the following solution
x = []
for j in t:
x.append(j['a'])
However, I don't like to loop over items, and was looking at a nicer way to achieve this goal.
You can use list comprehension:
t = [{'a': 1.0, 'b': 2.0},
{'a': 3.0, 'b': 4.0},
{'a': 5.0, 'b': 6.0},
{'a': 7.0, 'b': 9.0},
{'a': 9.0, 'b': 0.0}]
new_list = [i["a"] for i in t]
Output:
[1.0, 3.0, 5.0, 7.0, 9.0]
Since this solution uses a for-loop, you can use map instead:
x = list(map(lambda x: x["a"], t))
Output:
[1.0, 3.0, 5.0, 7.0, 9.0]
Performance-wise, you prefer to use list-comprehension solution rather the map one.
>>> timeit('new_list = [i["a"] for i in t]', setup='from __main__ import t', number=10000000)
4.318223718035199
>>> timeit('x = list(map(lambda x: x["a"], t))', setup='from __main__ import t', number=10000000)
16.243124993163093
def temp(p):
return p['a']
>>> timeit('x = list(map(temp, t))', setup='from __main__ import t, temp', number=10000000)
16.048683850689343
There is a slightly difference when using a lambda or a regular function; however, the comprehension execution takes 1/4 of the time.
You can use itemgetter:
from operator import itemgetter
t = [{'a': 1.0, 'b': 2.0},
{'a': 3.0, 'b': 4.0},
{'a': 5.0, 'b': 6.0},
{'a': 7.0, 'b': 9.0},
{'a': 9.0, 'b': 0.0}]
print map(itemgetter('a'), t)
result:
[1.0, 3.0, 5.0, 7.0, 9.0]
Use a list comprehension as suggested in Ajax1234'a answer, or even a generator expression if that would benefit your use case:
t = [{'a': 1.0, 'b': 2.0}, {'a': 3.0, 'b': 4.0}, {'a': 5.0, 'b': 6.0}, {'a': 7.0, 'b': 9.0}, {'a': 9.0, 'b': 0.0}]
x = (item["a"] for item in t)
print(x)
Output:
<generator object <genexpr> at 0x7f0027def550>
The generator has the advantage of not executing or consuming memory until a value is needed. Use next() to take the next item from the generator, or iterate over it with a for loop.
>>> next(x)
1.0
>>> next(x)
3.0
>>> for n in x:
... print(n)
5.0
7.0
9.0
An alternative, albeit a expensive one, is to use pandas:
import pandas as pd
x = pd.DataFrame(t)['a'].tolist()
print(x)
Output:
[1.0, 3.0, 5.0, 7.0, 9.0]

Yen's K-shortest Algorithm Python Implementation - For a 10-node all-connected graph, the maximum k I could reach is below what I expected

I've implemented Yen's K-shortest path algorithm based on the pseudocode on Wikipedia and a few open-source codes on GitHub (https://gist.github.com/ALenfant/5491853 and https://github.com/Pent00/YenKSP). The only thing I did differently was instead of removing (i, i+1) edges completely, I changed the length of the edge to infinity (which is equivalent to removing the edges in essense I guess?)
I tested my code with a 10-node graph where all nodes are connected to each other. I expected the maximum number of loop-less routes I could generate is above 100 thousands but it turns out that my code could only find up to the 9th shortest route. Is this a limitation of Yen's?
Following is my code and the 10-node sample data.
def yen(nodes, distances, start, end, max_k):
# Dictionary "solspace" stores actual k-shortest paths, the first of which comes from Dijkstra's algorithm.
solspace = {}
potentialsolspace = []
selected = []
# Adding the Dijkstra's shortest path into solspace dictionary
solspace[0] = (dijkstra(nodes, distances, start, end))[0]
# max_k is the specified number of shortest paths you want to find
max_k = max_k
# Looping from k = 1 to k = max_K and the 0 to (size of previous entry of solspace)-1
# Reference: http://en.wikipedia.org/wiki/Yen's_algorithm
for k in range(1, max_k):
#distances = copy.deepcopy(actual_distances)
for i in range(0, (len(solspace[k - 1]) - 1)):
spur_node = solspace[k - 1][i]
spur_node_plus_one = solspace[k - 1][i + 1]
root_path = solspace[k - 1][0:i + 1]
for shortPath in solspace:
path_root_path = (solspace[shortPath])[0:i + 1]
#print(path_root_path)
if root_path == path_root_path and (len(solspace[shortPath]) - 1 > i):
# make each overlapping edges of root path and path_root_path infinity, hence impossible to select
distances[spur_node][spur_node_plus_one] = float('inf')
distances[spur_node_plus_one][spur_node] = float('inf')
# Call Dijkstra function to compute spur path (the shortest path between spur node
# and end ignoring the i,i+1 edge
spur_path_a = dijkstra(nodes, distances, spur_node, end)
spur_path = spur_path_a[0]
# Restore actual dist to distances nested dictionary
# Total path is just the combination of root path & spur path
total_path_tempo = root_path + spur_path
total_path = []
# This removes duplicates nodes but note that this is O(n^2) computing time, not efficient
# Ref: Stack Overflow questions:480214
[total_path.append(item) for item in total_path_tempo if item not in total_path]
print(total_path)
# build up potentialsolspace by adding in total path which are yet found in solspace or Potential
# hence, the use of nested if
if total_path not in solspace.values():
if [total_path, cost_path(total_path, distances)] not in potentialsolspace[:]:
potentialsolspace.append([total_path, cost_path(total_path, distances)])
distances = copy.deepcopy(actual_distances)
# This handles the case of there being no spur paths, or no spur paths left.
# This could happen if the spur paths have already been exhausted (added to A),
# or there are no spur paths at all such as when both the source and sink vertices lie along a "dead end".
if len(potentialsolspace) is 0:
break
wcg = min(potentialsolspace, key=lambda x: x[1])
# remove selected potential shortest path from the potential solspace
potentialsolspace.remove(wcg)
# Attach minimum of potentialSolSpace into solspace dictionary
solspace[k] = wcg[0]
return solspace
Following is the 10-node example arranged in Python nested distionary format. Primary keys are origins while secondary keys are neighbors of primary keys. Values equal the distance between primary key and secondary key.
{'A': {'C': 4.0, 'B': 10.0, 'E': 10.0, 'D': 10.0, 'G': 1.0, 'F': 2.0, 'I': 3.0, 'H': 3.0, 'J': 10.0}, 'C': {'A': 4.0, 'B': 5.0, 'E': 9.0, 'D': 6.0, 'G': 9.0, 'F': 10.0, 'I': 5.0, 'H': 10.0, 'J': 5.0}, 'B': {'A': 2.0, 'C': 10.0, 'E': 8.0, 'D': 1.0, 'G': 8.0, 'F': 4.0, 'I': 2.0, 'H': 2.0, 'J': 6.0}, 'E': {'A': 9.0, 'C': 5.0, 'B': 10.0, 'D': 4.0, 'G': 9.0, 'F': 9.0, 'I': 3.0, 'H': 3.0, 'J': 7.0}, 'D': {'A': 4.0, 'C': 6.0, 'B': 5.0, 'E': 7.0, 'G': 1.0, 'F': 1.0, 'I': 2.0, 'H': 9.0, 'J': 3.0},
'G': {'A': 2.0, 'C': 10.0, 'B': 3.0, 'E': 1.0, 'D': 10.0, 'F': 5.0, 'I': 5.0, 'H': 6.0, 'J': 1.0}, 'F': {'A': 2.0, 'C': 3.0, 'B': 6.0, 'E': 7.0, 'D': 8.0, 'G': 10.0, 'I': 1.0, 'H': 8.0, 'J': 2.0}, 'I': {'A': 1.0, 'C': 1.0, 'B': 2.0, 'E': 1.0, 'D': 6.0, 'G': 7.0, 'F': 1.0, 'H': 6.0, 'J': 2.0},
'H': {'A': 3.0, 'C': 4.0, 'B': 5.0, 'E': 1.0, 'D': 2.0, 'G': 6.0, 'F': 4.0, 'I': 1.0, 'J': 4.0},
'J': {'A': 5.0, 'C': 6.0, 'B': 1.0, 'E': 8.0, 'D': 7.0, 'G': 9.0, 'F': 8.0, 'I': 10.0, 'H': 1.0}}
I think the problem is in this part:
for shortPath in solspace:
path_root_path = (solspace[shortPath])[0:i + 1]
#print(path_root_path)
if root_path == path_root_path and (len(solspace[shortPath]) - 1 > i):
# make each overlapping edges of root path and path_root_path infinity, hence impossible to select
distances[spur_node][spur_node_plus_one] = float('inf')
distances[spur_node_plus_one][spur_node] = float('inf')
# Call Dijkstra function to compute spur path (the shortest path between spur node
# and end ignoring the i,i+1 edge
spur_path_a = dijkstra(nodes, distances, spur_node, end)
Compare this to wikipedia:
for each path p in A:
if rootPath == p.nodes(0, i):
// Remove the links that are part of the previous shortest paths which share the same root path.
remove p.edge(i, i + 1) from Graph;
for each node rootPathNode in rootPath except spurNode:
remove rootPathNode from Graph;
// Calculate the spur path from the spur node to the sink.
spurPath = Dijkstra(Graph, spurNode, sink);
You are meant to loop over paths in A and remove lots of edges from the graph before running Dijkstra.
However, in your code you call Dijkstra from within the loop that should be removing edges, therefore you will only ever run Dijkstra on a graph with a single edge removed and this limits the number of alternative routes you can find.
Try reducing the indent by 2 tab stops on the part that calls Dijkstra.

Categories

Resources