% This is provides the Reach(able) vars in a Graph, when starting
% for any in a Set of variables. The return vars are in the same
% order as provided in the libary top_sort/2 predicate.
%
graph_variables_reach_ord( Set, Graph, Reach ) :-
	graph_variables_reach( Set, Graph, [], ReachSetOrd ),
	top_sort( Graph, TopOrder ),
	ord_set_narrows( TopOrder, ReachSetOrd, Reach ).

ord_set_narrows( [], [], [] ).
ord_set_narrows( [H|T], Set, Reach ) :-
	( ord_del_element( Set, H, Red ) ->
		Reach = [H|TReach],
		( Red == [] -> RemL = []; RemL = T )
		;
		Red = Set,
		Reach = TReach,
		RemL  = []
	),
	ord_set_narrows( RemL, Red, TReach ).


% graph_variables_reach( Vars, Graph, Acc, Reach ) :-
% Reach are all the variables that are reachable from
% some variable in Vars, according to the edges in Graph.
% Intermediate results are held in the set Acc.
% Currently Graph donot include no-edged vertices,
% thus one has to protect reachable/3.
%
graph_variables_reach( [V|Vs], Graph, Acc, Reach ) :-
	( reachable( V, Graph, VReach ) -> 
		true
		;
		VReach = [V]
	),
	% append( VReach, Acc, NewAcc ),
	% merge_set( VReach, Acc, NewAcc ), % swi ?
	ord_union( VReach, Acc, NewAcc ),
	graph_variables_reach( Vs, Graph, NewAcc, Reach ).
graph_variables_reach( [], _Graph, Acccumulated, Sorted ) :-
	list_to_ord_set( Acccumulated, Sorted ).

% graph_add_constraint_many_to_one( Vars, Constr, DepVar, Graph, NewGraph ) :-
graph_add_constraint_many_to_one( [], _Constr, _DepVar, Graph, Graph ).
graph_add_constraint_many_to_one( [V|Vs], Constr, DepVar, Graph, NewGraph ) :-
	graph_add_constraint( V, Constr, DepVar, Graph, NxGraph ),
	graph_add_constraint_many_to_one( Vs, Constr, DepVar, NxGraph, NewGraph ).

% graph_add_constraint( Var, _Constr, DepVar, Graph, NewGraph ) :-
% an edge from DepVar to Var is added from Graph to NewGraph,
% provisio that there is n't a path from Var to DepVar.
% Constr is not used, But if both = and # would be later
% supported, then one maybe able to weight the edges.
%
graph_add_constraint( Var, Constr, DepVar, Graph, NewGraph ) :-
	( reachable(Var,Graph,VarReachesThese) ->
		true
		;
		VarReachesThese = []
	),
	( memberchk(DepVar,VarReachesThese)  ->
		print_message( error, graph_cycle_while_adding(ind_var(Var),constr(Constr),dep_var(DepVar)))
		;
		true
	),
	add_edges( Graph, [DepVar-Var], NewGraph ).