35
36:- module(ugraphs,
37 [ add_edges/3, 38 add_vertices/3, 39 complement/2, 40 compose/3, 41 del_edges/3, 42 del_vertices/3, 43 edges/2, 44 neighbors/3, 45 neighbours/3, 46 reachable/3, 47 top_sort/2, 48 top_sort/3, 49 transitive_closure/2, 50 transpose_ugraph/2, 51 vertices/2, 52 vertices_edges_to_ugraph/3, 53 ugraph_union/3, 54 connect_ugraph/3 55 ]). 56
77
78:- autoload(library(lists),[append/3]). 79:- autoload(library(ordsets),
80 [ord_subtract/3,ord_union/3,ord_add_element/3,ord_union/4]). 81
82
130
131
139
140vertices([], []) :- !.
141vertices([Vertex-_|Graph], [Vertex|Vertices]) :-
142 vertices(Graph, Vertices).
143
144
165
166vertices_edges_to_ugraph(Vertices, Edges, Graph) :-
167 sort(Edges, EdgeSet),
168 p_to_s_vertices(EdgeSet, IVertexBag),
169 append(Vertices, IVertexBag, VertexBag),
170 sort(VertexBag, VertexSet),
171 p_to_s_group(VertexSet, EdgeSet, Graph).
172
173
174add_vertices(Graph, Vertices, NewGraph) :-
175 msort(Vertices, V1),
176 add_vertices_to_s_graph(V1, Graph, NewGraph).
177
178add_vertices_to_s_graph(L, [], NL) :-
179 !,
180 add_empty_vertices(L, NL).
181add_vertices_to_s_graph([], L, L) :- !.
182add_vertices_to_s_graph([V1|VL], [V-Edges|G], NGL) :-
183 compare(Res, V1, V),
184 add_vertices_to_s_graph(Res, V1, VL, V, Edges, G, NGL).
185
186add_vertices_to_s_graph(=, _, VL, V, Edges, G, [V-Edges|NGL]) :-
187 add_vertices_to_s_graph(VL, G, NGL).
188add_vertices_to_s_graph(<, V1, VL, V, Edges, G, [V1-[]|NGL]) :-
189 add_vertices_to_s_graph(VL, [V-Edges|G], NGL).
190add_vertices_to_s_graph(>, V1, VL, V, Edges, G, [V-Edges|NGL]) :-
191 add_vertices_to_s_graph([V1|VL], G, NGL).
192
193add_empty_vertices([], []).
194add_empty_vertices([V|G], [V-[]|NG]) :-
195 add_empty_vertices(G, NG).
196
214
215del_vertices(Graph, Vertices, NewGraph) :-
216 sort(Vertices, V1), 217 ( V1 = []
218 -> Graph = NewGraph
219 ; del_vertices(Graph, V1, V1, NewGraph)
220 ).
221
222del_vertices(G, [], V1, NG) :-
223 !,
224 del_remaining_edges_for_vertices(G, V1, NG).
225del_vertices([], _, _, []).
226del_vertices([V-Edges|G], [V0|Vs], V1, NG) :-
227 compare(Res, V, V0),
228 split_on_del_vertices(Res, V,Edges, [V0|Vs], NVs, V1, NG, NGr),
229 del_vertices(G, NVs, V1, NGr).
230
231del_remaining_edges_for_vertices([], _, []).
232del_remaining_edges_for_vertices([V0-Edges|G], V1, [V0-NEdges|NG]) :-
233 ord_subtract(Edges, V1, NEdges),
234 del_remaining_edges_for_vertices(G, V1, NG).
235
236split_on_del_vertices(<, V, Edges, Vs, Vs, V1, [V-NEdges|NG], NG) :-
237 ord_subtract(Edges, V1, NEdges).
238split_on_del_vertices(>, V, Edges, [_|Vs], Vs, V1, [V-NEdges|NG], NG) :-
239 ord_subtract(Edges, V1, NEdges).
240split_on_del_vertices(=, _, _, [_|Vs], Vs, _, NG, NG).
241
242add_edges(Graph, Edges, NewGraph) :-
243 p_to_s_graph(Edges, G1),
244 ugraph_union(Graph, G1, NewGraph).
245
250
251ugraph_union(Set1, [], Set1) :- !.
252ugraph_union([], Set2, Set2) :- !.
253ugraph_union([Head1-E1|Tail1], [Head2-E2|Tail2], Union) :-
254 compare(Order, Head1, Head2),
255 ugraph_union(Order, Head1-E1, Tail1, Head2-E2, Tail2, Union).
256
257ugraph_union(=, Head-E1, Tail1, _-E2, Tail2, [Head-Es|Union]) :-
258 ord_union(E1, E2, Es),
259 ugraph_union(Tail1, Tail2, Union).
260ugraph_union(<, Head1, Tail1, Head2, Tail2, [Head1|Union]) :-
261 ugraph_union(Tail1, [Head2|Tail2], Union).
262ugraph_union(>, Head1, Tail1, Head2, Tail2, [Head2|Union]) :-
263 ugraph_union([Head1|Tail1], Tail2, Union).
264
265del_edges(Graph, Edges, NewGraph) :-
266 p_to_s_graph(Edges, G1),
267 graph_subtract(Graph, G1, NewGraph).
268
272
273graph_subtract(Set1, [], Set1) :- !.
274graph_subtract([], _, []).
275graph_subtract([Head1-E1|Tail1], [Head2-E2|Tail2], Difference) :-
276 compare(Order, Head1, Head2),
277 graph_subtract(Order, Head1-E1, Tail1, Head2-E2, Tail2, Difference).
278
279graph_subtract(=, H-E1, Tail1, _-E2, Tail2, [H-E|Difference]) :-
280 ord_subtract(E1,E2,E),
281 graph_subtract(Tail1, Tail2, Difference).
282graph_subtract(<, Head1, Tail1, Head2, Tail2, [Head1|Difference]) :-
283 graph_subtract(Tail1, [Head2|Tail2], Difference).
284graph_subtract(>, Head1, Tail1, _, Tail2, Difference) :-
285 graph_subtract([Head1|Tail1], Tail2, Difference).
286
291
292edges(Graph, Edges) :-
293 s_to_p_graph(Graph, Edges).
294
295p_to_s_graph(P_Graph, S_Graph) :-
296 sort(P_Graph, EdgeSet),
297 p_to_s_vertices(EdgeSet, VertexBag),
298 sort(VertexBag, VertexSet),
299 p_to_s_group(VertexSet, EdgeSet, S_Graph).
300
301
302p_to_s_vertices([], []).
303p_to_s_vertices([A-Z|Edges], [A,Z|Vertices]) :-
304 p_to_s_vertices(Edges, Vertices).
305
306
307p_to_s_group([], _, []).
308p_to_s_group([Vertex|Vertices], EdgeSet, [Vertex-Neibs|G]) :-
309 p_to_s_group(EdgeSet, Vertex, Neibs, RestEdges),
310 p_to_s_group(Vertices, RestEdges, G).
311
312
313p_to_s_group([V1-X|Edges], V2, [X|Neibs], RestEdges) :- V1 == V2,
314 !,
315 p_to_s_group(Edges, V2, Neibs, RestEdges).
316p_to_s_group(Edges, _, [], Edges).
317
318
319
320s_to_p_graph([], []) :- !.
321s_to_p_graph([Vertex-Neibs|G], P_Graph) :-
322 s_to_p_graph(Neibs, Vertex, P_Graph, Rest_P_Graph),
323 s_to_p_graph(G, Rest_P_Graph).
324
325
326s_to_p_graph([], _, P_Graph, P_Graph) :- !.
327s_to_p_graph([Neib|Neibs], Vertex, [Vertex-Neib|P], Rest_P) :-
328 s_to_p_graph(Neibs, Vertex, P, Rest_P).
329
330
331transitive_closure(Graph, Closure) :-
332 warshall(Graph, Graph, Closure).
333
334warshall([], Closure, Closure) :- !.
335warshall([V-_|G], E, Closure) :-
336 memberchk(V-Y, E), 337 warshall(E, V, Y, NewE),
338 warshall(G, NewE, Closure).
339
340
341warshall([X-Neibs|G], V, Y, [X-NewNeibs|NewG]) :-
342 memberchk(V, Neibs),
343 !,
344 ord_union(Neibs, Y, NewNeibs),
345 warshall(G, V, Y, NewG).
346warshall([X-Neibs|G], V, Y, [X-Neibs|NewG]) :-
347 !,
348 warshall(G, V, Y, NewG).
349warshall([], _, _, []).
350
368
369transpose_ugraph(Graph, NewGraph) :-
370 edges(Graph, Edges),
371 vertices(Graph, Vertices),
372 flip_edges(Edges, TransposedEdges),
373 vertices_edges_to_ugraph(Vertices, TransposedEdges, NewGraph).
374
375flip_edges([], []).
376flip_edges([Key-Val|Pairs], [Val-Key|Flipped]) :-
377 flip_edges(Pairs, Flipped).
378
379
384
385compose(G1, G2, Composition) :-
386 vertices(G1, V1),
387 vertices(G2, V2),
388 ord_union(V1, V2, V),
389 compose(V, G1, G2, Composition).
390
391
392compose([], _, _, []) :- !.
393compose([Vertex|Vertices], [Vertex-Neibs|G1], G2,
394 [Vertex-Comp|Composition]) :-
395 !,
396 compose1(Neibs, G2, [], Comp),
397 compose(Vertices, G1, G2, Composition).
398compose([Vertex|Vertices], G1, G2, [Vertex-[]|Composition]) :-
399 compose(Vertices, G1, G2, Composition).
400
401
402compose1([V1|Vs1], [V2-N2|G2], SoFar, Comp) :-
403 compare(Rel, V1, V2),
404 !,
405 compose1(Rel, V1, Vs1, V2, N2, G2, SoFar, Comp).
406compose1(_, _, Comp, Comp).
407
408
409compose1(<, _, Vs1, V2, N2, G2, SoFar, Comp) :-
410 !,
411 compose1(Vs1, [V2-N2|G2], SoFar, Comp).
412compose1(>, V1, Vs1, _, _, G2, SoFar, Comp) :-
413 !,
414 compose1([V1|Vs1], G2, SoFar, Comp).
415compose1(=, V1, Vs1, V1, N2, G2, SoFar, Comp) :-
416 ord_union(N2, SoFar, Next),
417 compose1(Vs1, G2, Next, Comp).
418
434
435top_sort(Graph, Sorted) :-
436 vertices_and_zeros(Graph, Vertices, Counts0),
437 count_edges(Graph, Vertices, Counts0, Counts1),
438 select_zeros(Counts1, Vertices, Zeros),
439 top_sort(Zeros, Sorted, Graph, Vertices, Counts1).
440
441top_sort(Graph, Sorted0, Sorted) :-
442 vertices_and_zeros(Graph, Vertices, Counts0),
443 count_edges(Graph, Vertices, Counts0, Counts1),
444 select_zeros(Counts1, Vertices, Zeros),
445 top_sort(Zeros, Sorted, Sorted0, Graph, Vertices, Counts1).
446
447
448vertices_and_zeros([], [], []) :- !.
449vertices_and_zeros([Vertex-_|Graph], [Vertex|Vertices], [0|Zeros]) :-
450 vertices_and_zeros(Graph, Vertices, Zeros).
451
452
453count_edges([], _, Counts, Counts) :- !.
454count_edges([_-Neibs|Graph], Vertices, Counts0, Counts2) :-
455 incr_list(Neibs, Vertices, Counts0, Counts1),
456 count_edges(Graph, Vertices, Counts1, Counts2).
457
458
459incr_list([], _, Counts, Counts) :- !.
460incr_list([V1|Neibs], [V2|Vertices], [M|Counts0], [N|Counts1]) :-
461 V1 == V2,
462 !,
463 N is M+1,
464 incr_list(Neibs, Vertices, Counts0, Counts1).
465incr_list(Neibs, [_|Vertices], [N|Counts0], [N|Counts1]) :-
466 incr_list(Neibs, Vertices, Counts0, Counts1).
467
468
469select_zeros([], [], []) :- !.
470select_zeros([0|Counts], [Vertex|Vertices], [Vertex|Zeros]) :-
471 !,
472 select_zeros(Counts, Vertices, Zeros).
473select_zeros([_|Counts], [_|Vertices], Zeros) :-
474 select_zeros(Counts, Vertices, Zeros).
475
476
477
478top_sort([], [], Graph, _, Counts) :-
479 !,
480 vertices_and_zeros(Graph, _, Counts).
481top_sort([Zero|Zeros], [Zero|Sorted], Graph, Vertices, Counts1) :-
482 graph_memberchk(Zero-Neibs, Graph),
483 decr_list(Neibs, Vertices, Counts1, Counts2, Zeros, NewZeros),
484 top_sort(NewZeros, Sorted, Graph, Vertices, Counts2).
485
486top_sort([], Sorted0, Sorted0, Graph, _, Counts) :-
487 !,
488 vertices_and_zeros(Graph, _, Counts).
489top_sort([Zero|Zeros], [Zero|Sorted], Sorted0, Graph, Vertices, Counts1) :-
490 graph_memberchk(Zero-Neibs, Graph),
491 decr_list(Neibs, Vertices, Counts1, Counts2, Zeros, NewZeros),
492 top_sort(NewZeros, Sorted, Sorted0, Graph, Vertices, Counts2).
493
494graph_memberchk(Element1-Edges, [Element2-Edges2|_]) :-
495 Element1 == Element2,
496 !,
497 Edges = Edges2.
498graph_memberchk(Element, [_|Rest]) :-
499 graph_memberchk(Element, Rest).
500
501
502decr_list([], _, Counts, Counts, Zeros, Zeros) :- !.
503decr_list([V1|Neibs], [V2|Vertices], [1|Counts1], [0|Counts2], Zi, Zo) :-
504 V1 == V2,
505 !,
506 decr_list(Neibs, Vertices, Counts1, Counts2, [V2|Zi], Zo).
507decr_list([V1|Neibs], [V2|Vertices], [N|Counts1], [M|Counts2], Zi, Zo) :-
508 V1 == V2,
509 !,
510 M is N-1,
511 decr_list(Neibs, Vertices, Counts1, Counts2, Zi, Zo).
512decr_list(Neibs, [_|Vertices], [N|Counts1], [N|Counts2], Zi, Zo) :-
513 decr_list(Neibs, Vertices, Counts1, Counts2, Zi, Zo).
514
515
520
521neighbors(Vertex, Graph, Neig) :-
522 neighbours(Vertex, Graph, Neig).
523
524neighbours(V,[V0-Neig|_],Neig) :-
525 V == V0,
526 !.
527neighbours(V,[_|G],Neig) :-
528 neighbours(V,G,Neig).
529
530
549
550connect_ugraph([], 0, []) :- !.
551connect_ugraph(Graph, Start, [Start-Vertices|Graph]) :-
552 vertices(Graph, Vertices),
553 Vertices = [First|_],
554 before(First, Start).
555
562
563before(X, _) :-
564 var(X),
565 !,
566 instantiation_error(X).
567before(Number, Start) :-
568 number(Number),
569 !,
570 Start is Number - 1.
571before(_, 0).
572
573
580
581complement(G, NG) :-
582 vertices(G,Vs),
583 complement(G,Vs,NG).
584
585complement([], _, []).
586complement([V-Ns|G], Vs, [V-INs|NG]) :-
587 ord_add_element(Ns,V,Ns1),
588 ord_subtract(Vs,Ns1,INs),
589 complement(G, Vs, NG).
590
595
596reachable(N, G, Rs) :-
597 reachable([N], G, [N], Rs).
598
599reachable([], _, Rs, Rs).
600reachable([N|Ns], G, Rs0, RsF) :-
601 neighbours(N, G, Nei),
602 ord_union(Rs0, Nei, Rs1, D),
603 append(Ns, D, Nsi),
604 reachable(Nsi, G, Rs1, RsF)