1:- module(frtvec, [udg_path_count/3,
2 udg_path_count/4,
3 rect_path_count/4,
4 rect_links/2,
5 prepare_udg/1,
6 udg_path/2,
7 hamilton_filter/3
8 ]). 9
10:- use_module(zdd('zdd-array')). 11:- use_module(zdd(zdd)). 12:- use_module(pac(op)). 14udg_path(End, PathSet):- get_key(coa, Coa),
15 set_key(ends, End),
16 udg_mate_prune(Coa, 1, PathSet).
17
18 25
30
38
47udg_path_count(Ends, Links, C):- udg_path_count(Ends, Links, C, _).
48
50udg_path_count(Ends, Links, C, X):-
51 prepare_udg(Ends, Links),
52 ends_frontier(EF),
53 !,
54 get_key(coa, Coa),
55 udg_mate_prune(EF, Coa, 1, X0),
56 zdd_sort_paths(X0, X),
57 card(X, C).
59udg_mate_prune(EF, Ls, X, Y):-
60 add_links(EF, Ls, X, Y0),
61 get_key(ends, Pair),
62 prune_final(Pair, Y0, Y).
63
64
66
90
103
112
116
120
124
129
133
135
136
137rect_path_count(R, C):- rect_path_count(R, C, _).
139rect_path_count(R, C, X):-
140 R = rect(W, H),
141 rect_path_count( p(0,0) - p(W,H), R, C, X).
143rect_path_count(Pair, R, C, X):- rect_links(R, Links),
144 udg_path_count(Pair, Links, C, X).
145
148rect_links(rect(W, H), Links):-
149 findall( p(I,J) - p(K,L),
150 ( between(0, W, I),
151 between(0, H, J),
152 ( L = J, K is I + 1, K =< W
153 ; K = I, L is J + 1, L =< H
154 )
155 ),
156 Links).
157
158 161
170
173
183
184prepare_udg(ST, Links):-
185 prepare_udg(Links),
186 prepare_ends(ST, Pair),
187 set_key(ends, Pair).
189prepare_udg(Links):-
190 open_memo(memo_nodes),
191 prepare_udg(Links, Succs, D, Vec),
192 length(D, N),
193 completing_succs(Succs, Succs0, N),
194 set_key(coa, Succs0),
195 set_key(dom, D),
196 set_key(frontier, Vec).
198prepare_udg(Links, Succs, D, Vec):-
199 intern_links(Links, Links0),
200 normal_mate_list(Links0, Links1),
201 sort(Links1, Links2),
202 domain_of_links(Links2, D),
203 rel_to_fun(Links2, Succs),
204 Vec=..[#|D],
205 setup_frontier(Links1, Vec).
207prepare_ends(A-B, R):-!, R = A0-B0,
208 memo(node_id(A)-I, memo_nodes),
209 memo(node_id(B)-J, memo_nodes),
210 ( nonvar(I), nonvar(J) -> sort([I, J], [A0, B0])
211 ; format("No link at ~w or ~w\n", [A,B]),
212 fail
213 ).
214prepare_ends(E, _):-
215 format("Unexpected form of end nodes ~w \n", [E]),
216 fail.
217
220completing_succs(X, X, 0):-!.
221completing_succs([I-A|Ls], [I-A|Ms], I):-!, J is I - 1,
222 completing_succs(Ls, Ms, J).
223completing_succs(Ls, [I-[]|Ms], I):- J is I - 1,
224 completing_succs(Ls, Ms, J).
225
228normal_mate_list([], []).
229normal_mate_list([P|R], [P0|R0]):- P = I-J,
230 ( J @< I -> P0 = J - I
231 ; P0 = P
232 ),
233 normal_mate_list(R, R0).
243rel_to_fun(L, R):- sort(L, L0), rel_to_fun(L0, [], R).
245rel_to_fun([], X, X).
246rel_to_fun([A-B|L], [A-U|V], R):-!,
247 rel_to_fun(L, [A-[B|U]|V], R).
248rel_to_fun([A-B|L], U, R):-!,
249 rel_to_fun(L, [A-[B]|U], R).
250
252domain_of_links(X, Y):-
253 findall(A , ( member(L, X),
254 ( L = (A - _)
255 ; L = (_ - A)
256 )
257 ),
258 Y0),
259 sort(Y0, Y).
260
262node_id(N, C, C0):- node_id(N, _, C, C0).
263
267node_id(N, I, C, C0):- memo(node_id(N)-I, memo_nodes),
268 ( nonvar(I) -> C0 = C
269 ; C0 is C+1,
270 I = C0
271 ).
272
274intern_links(L, L0):- intern_links(L, L0, 0, _).
276intern_links([], [], C, C).
277intern_links([A-B|L], [I-J|M], C, D):-
278 node_id(A, I, C, C0),
279 node_id(B, J, C0, C1),
280 intern_links(L, M, C1, D).
281
282
293
294off_frontier(I, J, F):- arg(I, F, K), J =< K.
302on_frontier(I, J, F):- arg(I, F, K), K < J.
303
304
306setup_frontier([], _).
307setup_frontier([I-J|L], F):-
308 update_frontier(I, J, F),
309 !,
310 setup_frontier(L, F).
311
314update_frontier(I, J, V):-
315 arg(J, V, A),
316 ( I < A -> setarg(J, V, I)
317 ; true
318 ).
319
320 323
326arrow_symbol( _ -> _).
328arrow_symbol(A, A0):- functor(A, A0, 2).
329arrow_symbol(A, A0, A1, A2):- functor(A, A0, 2),
330 arg(1, A, A1),
331 arg(2, A, A2).
332
334composable_pairs(A-B, A-C, B, C).
335composable_pairs(A-B, C-A, B, C).
336composable_pairs(B-A, A-C, B, C).
337composable_pairs(B-A, C-A, B, C).
339normal_pair(A-B, B-A):- B < A, !.
340normal_pair(A->B, B->A):- B < A, !.
341normal_pair(X, X).
343strong_less_than(_-A, B-_):- A<B.
345ends_frontier(efr(E, Fr)):-
346 get_key(ends, E),
347 get_key(frontier, Fr).
348
349 352add_links(_, [], X, X):-!,
353 writeln(done).
354add_links(EF, [A-Ns|Ls], X, Y):-!,
355 writeln(A),
356 bdd_cons(X0, A-A, X),
357 add_links_(A, Ns, X0, X1),
358 prune_by_frontier(EF, X1, X2, A),
359 slim_gc(X2, X3),
360 add_links(EF, Ls, X3, Y).
361
363add_links_(_, [], X, X):-!.
364add_links_(A, [B|Ns], X, Y):- add_link(A-B, X, X0), !,
365 zdd_join(X, X0, X1),
366 add_links_(A, Ns, X1, Y).
368add_link(_, X, 0):- X<2, !.
369add_link(U, X, Y):- 370 cofact(X, t(A, L, R)),
371 add_link(U, L, L0),
372 ( A = (_->_) -> R0 = 0
373 ; U = A -> R0 = 0 374 ; strong_less_than(U, A) -> R0 = 0 375 ; ( composable_pairs(U, A, V, W) ->
376 U = (Ul-Ur),
377 subst_node([Ul->Ur], V, W, R, R0)
378 ; add_link(U, R, R1),
379 zdd_insert(A, R1, R0)
380 )
381 ),
382 zdd_join(L0, R0, Y).
385subst_node(_, _, _, X, 0):- X<2, !.
386subst_node(Es, A, P, X, Y):- 387 cofact(X, t(U, L, R)), 388 subst_node(Es, A, P, L, L0),
389 arrow_symbol(U, F, Lu, Ru),
390 ( F = (->) -> R0 = 0
391 ; Ru = A ->
392 normal_pair(Lu-P, V),
393 mate_ord_insert([V|Es], R, R0)
395 ; Lu = A ->
396 normal_pair(P-Ru, V),
397 mate_ord_insert([V|Es], R, R0)
399 ; subst_node(Es, A, P, R, R1),
400 zdd_insert(U, R1, R0)
401 ),
402 zdd_join(L0, R0, Y).
403
407mate_ord_insert(_, 0, 0):-!.
408mate_ord_insert([], X, X):-!.
409mate_ord_insert(As, 1, Y):-!, bdd_append(As, 1, Y).
410mate_ord_insert(As, X, Y):- 411 As = [A|U],
412 ( A = (_->_) ->
413 insert_arrows_after_links(As, X, Y)
414 ; cofact(X, t(B, L, R)),
415 zdd_compare(C, A, B),
416 ( C = (<) ->
417 mate_ord_insert(U, X, Y0),
418 bdd_cons(Y, A, Y0)
419 ; C = (=) ->
420 mate_ord_insert(U, L, L1),
421 mate_ord_insert(U, R, R1),
422 zdd_join(R1, L1, Y0),
423 bdd_cons(Y, A, Y0)
424 ; mate_ord_insert(As, L, L1),
425 mate_ord_insert(As, R, R1),
426 cofact(Y, t(B, L1, R1))
427 )
428 ).
430insert_arrows_after_links(_, 0, 0):-!.
431insert_arrows_after_links([], X, X):-!.
432insert_arrows_after_links(As, 1, Y):-!, bdd_append(As, 1, Y).
433insert_arrows_after_links(As, X, Y):- cofact(X, t(B, L, R)),
434 ( B = (_->_) -> bdd_append(As, X, Y)
435 ; insert_arrows_after_links(As, L, L0),
436 insert_arrows_after_links(As, R, R0),
437 cofact(Y, t(B, L0, R0))
438 ).
439
440 443
452prune_by_frontier(_, X, X, _):- X<2, !.
453prune_by_frontier(EF, X, Y, I):- cofact(X, t(A, L, R)),
454 EF = efr(Pair, V),
455 ( A = (_->_) -> Y = X
456 ; prune_by_frontier(EF, L, L0, I),
457 classify_pair(A, I, Pair, V, C),
458 ( C = arrow -> bdd_cons(R0, A, R)
459 ; C = keep ->
460 prune_by_frontier(EF, R, R1, I),
461 zdd_insert(A, R1, R0)
462 ; C = ignore ->
463 prune_by_frontier(EF, R, R0, I)
464 ; R0 = 0
465 ),
466 zdd_join(L0, R0, Y)
467 ).
468
470on_pair(I, J-K):- K=I; J=I.
471
473classify_pair((_->_), _, _, _, arrow):-!.
474classify_pair(J-J, I, _, V, C):-!,
475 ( on_frontier(J, I, V) -> C = keep
476 ; C = ignore
477 ).
478classify_pair(J-K, I, Pair, V, C):- 479 ( on_frontier(J, I, V) ->
480 ( on_frontier(K, I, V) -> C = keep
481 ; on_pair(K, Pair) -> C = keep
482 ; C = 0
483 )
484 ; on_frontier(K, I, V) ->
485 ( on_pair(J, Pair) -> C = keep
486 ; C = 0
487 )
488 ; (J-K) = Pair -> C = keep
489 ; C = 0
490 ).
494
496prune_final(_, X, 0):- X<2, !.
497prune_final(Pair, X, Y):- cofact(X, t(A, L, R)),
498 prune_final(Pair, L, L0),
499 ( A = (_->_) -> R0 = 0, writeln('unexpected ***arrow***')
500 ; A = Pair -> prune_final0(R, R0)
501 ; A = V-V -> prune_final(Pair, R, R0)
502 ; R0 = 0
503 ),
504 zdd_join(L0, R0, Y).
506prune_final0(X, X):- X<2, !.
507prune_final0(X, Y):- cofact(X, t(A, L, R)),
508 ( A = (_-_) -> Y = X
509 ; prune_final0(L, L0),
510 ( A = (_->_) -> bdd_cons(R0, A, R)
511 ; A = (V-V) -> prune_final0(R, R0)
512 ; R0 = 0
513 ),
514 zdd_join(L0, R0, Y)
515 ).
516
518hamilton_prune_final(P, P, _, 1):-!.
519hamilton_prune_final(_, _, X, 0):- X<2, !.
520hamilton_prune_final(P, Q, X, Y):- cofact(X, t(A, L, R)),
521 hamilton_prune_final(P, Q, L, L0),
522 ( A = (_->_) -> Y = 0
523 ; A = P-Q -> hamilton_prune_final0(R, R0)
524 ; R0 = 0
525 ),
526 zdd_join(L0, R0, Y).
528hamilton_prune_final0(X, X):- X<2, !.
529hamilton_prune_final0(X, Y):- cofact(X, t(A, L, _R)),
530 ( A = (_->_) -> Y = X
531 ; hamilton_prune_final0(L, L0),
532 R0 = 0,
533 zdd_join(L0, R0, Y)
534 ).
535
542
543hamilton_filter([I, J], X, Y):-!, hamilton_filter_special(I, J, X, Y).
544hamilton_filter(D, X, Y):- hamilton_filter_list(D, X, Y).
546hamilton_filter_special(_, _, X, 0):- X<2, !.
547hamilton_filter_special(I, J, X, Y):- cofact(X, t(A, L, R)),
548 hamilton_filter_special(I, J, L, L0),
549 ( A=(I->J) ->
550 ( R = 1 -> R0 = 1
551 ; R0 = 0
552 )
553 ; R0 = 0
554 ),
555 cofact(Y, t(A, L0, R0)).
557hamilton_filter_list([], X, X).
558hamilton_filter_list([J|Js], X, Y):-
559 hamilton_filter(2, J, X, X0),
560 hamilton_filter_list(Js, X0, Y).
562hamilton_filter(0, I, X, Y):-!, without_node(I, X, Y).
563hamilton_filter(_, _, X, 0):- X<2, !.
564hamilton_filter(K, I, X, Y):- memo(hamilton(K, I, X)-Y),
565 ( nonvar(Y) -> true 566 ; cofact(X, t(A, L, R)),
567 hamilton_filter(K, I, L, L0),
568 ( A=(E-_), I < E -> R0 = 0
569 ; ( on_arrow(I, A) ->
570 K0 is K-1,
571 hamilton_filter(K0, I, R, R0)
572 ; hamilton_filter(K, I, R, R0)
573 )
574 ),
575 cofact(Y, t(A, L0, R0))
576 ).
578without_node(_, X, X):- X<2, !.
579without_node(I, X, Y):- memo(without_node(I,X)-Y),
580 ( nonvar(Y) -> true 581 ; cofact(X, t(A, L, R)),
582 without_node(I, L, L0),
583 ( on_arrow(I, A) -> R0 = 0
584 ; without_node(I, R, R0)
585 ),
586 cofact(Y, t(A, L0, R0))
587 ).
589on_arrow(X, Y->Z):- (X=Y; X=Z).
590
593
594zdd_sort_paths(X, X):- X<2, !.
595zdd_sort_paths(X, Y):- memo(sort_paths(X)-Y),
596 ( nonvar(Y)->true 597 ; cofact(X, t(A, L, R)),
598 zdd_sort_paths(L, L0),
599 zdd_sort_paths(R, R0),
600 zdd_join(L0, R0, X0),
601 zdd_insert(A, X0, Y)
602 )