/* Maximum flow in a graph using min-cut theorem (Kannan Govindarajan) */
/*		(with stylistic changes by BJ)			     */

mode sum_edges(yes), cuts2(no,no,yes), cross_edges(no,yes),
     forward(no,yes,no), backward(no,yes,no).

closure parts/1.

/* maxflow(SourceNode, TargetNode, GraphNodes) */

maxflow(S,T,G) equals min(sum_edges(cuts(S,T,G))).

cuts(S,T,{S\{T\G}}) equals cuts2(S,T,parts(G)).

	parts(phi)      contains {p(phi,phi)}.
	parts({H\T})    contains distr(H,parts(T)).

		distr(H,{p(P1,P2)\_}) contains {p({H\P1},P2), p(P1,{H\P2})}.

	cuts2(S,T,{p(Ss,Ts)\_}) contains {p({S\Ss},{T\Ts})}.

sum_edges({P\_}) contains {sum(part_edges(P))}.

	part_edges(p({U\_},P2)) contains cross_edges(U,P2).

		cross_edges(U, P2)   contains forward(U,edgesfrom(U), P2).
		cross_edges(U,{V\_}) contains backward(V,edgesfrom(V),U). 

		    forward(U,{to(V,D)\_}, {V \ _}) contains {edge(U,V,D)}.
		    backward(U,{to(V,D)\_}, V)      contains {edge(U,V,0-D)}.
							% sorry, you can't say
							% -D here.

	sum(phi)   	     equals 0.
	sum({edge(_,_,X)\T}) equals sum(T) + X.

/* The Graph */

edgesfrom(s)  equals {to(v1,16),to(v2,13)}.  
edgesfrom(v1) equals {to(v3,12),to(v2,10)}.
edgesfrom(v2) equals {to(v1,4),to(v4,14)}.
edgesfrom(v3) equals {to(v2,9),to(t,20)}.
edgesfrom(v4) equals {to(v3,7),to(t,4)}.
edgesfrom(_)  equals phi.

/* Helper Functions */

min(phi)   equals infinity.
min({X\S}) equals min2(min(S),X).

	min2(D,X) equals if D > X then X else D.

infinity equals 99999.

/* Goal:

maxflow(s,t,{s,v1,v2,v3,v4,t}).

*/
