1:- module(path_count4, [
2 ]). 3
4:- use_module(library(apply)). 5:- use_module(library(apply_macros)). 6:- use_module(library(clpfd)). 7:- use_module(library(statistics)). 8:- use_module(zdd('zdd-array')). 9:- use_module(util(math)). 10:- use_module(util(meta2)). 11:- use_module(pac(basic)). 12:- use_module(pac(meta)). 13:- use_module(util(misc)). 14:- use_module(pac('expand-pac')). 15:- use_module(zdd('zdd-misc')). 16:- use_module(pac(op)). 17:- use_module(zdd(zdd)). 18:- use_module(zdd('update-link')). 19
20:- set_prolog_flag(stack_limit, 10_200_147_483_648). 21
22 :- op(1060, xfy, ~). 23 :- op(1060, xfy, #). 24 :- op(1060, xfy, <->). 25 :- op(1050, yfx, <-). 26 :- op(1060, xfy, <=> ). 27 :- op(1040, xfy, \/). 28 :- op(1030, xfy, /\). 29 :- op(1020, fy, \). 30 :- op(700, xfx, :=). 31 :- op(1000, xfy, &). 32
34 :- pac:op(1000, xfy, &). 35 :- pac:op(700, xfx, :=). 36
37term_expansion --> pac:expand_pac.
38
39
46
55
65
66dfs_rect_path_count(R, C):- @(dfs_rect_path_count(R, C)).
68dfs_rect_path_count(R, C, S):- R = rect(W, H),
69 rect_dg(R, N, E),
70 dfs_dg_path_count(dg(N, E), C, p(0,0)-p(W, H), S).
71
73dfs_dg_path_count(DG, C, ST):- @(dfs_dg_path_count(DG, C, ST)).
75
76dfs_dg_path_count(DG, C, ST, S):- DG = dg(N, E),
77 ST = A-_,
78 build_suc(dg(N, E), S),
79 findall(X-X, member(X, N), Id),
80 linear_zdd(Id, Zid, S),
81 dfs_build_qp(Zid, A, ST, S),
82 count_child_path(Zid, C, S).
84dfs_build_qp(X, A, ST, S):- memo(visited(X, A)-B, S),
85 ( nonvar(B) -> true
86 ; B = visited,
87 memo(suc(A)-M, S),
88 dfs_build_qp(M, X, A, ST, S)
89 ).
91dfs_build_qp([], _, _, _, _).
92dfs_build_qp([N|Ns], X, A, ST, S):-
93 dfs_qp_add_child(A-N, X, ST, S),
94 dfs_build_qp(Ns, X, A, ST, S).
95
100
101dfs_qp_add_child(E, X, ST):- @(dfs_qp_add_child(E, X, ST)).
103
104dfs_qp_add_child(E, X, ST, S):- update_qp(E, X, Y, S),
105 ( Y = 0 -> true
106 ; ( final_qp(Y, ST, S) -> Y0 = 1
107 ; Y0 = Y
108 ),
109 add_child(child(X), E-Y0, S),
110 E = _- R,
111 dfs_build_qp(Y0, R, ST, S) 112 ).
113
118
119final_qp(X, ST):- @(final_qp(X, ST)).
121final_qp(X, ST, S):- X>1,
122 cofact0(X, A, Y, S),
123 ( A = (I-I) -> final_qp(Y, ST, S)
124 ; A = ST -> qp_id(Y, S)
125 ).
127qp_id(1, _):-!.
128qp_id(X, S):- X>1,
129 cofact0(X, I-I, Y, S),
130 qp_id(Y, S).
131
135
136build_suc(R):- @(build_suc(R)).
138build_suc(dg(Ns, Rel), S):-
139 maplist(pred(S, [X]:- memo(suc(X)-[], S)), Ns),
140 rel_to_coa(suc, Rel, S).
141
145
146rel_to_coa(Key, R):- @(rel_to_coa(Key, R)).
148rel_to_coa(_, [], _):-!.
149rel_to_coa(Key, [A-B|R], S):-functor(U, Key, 1),
150 arg(1, U, A),
151 add_child(U, B, S),
152 rel_to_coa(Key, R, S).
154count_child_path(X, C):- @(count_child_path(X, C)).
156count_child_path(X, X, _):- X<2, !.
157count_child_path(X, C, S):- memo(count_child_path(X)-C, S),
158 ( nonvar(C) -> true
159 ; memo(child(X) - M, S),
160 count_child_path(M, 0, C, S)
161 ).
163count_child_path([], C, C, _).
164count_child_path([_-X|R], C, D, S):- count_child_path(X, U, S),
165 C0 is U + C,
166 count_child_path(R, C0, D, S).
167
168 171
172
183
186
190
191
192
193
197
198bfs_rect_path_count(R, C):- @(bfs_rect_path_count(R, C)).
200bfs_rect_path_count(R, C, S):- R = rect(W, H),
201 rect_dg(R, N, E),
202 bfs_dg_path_count(dg(N, E), C, p(0,0)-p(W, H), S).
204bfs_dg_path_count(DG, C, ST):- @(bfs_dg_path_count(DG, C, ST)).
206bfs_dg_path_count(DG, C, ST, S):- DG = dg(N, E),
207 ST= A-_,
208 build_suc(dg(N, E), S),
209 findall(X-X, member(X, N), Id),
210 linear_zdd(Id, Zid, S),
211 bfs_build_qp([A-Zid], [], ST, S),
212 count_child_path(Zid, C, S).
215bfs_build_qp([], [], _, _):-!.
216bfs_build_qp([], X, ST, S):-!, bfs_build_qp(X, [], ST, S).
217bfs_build_qp([A-X|R], R0, ST, S):- memo(visited(X, A)-B, S),
218 ( nonvar(B)
219 -> 220 bfs_build_qp(R, R0, ST, S)
221 ; B = visited,
222 memo(suc(A)-M, S),
223 bfs_build_qp(M, X, A, U-R0, ST, S),
224 bfs_build_qp(R, U, ST, S)
225 ).
226
228bfs_build_qp([], _, _, U-U, _, _).
229bfs_build_qp([N|Ns], X, A, U-V, ST, S):-
230 bfs_qp_add_child(A-N, X, Y, ST, S),
231 ( ( Y = 0; Y = 1) -> U0 = U
232 ; U = [N-Y|U0]
233 ),
234 bfs_build_qp(Ns, X, A, U0-V, ST, S).
235
240
241bfs_qp_add_child(E, X, Y, ST):- @(bfs_qp_add_child(E, X, Y, ST)).
243bfs_qp_add_child(E, X, Y, ST, S):- update_qp(E, X, Y0, S),
244 ( Y0 = 0 -> Y = 0
245 ; ( final_qp(Y0, ST, S) -> Y = 1
246 ; Y = Y0
247 ),
248 add_child(child(X), E-Y, S)
249 ).
250
251
252 255
264
265count_path_line(X, Y, C):- @(count_path_line(X, Y, C)).
267count_path_line(X, Y, C, S):-
268 qp_line(X, Y, R, S),
269 memo_final_line(R, X, Y, S),
270 qp_list(Q, [X-X], S),
271 path_tree(Q, Tree, S),
272 card(Tree, C, S).
274memo_final_line([], _, _, _).
275memo_final_line([A|R], X, Y, S):-
276 qp_list(A, List, S),
277 ( List = [X-Y]
278 -> memo(qp_final(A)-true, S)
279 ; true
280 ),
281 memo_final_line(R, X, Y, S).
282
284qp_line(X, Y, R):- @(qp_line(X, Y, R)).
286qp_line(X, X, [Q], S):-!,
287 zdd_insert_atoms([X-X], 1, Q, S),
288 memo(qp_suc(Q)-List, S),
289 ( var(List)-> List=[]; true).
290qp_line(X, Y, R, S):- X = p(I, K), Y = p(J, _),
291 M is (I+J)//2,
292 qp_line(X, p(M, K), R1, S),
293 M0 is M+1,
294 qp_line(p(M0,K), Y, R2, S),
295 qp_joint([p(M,K)-p(M0,K), p(M0,K)-p(M,K)], R1, R2, R3, S),
296 prune_qp_line_local(R3, X, Y, R, S).
298prune_qp_line_local([], _, _, [], _).
299prune_qp_line_local([Q|Qs], X, Y, Rs, S):-
300 X = p(I,K),
301 Y = p(J,K),
302 qp_list(Q, List, S),
303 ( member(p(A,_)-p(B,_), List),
304 A \== B,
305 ( I<A, A<J
306 ; I<B, B<J
307 )
308 -> Rs0 = Rs
309 ; Rs = [Q|Rs0]
310 ),
311 prune_qp_line_local(Qs, X, Y, Rs0, S).
312
313%% test basics.
314% ?- zdd((
315% qp_list(X, [a-a]), qp_list(Y, [b-b]),
316% qp_joint([a-b, b-a], [X], [Y], Z),
317% maplist(pred(([U]:-qp_list(U, List), writeln(List))), Z))).
318% ?- zdd((
319% qp_list(X, [a-a]), qp_list(Y, [b-b]),
320% qp_joint([a-b, b-a], [X], [Y], Z),
321% zdd_join(X, Y, A),
322% memo(qp_suc(A)-L), writeln(qp_suc(A)-L),
323% maplist(pred(([U]:-qp_list(U, List), writeln(List))), Z))).
324% ?- zdd((
325% qp_list(X, [a-a]), qp_list(Y, [b-b]),
326% qp_joint([a-b, b-a], [X], [Y], Z),
327% zdd_join(X, Y, A),
328% memo(qp_suc(A)-L), writeln(qp_suc(A)-L),
329% maplist(pred(([U]:-qp_list(U, List), writeln(List))), Z))).
330
331qp_joint(X, Y, Z, U):-@(qp_joint(X, Y, Z, U)).
333qp_joint(X, Y, Z, U, S):- map_prod_sum(Y, Z, V, [], S),
334 qp_bridge_links(X, Y, Z, U, V, S).
335
340
341qp_bridge(E, X, Y, Z):- @(qp_bridge(E, X, Y, Z)).
343qp_bridge(A-B, X, Y, Z, S):- 344 qp_list(X, L, S),
345 qp_list(Y, M, S),
346 ( select(U-A, L, L0),
347 select(B-V, M, M0)
348 ; select(B-V, L, L0),
349 select(U-A, M, M0)
350 ),
351 !,
352 ord_union(L0, M0, N0),
353 ord_union([U-V], N0, N),
354 qp_list(Z, N, S).
355qp_bridge(_, _, _, 0, _).
356
358qp_bridge_links(X, Y, Z, U, V):- @(qp_bridge_links(X, Y, Z, U, V)).
360qp_bridge_links([], _, _, Z, Z, _).
361qp_bridge_links([E|Es], X, Y, Z, U, S):-
362 qp_bridge_link(X, E, Y, Z, Z0, S),
363 qp_bridge_links(Es, X, Y, Z0, U, S).
365qp_bridge_link([], _, _, Z, Z, _).
366qp_bridge_link([X|Xs], E, Y, Z, U, S):-
367 qp_bridge_basic(Y, X, E, Z, Z0, S),
368 qp_bridge_link(Xs, E, Y, Z0, U, S).
370qp_bridge_basic([], _, _, Z, Z, _).
371qp_bridge_basic([Y|Ys], X, E, Z, U, S):- qp_bridge(E, X, Y, V, S),
372 ( V = 0
373 -> Z0 = Z
374 ; Z = [V|Z0],
375 select_goto(E, X, Y, V, S)
376 ),
377 qp_bridge_basic(Ys, X, E, Z0, U, S).
379select_goto(E, X, Y, Z):- @(select_goto(E, X, Y, Z)).
381select_goto(A-B, X, Y, Z, S):-
382 G = (A-B)-Z,
383 ( A@<B -> W = X ; W = Y ),
384 getmemo(qp_suc(W)-U, V, S),
385 ( var(V) -> V = [] ; true ),
386 add_new(G, V, U).
387
388 391
394belong(X, I, J):- I @=< J, !, I @=< X, X @=< J.
395belong(X, I, J):- J @=< X, X @=< I.
397sub_interval(I, J, X, Y):- belong(I, X, Y), belong(J, X, Y).
399disjoint_interval(I, J, X, Y):- \+ belong(I, X, Y), \+ belong(J, X, Y).
400
405
406compatible_interval(I, J, X, Y):- disjoint_interval(I, J, X, Y), !.
407compatible_interval(I, J, X, Y):- sub_interval(I, J, X, Y), !.
408compatible_interval(I, J, X, Y):- sub_interval(X, Y, I, J).
409
413
414rect_dg(rect(W, H), Nodes, Links):-
415 rect_nodes(W, H, Nodes),
416 rect_links(W, H, Nodes, Links).
417
419rect_nodes(W, H, Nodes):-
420 findall(p(I, J),
421 ( between(0, W, I),
422 between(0, H, J)
423 ),
424 Nodes0),
425 sort(Nodes0, Nodes).
426
428rect_links(W, H, Ns, Links):-
429 findall(P-Q,
430 ( member(P, Ns),
431 P = p(I, J),
432 ( Q = p(I, J1),
433 ( J1 is J-1,
434 J1 >= 0
435 ; J1 is J+1,
436 J1 =< H
437 )
438 ; Q = p(I1, J),
439 ( I1 is I-1,
440 I1 >= 0
441 ; I1 is I+1,
442 I1 =< W
443 )
444 )
445 ),
446 Links0),
447 sort(Links0, Links).
448
449 452
466
467path_count(Rect, C):- @(path_count(Rect, C)).
468
470path_count(rect(0,0), 1, _):-!.
471path_count(Rect, C, S):-
472 rect_dg(Rect, Ns, Links),
473 findall(A-A, member(A, Ns), Ids),
474 Rect = rect(W, H),
475 set_key(final, p(W, H), S),
476 qp_list(Q, Ids, S),
477 memo(qp_suc(Q)-[], S),
478 frontier(Links, [Q], FinalQs, S),
479 fold_qp_memo_final(FinalQs, S),
480 path_tree(Q, Tree, S),
481 card(Tree, C, S).
482
484frontier([], Qs, Qs, _).
485frontier([E|Es], Qs, Qs0, S):-
486 frontier_link(E, Qs, Qs1, Qs, S),
487 prune_frontier(Qs1, E, Qs2, S),
488 frontier(Es, Qs2, Qs0, S).
489
491frontier_link(_, [], Qs, Qs, _):-!.
492frontier_link(E, [X|Qs], Qs0, Qs1, S):- X<2, !,
493 frontier_link(E, Qs, Qs0, Qs1, S).
494frontier_link(E, [Q|Qs], Next, Qs1, S):-
495 qp_update(E, Q, Q0, S),
496 ( Q0 < 2
497 -> Next = Qs0
498 ; qp_memo_final(Q0, S),
499 Next = [Q0|Qs0]
500 ),
501 qp_update_succs(E-Q0, Q, S),
502 frontier_link(E, Qs, Qs0, Qs1, S).
503
508map_prod_sum(X, Y, Z):- map_prod_sum(X, Y, Z, []).
510map_prod_sum(X, Y, Z, U):- @(map_prod_sum(X, Y, Z, U)).
511
512map_prod_sum([], _, U, U, _).
513map_prod_sum([Q|Y], Z, U, V, S):- qp_list(Q, L, S),
514 map_qp_sum(Z, L, U, U0, S),
515 map_prod_sum(Y, Z, U0, V, S).
517map_qp_sum([], _, U, U, _).
518map_qp_sum([Q|As], L, [Q0|U], V, S):-qp_list(Q, M, S),
519 ord_union(L, M, N),
520 qp_list(Q0, N, S),
521 map_qp_sum(As, L, U, V, S).
522
524prune_frontier(F, Link, F0):- @(prune_frontier(F, Link, F0)).
526prune_frontier([], _, [], _).
527prune_frontier([Q|F], Link, [Q|F0], S):- admissible_qp(Q, Link, S), !,
528 prune_frontier(F, Link, F0, S).
529prune_frontier([_|F], Link, F0, S):- prune_frontier(F, Link, F0, S).
530
532admissible_qp(Q, Link, S):- qp_list(Q, List, S),
533 admissible_qp_list(List, Link).
534
536admissible_qp_list([], _):-!.
537admissible_qp_list([X-X|List], Link):-!, admissible_qp_list(List, Link).
538admissible_qp_list([_-X|_], P-_):- X @< P, !, fail.
539admissible_qp_list([_|List], Link):- admissible_qp_list(List, Link).
540
557
558qp_update(E, X, Y):- @(qp_update(E, X, Y)).
560qp_update(_, X, 0, _):- X < 2.
561qp_update(E, X, Y, S):- qp_list(X, U, S),
562 memo(qp_update(E, X)-Y, S),
563 ( nonvar(Y) -> true
564 ; select_touch(E, [A, B], U, U0)
565 -> connect_pairs(E, [A, B], W),
566 ord_union([W], U0, V),
567 qp_list(Y, V, S)
568 ; Y = 0
569 ).
570qp_update(_, _, 0, _).
571
573qp_update_succs(G, Q):- @(qp_update_succs(G, Q)).
574
576qp_update_succs(G, Q, S):- getmemo(qp_suc(Q)-U, V, S),
577 G = E-Q0,
578 ( var(V) -> U = [E-Q0]
579 ; add_new(E-Q0, V, U)
580 ).
581
582qp_admissible(L):-
583 forall((select(A-B, L, L0), select(C-D, L0, _)),
584 compatible_interval(A, B, C, D)).
585
590
596
601
605
606select_touch(_, [], V, V).
607select_touch(E, [A|As], [A|U], V):- touch(E, A), !,
608 select_touch(E, As, U, V).
609select_touch(E, As, [A|U], [A|V]):-select_touch(E, As, U, V).
610
612connect_pairs(X-Y, [U-X, Y-V], U-V).
613connect_pairs(X-Y, [Y-V, U-X], U-V).
614
617
618touch(A-_, _-A).
619touch(_-A, A-_).
620
622add_new(X, Y, Y):- memberchk(X, Y), !.
623add_new(X, Y, [X|Y]).
624
631
635qp_list(Q, List):- @(qp_list(Q, List)).
637qp_list(0, 0, _):-!.
638qp_list(1, [], _):-!.
639qp_list(Q, List, S):- var(Q), !,
640 zdd_insert_atoms(List, 1, Q, S),
641 memo(qp_suc(Q)-U, S),
642 ( var(U) -> U = []
643 ; true 644 ).
645qp_list(Q, [A|As], S):- cofact(Q, t(A, 0, R), S),
646 qp_list(R, As, S).
647
649qp_memo_final(X):- @(qp_memo_final(X)).
651qp_memo_final(Q, S):- memoq(qp_final(Q)-true, S), !.
652qp_memo_final(Q, S):- qp_list(Q, List, S),
653 get_key(final, F, S),
654 ( qp_final(List, F)
655 -> memo(qp_final(Q)-true, S)
656 ; true
657 ).
659fold_qp_memo_final([], _).
660fold_qp_memo_final([Q|Qs], S):- qp_memo_final(Q, S),
661 fold_qp_memo_final(Qs, S).
662
664path_tree(Q, T):- @(path_tree(Q, T)).
666
667path_tree(X, 0, _):- X<1, !.
668path_tree(Q, 1, S):- memoq(qp_final(Q)-true, S), !.
669path_tree(Q, T, S):- memo(path_tree(Q)-T, S),
670 ( nonvar(T) -> true
671 ; memo(qp_suc(Q) - L, S), 672 path_tree_list(L, 0, T, S)
673 ).
675path_tree_list([], C, C, _).
676path_tree_list([E-Q|Qs], C0, C, S):-
677 path_tree(Q, A, S),
678 zdd_insert(E, A, A0, S),
679 zdd_join(C0, A0, C1, S),
680 path_tree_list(Qs, C1, C, S).
681
683
684qp_final([p(0,0)-F|R], F):-!, qp_all_id(R).
685qp_final([A-A|R], F):- qp_final(R, F).
686
688qp_all_id([]).
689qp_all_id([A-A|R]):- qp_all_id(R).
690
692dag_card(Q, C):- @(dag_card(Q, C)).
694dag_card(Q, C, S):- open_state(M),
695 dag_card(Q, C, S, M),
696 close_state(M).
698dag_card(Q, 0, _, _):- Q<2, !.
699dag_card(Q, 1, S, _):- memoq(qp_final(Q)-true, S), !.
700dag_card(Q, C, S, M):- memo(dag_card(Q)-C, M),
701 ( nonvar(C) -> true
702 ; memo(qp_suc(Q) - L, S),
703 dag_card_list(L, 0, C, S, M)
704 ).
706dag_card_list([], C, C, _, _).
707dag_card_list([_-Q|Qs], C0, C, S, M):-
708 dag_card(Q, A, S, M),
709 C1 is C0 + A,
710 dag_card_list(Qs, C1, C, S, M).
711
712
713 717snap_qp_update(E, X, Y, S):- qp_update(E, X, Y, S),
718 qp_list(X, X0, S),
719 qp_list(Y, Y0, S),
720 format("~w\n~w\n~w\n\n", [qp_update(E, X, Y), X0, Y0]).
722dump_frontier(Qs, S):- maplist(pred(S,
723 ([Q]:- qp_list(Q, U, S), writeln(U))), Qs).
725dump_qp(X, _):- X<2, !, writeln(X).
726dump_qp(X, S):- qp_list(X, L, S),
727 writeln(X=L).
728
730delta_star([], Q, Q, _).
731delta_star([E|Es], Q, Q0, S):- memo(qp_suc(Q)-L, S),
732 writeln(E),
733 memberchk(E-Q1, L),
734 dump_qp(Q1, S),
735 delta_star(Es, Q1, Q0, S).
736
738mirror(X, Y):- @(mirror(X, Y)).
740mirror(X, X, _):- X<2, !.
741mirror(X, Y, S):- cofact(X, t(p(I,J)-p(K,L), Lx, Rx), S),
742 mirror(Lx, MLx, S),
743 mirror(Rx, MRx, S),
744 zdd_insert(p(J, I)-p(L, K), MRx, MRx0, S),
745 zdd_join(MLx, MRx0, Y, S).
746
747%
748rect_path_tree(Rect, T):-@(rect_path_tree(Rect, T)).
749
750rect_path_tree(Rect, T, S):-
751 sort_links_by_rank(Rect, Rs, Ids),
752 Rect = rect(W, H),
753 set_key(final, p(W, H), S),
754 qp_list(Q, Ids, S),
755 repeat_frontier(Rs, [Q], FinalQs, S),
756 fold_qp_memo_final(FinalQs, S),
757 path_tree(Q, T, S).
758
762
763remove_end_links(R, R0, ST):- maplist(pred(ST,
764 ( [J-Es, J-Es0]:- foldl(
765 pred([ST, Es, Es0],
766 ( [P-Q, U, V]:- ST = S-T,
767 ( ( Q==S; P==T)
768 -> V = U
769 ; U = [P-Q|V]
770 ))), Es, Es0, []))), R, R0).
771
773rest(Q, X, Y, S):- memo(qp_suc(Q)-L, S),
774 ( select(Q, X, X0)-> true
775 ; X0 = X
776 ),
777 rest_list(L, X0, Y, S).
779rest_list([], X, X, _).
780rest_list([_-Q|Qs], X, Y, S):-
781 rest(Q, X, X0, S),
782 rest_list(Qs, X0, Y, S).
783
784
788
789dbg_qp_update(E, X, Y):- @(dbg_qp_update(E, X, Y)).
791dbg_qp_update(E, X, Y, S):- qp_list(Q, X, S),
792 qp_update(E, Q, Q0, S),
793 qp_list(Q0, Y, S).
794
795
803
804