1:- module(gf2, [gf2_poly/3, gf2_poly_list/5,
2 gf2_poly_card/3, gf2_card/4,
3 gf2_poly_solve/3, gf2_poly_solve_list/3,
4 gf2_solve/4, gf2_solve_zero/4,
5 gf2_join/4, gf2_merge/4, gf2_join_list/4, gf2_merge_list/4,
6 gf2_subst/5, gf2_insert/4,
7 collect_atoms/2, collect_atoms_list/2, divide_at/4
8 ]). 9
10:- use_module(library(apply)). 11:- use_module(library(apply_macros)). 12:- use_module(zdd('zdd-array')). 13:- use_module(util(math)). 14:- use_module(util(meta2)). 15:- use_module(pac(basic)). 16:- use_module(pac(meta)). 17:- use_module(util(misc)). 18:- use_module(zdd(zdd)). 19:- use_module(pac(op)). 20
21 26
32power_poly(1, 1 + x(1)):-!.
33power_poly(N, P+x(N)*P):- N0 is N-1, power_poly(N0, P).
34
36
43
51
52 55
63
67
68
80divide_at(A, L, H, T):- divide_at(A, L, [], H, T).
82divide_at(A, [A|T], H, H, T):-!.
83divide_at(A, [B|T], H, H0, T0):-
84 divide_at(A, T, [B|H], H0, T0).
85
86
104
105gf2_poly_card(P, C, S):- collect_atoms(P, Vs),
106 gf2_poly(P, X, S),
107 gf2_card(Vs, X, C, S).
108
118gf2_poly_solve_card(P, C, S):- collect_atoms(P, Vs),
119 gf2_poly(P, X, S),
120 gf2_solve(Vs, X, Sols, S),
121 card(Sols, C, S).
123gf2_card(_, 0, 0, _):-!.
124gf2_card(Vs, 1, N, _):-!, length(Vs, K), N is 2^K.
125gf2_card(Vs, X, N, S):- memo(gf2_card(X, Vs)-N, S),
126 ( nonvar(N) -> true
127 ; cofact(X, t(A, L, R), S),
128 divide_at(A, Vs, H, T),
129 gf2_card(T, L, I, S),
130 gf2_join(L, R, U, S),
131 gf2_card(T, U, J, S),
132 N0 is I + J,
133 length(H, K),
134 N is N0*(2^K)
135 ).
136
147
148gf2_poly_solve(X, Y, S):- collect_atoms(X, Vs),
149 gf2_poly(X, X0, S),
150 gf2_solve(Vs, X0, Y, S).
151
152
155gf2_poly_solve_list(X, Y, S):- collect_atoms_list(X, A),
156 gf2_poly_list(X, X0, S),
157 zdd_power(A, Y0, S),
158 gf2_solve_list(A, X0, Y0, Y, S).
160gf2_solve_list(_, [], P, P, _):-!.
161gf2_solve_list(Vs, [X|Xs], P, Q, S):-
162 gf2_solve(Vs, X, P0, S),
163 zdd_meet(P0, P, Q0, S),
164 gf2_solve_list(Vs, Xs, Q0, Q, S).
165
167gf2_solve(_, 0, 0, _):-!.
168gf2_solve(Vs, 1, P, S):-!, zdd_power(Vs, P, S).
169gf2_solve(Vs, X, P, S):- memo(gf2_unit(X, Vs)-P, S),
170 ( nonvar(P) -> true
171 ; cofact(X, t(A, L, R), S),
172 divide_at(A, Vs, H, T),
173 gf2_solve(T, R, R0, S),
174 zdd_insert(A, R0, R1, S),
175 ( L = 0 -> P0 = R1
176 ; gf2_solve(T, L, L0, S),
177 cofact(L1, t(A, L0, L0), S),
178 zdd_xor(L1, R1, P0, S)
179 ),
180 zdd_power_rev(H, P0, P, S)
181 ).
182
202gf2_solve_zero(Vs, X, P, S):-
203 gf2_solve(Vs, X, U, S),
204 zdd_power(Vs, W, S),
205 zdd_subtr(W, U, P, S).
206
208zdd_power_rev([], P, P, _).
209zdd_power_rev([X|Xs], P, Q, S):- cofact(P0, t(X, P, P), S),
210 zdd_power_rev(Xs, P0, Q, S).
211
212 215
217collect_atoms(X, A):- collect_atoms(X, B, []), sort(B, A).
219collect_atoms_list(X, A):- collect_atoms_list(X, B, []), sort(B, A).
220
222collect_atoms(I, A, A) :- integer(I), !.
223collect_atoms(-(X), A, B):-!, collect_atoms(X, A, B).
224collect_atoms(P-Q, A, B):-!, collect_atoms(P+(-Q), A, B).
225collect_atoms(X * Y, A, B):-!,
226 collect_atoms(X, A, C),
227 collect_atoms(Y, C, B).
228collect_atoms(X + Y, A, B):-!,
229 collect_atoms(X, A, C),
230 collect_atoms(Y, C, B).
231collect_atoms(+(V), A, B):-!, collect_atoms_list(V, A, B).
232collect_atoms(*(V), A, B):-!, collect_atoms_list(V, A, B).
233collect_atoms(X,[X|A], A).
234
236collect_atoms_list([], A, A):-!.
237collect_atoms_list([X|Xs], A, B):-
238 collect_atoms(X, A, C),
239 collect_atoms_list(Xs, C, B).
240
242gf2_poly_list([], [], _).
243gf2_poly_list([P|Ps], [Q|Qs], S):-
244 gf2_poly(P, Q, S),
245 gf2_poly_list(Ps, Qs, S).
265gf2_poly(I, M, _) :- integer(I), !, M is I mod 2.
266gf2_poly(-(X), Y, S):-!, gf2_poly(X, Y, S).
267gf2_poly(P-Q, Y, S):-!, gf2_poly(P+(-Q), Y, S).
268gf2_poly(X * X, Y, S):-!, gf2_poly(X, Y, S).
269gf2_poly(X * Y, Z, S):-!, 270 gf2_poly(X, U, S),
271 gf2_poly(Y, V, S),
272 gf2_merge(U, V, Z, S).
273gf2_poly(X + X, 0, _):-!.
274gf2_poly(X + Y, Z, S):-!, 275 gf2_poly(X, U, S),
276 gf2_poly(Y, V, S),
277 gf2_join(U, V, Z, S).
279gf2_poly(+(V), Y, S):-!, gf2_poly_list(+, V, 0, Y, S).
280gf2_poly(*(V), Y, S):-!, gf2_poly_list(*, V, 1, Y, S).
281gf2_poly(X, Y, S) :- zdd_singleton(X, Y, S).
283gf2_poly_list(_, [], Y, Y, _):-!.
284gf2_poly_list(F, [X|Xs], Y0, Y, S):-
285 gf2_poly(X, A, S),
286 ( F = (*) -> gf2_merge(A, Y0, Y1, S)
287 ; gf2_join(A, Y0, Y1, S)
288 ),
289 gf2_poly_list(F, Xs, Y1, Y, S).
290
291
300gf2_insert(_, 0, 0, _):-!.
301gf2_insert(A, 1, J, S):-!, zdd_singleton(A, J, S).
302gf2_insert(A, I, J, S):- memo(gf2_insert(I, A)-J, S),
303 ( nonvar(J) -> true
304 ; cofact(I, t(B, L, R), S),
305 zdd_compare(C, A, B, S),
306 ( C = (=) -> gf2_insert(A, L, L0, S),
307 zdd_cons(R0, A, R, S),
308 gf2_join(L0, R0, J, S)
309 ; C = (<) -> zdd_cons(J, A, I, S)
310 ; C = (>) -> gf2_insert(A, R, R0, S),
311 gf2_insert(A, L, L0, S),
312 cofact(J, t(B, L0, R0), S)
313 )
314 ).
332gf2_join(X, X, 0, _):-!.
333gf2_join(0, X, X, _):-!.
334gf2_join(X, 0, X, _):-!.
335gf2_join(1, X, Y, S):-!, gf2_join_1(X, Y, S).
336gf2_join(X, 1, Y, S):-!, gf2_join_1(X, Y, S).
337gf2_join(X, Y, Z, S):-
338 ( X@<Y -> memo(gf2_join(X,Y)-Z, S)
339 ; memo(gf2_join(Y, X)-Z, S)
340 ),
341 ( nonvar(Z) -> true 342 ; cofact(X, t(A, L, R), S),
343 cofact(Y, t(A0, L0, R0), S),
344 zdd_compare(C, A, A0, S),
345 ( C = (<) -> gf2_join(L, Y, U, S),
346 cofact(Z, t(A, U, R), S)
347 ; C = (=) -> gf2_join(R, R0, U, S),
348 gf2_join(L, L0, V, S),
349 cofact(Z, t(A, V, U), S)
350 ; gf2_join(L0, X, U, S),
351 cofact(Z, t(A0, U, R0), S)
352 )
353 ).
354
356gf2_join_1(0, 1, _):-!.
357gf2_join_1(1, 0, _):-!.
358gf2_join_1(X, Y, S):-!, cofact(X, t(A, L, R), S),
359 gf2_join_1(L, L0, S),
360 cofact(Y, t(A, L0, R), S).
370gf2_merge(X, X, X, _):-!.
371gf2_merge(0, _, 0, _):-!.
372gf2_merge(_, 0, 0, _):-!.
373gf2_merge(1, X, X, _):-!.
374gf2_merge(X, 1, X, _):-!.
375gf2_merge(X, Y, Z, S):-
376 ( X@<Y -> memo(gf2_merge(X,Y)-Z, S)
377 ; memo(gf2_merge(Y,X)-Z, S)
378 ),
379 ( nonvar(Z) -> true
380 ; cofact(X, t(A, L, R), S),
381 gf2_merge(L, Y, L0, S),
382 gf2_merge(R, Y, R1, S),
383 gf2_insert(A, R1, R0, S),
384 gf2_join(L0, R0, Z, S)
385 ).
387gf2_merge_list([], X, X, _).
388gf2_merge_list([A|As], X, Z, S):-
389 gf2_merge(A, X, Y, S),
390 gf2_merge_list(As, Y, Z, S).
392gf2_join_list([], X, X, _).
393gf2_join_list([A|As], X, Y, S):-
394 gf2_join(A, X, Z, S),
395 gf2_join_list(As, Y, Z, S).
396
400gf2_subst(_, _, X, X, _):- X<2, !.
401gf2_subst(X, U, P, Q, S):- memo(gf2_subst(X, U, P)-Q, S),
402 ( nonvar(Q) -> true 403 ; cofact(P, t(Y, L, R), S),
404 gf2_subst(X, U, L, L0, S),
405 zdd_compare(C, X, Y, S),
406 ( C = (=) -> gf2_merge(U, R, R0, S)
407 ; C = (<) -> zdd_cons(R0, Y, R, S)
408 ; gf2_subst(X, U, R, R1, S),
409 gf2_insert(Y, R1, R0, S)
410 ),
411 gf2_join(L0, R0, Q, S)
412 )