1:- module(udgpc, [udg_path_count/5, udg_path_count/4]). 2 3:- use_module(pac(basic)). 4:- use_module(zdd('zdd-array')). 5:- use_module(zdd(zdd)). 6:- use_module(pac(op)). 7 8:- set_prolog_flag(toplevel_print_anon, false).
17% ?- udg_path_count(a, b, [a-b], C). 18% ?- udg_path_count(a, b, [a-b,b-c,a-c], C). 19% ?- udg_path_count(a, d, [a-b,c-d], C). 20% ?- W=3, H=3, rect_grid_graph(W, H, _L), 21% time(udg_path_count(p(0,0), p(W, H), _L, C)). 22% ?- W=7, H=7, rect_grid_graph(W, H, _L), 23% time(udg_path_count(p(0,0), p(W, H), _L, C)). 24% ?- _W=3, _H=3, rect_grid_graph(_W, _H, _L), 25% remove_links(_L, [p(1,1),p(2,2)], _L0), 26% udg_path_count(p(0,0), p(_W, _H), _L0, C). 27 28udg_path_count(A, B, L, C, S):- 29 links_to_mate(A, B, L, X, S), 30 card(X, C, S).
udg_path_count(A, B, Ls, C, S)
,
preparing S by fetch_state(S)
to use this udg_path_count/4
as a zdd command.37udg_path_count(A, B, L, C):- fetch_state(S), 38 udg_path_count(A, B, L, C, S). 39 40% ?- list_vector([1,2,3], V), writeln(V). 41list_vector(L, V):- V =.. [#|L].
47% ?- compare_minimax(z,a,C,z,a). 48compare_minimax(_, _, =, X, X):-!. 49compare_minimax(Min, Max, <, Min, Max):-!. 50compare_minimax(Min, Max, >, Max, Min):-!. 51compare_minimax(Min, _, <, Min, _):-!. 52compare_minimax(Min, _, >, _, Min):-!. 53compare_minimax(_, Max, >, Max, _):-!. 54compare_minimax(_, Max, <, _, Max):-!. 55compare_minimax(_, _, C, X, Y):- compare(C, X, Y). 56 57% 58lte_minimax(A, B, X, Y):- compare_minimax(A, B, C, X, Y), C == (<).
compare_minimax(Min, Max)
.63% ?- sort_minimax(z, a, [a, b, c, z], S). 64% ?- sort_minimax(z, a, [a, c, b, z], S). 65sort_minimax(Min, Max, X, Y):- predsort(compare_minimax(Min, Max), X, Y).
compare_minimax(Min, Max)
.70% ?- keysort_minimax(a, b, [b-[u,v], a-[x, y]], S). 71%@ S = [a-[x, y], b-[u, v]]. 72keysort_minimax(Min, Max, X, Y):- 73 predsort(keycompare_minimax(Min, Max), X, Y). 74 75% ?- predsort(keycompare_minimax(z, a), [a-[], z-[]], S). 76keycompare_minimax(Min, Max, C, X-_, Y-_):- 77 compare_minimax(Min, Max, C, X, Y).
compare_minimax(Min, Max)
above.
85% ?- links_to_udg(a,b,[a-b], U).
86% ?- links_to_udg(a,b,[], U).
87% ?- links_to_udg(a,c,[a-b, b-c], U).
88% ?- links_to_udg(a,c,[a-b, b-c, a-c], U, V).
99links_to_udg(Min, Max, Ls, F, H):-
100 findall(N, ( member(L, Ls), ( L = N-_; L = _-N)), Nodes),
101 sort_minimax(Min, Max,[Min, Max|Nodes], AllNodes),
102 normalize_links(Min, Max, Ls, Ls0),
103 findall(Y-S, ( member(Y, AllNodes),
104 findall(Z, ( member(M, Ls0),
105 ( M = Z-Y; M = Y-Z)
106 ),
107 S)
108 ),
109 F0),
110 findall(Y-U, ( member(Y, AllNodes),
111 findall(W, member(Y-W, Ls0), U)
112 ),
113 H0),
114 sort_udg(Min, Max, F0, F1),
115 number_nodes_graph(AllNodes, F1, F2),
116 maplist(pick_frontier, F2, F3),
117 list_vector(F3, F),
118 sort_udg(Min, Max, H0, H1),
119 number_nodes_graph(AllNodes, H1, H).
125% ?- number_nodes_graph([a,b,c], [a-[b],b-[a,b]], R). 126number_nodes_graph(Ns, X, Y):- 127 length(Ns, N), 128 numlist(1, N, L), 129 zip(Ns, L, Assoc), 130 subst_graph(X, Assoc, Y).
135subst_graph([],_,[]). 136subst_graph([A-S|L], Assoc, [A0-S0|L0]):- 137 memberchk(A-A0, Assoc), 138 subst_list(Assoc, S, S0), 139 subst_graph(L, Assoc, L0). 140% 141subst_list(_, [], []):-!. 142subst_list(As, [X|Y], [X0|Y0]):- 143 memberchk(X-X0, As), 144 subst_list(As, Y, Y0). 145 146% normalize_links(+Min, +Max, +Links, -L) is det. 147% Swap all liks a-b in Links to b-a if b < a in 148% the sense of compare_minimax(Min, Max). 149 150% ?- normalize_links(b, a,[a-b], L). 151% ?- normalize_links(b, a,[a-b, b-a], L). 152% ?- normalize_links(b, a,[a-b, b-a, d-c], L). 153% ?- normalize_links(a, c,[a-b, b-c, a-c], L). 154% ?- normalize_links(c, a,[a-b, b-c, a-c], L). 155normalize_links(Min, Max, L, M):- 156 maplist(normal_link(Min, Max), L, M0), 157 sort(M0, M). 158% 159normal_link(Min, Max, A-B, B-A):- lte_minimax(Min, Max, B, A), !. 160normal_link(_, _, X, X).
compare_minimax(Min, Max)
is used as he comparison predicate.167% ?- sort_udg(z, a, [a-[z,b], b-[a,z], z-[]], X). 168sort_udg(Min, Max, X, Y):- 169 predsort(keycompare_minimax(Min, Max), X, X0), 170 maplist(sort_udg_successors(Min, Max), X0, Y). 171 172% ?- sort_udg_successors(z, a, x-[a, z, a, z, b], R). 173sort_udg_successors(Min, Max, X-A, X-B):- sort_minimax(Min, Max, A, B). 174 175% reverse successors. 176reverse_successors(X-A, X-B):- reverse(A, B). 177 178 /******************* 179 * Tiny helpers * 180 *******************/ 181 182% ?- arrow_symbol(_->_, F). 183% ?- arrow_symbol(a->b, F, X, Y). 184arrow_symbol( _ -> _). 185% 186arrow_symbol(A, A0):- functor(A, A0, 2). 187arrow_symbol(A, A0, A1, A2):- functor(A, A0, 2), 188 arg(1, A, A1), 189 arg(2, A, A2). 190% 191mate_less_than(_ - A, B -_):- A @< B. 192 193% One of the most basic helpers. 194composable_pairs(A-B, A-C, B, C). 195composable_pairs(A-B, C-A, B, C). 196composable_pairs(B-A, A-C, B, C). 197composable_pairs(B-A, C-A, B, C). 198% 199normal_pair(A-B, U-V):-!, ( B @< A -> U=B, V=A; U=A, V=B ). 200normal_pair(A->B, U->V):- ( B @< A -> U=B, V=A; U=A, V=B ). 201 202 203 /**************************************************** 204 * replace_end/bypass: Most basic operations. * 205 ****************************************************/
?- zdd X<< {[c-d]}, subst_end([a->c], c, a, X, Y)
, psa(X)
, psa(Y)
.
214subst_end(_, _, _, X, 0, _):- X<2, !. 215subst_end(Es, A, P, X, Y, S):- % replace A with P 216 cofact(X, t(U, L, R), S), 217 arrow_symbol(U, U0,Ul,Ur), 218 ( U0 = (->) -> Y = 0 219 ; subst_end(Es, A, P, L, L0, S), 220 ( Ur = A -> 221 normal_pair(Ul-P, V), 222 zdd_ord_insert([V|Es], R, R0, S) 223 ; Ul = A -> 224 normal_pair(Ur-P, V), 225 zdd_ord_insert([V|Es], R, R0, S) 226 ; subst_end(Es, A, P, R, R1, S), 227 zdd_insert(U, R1, R0, S) 228 ), 229 zdd_join(L0, R0, Y, S) 230 ).
236pick_frontier(R-L, F):- pick_frontier(L, R, F). 237% 238pick_frontier([], _, 0). 239pick_frontier([I|Is], R, F):- 240 ( I @< R -> F=I 241 ; pick_frontier(Is, R, F) 242 ). 243 244% ?- links_to_mate(a, g, [a-b, b-c, c-d, d-e, e-f, f-a, 245% f-c, d-g, g-h, h-e], X, S), 246% psa(X, S), card(X, C, S). 247 248% ?- links_to_mate(a, e, [a-b, b-c, c-d, d-e, e-f, f-g, g-h, h-a, 249% i-b, i-h, i-d, i-f], X, S), 250% psa(X, S), card(X, C, S). 251 252links_to_mate(A, B, Links, X, S):-links_to_mate(A, B, Links, X, [], S).
259links_to_mate(A, B, Links, X, Ctrl, S):-
260 links_to_udg(A, B, Links, F, H),
261 maplist(reverse_successors, H, H1),
262 reverse(H1, Dg),
263 fetch_state(S),
264 udg_to_mate(Ctrl, F, Dg, 1, X0, S),
265 functor(F, _, Max),
266 prune_final(Max, X0, X, S).
273udg_to_mate(_, _, [], X, X, _):-!. 274udg_to_mate(Ctrl, F, [N-Ps|UDG], X, Y, S):- 275 add_node(N, Ps, X, X0, S), 276 ctrl_gc(Ctrl, N, X0, X1, S), 277 functor(F, _, Max), 278 prune_mates(N, F-Max, X1, X2, S), 279 udg_to_mate(Ctrl, F, UDG, X2, Y, S).
285ctrl_gc(Ctrl, P, X, Y, S):-!, 286 ( memberchk(gc(K), Ctrl) -> 287 GC = gc(K) 288 ; GC = nogc 289 ), 290 gc(GC, P, X, Y, S). 291% 292gc(gc(each), P, X, Y, S):-!, 293 format("GC at ~w \n", [P]), 294 zdd_slim(X, Y, S), 295 garbage_collect. 296gc(gc(K), P, X, Y, S):- K>0, !, 297 ( P//K =:= 0 -> 298 format("GC at ~w \n", [P]), 299 zdd_slim(X, Y, S), 300 garbage_collect 301 ; Y = X 302 ). 303gc(_, _, X, X, _). % no gc, otherwise
310% ?- zdd add_node(a, [], 1, X), psa(X). 311% ?- zdd add_node(b, [], 1, X), add_node(a, [b], X, Y), psa(Y). 312% ?- zdd add_node(b, [], 1, X), add_node(a, [b], X, Y), 313% add_node(c, [a,b], Y, Z), psa(Z). 314 315add_node(N, Ps, X, Y, S):- % psa(X, S), 316 zdd_insert(N-N, X, X1, S), % add node N first. 317 add_links(Ps, N, X1, Y, S). 318 319% 320add_links([], _, X, X, _):-!. 321add_links([P|Ps], N, X, Y, S):- 322 add_link(N-P, X, X1, S), 323 zdd_join(X, X1, X2, S), 324 add_links(Ps, N, X2, Y, S).
330% ?- zdd X<<{[a-b, c-d]}, psa(X), add_link(b-c, X, Y), psa(Y). 331% ?- zdd X<< {[a-b, c-d], [e-f]}, psa(X), add_link(b-c, X, Y), psa(Y). 332% ?- ( zdd X<< {[a-b, c-d], [a-a, b-b], [e-f]}, psa(X), add_link(b-c, X, Y), psa(Y) ). 333% ?- zdd X<< {[a-a, b-b, c-c]}, psa(X), add_link(b-c, X, Y), psa(Y). 334 335add_link(_ , X, 0, _):- X<2, !. 336add_link(U, X, Y, S):- cofact(X, t(A, L, R), S), 337 ( arrow_symbol(A) -> Y = 0 338 ; add_link(U, L, L0, S), 339 U = Ul-Ur, 340 ( mate_less_than(U, A) -> R0 = 0 341 ; A = U -> R0 = 0 % cycle found. 342 ; composable_pairs(U, A, U0, V0) -> 343 subst_end([Ul->Ur], U0, V0, R, R0, S) 344 ; add_link(U, R, R1, S), 345 zdd_insert(A, R1, R0, S) 346 ), 347 zdd_join(L0, R0, Y, S) 348 ).
355% ?- link_on_frontier(4-5, 2, #(1,3,1,2,2)). 356% ?- link_on_frontier(4-5, 2, #(1,3,1,3,2)). 357% ?- link_on_frontier(4-5, 2, #(1,3,1,3,3)). 358 359link_on_frontier(I-J, K, F):- % I \== J assumed. 360 node_on_frontier(I, K, F), 361 node_on_frontier(J, K, F).
367node_on_frontier(I, K, F):- arg(I, F, Hi),
368 ( Hi > 0, Hi =< K; I=K),
369 !.
375prune_mates(_, _, X, X, _):- X<2, !. 376prune_mates(P, Ctrl, X, Y, S):- cofact(X, t(A, L, R), S), 377 Ctrl = F-Max, 378 ( arrow_symbol(A) -> Y = X 379 ; prune_mates(P, Ctrl, L, L0, S), 380 ( link_on_frontier(A, P, F) -> 381 prune_mates(P, Ctrl, R, R1, S), 382 zdd_insert(A, R1, R0, S) 383 ; A = Max-Max -> R0 = 0 384 ; A = Ar-Max, node_on_frontier(Ar, P, F) -> 385 prune_mates(P, Ctrl, R, R1, S), 386 zdd_insert(A, R1, R0, S) 387 ; A = U-U, node_on_frontier(U, P, F) -> 388 prune_mates(P, Ctrl, R, R1, S), 389 zdd_insert(A, R1, R0, S) 390 ; A = U-U -> prune_mates(P, Ctrl, R, R0, S) 391 ; R0 = 0 392 ), 393 zdd_join(L0, R0, Y, S) 394 ).
400% prune_final/4 401prune_final(_, X, 0, _):- X<2, !. 402prune_final(Max, X, Y, S):- cofact(X, t(A, L, R), S), 403 ( arrow_symbol(A) -> Y = 0 404 ; prune_final(Max, L, L0, S), 405 ( A = 1-Max -> prune_final(R, R0, S) 406 ; A = U-U -> prune_final(Max, R, R0, S) 407 ; R0 = 0 408 ), 409 zdd_join(L0, R0, Y, S) 410 ). 411 412% prune_final/3 413prune_final(X, X, _):- X<2, !. 414prune_final(X, Y, S):- cofact(X, t(A, L, R), S), 415 ( arrow_symbol(A) -> Y = X 416 ; prune_final(L, L0, S), 417 ( A = U-U -> prune_final(R, R0, S) 418 ; R0 = 0 419 ), 420 zdd_join(L0, R0, Y, S) 421 ).
427% ?- remove_links([1-2, 2-3], [3], L). 428remove_links(L, Ns, L0):- 429 findall(A-B, ( member(A-B, L), 430 \+ memberchk(A, Ns), 431 \+ memberchk(B, Ns) 432 ), 433 L0).
rect(W, H)
such that
Hamitonian distance is 1.
441rect_grid_graph(W,H,Links):-
442 findall(P-Q,
443 ( P=p(I,J),
444 between(0, W, I),
445 between(0, H, J),
446 Q=p(K, L),
447 ( K is I + 1, K =< W, L = J
448 ; L is J + 1, L =< H, K = I
449 )
450 ),
451 Links)