YAP 7.1.0
All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
wundgraphs.yap
Go to the documentation of this file.
1/**
2 * @file wundgraphs.yap
3 * @author VITOR SANTOS COSTA <vsc@VITORs-MBP.lan>
4 * @date 2006
5 *
6 *
7*/
8
9
10:- module( wundgraphs,
11 [
12 wundgraph_add_edge/5,
13 wundgraph_add_edges/3,
14 wundgraph_del_edge/5,
15 wundgraph_del_edges/3,
16 wundgraph_del_vertex/3,
17 wundgraph_edges/2,
18 wundgraph_neighbours/3,
19 wundgraph_neighbors/3,
20 wundgraph_wneighbours/3,
21 wundgraph_wneighbors/3,
22 wundgraph_min_tree/3,
23 wundgraph_max_tree/3]).
24
25
26:- wdgraph_new/1wdgraph_add_vertex/3wdgraph_add_vertices/3wdgraph_vertices/2wdgraph_del_vertices/3wdgraph_edge/4wdgraph_symmetric_closure/2wdgraph_to_dgraph/2dgraph_to_wdgraph/2wdgraph_min_path/5wdgraph_min_paths/3wdgraph_max_path/5wdgraph_path/3wdgraph_reachable/3reexport( library(wdgraphs),
27 [
28 as wundgraph_new,
29 as wundgraph_add_vertex,
30 as wundgraph_add_vertices,
31 as wundgraph_vertices,
32 as wundgraph_del_vertices,
33 as wundgraph_edge,
34 as wdgraph_to_wundgraph,
35 as wundgraph_to_undgraph,
36 as undgraph_to_wundgraph,
37 as wundgraph_min_path,
38 as wundgraph_min_paths,
39 as wundgraph_max_path,
40 as wundgraph_path,
41 as wundgraph_reachable
42 ]).
43
44:- wdgraph_add_edge/5wdgraph_add_edges/3wdgraph_del_edge/5wdgraph_del_edges/3wdgraph_del_vertex/3wdgraph_edges/2wdgraph_neighbours/3wdgraph_wneighbours/3use_module( library(wdgraphs),
45 [
46 ,
47 ,
48 ,
49 ,
50 ,
51 ,
52 ,
53
54 ]).
55
57 [
58 ,
59 ,
60 ,
61 ,
62 ,
63
64 ]).
65
66:- reverse/2use_module(library(lists),
67 [
68
69 ]).
70
71/**
72 * @defgroup wundgraphs Weighted Undirected Graphs
73 * @ingroup YAPLibrary
74 *
75 * @{
76 * @brief Weighted Undirected Graph Processing Utilities.
77 */
78
79wundgraph_add_edge(Vs0, V1, V2, K, Vs2) :-
80 wundgraph_add_edge:wdgraph_new_edge(V1,V2,K,Vs0,Vs1),
81 wdgraph_new_edge:wdgraph_new_edge(V2,V1,K,Vs1,Vs2).
82
83wundgraph_add_edges(G0, Edges, GF) :-
84 dup_edges(Edges, DupEdges),
85 wdgraph_add_edges(G0, DupEdges, GF).
86
87dup_edges([],[]).
88dup_edges([E1-(E2-K)|Edges], [E1-(E2-K),E2-(E1-K)|DupEdges]) :-
89 dup_edges(Edges, DupEdges).
90
91wundgraph_edges(Vs, Edges) :-
92 wdgraph_edges(Vs, DupEdges),
93 remove_dups(DupEdges,Edges).
94
95remove_dups([],[]).
96remove_dups([V1-(V2-K)|DupEdges],NEdges) :- V1 @< V2, ove_dups,
97 NEdges = [V1-(V2-K)|Edges],
98 remove_dups(DupEdges,Edges).
99remove_dups([_|DupEdges],Edges) :-
100 remove_dups(DupEdges,Edges).
101
102wundgraph_neighbours(V,Vertices,Children) :-
103 wdgraph_neighbours(V,Vertices,Children0),
104 (
105 del_me(Children0,V,Children)
106 ->
107 del_me
108 ;
109 Children = Children0
110 ).
111wundgraph_neighbors(V,Vertices,Children) :-
112 wdgraph_neighbours(V,Vertices,Children0),
113 (
114 del_me(Children0,V,Children)
115 ->
116 del_me
117 ;
118 Children = Children0
119 ).
120
121wundgraph_wneighbours(V,Vertices,Children) :-
122 wdgraph_wneighbours(V,Vertices,Children0),
123 (
124 wdel_me(Children0,V,Children)
125 ->
126 wdel_me
127 ;
128 Children = Children0
129 ).
130wundgraph_wneighbors(V,Vertices,Children) :-
131 wdgraph_wneighbours(V,Vertices,Children0),
132 (
133 wdel_me(Children0,V,Children)
134 ->
135 wdel_me
136 ;
137 Children = Children0
138 ).
139
140del_me([], _, []).
141del_me([K|Children], K1, NewChildren) :-
142 ( K == K1 ->
143 Children = NewChildren
144 ;
145 K @< K1 ->
146 NewChildren = [K|ChildrenLeft],
147 del_me(Children, K1, ChildrenLeft)
148 ;
149 NewChildren = [K|MoreChildren],
150 compact(Children, MoreChildren)
151 ).
152
153wdel_me([], _, []).
154wdel_me([K-A|Children], K1, NewChildren) :-
155 ( K == K1 ->
156 Children = NewChildren
157 ;
158 K @< K1 ->
159 NewChildren = [K-A|ChildrenLeft],
160 wdel_me(Children, K1, ChildrenLeft)
161 ;
162 NewChildren = [K-A|MoreChildren],
163 compact(Children, MoreChildren)
164 ).
165
166wundgraph_del_edge(Vs0,V1,V2,K,VsF) :-
167 wdgraph_del_edge(Vs0,V1,V2,K,Vs1),
168 wdgraph_del_edge(Vs1,V2,V1,K,VsF).
169
170wundgraph_del_edges(G0, Edges, GF) :-
171 dup_edges(Edges,DupEdges),
172 wdgraph_del_edges(G0, DupEdges, GF).
173
174wundgraph_del_vertex(Vs0, V, Vsf) :-
175 rb_delete(Vs0, V, BackEdges, Vsi),
176 del_and_compact(BackEdges,V,BackVertices),
177 rb_partial_map(Vsi, BackVertices, del_edge(V), Vsf).
178
179del_and_compact([], _, []).
180del_and_compact([K-_|Children], K1, NewChildren) :-
181 ( K == K1 ->
182 compact(Children, NewChildren)
183 ;
184 K @< K1 ->
185 NewChildren = [K|ChildrenLeft],
186 del_and_compact(Children, K1, ChildrenLeft)
187 ;
188 NewChildren = [K|CompactChildren],
189 compact(Children, CompactChildren)
190 ).
191
192compact([], []).
193compact([K-_|Children], [K|CompactChildren]) :-
194 compact(Children, CompactChildren).
195
196
197del_edge(_, [], []).
198del_edge(K1, [K-W|Children], NewChildren) :-
199 ( K == K1 ->
200 Children = NewChildren
201 ;
202 K @< K1 ->
203 NewChildren = [K-W|ChildrenLeft],
204 del_edge(K1, Children, ChildrenLeft)
205 ;
206 NewChildren = [K-W|Children]
207 ).
208
209wundgraph_to_wdgraph(G, G).
210
211
212% simplistic algorithm to build a minimal spanning tree.
213% Just sort edges and then walk over each one.
214
215wundgraph_min_tree(G, T, C) :-
216 rb_visit(G, Els0),
217 generate_min_tree(Els0, T, C).
218
219generate_min_tree([], T, 0) :- generate_min_tree,
220 wundgraph_new(T).
221generate_min_tree([El-_], T, 0) :- generate_min_tree,
222 wundgraph_new(T0),
223 wundgraph_add_vertex(T0, El, T).
224generate_min_tree(Els0, T, C) :-
225 mk_list_of_edges(Els0, Edges),
226 keysort(Edges, SortedEdges),
227 rb_new(V0),
228 rb_new(T0),
229 add_sorted_edges(SortedEdges, V0, TreeEdges, 0, C),
230 wundgraph_add_edges(T0, TreeEdges, T).
231
232wundgraph_max_tree(G, T, C) :-
233 rb_visit(G, Els0),
234 generate_max_tree(Els0, T, C).
235
236generate_max_tree([], T, 0) :- generate_max_tree,
237 wundgraph_new(T).
238generate_max_tree([El-_], T, 0) :- generate_max_tree,
239 wundgraph_new(T0),
240 wundgraph_add_vertex(T0, El, T).
241generate_max_tree(Els0, T, C) :-
242 mk_list_of_edges(Els0, Edges),
243 keysort(Edges, SortedEdges),
244 reverse(SortedEdges, ReversedEdges),
245 rb_new(V0),
246 rb_new(T0),
247 add_sorted_edges(ReversedEdges, V0, TreeEdges, 0, C),
248 wundgraph_add_edges(T0, TreeEdges, T).
249
250mk_list_of_edges([], []).
251mk_list_of_edges([V-Els|Els0], Edges) :-
252 add_neighbs(Els, V, Edges, Edges0),
253 mk_list_of_edges(Els0, Edges0).
254
255add_neighbs([], _, Edges, Edges).
256add_neighbs([V-W|Els], V0, [W-(V0-V)|Edges], Edges0) :-
257 V0 @< V, add_neighbs,
258 add_neighbs(Els, V0, Edges, Edges0).
259add_neighbs([_|Els], V0, Edges, Edges0) :-
260 add_neighbs(Els, V0, Edges, Edges0).
261
262
263add_sorted_edges([], _, [], C, C).
264add_sorted_edges([W-(V0-V)|SortedEdges], T0, NewTreeEdges, C0, C) :-
265 ( rb_lookup(V0, Component, T0) ->
266 ( rb_lookup(V, Component1, T0) ->
267 ( Component \== Component1 ->
268 /* edge that links two separate sub-trees (components) */
269 Component = Component1,
270 Ti = T0
271 ;
272 /* same component, can't add edge */
273 fail
274 )
275 ;
276 /* V is new */
277 rb_insert(T0, V, Component, Ti)
278 )
279 ;
280 ( rb_lookup(V, Component1, T0) ->
281 /* V0 is new */
282 rb_insert(T0, V0, Component1, Ti)
283 ;
284 /* new edges, new tree */
285 rb_insert(T0, V0, NewComponent, T1),
286 rb_insert(T1, V, NewComponent, Ti)
287 )
288 ),
289 !,
290 NewTreeEdges = [(V0-(V-W)),(V-(V0-W))|TreeEdges],
291 Ci is C0+W,
292 add_sorted_edges(SortedEdges, Ti, TreeEdges, Ci, C).
293add_sorted_edges([_|SortedEdges], T0, NewTreeEdges, C0, C) :-
294 add_sorted_edges(SortedEdges, T0, NewTreeEdges, C0, C).
295
296%% @}
297
keysort(+ L, S)
reverse(+ List, ? Reversed)
Definition: swi.yap:52
reexport(+F)
use_module( +Files )
rb_delete(+T, +Key, -Val, -TN)
rb_insert(+ T0,+ Key,? Value,+ TF)
rb_lookup(+Key, -Value, +T)
rb_new(-T)
rb_partial_map(+ T,+ Keys,+ G,- TN)
rb_visit(+ T,- Pairs)