285 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			285 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								%   File   : dgraphs.yap
							 | 
						||
| 
								 | 
							
								%   Author : Vitor Santos Costa
							 | 
						||
| 
								 | 
							
								%   Updated: 2006
							 | 
						||
| 
								 | 
							
								%   Purpose: Directed Graph Processing Utilities.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:- module( wundgraphs,
							 | 
						||
| 
								 | 
							
									   [
							 | 
						||
| 
								 | 
							
									    wundgraph_new/1,
							 | 
						||
| 
								 | 
							
									    wundgraph_add_edge/5,
							 | 
						||
| 
								 | 
							
									    wundgraph_add_edges/3,
							 | 
						||
| 
								 | 
							
									    wundgraph_add_vertex/3,
							 | 
						||
| 
								 | 
							
									    wundgraph_add_vertices/3,
							 | 
						||
| 
								 | 
							
									    wundgraph_del_edge/5,
							 | 
						||
| 
								 | 
							
									    wundgraph_del_edges/3,
							 | 
						||
| 
								 | 
							
									    wundgraph_del_vertex/3,
							 | 
						||
| 
								 | 
							
									    wundgraph_del_vertices/3,
							 | 
						||
| 
								 | 
							
									    wundgraph_edge/4,
							 | 
						||
| 
								 | 
							
									    wundgraph_edges/2,
							 | 
						||
| 
								 | 
							
									    wundgraph_vertices/2,
							 | 
						||
| 
								 | 
							
									    wundgraph_neighbors/3,
							 | 
						||
| 
								 | 
							
									    wundgraph_neighbours/3,
							 | 
						||
| 
								 | 
							
									    wdgraph_to_wundgraph/2,
							 | 
						||
| 
								 | 
							
									    wundgraph_to_wdgraph/2,
							 | 
						||
| 
								 | 
							
									    undgraph_to_wundgraph/2,
							 | 
						||
| 
								 | 
							
									    wundgraph_to_undgraph/2,
							 | 
						||
| 
								 | 
							
									    wundgraph_min_tree/3,
							 | 
						||
| 
								 | 
							
									    wundgraph_max_tree/3,
							 | 
						||
| 
								 | 
							
									    wundgraph_min_path/5,
							 | 
						||
| 
								 | 
							
									    wundgraph_min_paths/3,
							 | 
						||
| 
								 | 
							
									    wundgraph_max_path/5,
							 | 
						||
| 
								 | 
							
									    wundgraph_path/3]).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:- use_module( library(wdgraphs),
							 | 
						||
| 
								 | 
							
									   [
							 | 
						||
| 
								 | 
							
									    wdgraph_new/1,
							 | 
						||
| 
								 | 
							
									    wdgraph_add_edge/5,
							 | 
						||
| 
								 | 
							
									    wdgraph_add_edges/3,
							 | 
						||
| 
								 | 
							
									    wdgraph_add_vertex/3,
							 | 
						||
| 
								 | 
							
									    wdgraph_add_vertices/3,
							 | 
						||
| 
								 | 
							
									    wdgraph_del_edge/5,
							 | 
						||
| 
								 | 
							
									    wdgraph_del_edges/3,
							 | 
						||
| 
								 | 
							
									    wdgraph_del_vertex/3,
							 | 
						||
| 
								 | 
							
									    wdgraph_del_vertices/3,
							 | 
						||
| 
								 | 
							
									    wdgraph_edge/4,
							 | 
						||
| 
								 | 
							
									    wdgraph_edges/2,
							 | 
						||
| 
								 | 
							
									    wdgraph_to_dgraph/2,
							 | 
						||
| 
								 | 
							
									    dgraph_to_wdgraph/2,
							 | 
						||
| 
								 | 
							
									    wdgraph_symmetric_closure/2,
							 | 
						||
| 
								 | 
							
									    wdgraph_min_path/5,
							 | 
						||
| 
								 | 
							
									    wdgraph_min_paths/3,
							 | 
						||
| 
								 | 
							
									    wdgraph_max_path/5,
							 | 
						||
| 
								 | 
							
									    wdgraph_path/3]).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:- use_module( library(dgraphs),
							 | 
						||
| 
								 | 
							
									   [
							 | 
						||
| 
								 | 
							
								            dgraph_vertices/2,
							 | 
						||
| 
								 | 
							
									    dgraph_neighbors/3
							 | 
						||
| 
								 | 
							
									]).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:- use_module(library(rbtrees),
							 | 
						||
| 
								 | 
							
									[  
							 | 
						||
| 
								 | 
							
								         rb_new/1,
							 | 
						||
| 
								 | 
							
								         rb_delete/4,
							 | 
						||
| 
								 | 
							
									 rb_partial_map/4,
							 | 
						||
| 
								 | 
							
									 rb_visit/2,
							 | 
						||
| 
								 | 
							
									 rb_insert/4,
							 | 
						||
| 
								 | 
							
									 rb_lookup/3
							 | 
						||
| 
								 | 
							
									]).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								:- use_module(library(lists),
							 | 
						||
| 
								 | 
							
									[  
							 | 
						||
| 
								 | 
							
								         reverse/2
							 | 
						||
| 
								 | 
							
									]).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								wundgraph_new(Vertices) :-
							 | 
						||
| 
								 | 
							
									wdgraph_new(Vertices).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								wundgraph_add_edge(V1,V2,K,Vs0,Vs2) :-
							 | 
						||
| 
								 | 
							
									wdgraphs:wdgraph_new_edge(V1,V2,K,Vs0,Vs1),
							 | 
						||
| 
								 | 
							
									wdgraphs:wdgraph_new_edge(V2,V1,K,Vs1,Vs2).
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
								wundgraph_add_edges(Edges) -->
							 | 
						||
| 
								 | 
							
									{ dup_edges(Edges, DupEdges) },
							 | 
						||
| 
								 | 
							
									wdgraph_add_edges(DupEdges).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								dup_edges([],[]).
							 | 
						||
| 
								 | 
							
								dup_edges([E1-(E2-K)|Edges], [E1-(E2-K),E2-(E1-K)|DupEdges]) :-
							 | 
						||
| 
								 | 
							
									dup_edges(Edges, DupEdges).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								wundgraph_add_vertices(Vs) -->
							 | 
						||
| 
								 | 
							
									wdgraph_add_vertices(Vs).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								wundgraph_add_vertex(V) -->
							 | 
						||
| 
								 | 
							
									wdgraph_add_vertex(V).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								wundgraph_edges(Vs,Edges) :-
							 | 
						||
| 
								 | 
							
									wdgraph_edges(Vs,DupEdges),
							 | 
						||
| 
								 | 
							
									remove_dups(DupEdges,Edges).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								remove_dups([],[]).
							 | 
						||
| 
								 | 
							
								remove_dups([V1-(V2-K)|DupEdges],NEdges) :- V1 @< V2, !,
							 | 
						||
| 
								 | 
							
									NEdges = [V1-(V2-K)|Edges],
							 | 
						||
| 
								 | 
							
									remove_dups(DupEdges,Edges).
							 | 
						||
| 
								 | 
							
								remove_dups([_|DupEdges],Edges) :-
							 | 
						||
| 
								 | 
							
									remove_dups(DupEdges,Edges).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								wundgraph_vertices(Vs,Vertices) :-
							 | 
						||
| 
								 | 
							
									dgraph_vertices(Vs,Vertices).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								wundgraph_neighbours(V,Vertices,Children) :-
							 | 
						||
| 
								 | 
							
									dgraph_neighbours(V,Vertices,Children0),
							 | 
						||
| 
								 | 
							
									(
							 | 
						||
| 
								 | 
							
									    del_me(Children0,V,Children)
							 | 
						||
| 
								 | 
							
									->
							 | 
						||
| 
								 | 
							
									    true
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
									    Children = Children0
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								wundgraph_neighbors(V,Vertices,Children) :-
							 | 
						||
| 
								 | 
							
									dgraph_neighbors(V,Vertices,Children0),
							 | 
						||
| 
								 | 
							
									(
							 | 
						||
| 
								 | 
							
									    del_me(Children0,V,Children)
							 | 
						||
| 
								 | 
							
									->
							 | 
						||
| 
								 | 
							
									    true
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
									    Children = Children0
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								del_me([], _, []).
							 | 
						||
| 
								 | 
							
								del_me([K-_|Children], K1, NewChildren) :-
							 | 
						||
| 
								 | 
							
									( K == K1 ->
							 | 
						||
| 
								 | 
							
									    Children = NewChildren
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
									    K @< K1 ->
							 | 
						||
| 
								 | 
							
									    NewChildren = [K|ChildrenLeft],
							 | 
						||
| 
								 | 
							
									    del_me(Children, K1, ChildrenLeft)
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
									    NewChildren = [K|MoreChildren],
							 | 
						||
| 
								 | 
							
									    compact(Children, MoreChildren)
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								wundgraph_del_edge(V1,V2,K,Vs0,VsF) :-
							 | 
						||
| 
								 | 
							
									wdgraph_del_edge(V1,V2,K,Vs0,Vs1),
							 | 
						||
| 
								 | 
							
									wdgraph_del_edge(V2,V1,K,Vs1,VsF).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								wundgraph_del_edges(Edges) -->
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
									  dup_edges(Edges,DupEdges)
							 | 
						||
| 
								 | 
							
									},
							 | 
						||
| 
								 | 
							
									wdgraph_del_edges(DupEdges).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								wundgraph_del_vertex(V, Vs0, Vsf) :-
							 | 
						||
| 
								 | 
							
									rb_delete(Vs0, V, BackEdges, Vsi),
							 | 
						||
| 
								 | 
							
									del_and_compact(BackEdges,V,BackVertices),
							 | 
						||
| 
								 | 
							
									rb_partial_map(Vsi, BackVertices, del_edge(V), Vsf).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								del_and_compact([], _, []).
							 | 
						||
| 
								 | 
							
								del_and_compact([K-_|Children], K1, NewChildren) :-
							 | 
						||
| 
								 | 
							
									( K == K1 ->
							 | 
						||
| 
								 | 
							
									    compact(Children, NewChildren)
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
									    K @< K1 ->
							 | 
						||
| 
								 | 
							
									    NewChildren = [K|ChildrenLeft],
							 | 
						||
| 
								 | 
							
									    del_and_compact(Children, K1, ChildrenLeft)
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
									    NewChildren = [K|CompactChildren],
							 | 
						||
| 
								 | 
							
									    compact(Children, CompactChildren)
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								compact([], []).
							 | 
						||
| 
								 | 
							
								compact([K-_|Children], [K|CompactChildren]) :-
							 | 
						||
| 
								 | 
							
									compact(Children, CompactChildren).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								wundgraph_del_vertices(Vs) -->
							 | 
						||
| 
								 | 
							
									wdgraph_del_vertices(Vs).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								del_edge(_, [], []).
							 | 
						||
| 
								 | 
							
								del_edge(K1, [K-W|Children], NewChildren) :-
							 | 
						||
| 
								 | 
							
									( K == K1 ->
							 | 
						||
| 
								 | 
							
									    Children = NewChildren
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
									    K @< K1 ->
							 | 
						||
| 
								 | 
							
									    NewChildren = [K-W|ChildrenLeft],
							 | 
						||
| 
								 | 
							
									    del_edge(K1, Children, ChildrenLeft)
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
									    NewChildren = [K-W|Children]
							 | 
						||
| 
								 | 
							
									).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								wundgraph_edge(N1, N2, K, G) :-
							 | 
						||
| 
								 | 
							
									wdgraph_edge(N1, N2, K, G).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								wdgraph_to_wundgraph(G, U) :-
							 | 
						||
| 
								 | 
							
									wdgraph_symmetric_closure(G, U).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								wundgraph_to_wdgraph(G, G).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								wundgraph_min_path(V1, V2, WGraph, Path, Cost) :-
							 | 
						||
| 
								 | 
							
									wdgraph_min_path(V1, V2, WGraph, Path, Cost).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								wundgraph_max_path(V1, V2, WGraph, Path, Cost) :-
							 | 
						||
| 
								 | 
							
									wdgraph_max_path(V1, V2, WGraph, Path, Cost).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								wundgraph_min_paths(V1, WGraph, T) :-
							 | 
						||
| 
								 | 
							
									wdgraph_min_paths(V1, WGraph, T).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								wundgraph_path(V, WG, P) :-
							 | 
						||
| 
								 | 
							
									wdgraph_path(V, WG, P).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								undgraph_to_wundgraph(G1, G2) :-
							 | 
						||
| 
								 | 
							
									dgraph_to_wdgraph(G1, G2).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								wundgraph_to_undgraph(G1, G2) :-
							 | 
						||
| 
								 | 
							
									    wdgraph_to_dgraph(G1, G2).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								% simplistic algorithm to build a minimal spanning tree.
							 | 
						||
| 
								 | 
							
								% Just sort edges and then walk over each one.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								wundgraph_min_tree(G, T, C) :-
							 | 
						||
| 
								 | 
							
									rb_visit(G, Els0),
							 | 
						||
| 
								 | 
							
									mk_list_of_edges(Els0, Edges),
							 | 
						||
| 
								 | 
							
									keysort(Edges, SortedEdges),
							 | 
						||
| 
								 | 
							
									rb_new(V0),
							 | 
						||
| 
								 | 
							
									rb_new(T0),
							 | 
						||
| 
								 | 
							
									add_sorted_edges(SortedEdges, V0, TreeEdges, 0, C),
							 | 
						||
| 
								 | 
							
									wundgraph_add_edges(TreeEdges, T0, T).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								wundgraph_max_tree(G, T, C) :-
							 | 
						||
| 
								 | 
							
									rb_visit(G, Els0),
							 | 
						||
| 
								 | 
							
									mk_list_of_edges(Els0, Edges),
							 | 
						||
| 
								 | 
							
									keysort(Edges, SortedEdges),
							 | 
						||
| 
								 | 
							
									reverse(SortedEdges, ReversedEdges),
							 | 
						||
| 
								 | 
							
									rb_new(V0),
							 | 
						||
| 
								 | 
							
									rb_new(T0),
							 | 
						||
| 
								 | 
							
									add_sorted_edges(ReversedEdges, V0, TreeEdges, 0, C),
							 | 
						||
| 
								 | 
							
									wundgraph_add_edges(TreeEdges, T0, T).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mk_list_of_edges([], []).
							 | 
						||
| 
								 | 
							
								mk_list_of_edges([V-Els|Els0], Edges) :-
							 | 
						||
| 
								 | 
							
									add_neighbs(Els, V, Edges, Edges0),
							 | 
						||
| 
								 | 
							
									mk_list_of_edges(Els0, Edges0).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								add_neighbs([], _, Edges, Edges).
							 | 
						||
| 
								 | 
							
								add_neighbs([V-W|Els], V0, [W-(V0-V)|Edges], Edges0) :-
							 | 
						||
| 
								 | 
							
									V0 @< V, !,
							 | 
						||
| 
								 | 
							
									add_neighbs(Els, V0, Edges, Edges0).
							 | 
						||
| 
								 | 
							
								add_neighbs([_|Els], V0, Edges, Edges0) :-
							 | 
						||
| 
								 | 
							
									add_neighbs(Els, V0, Edges, Edges0).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
								add_sorted_edges([], _, [], C, C).
							 | 
						||
| 
								 | 
							
								add_sorted_edges([W-(V0-V)|SortedEdges], T0, NewTreeEdges, C0, C) :-
							 | 
						||
| 
								 | 
							
									( rb_lookup(V0, Component, T0) ->
							 | 
						||
| 
								 | 
							
									    ( rb_lookup(V, Component1, T0) ->
							 | 
						||
| 
								 | 
							
										( Component \== Component1 ->
							 | 
						||
| 
								 | 
							
										    /* edge that links two separate sub-trees (components) */
							 | 
						||
| 
								 | 
							
									          Component = Component1,
							 | 
						||
| 
								 | 
							
										  Ti = T0
							 | 
						||
| 
								 | 
							
									        ;
							 | 
						||
| 
								 | 
							
									        /* same component, can't add edge */
							 | 
						||
| 
								 | 
							
									          fail
							 | 
						||
| 
								 | 
							
									        )
							 | 
						||
| 
								 | 
							
									      ;
							 | 
						||
| 
								 | 
							
								              /* V is new */
							 | 
						||
| 
								 | 
							
									      rb_insert(T0, V, Component, Ti)
							 | 
						||
| 
								 | 
							
									    )
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
									    ( rb_lookup(V, Component1, T0) ->
							 | 
						||
| 
								 | 
							
								              /* V0 is new */
							 | 
						||
| 
								 | 
							
									      rb_insert(T0, V0, Component1, Ti)
							 | 
						||
| 
								 | 
							
									    ;
							 | 
						||
| 
								 | 
							
								              /* new edges, new tree */
							 | 
						||
| 
								 | 
							
									      rb_insert(T0, V0, NewComponent, T1),
							 | 
						||
| 
								 | 
							
									      rb_insert(T1, V, NewComponent, Ti)
							 | 
						||
| 
								 | 
							
									    )
							 | 
						||
| 
								 | 
							
								        ),
							 | 
						||
| 
								 | 
							
									!,
							 | 
						||
| 
								 | 
							
									NewTreeEdges = [(V0-(V-W)),(V-(V0-W))|TreeEdges],
							 | 
						||
| 
								 | 
							
									Ci is C0+W,
							 | 
						||
| 
								 | 
							
									add_sorted_edges(SortedEdges, Ti, TreeEdges, Ci, C).
							 | 
						||
| 
								 | 
							
								add_sorted_edges([_|SortedEdges],  T0, NewTreeEdges, C0, C) :-
							 | 
						||
| 
								 | 
							
									add_sorted_edges(SortedEdges, T0, NewTreeEdges, C0, C).
							 | 
						||
| 
								 | 
							
								
							 |