|
@@ -10,6 +10,8 @@
|
|
-export([append/2, append/1, get_in/1, get_out/1, out_edges/2]).
|
|
-export([append/2, append/1, get_in/1, get_out/1, out_edges/2]).
|
|
% Checks for validity
|
|
% Checks for validity
|
|
-export([valid_edge/1, valid_edge_list/1, valid_graph/1]).
|
|
-export([valid_edge/1, valid_edge_list/1, valid_graph/1]).
|
|
|
|
+% Branching
|
|
|
|
+-export([detour/3, reroute/2]).
|
|
|
|
|
|
% Use the orddict module for clarity, and the dict module for speed.
|
|
% Use the orddict module for clarity, and the dict module for speed.
|
|
-define(DICT, orddict).
|
|
-define(DICT, orddict).
|
|
@@ -106,17 +108,16 @@ from_list(In = #vertex{}, Out = #vertex{}, Edges) ->
|
|
FG = lists:foldl(fun(E, G) -> add_edge(G, E) end,
|
|
FG = lists:foldl(fun(E, G) -> add_edge(G, E) end,
|
|
#flow_graph{in=In, out=Out, graph=?DICT:new()},
|
|
#flow_graph{in=In, out=Out, graph=?DICT:new()},
|
|
Edges),
|
|
Edges),
|
|
- G2 = ?DICT:update(Out, fun(X)->X end, [], FG#flow_graph.graph),
|
|
|
|
- FG#flow_graph{graph=G2}.
|
|
|
|
|
|
+ FG#flow_graph{graph=add_vertex(FG#flow_graph.graph, Out)}.
|
|
|
|
|
|
%% Graph manipulation
|
|
%% Graph manipulation
|
|
|
|
|
|
-append(FG1 = #flow_graph{in=In1, out=Out1},
|
|
|
|
- FG2 = #flow_graph{in=In2, out=Out2}) ->
|
|
|
|
- G = ?DICT:merge(fun(_, E1, E2) -> lists:append(E1,E2) end,
|
|
|
|
- FG1#flow_graph.graph,
|
|
|
|
- FG2#flow_graph.graph),
|
|
|
|
- add_edge(#flow_graph{in=In1, out=Out2, graph=G},
|
|
|
|
|
|
+merge_graphs(G1, G2) ->
|
|
|
|
+ ?DICT:merge(fun(_, E1, E2) -> lists:append(E1,E2) end, G1, G2).
|
|
|
|
+
|
|
|
|
+append(#flow_graph{in=In1, out=Out1, graph=G1},
|
|
|
|
+ #flow_graph{in=In2, out=Out2, graph=G2}) ->
|
|
|
|
+ add_edge(#flow_graph{in=In1, out=Out2, graph=merge_graphs(G1,G2)},
|
|
flow(Out1, In2)).
|
|
flow(Out1, In2)).
|
|
|
|
|
|
append([FG1|FGs]) ->
|
|
append([FG1|FGs]) ->
|
|
@@ -133,6 +134,9 @@ add_edge(FG = #flow_graph{graph=G}, E = #edge{from=From}) ->
|
|
Add = fun(Edges) -> [E|Edges] end,
|
|
Add = fun(Edges) -> [E|Edges] end,
|
|
FG#flow_graph{graph=?DICT:update(From, Add, [E], G)}.
|
|
FG#flow_graph{graph=?DICT:update(From, Add, [E], G)}.
|
|
|
|
|
|
|
|
+add_vertex(FG = #flow_graph{graph=G}, V = #vertex{}) ->
|
|
|
|
+ FG#flow_graph{graph=?DICT:update(V, fun(Es)->Es end, [], G)}.
|
|
|
|
+
|
|
% Checks for validity
|
|
% Checks for validity
|
|
valid_edge(#edge{from=From, to=To, through=Through}) ->
|
|
valid_edge(#edge{from=From, to=To, through=Through}) ->
|
|
IsNeutral = fun(flow) -> true;
|
|
IsNeutral = fun(flow) -> true;
|
|
@@ -178,3 +182,15 @@ valid_edge_list(Edges) ->
|
|
valid_graph(#flow_graph{graph=G}) ->
|
|
valid_graph(#flow_graph{graph=G}) ->
|
|
lists:all(fun({_, Es}) -> valid_edge_list(Es) end,
|
|
lists:all(fun({_, Es}) -> valid_edge_list(Es) end,
|
|
?DICT:to_list(G)).
|
|
?DICT:to_list(G)).
|
|
|
|
+
|
|
|
|
+% Branching
|
|
|
|
+detour(From = #flow_graph{out=FOut, graph=FG},
|
|
|
|
+ _Between = #flow_graph{in=BIn, out=BOut, graph=BG},
|
|
|
|
+ _To = #flow_graph{in=TIn}) ->
|
|
|
|
+ G = add_edge(add_edge(merge_graphs(FG,BG), flow(FOut, BIn)),
|
|
|
|
+ flow(BOut, TIn)),
|
|
|
|
+ From#flow_graph{graph=G}.
|
|
|
|
+
|
|
|
|
+reroute(#flow_graph{in=In1, graph=G1},
|
|
|
|
+ #flow_graph{out=Out2, graph=G2}) ->
|
|
|
|
+ #flow_graph{in=In1, out=Out2, graph=merge_graphs(G1, G2)}.
|