1:- module(mwp, []). 2
3 11
12
13:- use_module(zdd('zdd-array')). 14:- use_module(zdd(zdd)). 15:- use_module(pac(op)). 16
17udg_path(End, PathSet):- get_key(coa, Coa),
18 set_key(ends, End),
19 udg_mate_prune(Coa, 1, PathSet).
20
21
23connect_mate_path(X , A, Y, Z):- zdd_insert(A, X, X0),
24 zdd_merge(X0, Y, Z).
25
26 30
37udg_path_count(Ends, Links, C):- udg_path_count(Ends, Links, C, _).
38
40udg_path_count(Ends, Links, C, X):-
41 prepare_udg(Ends, Links),
42 !,
43 get_key(coa, Coa),
44 udg_mate_prune(Coa, 1, X),
45 card(X, C).
47udg_mate_prune(Ls, X, Y):-
48 add_links(Ls, X, Y0),
49 get_key(ends, A-B),
50 prune_final(A, B, Y0, Y).
51
59
60rect_path_count(R, C):- R = rect(W, H),
61 rect_path_count( p(0,0) - p(W,H), R, C, _).
63rect_path_count(Ends, R, C, X):- rect_links(R, Links),
64 udg_path_count(Ends, Links, C, X).
65
68rect_links(rect(W, H), Links):-
69 findall( p(I,J) - p(K,L),
70 ( between(0, W, I),
71 between(0, H, J),
72 ( L = J, K is I + 1, K =< W
73 ; K = I, L is J + 1, L =< H
74 )
75 ),
76 Links).
77
78 81
84
93
96
102
103prepare_udg(ST, Links):-
104 prepare_udg(Links),
105 prepare_ends(ST, A-B),
106 set_key(ends, A-B).
108prepare_udg(Links):-
109 prepare_udg(Links, Succs, D, Vec),
110 length(D, N),
111 completing_succs(Succs, Succs0, N),
112 set_key(coa, Succs0),
113 set_key(dom, D),
114 set_key(frontier, Vec).
116prepare_udg(Links, Succs, D, Vec):-
117 intern_links(Links, Links0),
118 normal_mate_list(Links0, Links1),
119 sort(Links1, Links2),
120 domain_of_links(Links2, D),
121 rel_to_fun(Links2, Succs),
122 Vec=..[#|D],
123 setup_frontier(Links1, Vec).
125prepare_ends(A-B, R):-!, R = A0-B0,
126 memo(node_id(A)-I),
127 memo(node_id(B)-J),
128 ( nonvar(I), nonvar(J) -> sort([I, J], [A0, B0])
129 ; format("No link at ~w or ~w\n", [A,B]),
130 fail
131 ).
132prepare_ends(E, _):-
133 format("Unexpected form of end nodes ~w \n", [E]),
134 fail.
135
138completing_succs(X, X, 0):-!.
139completing_succs([I-A|Ls], [I-A|Ms], I):-!, J is I - 1,
140 completing_succs(Ls, Ms, J).
141completing_succs(Ls, [I-[]|Ms], I):- J is I - 1,
142 completing_succs(Ls, Ms, J).
143
146normal_mate_list([], []).
147normal_mate_list([P|R], [P0|R0]):- P = I-J,
148 ( J @< I -> P0 = J - I
149 ; P0 = P
150 ),
151 normal_mate_list(R, R0).
161rel_to_fun(L, R):- sort(L, L0), rel_to_fun(L0, [], R).
163rel_to_fun([], X, X).
164rel_to_fun([A-B|L], [A-U|V], R):-!,
165 rel_to_fun(L, [A-[B|U]|V], R).
166rel_to_fun([A-B|L], U, R):-!,
167 rel_to_fun(L, [A-[B]|U], R).
168
170domain_of_links(X, Y):-
171 findall(A , ( member(L, X),
172 ( L = (A - _)
173 ; L = (_ - A)
174 )
175 ),
176 Y0),
177 sort(Y0, Y).
178
180node_id(N, C, C0):- node_id(N, _, C, C0).
181
184node_id(N, I, C, C0):- memo(node_id(N)-I),
185 ( nonvar(I) -> C0 = C
186 ; C0 is C+1,
187 I = C0
188 ).
189
192intern_links(L, L0):- intern_links(L, L0, 0, _).
194intern_links([], [], C, C).
195intern_links([A-B|L], [I-J|M], C, D):-
196 node_id(A, I, C, C0),
197 node_id(B, J, C0, C1),
198 intern_links(L, M, C1, D).
199
200
209on_frontier(I, J, F):- arg(I, F, K), J > K.
219
221off_frontier(I, J, F):- arg(I, F, K), J =< K.
222
224setup_frontier([], _).
225setup_frontier([I-J|L], F):-
226 update_frontier(I, J, F),
227 !,
228 setup_frontier(L, F).
229
232update_frontier(I, J, V):-
233 arg(J, V, A),
234 ( I < A -> setarg(J, V, I)
235 ; true
236 ).
237
238 241
244arrow_symbol( _ -> _).
246arrow_symbol(A, A0):- functor(A, A0, 2).
247arrow_symbol(A, A0, A1, A2):- functor(A, A0, 2),
248 arg(1, A, A1),
249 arg(2, A, A2).
250
252composable_pairs(A-B, A-C, B, C).
253composable_pairs(A-B, C-A, B, C).
254composable_pairs(B-A, A-C, B, C).
255composable_pairs(B-A, C-A, B, C).
257normal_pair(A-B, B-A):- B < A, !.
258normal_pair(X, X).
260strong_less_than(_-A, B-_):- A<B.
261
262 265
267
268add_links([], X, X):-!.
269add_links([A-Ns|Ls], X, Y):-!,
270 cofact(X0, t( mp(A-A,1), 0, X)),
271 add_links(A, Ns, X0, X1),
272 prune_by_frontier(A, X1, X2),
274 add_links(Ls, X2, Y).
276add_links(_, [], X, X):-!.
277add_links(A, [B|Ns], X, Y):-
278 add_link(A-B, X, X0),
279 zdd_join(X, X0, X1),
280 add_links(A, Ns, X1, Y).
282add_link(_, X, 0):- X<2, !.
283add_link(U, X, Y):-
284 cofact(X, t(MP, L, R)),
285 MP = mp(M, _),
286 add_link(U, L, L0),
287 ( U = M -> R0 = 0 288 ; strong_less_than(U, M) -> R0 = 0 289 ; ( composable_pairs(U, M, V, W) ->
290 subst_node(MP, V, W, R, R0)
291 ; add_link(U, R, R1),
292 zdd_insert(MP, R1, R0)
293 )
294 ),
295 zdd_join(L0, R0, Y).
296
306
309
310subst_node(_, _, _, X, 0):- X<2, !.
311subst_node(MP, A, P, X, Y):- memo(subst_node(A, P, MP, X)-Y),
312 ( nonvar(Y) -> true 313 ; cofact(X, t(MP0, L, R)), 314 subst_node(MP, A, P, L, L0),
315 MP = mp(M, Ps),
316 MP0 = mp(Lu-Ru, Ps0),
317 ( A < Lu -> R0 = 0 318 ; ( Ru = A ->
319 normal_pair(Lu-P, V),
320 zdd_merge(Ps, Ps0, Ps1),
321 zdd_insert(M, Ps1, Ps2),
322 zdd_insert(mp(V, Ps2), R, R0)
323 ; Lu = A ->
324 normal_pair(P-Ru, V),
325 zdd_merge(Ps, Ps0, Ps1),
326 zdd_insert(M, Ps1, Ps2),
327 zdd_insert(mp(V, Ps2), R, R0)
328 ; subst_node(MP, A, P, R, R1),
329 zdd_insert(MP0, R1, R0)
330 )
331 ),
332 zdd_join(L0, R0, Y)
333 ).
334
335 338
339prune_by_frontier(I, X, Y):-
340 get_key(frontier, V),
341 get_key(ends, M),
342 prune_by_frontier(X, Y, I, M, V).
349prune_by_frontier(X, X, _, _, _):- X<2, !.
350prune_by_frontier(X, Y, I, M, V):- cofact(X, t(MP, L, R)),
351 MP = mp(A, _),
352 classify_pair(A, I, M, V, C),
353 prune_by_frontier(L, L0, I, M, V),
354 ( C = keep ->
355 prune_by_frontier(R, R1, I, M, V),
356 zdd_insert(MP, R1, R0)
357 ; C = ignore ->
358 prune_by_frontier(R, R0, I, M, V)
359 ; R0 = 0
360 ),
361 zdd_join(L0, R0, Y).
362
364on_pair(J, J-_).
365on_pair(J, _-J).
366
368classify_pair(J-J, I, Pair, V, C):-!,
369 ( on_frontier(J, I, V) -> C = keep
370 ; ( on_pair(J, Pair) -> C = 0
371 ; C = ignore
372 )
373 ).
374classify_pair(J-K, I, Pair, V, C):-
375 ( on_frontier(J, I, V) ->
376 ( on_frontier(K, I, V) -> C = keep
377 ; ( on_pair(K, Pair) -> C = keep
378 ; C = 0
379 )
380 )
381 ; ( on_frontier(K, I, V) -> C = keep
382 ; ( on_pair(J, Pair) -> C = keep
383 ; C = 0
384 )
385 )
386 ).
387
389prune_final(_, _, X, 0):- X<2, !.
390prune_final(P, Q, X, Y):- cofact(X, t(MP, L, R)),
391 MP = mp(A, Ps),
392 prune_final(P, Q, L, L0),
393 ( A = P-Q ->
394 ( prune_final0(R)->
395 R0 = Ps
396 ; R0 = 0
397 )
398 ; A = V-V -> prune_final(P, Q, R, R0)
399 ; R0 = 0
400 ),
401 zdd_join(L0, R0, Y).
403prune_final0(1):-!.
404prune_final0(X):- X>2,
405 cofact(X, t(MP, L, R)),
406 ( prune_final0(L) -> true
407 ; MP = mp(V-V, _) ->
408 prune_final0(R)
409 )