36
37:- module(ugraphs,
38 [ add_edges/3, 39 add_vertices/3, 40 complement/2, 41 compose/3, 42 del_edges/3, 43 del_vertices/3, 44 edges/2, 45 neighbors/3, 46 neighbours/3, 47 reachable/3, 48 top_sort/2, 49 top_sort/3, 50 transitive_closure/2, 51 transpose_ugraph/2, 52 vertices/2, 53 vertices_edges_to_ugraph/3, 54 ugraph_union/3, 55 connect_ugraph/3 56 ]). 57
78
79:- autoload(library(lists),[append/3]). 80:- autoload(library(ordsets),
81 [ord_subtract/3,ord_union/3,ord_add_element/3,ord_union/4]). 82
89
90vertices([], []) :- !.
91vertices([Vertex-_|Graph], [Vertex|Vertices]) :-
92 vertices(Graph, Vertices).
93
94
115
116vertices_edges_to_ugraph(Vertices, Edges, Graph) :-
117 sort(Edges, EdgeSet),
118 p_to_s_vertices(EdgeSet, IVertexBag),
119 append(Vertices, IVertexBag, VertexBag),
120 sort(VertexBag, VertexSet),
121 p_to_s_group(VertexSet, EdgeSet, Graph).
122
123
133
134add_vertices(Graph, Vertices, NewGraph) :-
135 msort(Vertices, V1),
136 add_vertices_to_s_graph(V1, Graph, NewGraph).
137
138add_vertices_to_s_graph(L, [], NL) :-
139 !,
140 add_empty_vertices(L, NL).
141add_vertices_to_s_graph([], L, L) :- !.
142add_vertices_to_s_graph([V1|VL], [V-Edges|G], NGL) :-
143 compare(Res, V1, V),
144 add_vertices_to_s_graph(Res, V1, VL, V, Edges, G, NGL).
145
146add_vertices_to_s_graph(=, _, VL, V, Edges, G, [V-Edges|NGL]) :-
147 add_vertices_to_s_graph(VL, G, NGL).
148add_vertices_to_s_graph(<, V1, VL, V, Edges, G, [V1-[]|NGL]) :-
149 add_vertices_to_s_graph(VL, [V-Edges|G], NGL).
150add_vertices_to_s_graph(>, V1, VL, V, Edges, G, [V-Edges|NGL]) :-
151 add_vertices_to_s_graph([V1|VL], G, NGL).
152
153add_empty_vertices([], []).
154add_empty_vertices([V|G], [V-[]|NG]) :-
155 add_empty_vertices(G, NG).
156
174
175del_vertices(Graph, Vertices, NewGraph) :-
176 sort(Vertices, V1), 177 ( V1 = []
178 -> Graph = NewGraph
179 ; del_vertices(Graph, V1, V1, NewGraph)
180 ).
181
182del_vertices(G, [], V1, NG) :-
183 !,
184 del_remaining_edges_for_vertices(G, V1, NG).
185del_vertices([], _, _, []).
186del_vertices([V-Edges|G], [V0|Vs], V1, NG) :-
187 compare(Res, V, V0),
188 split_on_del_vertices(Res, V,Edges, [V0|Vs], NVs, V1, NG, NGr),
189 del_vertices(G, NVs, V1, NGr).
190
191del_remaining_edges_for_vertices([], _, []).
192del_remaining_edges_for_vertices([V0-Edges|G], V1, [V0-NEdges|NG]) :-
193 ord_subtract(Edges, V1, NEdges),
194 del_remaining_edges_for_vertices(G, V1, NG).
195
196split_on_del_vertices(<, V, Edges, Vs, Vs, V1, [V-NEdges|NG], NG) :-
197 ord_subtract(Edges, V1, NEdges).
198split_on_del_vertices(>, V, Edges, [_|Vs], Vs, V1, [V-NEdges|NG], NG) :-
199 ord_subtract(Edges, V1, NEdges).
200split_on_del_vertices(=, _, _, [_|Vs], Vs, _, NG, NG).
201
215
216add_edges(Graph, Edges, NewGraph) :-
217 p_to_s_graph(Edges, G1),
218 ugraph_union(Graph, G1, NewGraph).
219
228
229ugraph_union(Set1, [], Set1) :- !.
230ugraph_union([], Set2, Set2) :- !.
231ugraph_union([Head1-E1|Tail1], [Head2-E2|Tail2], Union) :-
232 compare(Order, Head1, Head2),
233 ugraph_union(Order, Head1-E1, Tail1, Head2-E2, Tail2, Union).
234
235ugraph_union(=, Head-E1, Tail1, _-E2, Tail2, [Head-Es|Union]) :-
236 ord_union(E1, E2, Es),
237 ugraph_union(Tail1, Tail2, Union).
238ugraph_union(<, Head1, Tail1, Head2, Tail2, [Head1|Union]) :-
239 ugraph_union(Tail1, [Head2|Tail2], Union).
240ugraph_union(>, Head1, Tail1, Head2, Tail2, [Head2|Union]) :-
241 ugraph_union([Head1|Tail1], Tail2, Union).
242
254
255del_edges(Graph, Edges, NewGraph) :-
256 p_to_s_graph(Edges, G1),
257 graph_subtract(Graph, G1, NewGraph).
258
262
263graph_subtract(Set1, [], Set1) :- !.
264graph_subtract([], _, []).
265graph_subtract([Head1-E1|Tail1], [Head2-E2|Tail2], Difference) :-
266 compare(Order, Head1, Head2),
267 graph_subtract(Order, Head1-E1, Tail1, Head2-E2, Tail2, Difference).
268
269graph_subtract(=, H-E1, Tail1, _-E2, Tail2, [H-E|Difference]) :-
270 ord_subtract(E1,E2,E),
271 graph_subtract(Tail1, Tail2, Difference).
272graph_subtract(<, Head1, Tail1, Head2, Tail2, [Head1|Difference]) :-
273 graph_subtract(Tail1, [Head2|Tail2], Difference).
274graph_subtract(>, Head1, Tail1, _, Tail2, Difference) :-
275 graph_subtract([Head1|Tail1], Tail2, Difference).
276
283
284edges(Graph, Edges) :-
285 s_to_p_graph(Graph, Edges).
286
287p_to_s_graph(P_Graph, S_Graph) :-
288 sort(P_Graph, EdgeSet),
289 p_to_s_vertices(EdgeSet, VertexBag),
290 sort(VertexBag, VertexSet),
291 p_to_s_group(VertexSet, EdgeSet, S_Graph).
292
293
294p_to_s_vertices([], []).
295p_to_s_vertices([A-Z|Edges], [A,Z|Vertices]) :-
296 p_to_s_vertices(Edges, Vertices).
297
298
299p_to_s_group([], _, []).
300p_to_s_group([Vertex|Vertices], EdgeSet, [Vertex-Neibs|G]) :-
301 p_to_s_group(EdgeSet, Vertex, Neibs, RestEdges),
302 p_to_s_group(Vertices, RestEdges, G).
303
304
305p_to_s_group([V1-X|Edges], V2, [X|Neibs], RestEdges) :- V1 == V2,
306 !,
307 p_to_s_group(Edges, V2, Neibs, RestEdges).
308p_to_s_group(Edges, _, [], Edges).
309
310
311
312s_to_p_graph([], []) :- !.
313s_to_p_graph([Vertex-Neibs|G], P_Graph) :-
314 s_to_p_graph(Neibs, Vertex, P_Graph, Rest_P_Graph),
315 s_to_p_graph(G, Rest_P_Graph).
316
317
318s_to_p_graph([], _, P_Graph, P_Graph) :- !.
319s_to_p_graph([Neib|Neibs], Vertex, [Vertex-Neib|P], Rest_P) :-
320 s_to_p_graph(Neibs, Vertex, P, Rest_P).
321
331
332transitive_closure(Graph, Closure) :-
333 warshall(Graph, Graph, Closure).
334
335warshall([], Closure, Closure) :- !.
336warshall([V-_|G], E, Closure) :-
337 memberchk(V-Y, E), 338 warshall(E, V, Y, NewE),
339 warshall(G, NewE, Closure).
340
341
342warshall([X-Neibs|G], V, Y, [X-NewNeibs|NewG]) :-
343 memberchk(V, Neibs),
344 !,
345 ord_union(Neibs, Y, NewNeibs),
346 warshall(G, V, Y, NewG).
347warshall([X-Neibs|G], V, Y, [X-Neibs|NewG]) :-
348 !,
349 warshall(G, V, Y, NewG).
350warshall([], _, _, []).
351
369
370transpose_ugraph(Graph, NewGraph) :-
371 edges(Graph, Edges),
372 vertices(Graph, Vertices),
373 flip_edges(Edges, TransposedEdges),
374 vertices_edges_to_ugraph(Vertices, TransposedEdges, NewGraph).
375
376flip_edges([], []).
377flip_edges([Key-Val|Pairs], [Val-Key|Flipped]) :-
378 flip_edges(Pairs, Flipped).
379
387
388compose(G1, G2, Composition) :-
389 vertices(G1, V1),
390 vertices(G2, V2),
391 ord_union(V1, V2, V),
392 compose(V, G1, G2, Composition).
393
394compose([], _, _, []) :- !.
395compose([Vertex|Vertices], [Vertex-Neibs|G1], G2,
396 [Vertex-Comp|Composition]) :-
397 !,
398 compose1(Neibs, G2, [], Comp),
399 compose(Vertices, G1, G2, Composition).
400compose([Vertex|Vertices], G1, G2, [Vertex-[]|Composition]) :-
401 compose(Vertices, G1, G2, Composition).
402
403
404compose1([V1|Vs1], [V2-N2|G2], SoFar, Comp) :-
405 compare(Rel, V1, V2),
406 !,
407 compose1(Rel, V1, Vs1, V2, N2, G2, SoFar, Comp).
408compose1(_, _, Comp, Comp).
409
410
411compose1(<, _, Vs1, V2, N2, G2, SoFar, Comp) :-
412 !,
413 compose1(Vs1, [V2-N2|G2], SoFar, Comp).
414compose1(>, V1, Vs1, _, _, G2, SoFar, Comp) :-
415 !,
416 compose1([V1|Vs1], G2, SoFar, Comp).
417compose1(=, V1, Vs1, V1, N2, G2, SoFar, Comp) :-
418 ord_union(N2, SoFar, Next),
419 compose1(Vs1, G2, Next, Comp).
420
436
437top_sort(Graph, Sorted) :-
438 vertices_and_zeros(Graph, Vertices, Counts0),
439 count_edges(Graph, Vertices, Counts0, Counts1),
440 select_zeros(Counts1, Vertices, Zeros),
441 top_sort(Zeros, Sorted, Graph, Vertices, Counts1).
442
443top_sort(Graph, Sorted0, Sorted) :-
444 vertices_and_zeros(Graph, Vertices, Counts0),
445 count_edges(Graph, Vertices, Counts0, Counts1),
446 select_zeros(Counts1, Vertices, Zeros),
447 top_sort(Zeros, Sorted, Sorted0, Graph, Vertices, Counts1).
448
449
450vertices_and_zeros([], [], []) :- !.
451vertices_and_zeros([Vertex-_|Graph], [Vertex|Vertices], [0|Zeros]) :-
452 vertices_and_zeros(Graph, Vertices, Zeros).
453
454
455count_edges([], _, Counts, Counts) :- !.
456count_edges([_-Neibs|Graph], Vertices, Counts0, Counts2) :-
457 incr_list(Neibs, Vertices, Counts0, Counts1),
458 count_edges(Graph, Vertices, Counts1, Counts2).
459
460
461incr_list([], _, Counts, Counts) :- !.
462incr_list([V1|Neibs], [V2|Vertices], [M|Counts0], [N|Counts1]) :-
463 V1 == V2,
464 !,
465 N is M+1,
466 incr_list(Neibs, Vertices, Counts0, Counts1).
467incr_list(Neibs, [_|Vertices], [N|Counts0], [N|Counts1]) :-
468 incr_list(Neibs, Vertices, Counts0, Counts1).
469
470
471select_zeros([], [], []) :- !.
472select_zeros([0|Counts], [Vertex|Vertices], [Vertex|Zeros]) :-
473 !,
474 select_zeros(Counts, Vertices, Zeros).
475select_zeros([_|Counts], [_|Vertices], Zeros) :-
476 select_zeros(Counts, Vertices, Zeros).
477
478
479
480top_sort([], [], Graph, _, Counts) :-
481 !,
482 vertices_and_zeros(Graph, _, Counts).
483top_sort([Zero|Zeros], [Zero|Sorted], Graph, Vertices, Counts1) :-
484 graph_memberchk(Zero-Neibs, Graph),
485 decr_list(Neibs, Vertices, Counts1, Counts2, Zeros, NewZeros),
486 top_sort(NewZeros, Sorted, Graph, Vertices, Counts2).
487
488top_sort([], Sorted0, Sorted0, Graph, _, Counts) :-
489 !,
490 vertices_and_zeros(Graph, _, Counts).
491top_sort([Zero|Zeros], [Zero|Sorted], Sorted0, Graph, Vertices, Counts1) :-
492 graph_memberchk(Zero-Neibs, Graph),
493 decr_list(Neibs, Vertices, Counts1, Counts2, Zeros, NewZeros),
494 top_sort(NewZeros, Sorted, Sorted0, Graph, Vertices, Counts2).
495
496graph_memberchk(Element1-Edges, [Element2-Edges2|_]) :-
497 Element1 == Element2,
498 !,
499 Edges = Edges2.
500graph_memberchk(Element, [_|Rest]) :-
501 graph_memberchk(Element, Rest).
502
503
504decr_list([], _, Counts, Counts, Zeros, Zeros) :- !.
505decr_list([V1|Neibs], [V2|Vertices], [1|Counts1], [0|Counts2], Zi, Zo) :-
506 V1 == V2,
507 !,
508 decr_list(Neibs, Vertices, Counts1, Counts2, [V2|Zi], Zo).
509decr_list([V1|Neibs], [V2|Vertices], [N|Counts1], [M|Counts2], Zi, Zo) :-
510 V1 == V2,
511 !,
512 M is N-1,
513 decr_list(Neibs, Vertices, Counts1, Counts2, Zi, Zo).
514decr_list(Neibs, [_|Vertices], [N|Counts1], [N|Counts2], Zi, Zo) :-
515 decr_list(Neibs, Vertices, Counts1, Counts2, Zi, Zo).
516
517
529
530neighbors(Vertex, Graph, Neig) :-
531 neighbours(Vertex, Graph, Neig).
532
533neighbours(V,[V0-Neig|_],Neig) :-
534 V == V0,
535 !.
536neighbours(V,[_|G],Neig) :-
537 neighbours(V,G,Neig).
538
539
558
559connect_ugraph([], 0, []) :- !.
560connect_ugraph(Graph, Start, [Start-Vertices|Graph]) :-
561 vertices(Graph, Vertices),
562 Vertices = [First|_],
563 before(First, Start).
564
571
572before(X, _) :-
573 var(X),
574 !,
575 instantiation_error(X).
576before(Number, Start) :-
577 number(Number),
578 !,
579 Start is Number - 1.
580before(_, 0).
581
582
598
599complement(G, NG) :-
600 vertices(G,Vs),
601 complement(G,Vs,NG).
602
603complement([], _, []).
604complement([V-Ns|G], Vs, [V-INs|NG]) :-
605 ord_add_element(Ns,V,Ns1),
606 ord_subtract(Vs,Ns1,INs),
607 complement(G, Vs, NG).
608
616
617reachable(N, G, Rs) :-
618 reachable([N], G, [N], Rs).
619
620reachable([], _, Rs, Rs).
621reachable([N|Ns], G, Rs0, RsF) :-
622 neighbours(N, G, Nei),
623 ord_union(Rs0, Nei, Rs1, D),
624 append(Ns, D, Nsi),
625 reachable(Nsi, G, Rs1, RsF)