1:- module(cpbdc, []). 2:- use_module(zdd('zdd-array')). 3:- use_module(zdd(zdd)). 4:- use_module(pac(op)). 5
6
7 11
16
17compare0(<, n(_,_,_), _-_):-!.
18compare0(>, _-_, n(_,_,_)):-!.
19compare0(C, X, Y):- functor(X,F,N), functor(Y, F, N), !,
20 compare(C, X, Y).
21compare0(>, _, n(_,_,_)):-!.
22compare0(>, _, _-_):-!.
23compare0(<, n(_,_,_),_):-!.
24compare0(<, _-_, _).
25
28
37
45
49
54
57
58udg_path(End, PathSet):- get_key(coa, Coa),
59 set_key(ends, End),
60 udg_mate_prune(Coa, 1, PathSet).
61
62 69
76
84
93udg_path_count(Ends, Links, C):- udg_path_count(Ends, Links, C, _).
95udg_path_count(Ends, Links, C, X):-
96 prepare_udg(Ends, Links),
97 !,
98 get_key(coa, Coa),
99 udg_mate_prune(Coa, 1, X),
100 card(X, C).
102udg_mate_prune(Ls, X, Y):-
103 add_links(Ls, X, Y0),
104 prune_final(Y0, Y).
105
116
117rect_path_count(R, C):- R = rect(W, H),
118 rect_path_count( p(0,0) - p(W,H), R, C, _).
120rect_path_count(Ends, R, C, X):- rect_links(R, Links),
121 udg_path_count(Ends, Links, C, X).
122
125rect_links(rect(W, H), Links):-
126 findall( p(I,J) - p(K,L),
127 ( between(0, W, I),
128 between(0, H, J),
129 ( L = J, K is I + 1, K =< W
130 ; K = I, L is J + 1, L =< H
131 )
132 ),
133 Links).
134
135 138
142
151
160
166
167prepare_udg(ST, Links):-
168 prepare_udg(Links),
169 prepare_ends(ST, A-B),
170 set_key(ends, A-B).
172prepare_udg(Links):-
173 prepare_udg(Links, Succs, D, Vec),
174 length(D, N),
175 completing_succs(Succs, Succs0, N),
176 set_key(coa, Succs0),
177 set_key(dom, D),
178 set_key(frontier, Vec).
180prepare_udg(Links, Succs, D, Vec):-
181 intern_links(Links, Links0),
182 normal_mate_list(Links0, Links1),
183 sort(Links1, Links2),
184 domain_of_links(Links2, D),
185 rel_to_fun(Links2, Succs),
186 Vec=..[#|D],
187 setup_frontier(Links1, Vec).
189prepare_ends(A-B, R):-!, R = A0-B0,
190 memo(node_id(A)-I),
191 memo(node_id(B)-J),
192 ( nonvar(I), nonvar(J) -> sort([I, J], [A0, B0])
193 ; format("No link at ~w or ~w\n", [A,B]),
194 fail
195 ).
196prepare_ends(E, _):-
197 format("Unexpected form of end nodes ~w \n", [E]),
198 fail.
199
202completing_succs(X, X, 0):-!.
203completing_succs([I-A|Ls], [I-A|Ms], I):-!, J is I - 1,
204 completing_succs(Ls, Ms, J).
205completing_succs(Ls, [I-[]|Ms], I):- J is I - 1,
206 completing_succs(Ls, Ms, J).
207
210normal_mate_list([], []).
211normal_mate_list([P|R], [P0|R0]):- P = I-J,
212 ( J @< I -> P0 = J - I
213 ; P0 = P
214 ),
215 normal_mate_list(R, R0).
225rel_to_fun(L, R):- sort(L, L0), rel_to_fun(L0, [], R).
227rel_to_fun([], X, X).
228rel_to_fun([A-B|L], [A-U|V], R):-!,
229 rel_to_fun(L, [A-[B|U]|V], R).
230rel_to_fun([A-B|L], U, R):-!,
231 rel_to_fun(L, [A-[B]|U], R).
232
234domain_of_links(X, Y):-
235 findall(A , ( member(L, X),
236 ( L = (A - _)
237 ; L = (_ - A)
238 )
239 ),
240 Y0),
241 sort(Y0, Y).
242
244node_id(N, C, C0):- node_id(N, _, C, C0).
245
252
253node_id(N, I, C, C0):- memo(node_id(N)-I),
254 ( nonvar(I) -> C0 = C
255 ; C0 is C+1,
256 I = C0
257 ).
258
261intern_links(L, L0):- intern_links(L, L0, 0, _).
263intern_links([], [], C, C).
264intern_links([A-B|L], [I-J|M], C, D):-
265 node_id(A, I, C, C0),
266 node_id(B, J, C0, C1),
267 intern_links(L, M, C1, D).
268
269
279on_frontier(I, J, F):- arg(I, F, K), J > K.
286off_frontier(I, J, F):- arg(I, F, K), J =< K.
287
289setup_frontier([], _).
290setup_frontier([I-J|L], F):-
291 update_frontier(I, J, F),
292 !,
293 setup_frontier(L, F).
294
297update_frontier(I, J, V):-
298 arg(J, V, A),
299 ( I < A -> setarg(J, V, I)
300 ; true
301 ).
302
303
304 307add_links([], X, X):-!.
308add_links([A-Ns|Ls], X, Y):-!,
309 cofact(X0, t(n(A,0,A), 0, X)),
310 add_links(A, Ns, X0, X1),
311 prune_by_frontier(A, X1, X2),
312 add_links(Ls, X2, Y).
314add_links(_, [], X, X):-!.
315add_links(A, [B|Ns], X, Y):-
316 b_setval(current_link, A-B),
317 add_link(X, X0),
318 zdd_join(X, X0, X1),
319 add_links(A, Ns, X1, Y).
320
331
332add_link(X, 0):- X<2, !.
333add_link(X, Y):-
334 cofact(X, t(A, L, R)),
335 add_link(L, L0),
336 b_getval(current_link, I-J),
337 A = n(K,G,C),
338 ( I @< K -> R0 = 0
339 ; G = 2 -> R0 = 0
340 ; K = I ->
341 update_class_degree(J, C, R, R1),
342 cleanup_dot_star(R1, R2),
343 G1 is G + 1,
344 A1 = n(I, G1, C),
345 zdd_insert(A1, R2, R0)
346 ; add_link(R, R1),
347 zdd_insert(A, R1, R0)
348 ),
349 zdd_join(L0, R0, Y).
350
352update_class_degree(_, _, X, 0):- X < 2, !.
353update_class_degree(J, C, X, Y):- cofact(X, t(V, L, R)),
354 ( V=(_-_) -> Y = X
355 ; update_class_degree(J, C, L, L0),
356 V = n(K, G, C0),
357 ( J = K ->
358 ( G = 2 -> R0 = 0 359 ; C = C0 -> R0 = 0 360 ; G1 is G + 1,
361 subst_class_id(C0, C, R, R1), 362 b_getval(current_link, Link),
363 zdd_ord_insert([n(K, G1, C),Link], R1, R2),
364 cofact(R0, t(*, change(C0, C), R2))
365 )
366 ; update_class_degree(J, C, R, R1),
367 insert_through_dot(V, R1, R0)
368 ),
369 cofact(Y, t((.), L0, R0))
370 ).
372subst_class_id(_, _, X, X):- X<2, !.
373subst_class_id(C, D, X, Y):- memo(subst_cla_id(C,D,X)-Y),
374 ( nonvar(Y)->true 375 ; cofact(X, t(U,L,R)),
376 ( U = (_-_) -> Y = X
377 ; subst_class_id(C, D, L, L0),
378 subst_class_id(C, D, R, R0),
379 U = n(I, G, C0),
380 ( C = C0 -> C1 = D
381 ; C1 = C0
382 ),
383 cofact(Y, t(n(I, G, C1), L0, R0))
384 )
385 ).
387cleanup_dot_star(X, X):- X<2, !.
388cleanup_dot_star(X, Y):- cofact(X, U),
389 cleanup_dot_star_case(U, Y).
391cleanup_dot_star_case(t(., L, R), V):-!,
392 cleanup_dot_star(R, R0),
393 cleanup_dot_star(L, L0),
394 zdd_join(L0, R0, V).
395cleanup_dot_star_case(t(*, _, R), R):-!.
396cleanup_dot_star_case(X, Y):- cofact(Y, X).
397
399insert_through_dot(_, X, 0):- X<2, !.
400insert_through_dot(A, X, Y):- cofact(X, T),
401 T = t(U, L, R),
402 ( U = (.) ->
403 insert_through_dot(A, L, L0),
404 insert_through_dot(A, R, R0),
405 cofact(Y, t(U, L0, R0))
406 ; U = (*) ->
407 insert_aside_star(A, T, Y)
408 ).
410insert_aside_star(n(I, Deg, C), T, Y):-
411 T = t(*, change(C0, C1), R),
412 ( C = C0 -> N = n(I, Deg, C1)
413 ; N = n(I, Deg, C)
414 ),
415 zdd_insert(N, R, R0),
416 cofact(Y, t(*, change(C0, C1), R0)).
417
418 421
422prune_by_frontier(I, X, Y):-
423 get_key(frontier, V),
424 get_key(ends, M),
425 prune_by_frontier(X, Y, I, M, V).
432prune_by_frontier(X, X, _, _, _):- X<2, !.
433prune_by_frontier(X, Y, I, M, V):- memo(prune_by_frontier(X, I)-Y),
434 ( nonvar(Y)->true, write(.);
435 cofact(X, t(A, L, R)),
436 ( A = (_-_) -> Y = X
437 ; classify_triple(A, I, M, V, C),
438 prune_by_frontier(L, L0, I, M, V),
439 ( C = keep ->
440 prune_by_frontier(R, R1, I, M, V),
441 zdd_insert(A, R1, R0)
442 ; R0 = 0
443 ),
444 zdd_join(L0, R0, Y)
445 )).
446
447
449on_pair(J, J-_).
450on_pair(J, _-J).
451
453classify_triple(n(J, Deg, _), I, Pair, V, C):-!,
454 ( on_frontier(J, I, V) -> C = keep
455 ; ( on_pair(J, Pair) ->
456 ( Deg = 1 -> C = keep
457 ; C = 0
458 )
459 ; ( Deg = 1 -> C = 0
460 ; C = keep
461 )
462 )
463 ).
465prune_final(X, Y):-
466 get_key(ends, Pair),
467 prune_final(Pair, X, Y).
468
470prune_final(_, X, X):- X<2, !.
471prune_final(Pair, X, Y):- cofact(X, t(A, L, R)),
472 ( A= (_-_) -> Y = X
473 ; prune_final(Pair, L, L0),
474 A = n(_, _, C),
475 prune_final(C, Pair, R, R1),
476 zdd_insert(A, R1, R0),
477 zdd_join(L0, R0, Y)
478 ).
480prune_final(_, _, X, X):- X<2, !.
481prune_final(C0, Pair, X, Y):- cofact(X, t(A, L, R)),
482 ( A = (_-_) -> Y = X
483 ; prune_final(C0, Pair, L, L0),
484 A = n(J, Deg, C),
485 ( on_pair(J, Pair) ->
486 ( Deg = 1 -> prune_final(C0, Pair, R, R0)
487 ; R0 = 0
488 )
489 ; ( Deg = 1 -> R0 = 0
490 ; Deg = 2 ->
491 ( C0 = C ->
492 prune_final(C, Pair, R, R1),
493 zdd_insert(A, R1, R0)
494 ; R0 = 0
495 )
496 ; prune_final(C0, Pair, R, R1),
497 zdd_insert(A, R1, R0)
498 )
499 ),
500 zdd_join(L0, R0, Y)
501 )