1:- module(crbd, []). 2
3:- use_module(zdd('zdd-array')). 4:- use_module(zdd(zdd)). 5:- use_module(pac(op)). 6
7 13
16
23
27
32
35
36udg_path(End, PathSet):- get_key(coa, Coa),
37 set_key(ends, End),
38 udg_mate_prune(Coa, 1, PathSet).
39
40 47
54
62
71udg_path_count(Ends, Links, C):- udg_path_count(Ends, Links, C, _).
73udg_path_count(Ends, Links, C, X):-
74 prepare_udg(Ends, Links),
75 !,
76 get_key(coa, Coa),
77 udg_mate_prune(Coa, 1, X),
78 card(X, C).
80udg_mate_prune(Ls, X, Y):-
81 add_links(Ls, X, Y0),
82 prune_final(Y0, Y).
83
93
94rect_path_count(R, C):- R = rect(W, H),
95 rect_path_count( p(0,0) - p(W,H), R, C, _).
97rect_path_count(Ends, R, C, X):- rect_links(R, Links),
98 udg_path_count(Ends, Links, C, X).
99
102rect_links(rect(W, H), Links):-
103 findall( p(I,J) - p(K,L),
104 ( between(0, W, I),
105 between(0, H, J),
106 ( L = J, K is I + 1, K =< W
107 ; K = I, L is J + 1, L =< H
108 )
109 ),
110 Links).
111
112 115
119
128
137
143
144prepare_udg(ST, Links):-
145 prepare_udg(Links),
146 prepare_ends(ST, A-B),
147 set_key(ends, A-B).
149prepare_udg(Links):-
150 prepare_udg(Links, Succs, D, Vec),
151 length(D, N),
152 completing_succs(Succs, Succs0, N),
153 set_key(coa, Succs0),
154 set_key(dom, D),
155 set_key(frontier, Vec).
157prepare_udg(Links, Succs, D, Vec):-
158 intern_links(Links, Links0),
159 normal_mate_list(Links0, Links1),
160 sort(Links1, Links2),
161 domain_of_links(Links2, D),
162 rel_to_fun(Links2, Succs),
163 Vec=..[#|D],
164 setup_frontier(Links1, Vec).
166prepare_ends(A-B, R):-!, R = A0-B0,
167 memo(node_id(A)-I),
168 memo(node_id(B)-J),
169 ( nonvar(I), nonvar(J) -> sort([I, J], [A0, B0])
170 ; format("No link at ~w or ~w\n", [A,B]),
171 fail
172 ).
173prepare_ends(E, _):-
174 format("Unexpected form of end nodes ~w \n", [E]),
175 fail.
176
179completing_succs(X, X, 0):-!.
180completing_succs([I-A|Ls], [I-A|Ms], I):-!, J is I - 1,
181 completing_succs(Ls, Ms, J).
182completing_succs(Ls, [I-[]|Ms], I):- J is I - 1,
183 completing_succs(Ls, Ms, J).
184
187normal_mate_list([], []).
188normal_mate_list([P|R], [P0|R0]):- P = I-J,
189 ( J @< I -> P0 = J - I
190 ; P0 = P
191 ),
192 normal_mate_list(R, R0).
202rel_to_fun(L, R):- sort(L, L0), rel_to_fun(L0, [], R).
204rel_to_fun([], X, X).
205rel_to_fun([A-B|L], [A-U|V], R):-!,
206 rel_to_fun(L, [A-[B|U]|V], R).
207rel_to_fun([A-B|L], U, R):-!,
208 rel_to_fun(L, [A-[B]|U], R).
209
211domain_of_links(X, Y):-
212 findall(A , ( member(L, X),
213 ( L = (A - _)
214 ; L = (_ - A)
215 )
216 ),
217 Y0),
218 sort(Y0, Y).
219
221node_id(N, C, C0):- node_id(N, _, C, C0).
222
229
230node_id(N, I, C, C0):- memo(node_id(N)-I),
231 ( nonvar(I) -> C0 = C
232 ; C0 is C+1,
233 I = C0
234 ).
235
238intern_links(L, L0):- intern_links(L, L0, 0, _).
240intern_links([], [], C, C).
241intern_links([A-B|L], [I-J|M], C, D):-
242 node_id(A, I, C, C0),
243 node_id(B, J, C0, C1),
244 intern_links(L, M, C1, D).
245
246
256on_frontier(I, J, F):- arg(I, F, K), J > K.
263off_frontier(I, J, F):- arg(I, F, K), J =< K.
264
266setup_frontier([], _).
267setup_frontier([I-J|L], F):-
268 update_frontier(I, J, F),
269 !,
270 setup_frontier(L, F).
271
274update_frontier(I, J, V):-
275 arg(J, V, A),
276 ( I < A -> setarg(J, V, I)
277 ; true
278 ).
279
280
281 284add_links([], X, X):-!.
285add_links([A-Ns|Ls], X, Y):-!,
286 cofact(X0, t(n(A,0,A), 0, X)),
287 add_links(A, Ns, X0, X1),
288 prune_by_frontier(A, X1, X2),
289 add_links(Ls, X2, Y).
291add_links(_, [], X, X):-!.
292add_links(A, [B|Ns], X, Y):-
293 add_link(A-B, X, X0),
294 zdd_join(X, X0, X1),
295 add_links(A, Ns, X1, Y).
297add_link(_, X, 0):- X<2, !.
298add_link(I-J, X, Y):-
299 cofact(X, t(A, L, R)),
300 add_link(I-J, L, L0),
301 A = n(K,G,C),
302 ( I @< K -> R0 = 0
303 ; G = 2 -> R0 = 0
304 ; K = I ->
305 update_class_degree(J, C, R, R1),
306 cleanup_dot_star(R1, R2),
307 G1 is G + 1,
308 A1 = n(I, G1, C),
309 zdd_insert(A1, R2, R0)
310 ; add_link(I-J, R, R1),
311 zdd_insert(A, R1, R0)
312 ),
313 zdd_join(L0, R0, Y).
315update_class_degree(_, _, X, 0):- X < 2, !.
316update_class_degree(J, C, X, Y):- cofact(X, t(V, L, R)),
317 update_class_degree(J, C, L, L0),
318 V = n(K, G, C0),
319 ( J = K ->
320 ( G = 2 -> R0 = 0 321 ; C = C0 -> R0 = 0 322 ; G1 is G + 1,
323 subst_class_id(C0, C, R, R1), 324 zdd_insert(n(K, G1, C), R1, R2),
325 cofact(R0, t(*, change(C0, C), R2))
326 )
327 ; update_class_degree(J, C, R, R1),
328 insert_through_dot(V, R1, R0)
329 ),
330 cofact(Y, t((.), L0, R0)).
332subst_class_id(_, _, X, X):-X<2,!.
333subst_class_id(C, D, X, Y):- cofact(X, t(U,L,R)),
334 subst_class_id(C, D, L, L0),
335 subst_class_id(C, D, R, R0),
336 U = n(I, G, C0),
337 ( C = C0 -> C1 = D
338 ; C1 = C0
339 ),
340 cofact(Y, t(n(I, G, C1), L0, R0)).
342cleanup_dot_star(X, X):- X<2, !.
343cleanup_dot_star(X, Y):- cofact(X, U),
344 cleanup_dot_star_case(U, Y).
346cleanup_dot_star_case(t(., L, R), V):-!,
347 cleanup_dot_star(R, R0),
348 cleanup_dot_star(L, L0),
349 zdd_join(L0, R0, V).
350cleanup_dot_star_case(t(*, _, R), R):-!.
351cleanup_dot_star_case(X, X).
352
354insert_through_dot(_, X, 0):- X<2, !.
355insert_through_dot(A, X, Y):- cofact(X, T),
356 T = t(U, L, R),
357 ( U = (.) ->
358 insert_through_dot(A, L, L0),
359 insert_through_dot(A, R, R0),
360 cofact(Y, t(U, L0, R0))
361 ; U = (*) ->
362 insert_aside_star(A, T, Y)
363 ).
365insert_aside_star(n(I, Deg, C), T, Y):-
366 T = t(*, change(C0, C1), R),
367 ( C = C0 -> N = n(I, Deg, C1)
368 ; N = n(I, Deg, C)
369 ),
370 zdd_insert(N, R, R0),
371 cofact(Y, t(*, change(C0, C1), R0)).
372
373 376
377prune_by_frontier(I, X, Y):-
378 get_key(frontier, V),
379 get_key(ends, M),
380 prune_by_frontier(X, Y, I, M, V).
387prune_by_frontier(X, X, _, _, _):- X<2, !.
388prune_by_frontier(X, Y, I, M, V):- cofact(X, t(A, L, R)),
389 classify_triple(A, I, M, V, C),
390 prune_by_frontier(L, L0, I, M, V),
391 ( C = keep ->
392 prune_by_frontier(R, R1, I, M, V),
393 zdd_insert(A, R1, R0)
394 ; R0 = 0
395 ),
396 zdd_join(L0, R0, Y).
397
398
400on_pair(J, J-_).
401on_pair(J, _-J).
402
404classify_triple(n(J, Deg, _), I, Pair, V, C):-!,
405 ( on_frontier(J, I, V) -> C = keep
406 ; ( on_pair(J, Pair) ->
407 ( Deg = 1 -> C = keep
408 ; C = 0
409 )
410 ; ( Deg = 1 -> C = 0
411 ; C = keep
412 )
413 )
414 ).
416prune_final(X, Y):-
417 get_key(ends, Pair),
418 prune_final(Pair, X, Y).
419
421prune_final(_, X, X):- X<2, !.
422prune_final(Pair, X, Y):- cofact(X, t(A, L, R)),
423 prune_final(Pair, L, L0),
424 A = n(_, _, C),
425 prune_final(C, Pair, R, R1),
426 zdd_insert(A, R1, R0),
427 zdd_join(L0, R0, Y).
429prune_final(_, _, X, X):- X<2, !.
430prune_final(C0, Pair, X, Y):- cofact(X, t(A, L, R)),
431 prune_final(C0, Pair, L, L0),
432 A = n(J, Deg, C),
433 ( on_pair(J, Pair) ->
434 ( Deg = 1 -> prune_final(C0, Pair, R, R0)
435 ; R0 = 0
436 )
437 ; ( Deg = 1 -> R0 = 0
438 ; Deg = 2 ->
439 ( C0 = C ->
440 prune_final(C, Pair, R, R1),
441 zdd_insert(A, R1, R0)
442 ; R0 = 0
443 )
444 ; prune_final(C0, Pair, R, R1),
445 zdd_insert(A, R1, R0)
446 )
447 ),
448 zdd_join(L0, R0, Y)