Skip to content

Commit

Permalink
fix bug in graphwalker balancing algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxBo committed Oct 22, 2019
1 parent 959aee7 commit bb110da
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 24 deletions.
31 changes: 18 additions & 13 deletions repair/apps/asmfa/graphs/graphwalker.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ def examine_vertex(self, u):

sum_in_deltas = u.in_degree(self.change)
sum_out_deltas = u.out_degree(self.change)
delta = sum_in_deltas - sum_out_deltas
if not delta:
return
bf = self.balance_factor[vertex_id]
balanced_delta = delta * bf
balanced_out_deltas = sum_out_deltas / bf
balanced_delta = sum_in_deltas - balanced_out_deltas
if abs(balanced_delta) < 0.0000001:
return
sum_out_f = u.out_degree(weight=self.amount)
if sum_out_f:
amount_factor = balanced_delta / sum_out_f
Expand Down Expand Up @@ -98,30 +98,35 @@ def traverse_graph(g, edge, delta, upstream=True):
change = g.new_edge_property("float", val=0.0)
total_change = g.new_edge_property("float", val=0.0)

# We are only interested in the edges that define the solution
g.set_edge_filter(g.ep.include)
MAX_ITERATIONS = 20
balance_factor = g.vp.downstream_balance_factor.a
node_visitor = NodeVisitor(g.vp["id"], amount, change,
balance_factor)
node_visitor2 = NodeVisitorBalanceDeltas(g.vp["id"], amount, change,
balance_factor)

if plot:
# prepare plotting of intermediate results
from repair.apps.asmfa.tests import flowmodeltestdata
flowmodeltestdata.plot_materials(g, file='materials.png')
flowmodeltestdata.plot_amounts(g,'amounts.png', 'amount')
g.ep.change = change

# We are only interested in the edges that define the solution
g.set_edge_filter(g.ep.include)
MAX_ITERATIONS = 20
balance_factor = g.vp.downstream_balance_factor.a

# make a first run with the given changes to the implementation edge

# By default we go upstream first, because 'demand dictates supply'
if upstream:
node = edge.source()
g.set_reversed(True)
balance_factor = 1 / balance_factor
else:
node = edge.target()
g.set_reversed(False)

# initialize the node-visitors
node_visitor = NodeVisitor(g.vp["id"], amount, change,
balance_factor)
node_visitor2 = NodeVisitorBalanceDeltas(g.vp["id"], amount, change,
balance_factor)

node_visitor.forward = True
total_change.a[:] = 0
new_delta = delta
Expand Down
2 changes: 1 addition & 1 deletion repair/apps/asmfa/tests/flowmodeltestdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ def plot_amounts(g, file=None, prop='amount'):
vertex_ids = [f'{int(v)}' for v in g.vertices()]
vertex_text = g.new_vertex_property("string", vals=vertex_ids)
mass_text = g.new_edge_property("string",
vals=[str(round(i, 3))for i in quantities])
vals=[str(round(i, 3)) for i in quantities])
gt.draw.graph_draw(g, vertex_size=20, vertex_text=vertex_text,
vprops={"text_position": -1,
"font_size": 10},
Expand Down
35 changes: 25 additions & 10 deletions repair/apps/asmfa/tests/test_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ def test_plastic_packaging(self):
Consumption --> Recycling -0.12
Recycling --> Production -0.06
"""
return
plastic = flowmodeltestdata.plastic_package_graph()
gw = GraphWalker(plastic)
change = gw.graph.new_edge_property('float')
Expand All @@ -101,45 +100,61 @@ def test_plastic_packaging(self):
gw.graph.ep.include[e] = False
result = gw.calculate(implementation_edges, deltas)
for i, e in enumerate(result.edges()):
print(f"{result.vp.id[e.source()]} --> {result.vp.id[e.target()]} / {result.ep.material[e]}: {result.ep.amount[e]}")
print(f"{result.vp.id[e.source()]} --> {result.vp.id[e.target()]} "
f"/ {result.ep.material[e]}: {result.ep.amount[e]}")
if result.vp.id[e.source()] == 'Packaging' \
and result.vp.id[e.target()] == 'Consumption' \
and result.ep.material[e] == 'plastic':
expected = 5.0 - 0.3
self.assertAlmostEqual(result.ep.amount[e], expected, 2, 'Packaging->Consumption')
self.assertAlmostEqual(
result.ep.amount[e], expected, delta=0.2,
msg='Packaging->Consumption')
elif result.vp.id[e.source()] == 'Oil rig' \
and result.vp.id[e.target()] == 'Oil refinery' \
and result.ep.material[e] == 'crude oil':
expected = 20.0 - 0.3
self.assertAlmostEqual(result.ep.amount[e], expected, 2, 'Oil rig->Oil refinery')
self.assertAlmostEqual(
result.ep.amount[e], expected, delta=0.2,
msg='Oil rig->Oil refinery')
elif result.vp.id[e.source()] == 'Oil refinery' \
and result.vp.id[e.target()] == 'Production' \
and result.ep.material[e] == 'plastic':
expected = 4.0 - 0.24
self.assertAlmostEqual(result.ep.amount[e], expected, 2, 'Oil refinery->Production')
self.assertAlmostEqual(
result.ep.amount[e], expected, delta=0.2,
msg='Oil refinery->Production')
elif result.vp.id[e.source()] == 'Production' \
and result.vp.id[e.target()] == 'Packaging' \
and result.ep.material[e] == 'plastic':
expected = 5.0 - 0.3
self.assertAlmostEqual(result.ep.amount[e], expected, 2, 'Production->Packaging')
self.assertAlmostEqual(
result.ep.amount[e], expected, delta=0.2,
msg='Production->Packaging')
elif result.vp.id[e.source()] == 'Consumption' \
and result.vp.id[e.target()] == 'Burn' \
and result.ep.material[e] == 'plastic':
expected = 3.0 - 0.18
self.assertAlmostEqual(result.ep.amount[e], expected, 2, 'Consumption->Burn')
self.assertAlmostEqual(
result.ep.amount[e], expected, delta=0.1,
msg='Consumption->Burn')
elif result.vp.id[e.source()] == 'Consumption' \
and result.vp.id[e.target()] == 'Recycling' \
and result.ep.material[e] == 'plastic':
expected = 2.0 - 0.12
self.assertAlmostEqual(result.ep.amount[e], expected, 2, 'Consumption->Recycling')
self.assertAlmostEqual(
result.ep.amount[e], expected, delta=0.1,
msg='Consumption->Recycling')
elif result.vp.id[e.source()] == 'Recycling' \
and result.vp.id[e.target()] == 'Production' \
and result.ep.material[e] == 'plastic':
expected = 1.0 - 0.06
self.assertAlmostEqual(result.ep.amount[e], expected, 2, 'Recycling->Production')
self.assertAlmostEqual(
result.ep.amount[e], expected, delta=0.06,
msg='Recycling->Production')
else:
self.assertAlmostEqual(result.ep.amount[e],
gw.graph.ep.amount[e], places=2)
gw.graph.ep.amount[e],
delta=result.ep.amount[e]/10)


def test_milk_production(self):
Expand Down

0 comments on commit bb110da

Please sign in to comment.