├── clpb.pdf ├── figures ├── xor.png ├── cycle7.png ├── filler.png ├── cycle100.png ├── filler20.png ├── domino2x8.png ├── domino8x8.png ├── euler_161.png ├── cycle7_kernel.png ├── matchsticks1.png ├── matchsticks2.png ├── matchsticks3.png ├── polyomino8x8.png ├── cycle100_maximum.png ├── cycle100_minimum.png └── card.svg ├── tests ├── test_restrict.pl ├── test_bdd_merging.pl └── testing.pl ├── bddcalc ├── README.md ├── bddcalc.pl ├── c432.cal ├── c499.cal ├── c1908.cal ├── c1355.cal └── c2670.cal ├── xor.pl ├── pigeon.pl ├── schur.pl ├── euler_172.pl ├── knights_and_knaves.pl ├── langford.pl ├── zdd ├── langford.pl ├── euler_161.pl ├── README.md ├── polyomino_tiling.pl └── clpb.pl ├── triomino_tiling.pl ├── n_queens.pl ├── matchsticks.pl ├── domino_tiling.pl ├── cycle_n.pl └── README.md /clpb.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triska/clpb/HEAD/clpb.pdf -------------------------------------------------------------------------------- /figures/xor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triska/clpb/HEAD/figures/xor.png -------------------------------------------------------------------------------- /figures/cycle7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triska/clpb/HEAD/figures/cycle7.png -------------------------------------------------------------------------------- /figures/filler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triska/clpb/HEAD/figures/filler.png -------------------------------------------------------------------------------- /figures/cycle100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triska/clpb/HEAD/figures/cycle100.png -------------------------------------------------------------------------------- /figures/filler20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triska/clpb/HEAD/figures/filler20.png -------------------------------------------------------------------------------- /figures/domino2x8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triska/clpb/HEAD/figures/domino2x8.png -------------------------------------------------------------------------------- /figures/domino8x8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triska/clpb/HEAD/figures/domino8x8.png -------------------------------------------------------------------------------- /figures/euler_161.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triska/clpb/HEAD/figures/euler_161.png -------------------------------------------------------------------------------- /figures/cycle7_kernel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triska/clpb/HEAD/figures/cycle7_kernel.png -------------------------------------------------------------------------------- /figures/matchsticks1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triska/clpb/HEAD/figures/matchsticks1.png -------------------------------------------------------------------------------- /figures/matchsticks2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triska/clpb/HEAD/figures/matchsticks2.png -------------------------------------------------------------------------------- /figures/matchsticks3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triska/clpb/HEAD/figures/matchsticks3.png -------------------------------------------------------------------------------- /figures/polyomino8x8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triska/clpb/HEAD/figures/polyomino8x8.png -------------------------------------------------------------------------------- /figures/cycle100_maximum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triska/clpb/HEAD/figures/cycle100_maximum.png -------------------------------------------------------------------------------- /figures/cycle100_minimum.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/triska/clpb/HEAD/figures/cycle100_minimum.png -------------------------------------------------------------------------------- /tests/test_restrict.pl: -------------------------------------------------------------------------------- 1 | :- use_module(clpb). 2 | :- use_module(library(lists)). 3 | :- use_module(library(format)). 4 | 5 | clpb:validation. 6 | 7 | sat( _) --> []. 8 | sat(X*Y) --> [_], sat(X), sat(Y). 9 | sat(X+Y) --> [_], sat(X), sat(Y). 10 | sat(X#Y) --> [_], sat(X), sat(Y). 11 | 12 | run(N) :- 13 | length(Ls, N), 14 | portray_clause(N), 15 | phrase(sat(Sat), Ls), 16 | term_variables(Sat, Vs0), 17 | sat(Sat), 18 | permutation(Vs0, Vs), 19 | labeling(Vs), 20 | false. 21 | 22 | run :- run(_). 23 | 24 | -------------------------------------------------------------------------------- /tests/test_bdd_merging.pl: -------------------------------------------------------------------------------- 1 | :- use_module(clpb). 2 | 3 | clpb:validation. 4 | 5 | sat(X, Y, X=:=Y). 6 | sat(X, Y, X#Y). 7 | sat(X, Y, X+Y). 8 | sat(X, Y, X*Y). 9 | 10 | 11 | vs_formula([V|Vs], F) :- vs_formula_(Vs, V, F). 12 | 13 | vs_formula_([], F, F). 14 | vs_formula_([V|Vs], F0, F) :- 15 | sat(V, F0, Sat), 16 | vs_formula_(Vs, Sat, F). 17 | 18 | run :- 19 | sat(A, B, Sat1), 20 | sat(C, D, Sat2), 21 | sat(E, F, Sat3), 22 | sat(Sat1), 23 | sat(Sat2), 24 | sat(Sat3), 25 | vs_formula([A,B,C,D,E,F], Formula), 26 | sat(Formula), 27 | false. 28 | 29 | 30 | %?- run. 31 | -------------------------------------------------------------------------------- /bddcalc/README.md: -------------------------------------------------------------------------------- 1 | ## Simple BDD calculator 2 | 3 | [**bddcalc.pl**](bddcalc.pl) implements a very simple calculator for 4 | BDDs. It can parse and run the sample files that are contained in this 5 | directory, which are copied from the BuDDy distribution. 6 | 7 | The interface predicate is **`run(+File)`**. For example: 8 | 9 | ?- run("c499.cal"). 10 | t2 = id(id0) 11 | t3 = id(id4) 12 | t4 = id(t2)xor id(t3) 13 | ... 14 | t191 is a tautology. 15 | t196 is a tautology. 16 | t201 is a tautology. 17 | t212 is a tautology. 18 | t217 is a tautology. 19 | true. 20 | 21 | **Beware**: `bddcalc.pl` uses **internal** predicates of 22 | `library(clpb)`. Changes in these predicates may therefore require 23 | adaptions. 24 | -------------------------------------------------------------------------------- /xor.pl: -------------------------------------------------------------------------------- 1 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 | Expressing XOR with 4 NAND gates. 3 | 4 | Using universally quantified variables, you can use CLP(B) 5 | constraints to show that the circuit computes XOR as intended. 6 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 7 | 8 | :- use_module(library(clpb)). 9 | 10 | nand_gate(X, Y, Z) :- sat(Z =:= ~(X*Y)). 11 | 12 | xor(X, Y, Z) :- 13 | nand_gate(X, Y, T1), 14 | nand_gate(X, T1, T2), 15 | nand_gate(Y, T1, T3), 16 | nand_gate(T2, T3, Z). 17 | 18 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 19 | ?- xor(X, Y, Z). 20 | %@ sat(X=:=Y#Z). 21 | 22 | ?- xor(x, y, Z). 23 | %@ sat(Z=:=x#y). 24 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ -------------------------------------------------------------------------------- /pigeon.pl: -------------------------------------------------------------------------------- 1 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 | Pigeon I x J: Place j pigeons into i holes, such that each hole 3 | holds at most one pigeon. 4 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 5 | 6 | :- use_module(library(clpb)). 7 | :- use_module(library(clpz)). 8 | :- use_module(library(format)). 9 | :- use_module(library(lists)). 10 | :- use_module(library(dcgs)). 11 | 12 | %?- pigeon(8, 8, Rows, _, Conj), sat(Conj), maplist(labeling, Rows), maplist(portray_clause, Rows). 13 | %@ [0,0,0,0,0,0,0,1]. 14 | %@ [0,0,0,0,0,0,1,0]. 15 | %@ [0,0,0,0,0,1,0,0]. 16 | %@ [0,0,0,0,1,0,0,0]. 17 | %@ [0,0,0,1,0,0,0,0]. 18 | %@ [0,0,1,0,0,0,0,0]. 19 | %@ [0,1,0,0,0,0,0,0]. 20 | %@ [1,0,0,0,0,0,0,0]. 21 | 22 | %?- pigeon(8, 9, _, _, Conj), sat(Conj). 23 | %@ false. 24 | 25 | pigeon(I, J, Rows, Ls, *(Ls)) :- 26 | length(Rows, J), 27 | maplist(length_list(I), Rows), 28 | transpose(Rows, TRows), 29 | phrase((all_card1(Rows),all_max1(TRows)), Ls). 30 | 31 | length_list(N, Ls) :- length(Ls, N). 32 | 33 | all_card1([]) --> []. 34 | all_card1([Ls|Lss]) --> [card([1],Ls)], all_card1(Lss). 35 | 36 | all_max1([]) --> []. 37 | all_max1([Ls|Lss]) --> [card([0,1],Ls)], all_max1(Lss). 38 | -------------------------------------------------------------------------------- /tests/testing.pl: -------------------------------------------------------------------------------- 1 | :- use_module(clpb). 2 | :- use_module(library(dcgs)). 3 | :- use_module(library(lists)). 4 | :- use_module(library(format)). 5 | 6 | clpb:validation. 7 | 8 | sat(_) --> []. 9 | sat(X*Y) --> [_], sat(X), sat(Y). 10 | sat(X+Y) --> [_], sat(X), sat(Y). 11 | sat(X#Y) --> [_], sat(X), sat(Y). 12 | 13 | 14 | %?- vs_eqs([A,B,C,D], Eqs). 15 | 16 | vs_eqs(Vs, Eqs) :- phrase(vs_eqs(Vs), Eqs). 17 | 18 | vs_eqs([]) --> []. 19 | vs_eqs([V|Vs]) --> vs_eqs_(Vs, V), vs_eqs(Vs). 20 | 21 | vs_eqs_([], _) --> []. 22 | vs_eqs_([V|Vs], X) --> vs_eqs_(Vs, X), ( [X=V] ; [] ). 23 | 24 | run(N) :- 25 | length(Ls, N), 26 | portray_clause(N), 27 | phrase(sat(Sat1), Ls), 28 | phrase(sat(Sat2), Ls), 29 | term_variables(Sat1-Sat2, Vs0), 30 | permutation(Vs0, Vs), 31 | vs_eqs(Vs, Eqs), 32 | findall(Vs, (sat(Sat1),sat(Sat2),maplist(call, Eqs),labeling(Vs)), Sols1), 33 | findall(Vs, (labeling(Vs),maplist(call,Eqs),sat(Sat1*Sat2)), Sols2), 34 | ( sort(Sols1, Sols), sort(Sols2, Sols) -> true 35 | ; throw(neq-Sat1-Sat2-Eqs-Vs0-Vs-Sols1-Sols2) 36 | ), 37 | % ( Sols1 == [] -> 38 | % ( \+ \+ (maplist(call,Eqs), taut(Sat, T), T == 0) -> true 39 | % ; throw(tautfail-Eqs-Sat) 40 | % ) 41 | % ; true 42 | % ), 43 | false. 44 | 45 | run :- run(_). 46 | 47 | %?- run. 48 | -------------------------------------------------------------------------------- /schur.pl: -------------------------------------------------------------------------------- 1 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 | Partition the integers 1,...,N into 3 sum-free sets. A set is 3 | sum-free iff it does not contain i, j, and i+j. 4 | 5 | The Schur number for 3 is 13, so this is possible up to N = 13. 6 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 7 | 8 | :- use_module(library(clpb)). 9 | :- use_module(library(clpz)). 10 | :- use_module(library(lists)). 11 | :- use_module(library(between)). 12 | :- use_module(library(time)). 13 | 14 | %?- schur_ands_conj(13, _, Sat), time(taut(Sat, T)). 15 | %@ % CPU time: 29.837s 16 | %@ false. 17 | 18 | %?- schur_ands_conj(14, _, Sat), time(taut(Sat, T)). 19 | %@ % CPU time: 37.603s 20 | %@ Sat = *(...), T = 0, ... . 21 | 22 | 23 | schur_ands_conj(N, Ands, *(Ands)) :- 24 | length(Ls, N), 25 | maplist(same_length([_,_,_]), Ls), 26 | findall(triple(I,J,Sum), (between(1,N,I), 27 | between(I,N,J), 28 | Sum #= I+J, Sum #=< N), Triples), 29 | phrase((cards1(Ls), 30 | triples(Triples, Ls)), Ands). 31 | 32 | triples([], _) --> []. 33 | triples([T|Ts], Ls) --> triple(T, Ls), triples(Ts, Ls). 34 | 35 | triple(triple(I,J,Sum), Ls) --> 36 | { nth1(I, Ls, As), 37 | nth1(J, Ls, Bs), 38 | nth1(Sum, Ls, Cs), 39 | transpose([As,Bs,Cs], Ts) }, 40 | cards012(Ts). 41 | 42 | cards1([]) --> []. 43 | cards1([L|Ls]) --> [card([1],L)], cards1(Ls). 44 | 45 | cards012([]) --> []. 46 | cards012([L|Ls]) --> [card([0,1,2],L)], cards012(Ls). 47 | -------------------------------------------------------------------------------- /euler_172.pl: -------------------------------------------------------------------------------- 1 | 2 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3 | Project Euler, Problem 172: 4 | 5 | How many 18-digit numbers n (without leading zeros) are there such 6 | that no digit occurs more than three times in n? 7 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 8 | 9 | :- use_module(library(clpb)). 10 | :- use_module(library(clpz)). 11 | :- use_module(library(lists)). 12 | :- use_module(library(format)). 13 | :- use_module(library(time)). 14 | 15 | 16 | len_num(L, N) :- 17 | length(Digits, L), 18 | maplist(length_list(10), Digits), 19 | Digits = [First|_], 20 | First = [0|_], % no leading zero 21 | transpose(Digits, DigitsT), 22 | % the order of the following 2 constraints has a huge impact 23 | % on performance! 24 | maplist(card([0,1,2,3]), DigitsT), 25 | maplist(card([1]), Digits), 26 | append(Digits, Vs), 27 | sat_count(+[1|Vs], N). 28 | 29 | card(C, Ls) :- sat(card(C, Ls)). 30 | 31 | length_list(L, Ls) :- length(Ls, L). 32 | 33 | run(L) :- 34 | len_num(L, N), 35 | portray_clause(len_num(L,N)). 36 | 37 | run :- 38 | length(_, N), 39 | time(run(N)), 40 | false. 41 | 42 | %?- run. 43 | %@ % CPU time: 0.000s 44 | %@ len_num(1,9). 45 | %@ % CPU time: 0.005s 46 | %@ len_num(2,90). 47 | %@ % CPU time: 0.015s 48 | %@ len_num(3,900). 49 | %@ % CPU time: 0.046s 50 | %@ len_num(4,8991). 51 | %@ % CPU time: 0.155s 52 | %@ len_num(5,89586). 53 | %@ % CPU time: 0.488s 54 | %@ len_num(6,888570). 55 | %@ % CPU time: 1.401s 56 | %@ len_num(7,8754480). 57 | %@ % CPU time: 3.751s 58 | %@ len_num(8,85480920). 59 | %@ % CPU time: 9.623s 60 | -------------------------------------------------------------------------------- /knights_and_knaves.pl: -------------------------------------------------------------------------------- 1 | % You are on an island where every inhabitant is either a knight or a 2 | % knave. Knights always tell the truth, and knaves always lie. The 3 | % following examples show how various cases can be solved with CLP(B), 4 | % Constraint Logic Programming over Boolean variables. 5 | 6 | % These examples appear in Raymond Smullyan's "What Is the Name of 7 | % this Book" and Maurice Kraitchik's "Mathematical Recreations". 8 | 9 | 10 | :- use_module(library(clpb)). 11 | 12 | 13 | % We use Boolean variables A, B and C to represent the inhabitants. 14 | % Each variable is true iff the respective inhabitant is a knight. 15 | % Notice that no search is required for any of these examples. 16 | 17 | 18 | % Example 1: You meet two inhabitants, A and B. 19 | % A says: "Either I am a knave or B is a knight." 20 | 21 | example_knights(1, [A,B]) :- 22 | sat(A=:=(~A + B)). 23 | 24 | 25 | % Example 2: A says: "I am a knave, but B isn't." 26 | 27 | example_knights(2, [A,B]) :- 28 | sat(A=:=(~A * B)). 29 | 30 | 31 | % Example 3: A says: "At least one of us is a knave." 32 | 33 | example_knights(3, [A,B]) :- 34 | sat(A=:=card([1,2],[~A,~B])). 35 | 36 | 37 | % Example 4: You meet 3 inhabitants. A says: "All of us are knaves." 38 | % B says: "Exactly one of us is a knight." 39 | 40 | example_knights(4, Ks) :- 41 | Ks = [A,B,C], 42 | sat(A=:=(~A * ~B * ~C)), 43 | sat(B=:=card([1],Ks)). 44 | 45 | 46 | % Example 5: A says: "B is a knave." 47 | % B says: "A and C are of the same kind." 48 | % What is C? 49 | 50 | example_knights(5, [A,B,C]) :- 51 | sat(A=:= ~B), 52 | sat(B=:=(A=:=C)). 53 | 54 | 55 | /** 56 | 57 | ?- example_knights(1, [A,B]). 58 | ?- example_knights(2, [A,B]). 59 | ?- example_knights(Example, Knights). 60 | 61 | */ 62 | -------------------------------------------------------------------------------- /langford.pl: -------------------------------------------------------------------------------- 1 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 | Langford Sequence of order N: sequence of numbers 1,1,2,2,...,N,N 3 | such that the two occurrences of all k in 1..N are k units apart. 4 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 5 | 6 | :- use_module(library(clpb)). 7 | :- use_module(library(clpz)). 8 | :- use_module(library(lists)). 9 | :- use_module(library(format)). 10 | :- use_module(library(between)). 11 | :- use_module(library(dcgs)). 12 | 13 | run :- 14 | length(_, N), 15 | langford(N, _, Sat), 16 | sat_count(Sat, Count), 17 | portray_clause(N=Count), 18 | false. 19 | 20 | %?- run. 21 | %@ 0=1. 22 | %@ 1=1. 23 | %@ 2=0. 24 | %@ 3=2. 25 | %@ 4=2. 26 | %@ 5=0. 27 | %@ 6=0. 28 | %@ 7=52. 29 | 30 | langford(N, Vs, *(Sats)) :- 31 | Len #= 3*N, 32 | length(Row, Len), 33 | findall(Row, (between(1,N,K), phrase(row(N,K), Row)), Matrix0), 34 | sort(Matrix0, Matrix), 35 | transpose(Matrix, TMatrix), 36 | phrase(sats(TMatrix, Vs), Sats). 37 | 38 | sats([], _) --> []. 39 | sats([Col|Cols], Vs0) --> 40 | { phrase(column_selection(Col, Vs0), Vs) }, 41 | [card([1],Vs)], 42 | sats(Cols, Vs0). 43 | 44 | column_selection([], []) --> []. 45 | column_selection([C|Cs], [V|Vs]) --> 46 | ( { C =:= 1 } -> [V] 47 | ; [] 48 | ), 49 | column_selection(Cs, Vs). 50 | 51 | row(N, K) --> 52 | n_zeros(_), [1], n_zeros(K), [1], n_zeros(_), % langford sequence 53 | { Prefix #= K - 1, % rest: represent K 54 | Suffix #= N - K }, 55 | n_zeros(Prefix), 56 | [1], 57 | n_zeros(Suffix). 58 | 59 | n_zeros(0) --> []. 60 | n_zeros(K0) --> [0], { K0 #> 0, K #= K0 - 1 }, n_zeros(K). 61 | 62 | %?- length(Ls, 10), phrase(row(4, 3), Ls). 63 | %@ Ls = [1,0,0,0,1,0,0,0,1,0] 64 | %@ ; Ls = [0,1,0,0,0,1,0,0,1,0] 65 | %@ ; false. 66 | -------------------------------------------------------------------------------- /zdd/langford.pl: -------------------------------------------------------------------------------- 1 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 | Langford Sequence of order N: sequence of numbers 1,1,2,2,...,N,N 3 | such that the two occurrences of all k in 1..N are k units apart. 4 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 5 | 6 | :- use_module(clpb). 7 | :- use_module(library(clpz)). 8 | :- use_module(library(lists)). 9 | :- use_module(library(format)). 10 | :- use_module(library(dcgs)). 11 | :- use_module(library(reif)). 12 | :- use_module(library(between)). 13 | :- use_module(library(pairs)). 14 | 15 | run :- 16 | length(_, N), 17 | langford(N, _, Sat), 18 | sat_count(Sat, Count), 19 | portray_clause(N=Count), 20 | %statistics, 21 | false. 22 | 23 | %?- run. 24 | %@ 2=0. 25 | %@ 3=2. 26 | %@ 4=2. 27 | %@ 5=0. 28 | %@ 6=0. 29 | %@ 7=52. 30 | %@ etc. 31 | 32 | langford(N, Vs, *(Sats)) :- 33 | Len #= 3*N, 34 | length(Row, Len), 35 | findall(Row, (between(1,N,K), phrase(row(N,K), Row)), Matrix0), 36 | sort(Matrix0, Matrix), 37 | transpose(Matrix, TMatrix), 38 | TMatrix = [First|_], 39 | same_length(Vs, First), 40 | phrase(sats(TMatrix, Vs), Sats), 41 | zdd_set_vars(Vs). 42 | 43 | sats([], _) --> []. 44 | sats([Col|Cols], Vs0) --> 45 | { pairs_keys_values(Pairs0, Col, Vs0), 46 | tfilter(key_one_t, Pairs0, Pairs), 47 | pairs_values(Pairs, Vs) }, 48 | [card([1],Vs)], 49 | sats(Cols, Vs0). 50 | 51 | key_one_t(K-_, T) :- =(K, 1, T). 52 | 53 | row(N, K) --> 54 | n_zeros(_), [1], n_zeros(K), [1], n_zeros(_), % langford sequence 55 | { Prefix #= K - 1, % rest: represent K 56 | Suffix #= N - K }, 57 | n_zeros(Prefix), 58 | [1], 59 | n_zeros(Suffix). 60 | 61 | n_zeros(0) --> []. 62 | n_zeros(K0) --> [0], { K0 #> 0, K #= K0 - 1 }, n_zeros(K). 63 | 64 | %?- length(Ls, 10), phrase(row(4, 3), Ls). 65 | %@ Ls = [1,0,0,0,1,0,0,0,1,0] 66 | %@ ; Ls = [0,1,0,0,0,1,0,0,1,0] 67 | %@ ; false. 68 | -------------------------------------------------------------------------------- /triomino_tiling.pl: -------------------------------------------------------------------------------- 1 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 | Triomino tiling of an N x N chessboard. 3 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 4 | 5 | :- use_module(library(clpb)). 6 | :- use_module(library(clpz)). 7 | :- use_module(library(lists)). 8 | :- use_module(library(dcgs)). 9 | :- use_module(library(format)). 10 | :- use_module(library(pairs)). 11 | :- use_module(library(reif)). 12 | 13 | tile([[1,1], 14 | [1,0]]). 15 | 16 | tile([[1,0], 17 | [1,1]]). 18 | 19 | tile([[0,1], 20 | [1,1]]). 21 | 22 | tile([[1,1], 23 | [0,1]]). 24 | 25 | tile([[1,1,1]]). 26 | 27 | tile([[1], 28 | [1], 29 | [1]]). 30 | 31 | %?- triominoes(4, Vs, _, Sat), sat(Sat). 32 | %@ false. 33 | 34 | triominoes(N, Vs, Cs, *(Cs)) :- 35 | matrix(N, N, Rows), 36 | same_length(Rows, Vs), 37 | transpose(Rows, Cols), 38 | phrase(all_cardinalities(Cols, Vs), Cs). 39 | 40 | all_cardinalities([], _) --> []. 41 | all_cardinalities([Col|Cols], Vs) --> 42 | { pairs_keys_values(Pairs0, Col, Vs), 43 | tfilter(key_one_t, Pairs0, Pairs), 44 | pairs_values(Pairs, Cs) }, 45 | [card([1], Cs)], 46 | all_cardinalities(Cols, Vs). 47 | 48 | key_one_t(K-_, T) :- =(K, 1, T). 49 | 50 | matrix(M, N, Ms) :- 51 | Squares #= M*N, 52 | length(Ls, Squares), 53 | findall(Ls, line(N,Ls), Ms0), 54 | sort(Ms0, Ms). 55 | 56 | line(N, Ls) :- 57 | tile(Ts), 58 | length(Ls, Max), 59 | phrase((zeros(0,P0),tile_(Ts,N,Max,P0,P1),zeros(P1,_)), Ls). 60 | 61 | tile_([], _, _, P, P) --> []. 62 | tile_([T|Ts], N, Max, P0, P) --> 63 | tile_part(T, N, P0, P1), 64 | { (P1 - 1) mod N #>= P0 mod N, 65 | P2 #= min(P0 + N, Max) }, 66 | zeros(P1, P2), 67 | tile_(Ts, N, Max, P2, P). 68 | 69 | tile_part([], _, P, P) --> []. 70 | tile_part([L|Ls], N, P0, P) --> 71 | [L], 72 | { P1 #= P0 + 1 }, 73 | tile_part(Ls, N, P1, P). 74 | 75 | zeros(P, P) --> []. 76 | zeros(P0, P) --> [0], 77 | { P1 #= P0 + 1 }, 78 | zeros(P1, P). 79 | 80 | %?- matrix(4, 4, Ms), maplist(portray_clause, Ms). 81 | -------------------------------------------------------------------------------- /zdd/euler_161.pl: -------------------------------------------------------------------------------- 1 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 | Project Euler Problem 161: 3 | Number of Tromino tilings of a 9x12 board. 4 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 5 | 6 | :- use_module(clpb). 7 | :- use_module(library(clpz)). 8 | :- use_module(library(pairs)). 9 | :- use_module(library(lists)). 10 | :- use_module(library(between)). 11 | :- use_module(library(dcgs)). 12 | :- use_module(library(format)). 13 | :- use_module(library(reif)). 14 | 15 | euler_161(Count) :- 16 | triominoes(9, 12, Vs, Conj), 17 | zdd_set_vars(Vs), 18 | sat_count(Conj, Count). 19 | 20 | %?- between(1,10, Cols), triominoes(2, Cols, Vs, Conj), zdd_set_vars(Vs), sat_count(Conj, N), portray_clause(Cols=N), false. 21 | 22 | 23 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 24 | Trominoes 25 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 26 | 27 | tile([[1,1], 28 | [1,0]]). 29 | 30 | tile([[1,0], 31 | [1,1]]). 32 | 33 | tile([[0,1], 34 | [1,1]]). 35 | 36 | tile([[1,1], 37 | [0,1]]). 38 | 39 | tile([[1,1,1]]). 40 | 41 | tile([[1], 42 | [1], 43 | [1]]). 44 | 45 | 46 | triominoes(M, N, Vs, *(Cs)) :- 47 | matrix(M, N, Rows), 48 | same_length(Rows, Vs), 49 | transpose(Rows, Cols), 50 | phrase(all_cardinalities(Cols, Vs), Cs). 51 | 52 | all_cardinalities([], _) --> []. 53 | all_cardinalities([Col|Cols], Vs) --> 54 | { pairs_keys_values(Pairs0, Col, Vs), 55 | tfilter(key_one_t, Pairs0, Pairs), 56 | pairs_values(Pairs, Cs) }, 57 | [card([1], Cs)], 58 | all_cardinalities(Cols, Vs). 59 | 60 | key_one_t(K-_, T) :- =(K, 1, T). 61 | 62 | 63 | matrix(M, N, Ms) :- 64 | Squares #= M*N, 65 | length(Ls, Squares), 66 | findall(Ls, line(N,Ls), Ms0), 67 | sort(Ms0, Ms). 68 | 69 | 70 | line(N, Ls) :- 71 | tile(Ts), 72 | length(Ls, Max), 73 | phrase((zeros(0,P0),tile_(Ts,N,Max,P0,P1),zeros(P1,_)), Ls). 74 | 75 | tile_([], _, _, P, P) --> []. 76 | tile_([T|Ts], N, Max, P0, P) --> 77 | tile_part(T, N, P0, P1), 78 | { (P1 - 1) mod N #>= P0 mod N, 79 | P2 #= min(P0 + N, Max) }, 80 | zeros(P1, P2), 81 | tile_(Ts, N, Max, P2, P). 82 | 83 | tile_part([], _, P, P) --> []. 84 | tile_part([L|Ls], N, P0, P) --> 85 | [L], 86 | { P1 #= P0 + 1 }, 87 | tile_part(Ls, N, P1, P). 88 | 89 | zeros(P, P) --> []. 90 | zeros(P0, P) --> [0], 91 | { P1 #= P0 + 1 }, 92 | zeros(P1, P). 93 | 94 | %?- matrix(4, 4, Ms), maplist(portray_clause, Ms). 95 | -------------------------------------------------------------------------------- /zdd/README.md: -------------------------------------------------------------------------------- 1 | 2 | # ZDD-based variant of `library(clpb)` 3 | 4 | Zero-suppressed Binary Decision Diagrams (ZDDs) can save a lot of 5 | memory when most Boolean variables are equal to 0 in solutions. 6 | This is the case in many covering tasks. 7 | 8 | [**clpb.pl**](clpb.pl) is a ZDD-based variant of `library(clpb)`. It 9 | is mostly a drop-in-replacement for the library that ships with 10 | Scryer Prolog, with the following important difference: Before using 11 | `sat/1`, you *must* call `zdd_set_vars/1` with a list of all Boolean 12 | variables that occur in your model. 13 | 14 | ## Examples 15 | 16 | ### Polyomino tilings 17 | 18 | This variant of the library can be used to more space-efficiently 19 | compute that there are exactly 20 | 92,109,458,286,284,989,468,604 ways to cover an 21 | 8×8 chessboard with monominoes, dominoes and trominoes. See 22 | [**polyomino_tiling.pl**](polyomino_tiling.pl) for more information. 23 | 24 | In addition, as with `library(clpb)`, solutions can also be picked in 25 | such a way that each solution is equally likely. 26 | 27 | Sample solution: 28 | 29 | ![](../figures/filler.png) ![Polyomino tiling of an 8x8 chessboard](../figures/polyomino8x8.png) 30 | 31 | **Exercises**: 32 | 33 | - A chessboard tiling is *faultfree* if every straight line that 34 | passes through the interior of the board also passes through the 35 | interior of some domino. Add suitable constraints to describe 36 | solutions that are faultfree. 37 | 38 | - How many of the above solutions satisfy the additional property that 39 | *no two congruent pieces are adjacent*? 40 | 41 | - And of those, how many are there where congruent pieces touch at 42 | their corners? 43 | 44 | ### Project Euler Problem 161 45 | 46 | Project Euler [Problem 161](https://projecteuler.net/problem=161) asks 47 | for the number of *Triomino tilings* of a 9×12 grid. 48 | 49 | [**euler_161.pl**](euler_161.pl) shows how this can be solved with the 50 | ZDD-based variant of CLP(B) constraints. Using an Intel 51 | Core i7 CPU (2.67 GHz), you know after a few days of 52 | computation time: There are exactly 53 | 20,574,308,184,277,971 ways to do it. 54 | 55 | One of these solutions, picked at random: 56 | 57 | ![](../figures/filler.png) ![Triominoe tiling of a 9x12 grid](../figures/euler_161.png) 58 | 59 | ## Limitations 60 | 61 | There are currently some limitations: 62 | 63 | - unification of CLP(B) variables is *not* yet implemented in this variant 64 | - `labeling/1` does *not* work yet. 65 | 66 | In addition, `card/2` does not yet support integer ranges. 67 | 68 | Please see the [source file](clpb.pl) for more information about these 69 | issues. 70 | -------------------------------------------------------------------------------- /n_queens.pl: -------------------------------------------------------------------------------- 1 | :- use_module(library(clpb)). 2 | :- use_module(library(clpz)). 3 | :- use_module(library(lists)). 4 | :- use_module(library(dcgs)). 5 | :- use_module(library(time)). 6 | :- use_module(library(format)). 7 | 8 | %?- run. 9 | %@ |queens(0)| = 1 after 0.00s 10 | %@ |queens(1)| = 1 after 0.00s 11 | %@ |queens(2)| = 0 after 0.00s 12 | %@ |queens(3)| = 0 after 0.01s 13 | %@ |queens(4)| = 2 after 0.08s 14 | %@ |queens(5)| = 10 after 0.51s 15 | %@ |queens(6)| = 4 after 2.10s 16 | %@ |queens(7)| = 40 after 10.34s 17 | %@ |queens(8)| = 92 after 48.73s 18 | %@ etc. 19 | 20 | 21 | %?- n_queens(4, Qs, _, Sat), sat(Sat), append(Qs, Vs), labeling(Vs), maplist(portray_clause, Qs). 22 | %@ [0,0,1,0] 23 | %@ [1,0,0,0] 24 | %@ [0,0,0,1] 25 | %@ [0,1,0,0] 26 | %@ etc. 27 | 28 | run :- 29 | length(_, N), 30 | statistics(runtime, [T0,_]), 31 | n_queens(N, _, _, Sat), 32 | sat_count(Sat, C), 33 | statistics(runtime, [T1|_]), 34 | Time is T1 - T0, 35 | format("|queens(~w)| = ~w ~t~25| after ~2fs\n", [N,C,Time/1000]), 36 | false. 37 | 38 | n_queens(N, Qs, Ands, *(Ands)) :- 39 | length(Qs, N), 40 | maplist(length_(N), Qs), 41 | transpose(Qs, TQs), 42 | phrase((rows(Qs),rows(TQs), 43 | diagonals(Qs, 1, 1, N)), Ands). 44 | 45 | rows([]) --> []. 46 | rows([Row|Rows]) --> 47 | [+Row], 48 | not_same_row(Row), 49 | rows(Rows). 50 | 51 | not_same_row([]) --> []. 52 | not_same_row([Q|Qs]) --> 53 | not_same_row_(Qs, Q), 54 | not_same_row(Qs). 55 | 56 | not_same_row_([], _) --> []. 57 | not_same_row_([L|Ls], Q) --> 58 | [~Q + ~L], 59 | not_same_row_(Ls, Q). 60 | 61 | length_(L, Ls) :- length(Ls, L). 62 | 63 | diagonals(Qs, Row, Col, N) --> 64 | ( { Row #> N } -> [] 65 | ; { Col #> N } -> 66 | { Row1 #= Row + 1 }, 67 | diagonals(Qs, Row1, 1, N) 68 | ; { queen_at(Qs, Row, Col, Q), 69 | DRow #= Row + 1, 70 | DCol #= Col + 1 }, 71 | diagonal_down(Qs, DRow, DCol, N, Q), 72 | { URow #= Row - 1, 73 | UCol #= Col + 1 }, 74 | diagonal_up(Qs, URow, UCol, N, Q), 75 | { Col1 #= Col + 1 }, 76 | diagonals(Qs, Row, Col1, N) 77 | ). 78 | 79 | diagonal_down(Qs, Row, Col, N,Q) --> 80 | ( { Row #> N } -> [] 81 | ; { Col #> N } -> [] 82 | ; { queen_at(Qs, Row, Col, Q0) }, 83 | [~Q + ~Q0], 84 | { Row1 #= Row + 1, 85 | Col1 #= Col + 1 }, 86 | diagonal_down(Qs, Row1, Col1, N, Q) 87 | ). 88 | 89 | diagonal_up(Qs, Row, Col, N, Q) --> 90 | ( { Row #< 1 } -> [] 91 | ; { Col #> N } -> [] 92 | ; { queen_at(Qs, Row, Col, Q0) }, 93 | [~Q + ~Q0], 94 | { Row1 #= Row - 1, 95 | Col1 #= Col + 1 }, 96 | diagonal_up(Qs, Row1, Col1, N, Q) 97 | ). 98 | 99 | 100 | 101 | queen_at(Qs, NRow, NCol, Q) :- 102 | nth1(NRow, Qs, Row), 103 | nth1(NCol, Row, Q). 104 | -------------------------------------------------------------------------------- /matchsticks.pl: -------------------------------------------------------------------------------- 1 | :- use_module(library(clpz)). 2 | :- use_module(library(clpb)). 3 | :- use_module(library(between)). 4 | :- use_module(library(pairs)). 5 | :- use_module(library(format)). 6 | :- use_module(library(lists)). 7 | :- use_module(library(dcgs)). 8 | 9 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 10 | Task: Remove minimum number of matchsticks so that no subsquare remains. 11 | 12 | Tested with Scryer Prolog. 13 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 14 | 15 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 16 | o = inside of the square 17 | variable = matchstick 18 | x = nothing here 19 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 20 | 21 | layout(L) :- 22 | L = [[x,_,x,_,x,_,x,_,x], 23 | [_,o,_,o,_,o,_,o,_], 24 | [x,_,x,_,x,_,x,_,x], 25 | [_,o,_,o,_,o,_,o,_], 26 | [x,_,x,_,x,_,x,_,x], 27 | [_,o,_,o,_,o,_,o,_], 28 | [x,_,x,_,x,_,x,_,x], 29 | [_,o,_,o,_,o,_,o,_], 30 | [x,_,x,_,x,_,x,_,x]]. 31 | 32 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 33 | ?- matchsticks(L, Vs), 34 | same_length(Vs, Coeffs), maplist(=(1), Coeffs), 35 | weighted_maximum(Coeffs, Vs, Maximum), 36 | maplist(portray_clause, L). 37 | %@ [x,1,x,0,x,1,x,1,x]. 38 | %@ [1,o,1,o,1,o,1,o,1]. 39 | %@ [x,0,x,1,x,0,x,0,x]. 40 | %@ [1,o,1,o,1,o,1,o,1]. 41 | %@ [x,1,x,0,x,0,x,1,x]. 42 | %@ [1,o,1,o,1,o,1,o,1]. 43 | %@ [x,0,x,1,x,1,x,0,x]. 44 | %@ [1,o,1,o,0,o,1,o,1]. 45 | %@ [x,1,x,1,x,1,x,1,x]. 46 | %@ L = [[x,1,x,0,x,1,x,1,x]|...], Vs = [1,1,0,1,0,1,1,1,0,1,1,0,1,1,1,1,0,1,0,1,...], Coeffs = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,...], Maximum = 31 47 | %@ ; ... . 48 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 49 | 50 | matchsticks(L, Vs) :- 51 | findall(L-S, layout_subsquare(L,S), LSs), 52 | pairs_keys_values(LSs, Ls, Subs), 53 | maplist(=(L), Ls), 54 | maplist(not_subsquare, Subs), 55 | term_variables(Subs, Vs). 56 | 57 | list_odds_evens([], [], []). 58 | list_odds_evens([E], [], [E]). 59 | list_odds_evens([E,O|Ls], [O|Os], [E|Es]) :- list_odds_evens(Ls, Os, Es). 60 | 61 | not_subsquare(Subs) :- sat(~ *(Subs)). 62 | 63 | layout_subsquare(L, Sub) :- 64 | layout(L), 65 | anyeven(SubList, Len), 66 | Len #> 0, 67 | anyeven(DropsTop, _), 68 | append(DropsTop, Rest0, L), 69 | anyeven(DropsLeft, _), 70 | maplist(drop_first(DropsLeft), Rest0, Rest), 71 | Rest = [First|_], 72 | phrase(horizontals(SubList, First), Tops), 73 | nth0(Len, Rest, Bot), 74 | phrase(horizontals(SubList, Bot), Bots), 75 | phrase(verticals(SubList, Rest), Lefts), 76 | maplist(drop_first(SubList), Rest, Rests1), 77 | phrase(verticals(SubList, Rests1), Rights), 78 | append([Tops,Lefts,Bots,Rights], Sub). 79 | 80 | %?- findall(., layout_subsquare(_, _), Ls), length(Ls, L). 81 | 82 | %?- layout_subsquare(L, Sub), maplist(writeln, L). 83 | 84 | verticals([], _) --> []. 85 | verticals([_,_|Vs], [_,[Var|_]|Rest]) --> [Var], verticals(Vs, Rest). 86 | 87 | horizontals([], _) --> []. 88 | horizontals([_,_|Hs], [_,Var|Rest]) --> [Var], horizontals(Hs, Rest). 89 | 90 | drop_first(Ls0, Rests0, Rests) :- 91 | same_length(Ls0, Ls), 92 | append(Ls, Rests, Rests0). 93 | 94 | 95 | anyeven(Ls, E) :- 96 | between(0, 4, E0), 97 | E #= E0 * 2, 98 | length(Ls, E). 99 | -------------------------------------------------------------------------------- /domino_tiling.pl: -------------------------------------------------------------------------------- 1 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 | Domino tiling of an M x N chessboard. 3 | Tested with Scryer Prolog. 4 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 5 | 6 | :- use_module(library(clpb)). 7 | :- use_module(library(clpz)). 8 | :- use_module(library(lists)). 9 | :- use_module(library(format)). 10 | :- use_module(library(pairs)). 11 | :- use_module(library(dcgs)). 12 | :- use_module(library(time)). 13 | :- use_module(library(between)). 14 | :- use_module(library(reif)). 15 | 16 | %?- run. 17 | 18 | run :- 19 | length(_, N), 20 | time((dominoes(N, N, _Vs, Conj), sat_count(Conj, Count), 21 | portray_clause(N=Count))), 22 | false. 23 | 24 | %?- dominoes(8, 8, Vs, Conj), sat_count(Conj, Count). 25 | 26 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 27 | Interestingly, the Fibonacci numbers arise when we ask for the 28 | number of domino tilings of a 2xN board. 29 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 30 | 31 | %?- between(1,10,N), dominoes(2, N, Vs, Conj), sat_count(Conj, Count), portray_clause(N=Count), false. 32 | %@ 1=1. 33 | %@ 2=2. 34 | %@ 3=3. 35 | %@ 4=5. 36 | %@ 5=8. 37 | %@ 6=13. 38 | %@ 7=21. 39 | %@ 8=34. 40 | %@ 9=55. 41 | %@ 10=89. 42 | %@ false. 43 | 44 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 45 | Monomino 46 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 47 | 48 | %tile([[1]]). 49 | 50 | 51 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 52 | Dominoes 53 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 54 | 55 | tile([[1,1]]). 56 | 57 | tile([[1], 58 | [1]]). 59 | 60 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 61 | Trominoes 62 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 63 | 64 | % tile([[1,1], 65 | % [1,0]]). 66 | 67 | % tile([[1,0], 68 | % [1,1]]). 69 | 70 | % tile([[0,1], 71 | % [1,1]]). 72 | 73 | % tile([[1,1], 74 | % [0,1]]). 75 | 76 | % tile([[1,1,1]]). 77 | 78 | % tile([[1], 79 | % [1], 80 | % [1]]). 81 | 82 | 83 | dominoes(M, N, Vs, *(Cards)) :- 84 | matrix(M, N, Rows), 85 | same_length(Rows, Vs), 86 | transpose(Rows, Cols), 87 | maplist(column_card_1(Vs), Cols, Cards). 88 | 89 | column_card_1(Vs, Col, card([1],Cs)) :- 90 | pairs_keys_values(Pairs0, Col, Vs), 91 | tfilter(key_one_t, Pairs0, Pairs), 92 | pairs_values(Pairs, Cs). 93 | 94 | key_one_t(Key-_, T) :- =(Key, 1, T). 95 | 96 | matrix(M, N, Ms) :- 97 | Squares #= M*N, 98 | length(Ls, Squares), 99 | findall(Ls, line(N,Ls), Ms). 100 | 101 | 102 | line(N, Ls) :- 103 | tile(Ts), 104 | length(Ls, Max), 105 | phrase((zeros(0,P0),tile_(Ts,N,Max,P0,P1),zeros(P1,_)), Ls). 106 | 107 | tile_([], _, _, P, P) --> []. 108 | tile_([T|Ts], N, Max, P0, P) --> 109 | tile_part(T, P0, P1), 110 | { (P1 - 1) mod N #>= P0 mod N, 111 | P2 #= min(P0 + N, Max) }, 112 | zeros(P1, P2), 113 | tile_(Ts, N, Max, P2, P). 114 | 115 | tile_part([], P, P) --> []. 116 | tile_part([L|Ls], P0, P) --> 117 | [L], 118 | { P1 #= P0 + 1 }, 119 | tile_part(Ls, P1, P). 120 | 121 | zeros(P, P) --> []. 122 | zeros(P0, P) --> [0], 123 | { P1 #= P0 + 1 }, 124 | zeros(P1, P). 125 | 126 | %?- matrix(4, 4, Ms), maplist(portray_clause, Ms). 127 | -------------------------------------------------------------------------------- /zdd/polyomino_tiling.pl: -------------------------------------------------------------------------------- 1 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 | Polyomino tiling of an N x M chessboard. 3 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 4 | 5 | :- use_module(clpb). 6 | :- use_module(library(clpz)). 7 | :- use_module(library(lists)). 8 | :- use_module(library(pairs)). 9 | :- use_module(library(dcgs)). 10 | :- use_module(library(reif)). 11 | :- use_module(library(time)). 12 | :- use_module(library(format)). 13 | :- use_module(library(between)). 14 | 15 | 16 | %?- run. 17 | %@ 0=1. 18 | %@ % CPU time: 0.000s, 552 inferences 19 | %@ 1=1. 20 | %@ % CPU time: 0.000s, 1_909 inferences 21 | %@ 2=11. 22 | %@ % CPU time: 0.013s, 63_662 inferences 23 | %@ 3=583. 24 | %@ % CPU time: 0.240s, 1_179_806 inferences 25 | %@ 4=177332. 26 | %@ % CPU time: 2.343s, 11_429_112 inferences 27 | %@ 5=329477745. 28 | %@ % CPU time: 18.502s, 91_996_815 inferences 29 | 30 | run :- 31 | length(_, N), 32 | time((polyominoes(N, N, Vs, Conj), 33 | zdd_set_vars(Vs), 34 | sat_count(Conj, Count), 35 | portray_clause(N=Count))), 36 | false. 37 | 38 | %?- between(1,10, Cols), polyominoes(2, Cols, Vs, Conj), zdd_set_vars(Vs), sat_count(Conj, N), portray_clause(Cols=N), false. 39 | 40 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 41 | Monomino 42 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 43 | 44 | tile([[1]]). 45 | 46 | 47 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 48 | Dominoes 49 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 50 | 51 | tile([[1,1]]). 52 | 53 | tile([[1], 54 | [1]]). 55 | 56 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 57 | Trominoes 58 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 59 | 60 | tile([[1,1], 61 | [1,0]]). 62 | 63 | tile([[1,0], 64 | [1,1]]). 65 | 66 | tile([[0,1], 67 | [1,1]]). 68 | 69 | tile([[1,1], 70 | [0,1]]). 71 | 72 | tile([[1,1,1]]). 73 | 74 | tile([[1], 75 | [1], 76 | [1]]). 77 | 78 | 79 | polyominoes(M, N, Vs, *(Cs)) :- 80 | matrix(M, N, Rows), 81 | same_length(Rows, Vs), 82 | transpose(Rows, Cols), 83 | phrase(all_cardinalities(Cols, Vs), Cs). 84 | 85 | all_cardinalities([], _) --> []. 86 | all_cardinalities([Col|Cols], Vs) --> 87 | { pairs_keys_values(Pairs0, Col, Vs), 88 | tfilter(key_one_t, Pairs0, Pairs), 89 | pairs_values(Pairs, Cs) }, 90 | [card([1], Cs)], 91 | all_cardinalities(Cols, Vs). 92 | 93 | key_one_t(K-_, T) :- =(K, 1, T). 94 | 95 | 96 | matrix(M, N, Ms) :- 97 | Squares #= M*N, 98 | length(Ls, Squares), 99 | findall(Ls, line(N,Ls), Ms0), 100 | sort(Ms0, Ms). 101 | 102 | 103 | line(N, Ls) :- 104 | tile(Ts), 105 | length(Ls, Max), 106 | phrase((zeros(0,P0),tile_(Ts,N,Max,P0,P1),zeros(P1,_)), Ls). 107 | 108 | tile_([], _, _, P, P) --> []. 109 | tile_([T|Ts], N, Max, P0, P) --> 110 | tile_part(T, N, P0, P1), 111 | { (P1 - 1) mod N #>= P0 mod N, 112 | P2 #= min(P0 + N, Max) }, 113 | zeros(P1, P2), 114 | tile_(Ts, N, Max, P2, P). 115 | 116 | tile_part([], _, P, P) --> []. 117 | tile_part([L|Ls], N, P0, P) --> 118 | [L], 119 | { P1 #= P0 + 1 }, 120 | tile_part(Ls, N, P1, P). 121 | 122 | zeros(P, P) --> []. 123 | zeros(P0, P) --> [0], 124 | { P1 #= P0 + 1 }, 125 | zeros(P1, P). 126 | 127 | %?- matrix(4, 4, Ms), maplist(portray_clause, Ms). 128 | -------------------------------------------------------------------------------- /bddcalc/bddcalc.pl: -------------------------------------------------------------------------------- 1 | :- use_module(library(pio)). 2 | :- use_module(library(clpb)). 3 | :- use_module(library(dcgs)). 4 | :- use_module(library(format)). 5 | :- use_module(library(assoc)). 6 | :- use_module(library(charsio)). 7 | 8 | eval_actions([]) --> []. 9 | eval_actions([A|As]) --> 10 | eval_action(A), 11 | eval_actions(As). 12 | 13 | state(S), [S] --> [S]. 14 | 15 | state(S0, S), [S] --> [S0]. 16 | 17 | eval_action(ID=Expr) --> 18 | expr_value(Expr, Value), 19 | state(Assoc0, Assoc), 20 | { format("~w = ~w\n", [ID,Expr]), 21 | put_assoc(ID, Assoc0, Value, Assoc) }. 22 | eval_action(taut(T)) --> 23 | state(Assoc), 24 | { get_assoc(T, Assoc, Value) }, 25 | ( { Value == 1 } -> 26 | { format("~w is a tautology.\n", [T]) } 27 | ; { throw(no_tautology(T,Value)) } 28 | ). 29 | 30 | expr_value(id(ID), Value) --> 31 | state(Assoc0, Assoc), 32 | ( { get_assoc(ID, Assoc0, Value) } -> { Assoc = Assoc0 } 33 | ; { clpb:enumerate_variable(V), 34 | clpb:make_node(V, 0, 1, Value), 35 | put_assoc(ID, Assoc0, Value, Assoc) } 36 | ). 37 | expr_value(not(E), Value) --> 38 | expr_value(E, V), 39 | clpb:apply(#, 1, V, Value). 40 | expr_value(xor(E1,E2), Value) --> 41 | expr_value(E1, V1), 42 | expr_value(E2, V2), 43 | clpb:apply(#, V1, V2, Value). 44 | expr_value(nand(E1,E2), Value) --> expr_value(not(and(E1,E2)), Value). 45 | expr_value(nor(E1,E2), Value) --> expr_value(not(or(E1,E2)), Value). 46 | expr_value(or(E1,E2), Value) --> 47 | expr_value(E1, V1), 48 | expr_value(E2, V2), 49 | clpb:apply(+, V1, V2, Value). 50 | expr_value(and(E1,E2), Value) --> 51 | expr_value(E1, V1), 52 | expr_value(E2, V2), 53 | clpb:apply(*, V1, V2, Value). 54 | expr_value(biimp(E1,E2), Value) --> expr_value(xor(not(E1),E2), Value). 55 | 56 | 57 | sample_calfile(1, "c1355.cal"). 58 | sample_calfile(2, "c1908.cal"). 59 | sample_calfile(3, "c2670.cal"). 60 | sample_calfile(4, "c3540.cal"). 61 | sample_calfile(5, "c432.cal"). 62 | sample_calfile(6, "c499.cal"). 63 | 64 | id(ID) --> 65 | [L], 66 | { (char_type(L, alpha) ; L = '_' ) }, 67 | alnums(Ls), 68 | { atom_chars(ID, [L|Ls]) }. 69 | 70 | alnums([A|As]) --> 71 | [A], 72 | { char_type(A, alnum) }, 73 | alnums(As). 74 | alnums([]) --> []. 75 | 76 | 77 | run(File) :- 78 | phrase_from_file(calfile(As), File), 79 | empty_assoc(E), 80 | phrase(eval_actions(As), [E], [_]). 81 | 82 | 83 | calfile(As) --> 84 | comment, 85 | ws, 86 | "initial", ..., ";", ws, 87 | "inputs", ..., ";", ws, 88 | "actions", ws, 89 | "autoreorder", ..., ";", ws, 90 | !, 91 | actions(As). 92 | 93 | %?- phrase(action(A), "t4 = not t3;"). 94 | 95 | actions([A|As]) --> 96 | action(A), 97 | ws, 98 | !, % single solution: longest input match 99 | actions(As). 100 | actions([]) --> []. 101 | 102 | action(ID = Expr) --> id(ID), ws, "=", ws, expr(Expr), ws, ";". 103 | action(taut(ID)) --> "tautology", ws, id(ID), ws, ";". 104 | 105 | expr(E) --> factor(F), expr_r(F, E). 106 | 107 | expr_r(E0, E) --> ws, binop(Op), ws, factor(E1), { E =.. [Op,E0,E1] }. 108 | expr_r(E, E) --> []. 109 | 110 | binop(xor) --> "xor". 111 | binop(nand) --> "nand". 112 | binop(nor) --> "nor". 113 | binop(or) --> "or". 114 | binop(biimp) --> "biimp". 115 | binop(and) --> "and". 116 | 117 | factor(id(ID)) --> id(ID). 118 | factor(not(E)) --> "not", ws, factor(E). 119 | 120 | comment --> "/*", ..., "*/". 121 | comment --> []. 122 | 123 | ws --> [W], { char_type(W, whitespace) }, ws. 124 | ws --> []. 125 | 126 | -------------------------------------------------------------------------------- /figures/card.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | G 11 | 12 | 13 | 4 14 | 15 | X 16 | 17 | 18 | 2 19 | 20 | Y 21 | 22 | 23 | 4->2 24 | 25 | 26 | 27 | 28 | 3 29 | 30 | Y 31 | 32 | 33 | 4->3 34 | 35 | 36 | 37 | 38 | 0 39 | 40 | Z 41 | 42 | 43 | 2->0 44 | 45 | 46 | 47 | 48 | false 49 | 50 | false 51 | 52 | 53 | 2->false 54 | 55 | 56 | 57 | 58 | 0->false 59 | 60 | 61 | 62 | 63 | true 64 | 65 | true 66 | 67 | 68 | 0->true 69 | 70 | 71 | 72 | 73 | 3->0 74 | 75 | 76 | 77 | 78 | 1 79 | 80 | Z 81 | 82 | 83 | 3->1 84 | 85 | 86 | 87 | 88 | 1->false 89 | 90 | 91 | 92 | 93 | 1->true 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /cycle_n.pl: -------------------------------------------------------------------------------- 1 | :- use_module(library(clpb)). 2 | :- use_module(library(clpz)). 3 | :- use_module(library(lists)). 4 | :- use_module(library(dcgs)). 5 | :- use_module(library(between)). 6 | :- use_module(library(pairs)). 7 | :- use_module(library(time)). 8 | :- use_module(library(assoc)). 9 | :- use_module(library(reif)). 10 | :- use_module(library(lambda)). 11 | 12 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 13 | Independent sets, maximal independent sets (kernels) and maximal 14 | independent sets with maximum weight of the Cycle graph C_100. 15 | 16 | Example queries, tested with Scryer Prolog: 17 | 18 | (1) Independent sets: 19 | 20 | ?- N+\time((independent_set(I,_),sat_count(I,N))). 21 | %@ % CPU time: 0.616s, 2_654_474 inferences 22 | %@ N = 792070839848372253127. 23 | 24 | (2) Maximal independent sets: 25 | 26 | ?- N+\time((kernel(K,_),sat_count(K,N))). 27 | %@ % CPU time: 2.793s, 12_660_789 inferences 28 | %@ N = 1630580875002. 29 | 30 | (3) Maximal independent sets with maximum weight: 31 | 32 | %?- time(maximum_thue_morse_kernel(Is, Negatives, Max)). 33 | %@ % CPU time: 10.228s, 45_547_552 inferences 34 | %@ Is = [1,3,6,9,12,15,18,20,23,25,27,30,33,36,39,41,43,46,48,51|...], Negatives = [1,25,41,73,97], Max = 28 35 | %@ ; ... . 36 | 37 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 38 | 39 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 40 | Cycle graph C_100. 41 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 42 | 43 | cycle(100). 44 | 45 | edge(X, Y) :- edge_(1, 2, X, Y). 46 | edge(1, Limit) :- cycle(Limit). 47 | 48 | edge_(A, B, A, B). 49 | edge_(_, N1, X, Y) :- 50 | N2 #= N1 + 1, 51 | cycle(Limit), 52 | N2 #=< Limit, 53 | edge_(N1, N2, X, Y). 54 | 55 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 56 | Node N has weight w_N = (-1)^n(N), where n(N) is the number of 1s in 57 | the binary representation of N. This is similar to Thue-Morse codes. 58 | 59 | For example, the Thue-Morse weights of the integers 1,...,10 are: 60 | 61 | ?- thue_morse_weights(10, Ms). 62 | %@ Ms = [-1,-1,1,-1,1,1,-1,-1,1,1]. 63 | 64 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 65 | 66 | integer_binaries(I, Bs) :- 67 | once(phrase(binaries(I, 0), Bs0)), 68 | reverse(Bs0, Bs). 69 | 70 | binaries(0, _) --> []. 71 | binaries(I, E0) --> 72 | ( { I mod 2 #= 0 } -> [0] 73 | ; [1] 74 | ), 75 | { I1 #= I // 2, E1 #= E0 + 1 }, 76 | binaries(I1, E1). 77 | 78 | thue_morse_weights(N, Ms) :- 79 | length(Ms, N), 80 | numlist(1, N, Ns), 81 | maplist(integer_binaries, Ns, Bss), 82 | maplist(sum_list, Bss, Cards), 83 | maplist(neg1_pow, Cards, Ms). 84 | 85 | neg1_pow(Card, Pow) :- Pow #= (-1)^Card. 86 | 87 | maximum_thue_morse_kernel(Is, Negatives, Max) :- 88 | kernel(K, Assoc), 89 | assoc_to_values(Assoc, Vs), 90 | sat(K), 91 | length(Vs, L), 92 | thue_morse_weights(L, Weights), 93 | weighted_maximum(Weights, Vs, Max), 94 | numlist(1, L, Ns), 95 | pairs_keys_values(Pairs0, Vs, Ns), 96 | tfilter(key_one_t, Pairs0, Pairs), 97 | pairs_values(Pairs, Is), 98 | pairs_keys_values(WNs, Weights, Ns), 99 | pairs_keys_values(WPairs0, Vs, WNs), 100 | tfilter(key_one_t, WPairs0, WPairs1), 101 | pairs_values(WPairs1, WPairs2), 102 | tfilter(key_negative_t, WPairs2, WPairs), 103 | pairs_values(WPairs, Negatives). 104 | 105 | key_negative_t(K-_, T) :- clpz_t(K #< 0, T). 106 | 107 | key_one_t(K-_, T) :- =(K, 1, T). 108 | 109 | %?- time(maximum_thue_morse_kernel(Is, Negatives, Max)). 110 | %@ % CPU time: 10.104s, 45_547_575 inferences 111 | %@ Is = [1,3,6,9,12,15,18,20,23,25,27,30,33,36,39,41,43,46,48,51|...], Negatives = [1,25,41,73,97], Max = 28 112 | %@ ; % CPU time: 0.016s, 63_185 inferences 113 | %@ Is = [1,3,6,9,12,15,18,20,23,25,27,30,33,36,39,41,43,46,48,51|...], Negatives = [1,25,41,73,94], Max = 28 114 | %@ ; % CPU time: 0.099s, 319_668 inferences 115 | %@ Is = [1,3,6,9,12,15,18,20,23,25,27,30,33,36,39,41,43,46,48,51|...], Negatives = [1,25,41,73,97], Max = 28 116 | %@ ; ... . 117 | 118 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 119 | Independent set: 120 | 121 | IND(X) = not OR_(u->v){ x_u /\ x_v } = AND_(u->v){not x_u \/ not x_v} 122 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 123 | 124 | %?- N+\time((independent_set(I,_),sat_count(I,N))). 125 | %@ % CPU time: 0.615s, 2_654_474 inferences 126 | %@ N = 792070839848372253127. 127 | 128 | 129 | independent_set(*(NBs), Assoc) :- 130 | findall(U-V, edge(U, V), Edges), 131 | setof(U, V^(member(U-V, Edges);member(V-U, Edges)), Nodes), 132 | pairs_keys_values(Pairs, Nodes, _), 133 | list_to_assoc(Pairs, Assoc), 134 | maplist(not_both(Assoc), Edges, NBs). 135 | 136 | not_both(Assoc, U-V, ~BU + ~BV) :- 137 | get_assoc(U, Assoc, BU), 138 | get_assoc(V, Assoc, BV). 139 | 140 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 141 | Kernels. 142 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 143 | 144 | kernel(Ind* *(Ors), Assoc) :- 145 | independent_set(Ind, Assoc), 146 | assoc_to_keys(Assoc, Nodes), 147 | maplist(node_or(Assoc), Nodes, Ors). 148 | 149 | node_or(Assoc, Node, Var + +(Vars)) :- 150 | get_assoc(Node, Assoc, Var), 151 | setof(U-Node, (edge(U, Node);edge(Node,U)), Edges), 152 | pairs_keys(Edges, Us), 153 | maplist(u_to_var(Assoc), Us, Vars). 154 | 155 | u_to_var(Assoc, Node, Var) :- get_assoc(Node, Assoc, Var). 156 | 157 | %?- C+\(kernel(Sat, _), sat_count(Sat, C)). 158 | %@ C = 1630580875002. 159 | -------------------------------------------------------------------------------- /bddcalc/c432.cal: -------------------------------------------------------------------------------- 1 | /* BDD Calculator data file */ 2 | 3 | initial 10000 10000; 4 | 5 | inputs 6 | _1gat _4gat _8gat _11gat _14gat _17gat _21gat _24gat _27gat _30gat 7 | _34gat _37gat _40gat _43gat _47gat _50gat _53gat _56gat _60gat _63gat 8 | _66gat _69gat _73gat _76gat _79gat _82gat _86gat _89gat _92gat _95gat 9 | _99gat _102gat _105gat _108gat _112gat _115gat ; 10 | 11 | actions 12 | autoreorder 0 win2ite; 13 | 14 | t2 = _8gat; 15 | t3 = _89gat; 16 | t4 = not t3; 17 | t5 = _95gat; 18 | t6 = t4 nand t5; 19 | t7 = _76gat; 20 | t8 = not t7; 21 | t9 = _82gat; 22 | t10 = t8 nand t9; 23 | t11 = _63gat; 24 | t12 = not t11; 25 | t13 = _69gat; 26 | t14 = t12 nand t13; 27 | t15 = _50gat; 28 | t16 = not t15; 29 | t17 = _56gat; 30 | t18 = t16 nand t17; 31 | t19 = _37gat; 32 | t20 = not t19; 33 | t21 = _43gat; 34 | t22 = t20 nand t21; 35 | t23 = _24gat; 36 | t24 = not t23; 37 | t25 = _30gat; 38 | t26 = t24 nand t25; 39 | t27 = _1gat; 40 | t28 = not t27; 41 | t29 = _4gat; 42 | t30 = t28 nand t29; 43 | t31 = _11gat; 44 | t32 = not t31; 45 | t33 = _17gat; 46 | t34 = t32 nand t33; 47 | t35 = t30 and t34; 48 | t36 = t26 and t35; 49 | t37 = t22 and t36; 50 | t38 = t18 and t37; 51 | t39 = t14 and t38; 52 | t40 = t10 and t39; 53 | t41 = t6 and t40; 54 | t42 = _102gat; 55 | t43 = not t42; 56 | t44 = _108gat; 57 | t45 = t43 nand t44; 58 | t46 = t41 and t45; 59 | t47 = not t46; 60 | t48 = t47 xor t6; 61 | t49 = _99gat; 62 | t50 = not t5; 63 | t51 = t49 nor t50; 64 | t52 = t48 nand t51; 65 | t53 = t47 xor t10; 66 | t54 = _86gat; 67 | t55 = not t9; 68 | t56 = t54 nor t55; 69 | t57 = t53 nand t56; 70 | t58 = t47 xor t14; 71 | t59 = _73gat; 72 | t60 = not t13; 73 | t61 = t59 nor t60; 74 | t62 = t58 nand t61; 75 | t63 = t47 xor t18; 76 | t64 = _60gat; 77 | t65 = not t17; 78 | t66 = t64 nor t65; 79 | t67 = t63 nand t66; 80 | t68 = t47 xor t22; 81 | t69 = _47gat; 82 | t70 = not t21; 83 | t71 = t69 nor t70; 84 | t72 = t68 nand t71; 85 | t73 = t47 xor t26; 86 | t74 = _34gat; 87 | t75 = not t25; 88 | t76 = t74 nor t75; 89 | t77 = t73 nand t76; 90 | t78 = t47 xor t30; 91 | t79 = not t29; 92 | t80 = t2 nor t79; 93 | t81 = t78 nand t80; 94 | t82 = t47 xor t34; 95 | t83 = _21gat; 96 | t84 = not t33; 97 | t85 = t83 nor t84; 98 | t86 = t82 nand t85; 99 | t87 = t81 and t86; 100 | t88 = t77 and t87; 101 | t89 = t72 and t88; 102 | t90 = t67 and t89; 103 | t91 = t62 and t90; 104 | t92 = t57 and t91; 105 | t93 = t52 and t92; 106 | t94 = t47 xor t45; 107 | t95 = _112gat; 108 | t96 = not t44; 109 | t97 = t95 nor t96; 110 | t98 = t94 nand t97; 111 | t99 = t93 and t98; 112 | t100 = not t99; 113 | t101 = t2 nand t100; 114 | t102 = t27 nand t47; 115 | t103 = t29 and t102; 116 | t104 = t101 and t103; 117 | t105 = _14gat; 118 | t106 = t100 xor t52; 119 | t107 = _105gat; 120 | t108 = t107 nor t50; 121 | t109 = t48 nand t108; 122 | t110 = not t109; 123 | t111 = t106 nand t110; 124 | t112 = t100 xor t57; 125 | t113 = _92gat; 126 | t114 = t113 nor t55; 127 | t115 = t53 nand t114; 128 | t116 = not t115; 129 | t117 = t112 nand t116; 130 | t118 = t100 xor t62; 131 | t119 = _79gat; 132 | t120 = t119 nor t60; 133 | t121 = t58 nand t120; 134 | t122 = not t121; 135 | t123 = t118 nand t122; 136 | t124 = t100 xor t67; 137 | t125 = _66gat; 138 | t126 = t125 nor t65; 139 | t127 = t63 nand t126; 140 | t128 = not t127; 141 | t129 = t124 nand t128; 142 | t130 = t100 xor t72; 143 | t131 = _53gat; 144 | t132 = t131 nor t70; 145 | t133 = t68 nand t132; 146 | t134 = not t133; 147 | t135 = t130 nand t134; 148 | t136 = t100 xor t77; 149 | t137 = _40gat; 150 | t138 = t137 nor t75; 151 | t139 = t73 nand t138; 152 | t140 = not t139; 153 | t141 = t136 nand t140; 154 | t142 = t100 xor t81; 155 | t143 = t105 nor t79; 156 | t144 = t78 nand t143; 157 | t145 = not t144; 158 | t146 = t142 nand t145; 159 | t147 = t100 xor t86; 160 | t148 = _27gat; 161 | t149 = t148 nor t84; 162 | t150 = t82 nand t149; 163 | t151 = not t150; 164 | t152 = t147 nand t151; 165 | t153 = t146 and t152; 166 | t154 = t141 and t153; 167 | t155 = t135 and t154; 168 | t156 = t129 and t155; 169 | t157 = t123 and t156; 170 | t158 = t117 and t157; 171 | t159 = t111 and t158; 172 | t160 = t100 xor t98; 173 | t161 = _115gat; 174 | t162 = t161 nor t96; 175 | t163 = t94 nand t162; 176 | t164 = not t163; 177 | t165 = t160 nand t164; 178 | t166 = t159 and t165; 179 | t167 = not t166; 180 | t168 = t105 nand t167; 181 | t169 = t104 nand t168; 182 | t170 = not t169; 183 | t171 = t167 nand t107; 184 | t172 = t47 nand t3; 185 | t173 = t100 nand t49; 186 | t174 = t172 and t173; 187 | t175 = t171 and t174; 188 | t176 = t175 nand t5; 189 | t177 = t167 nand t113; 190 | t178 = t47 nand t7; 191 | t179 = t100 nand t54; 192 | t180 = t178 and t179; 193 | t181 = t177 and t180; 194 | t182 = t181 nand t9; 195 | t183 = t167 nand t119; 196 | t184 = t47 nand t11; 197 | t185 = t100 nand t59; 198 | t186 = t184 and t185; 199 | t187 = t183 and t186; 200 | t188 = t187 nand t13; 201 | t189 = t167 nand t125; 202 | t190 = t47 nand t15; 203 | t191 = t100 nand t64; 204 | t192 = t190 and t191; 205 | t193 = t189 and t192; 206 | t194 = t193 nand t17; 207 | t195 = t167 nand t131; 208 | t196 = t47 nand t19; 209 | t197 = t100 nand t69; 210 | t198 = t196 and t197; 211 | t199 = t195 and t198; 212 | t200 = t199 nand t21; 213 | t201 = t167 nand t148; 214 | t202 = t47 nand t31; 215 | t203 = t100 nand t83; 216 | t204 = t202 and t203; 217 | t205 = t201 and t204; 218 | t206 = t205 nand t33; 219 | t207 = t167 nand t137; 220 | t208 = t47 nand t23; 221 | t209 = t100 nand t74; 222 | t210 = t208 and t209; 223 | t211 = t207 and t210; 224 | t212 = t211 nand t25; 225 | t213 = t206 and t212; 226 | t214 = t200 and t213; 227 | t215 = t194 and t214; 228 | t216 = t188 and t215; 229 | t217 = t182 and t216; 230 | t218 = t176 and t217; 231 | t219 = t167 nand t161; 232 | t220 = t47 nand t42; 233 | t221 = t100 nand t95; 234 | t222 = t220 and t221; 235 | t223 = t219 and t222; 236 | t224 = t223 nand t44; 237 | t225 = t218 and t224; 238 | t226 = t170 nor t225; 239 | t227 = t218 and t96; 240 | t228 = t170 nor t227; 241 | t229 = t226 biimp t228; 242 | t230 = not t188; 243 | t231 = t212 and t200; 244 | t232 = t230 and t231; 245 | t233 = t232 nand t194; 246 | t234 = not t200; 247 | t235 = t212 nand t234; 248 | t236 = t206 and t235; 249 | t237 = t233 and t236; 250 | t238 = t182 and t231; 251 | t239 = not t176; 252 | t240 = t238 nand t239; 253 | t241 = t237 nand t240; 254 | t242 = t212 and t182; 255 | t243 = t242 nand t239; 256 | t244 = t237 nand t243; 257 | t245 = t241 biimp t244; 258 | 259 | tautology t229; 260 | tautology t245; 261 | -------------------------------------------------------------------------------- /bddcalc/c499.cal: -------------------------------------------------------------------------------- 1 | /* BDD Calculator data file */ 2 | 3 | initial 10000 10000; 4 | 5 | inputs 6 | id0 id1 id2 id3 id4 id5 id6 id7 id8 id9 7 | id10 id11 id12 id13 id14 id15 id16 id17 id18 id19 8 | id20 id21 id22 id23 id24 id25 id26 id27 id28 id29 9 | id30 id31 ic0 ic1 ic2 ic3 ic4 ic5 ic6 ic7 10 | r ; 11 | 12 | actions 13 | autoreorder 0 sift; 14 | t2 = id0; 15 | t3 = id4; 16 | t4 = t2 xor t3; 17 | t5 = id8; 18 | t6 = id12; 19 | t7 = t5 xor t6; 20 | t8 = t4 xor t7; 21 | t9 = ic0; 22 | t10 = r; 23 | t11 = t9 and t10; 24 | t12 = id16; 25 | t13 = id17; 26 | t14 = t12 xor t13; 27 | t15 = id18; 28 | t16 = id19; 29 | t17 = t15 xor t16; 30 | t18 = t14 xor t17; 31 | t19 = id20; 32 | t20 = id21; 33 | t21 = t19 xor t20; 34 | t22 = id22; 35 | t23 = id23; 36 | t24 = t22 xor t23; 37 | t25 = t21 xor t24; 38 | t26 = t18 xor t25; 39 | t27 = t11 xor t26; 40 | t28 = t8 xor t27; 41 | t29 = t16 xor t23; 42 | t30 = id27; 43 | t31 = id31; 44 | t32 = t30 xor t31; 45 | t33 = t29 xor t32; 46 | t34 = ic7; 47 | t35 = t34 and t10; 48 | t36 = id5; 49 | t37 = t3 xor t36; 50 | t38 = id6; 51 | t39 = id7; 52 | t40 = t38 xor t39; 53 | t41 = t37 xor t40; 54 | t42 = id13; 55 | t43 = t6 xor t42; 56 | t44 = id14; 57 | t45 = id15; 58 | t46 = t44 xor t45; 59 | t47 = t43 xor t46; 60 | t48 = t41 xor t47; 61 | t49 = t35 xor t48; 62 | t50 = t33 xor t49; 63 | t51 = not t50; 64 | t52 = t15 xor t22; 65 | t53 = id26; 66 | t54 = id30; 67 | t55 = t53 xor t54; 68 | t56 = t52 xor t55; 69 | t57 = ic6; 70 | t58 = t57 and t10; 71 | t59 = id1; 72 | t60 = t2 xor t59; 73 | t61 = id2; 74 | t62 = id3; 75 | t63 = t61 xor t62; 76 | t64 = t60 xor t63; 77 | t65 = id9; 78 | t66 = t5 xor t65; 79 | t67 = id10; 80 | t68 = id11; 81 | t69 = t67 xor t68; 82 | t70 = t66 xor t69; 83 | t71 = t64 xor t70; 84 | t72 = t58 xor t71; 85 | t73 = t56 xor t72; 86 | t74 = t12 xor t19; 87 | t75 = id24; 88 | t76 = id28; 89 | t77 = t75 xor t76; 90 | t78 = t74 xor t77; 91 | t79 = ic4; 92 | t80 = t79 and t10; 93 | t81 = t64 xor t41; 94 | t82 = t80 xor t81; 95 | t83 = t78 xor t82; 96 | t84 = t13 xor t20; 97 | t85 = id25; 98 | t86 = id29; 99 | t87 = t85 xor t86; 100 | t88 = t84 xor t87; 101 | t89 = ic5; 102 | t90 = t89 and t10; 103 | t91 = t70 xor t47; 104 | t92 = t90 xor t91; 105 | t93 = t88 xor t92; 106 | t94 = not t93; 107 | t95 = t83 and t94; 108 | t96 = t73 and t95; 109 | t97 = t51 and t96; 110 | t98 = t61 xor t38; 111 | t99 = t67 xor t44; 112 | t100 = t98 xor t99; 113 | t101 = ic2; 114 | t102 = t101 and t10; 115 | t103 = t75 xor t85; 116 | t104 = t53 xor t30; 117 | t105 = t103 xor t104; 118 | t106 = t18 xor t105; 119 | t107 = t102 xor t106; 120 | t108 = t100 xor t107; 121 | t109 = not t108; 122 | t110 = not t28; 123 | t111 = t59 xor t36; 124 | t112 = t65 xor t42; 125 | t113 = t111 xor t112; 126 | t114 = ic1; 127 | t115 = t114 and t10; 128 | t116 = t76 xor t86; 129 | t117 = t54 xor t31; 130 | t118 = t116 xor t117; 131 | t119 = t105 xor t118; 132 | t120 = t115 xor t119; 133 | t121 = t113 xor t120; 134 | t122 = t110 and t121; 135 | t123 = t109 and t122; 136 | t124 = t62 xor t39; 137 | t125 = t68 xor t45; 138 | t126 = t124 xor t125; 139 | t127 = ic3; 140 | t128 = t127 and t10; 141 | t129 = t25 xor t118; 142 | t130 = t128 xor t129; 143 | t131 = t126 xor t130; 144 | t132 = not t131; 145 | t133 = t123 and t132; 146 | t134 = not t121; 147 | t135 = t110 and t134; 148 | t136 = t109 and t135; 149 | t137 = t136 and t131; 150 | t138 = t108 and t135; 151 | t139 = t138 and t132; 152 | t140 = t137 or t139; 153 | t141 = t133 or t140; 154 | t142 = t28 and t134; 155 | t143 = t109 and t142; 156 | t144 = t143 and t132; 157 | t145 = t141 or t144; 158 | t146 = t97 and t145; 159 | t147 = t28 and t146; 160 | t148 = t2 xor t147; 161 | t149 = t110 and t109; 162 | t150 = t149 and t132; 163 | t151 = t135 and t109; 164 | t152 = t135 and t132; 165 | t153 = t151 or t152; 166 | t154 = t150 or t153; 167 | t155 = t134 and t109; 168 | t156 = t155 and t132; 169 | t157 = t154 or t156; 170 | t158 = t97 and t157; 171 | t159 = t28 and t158; 172 | t160 = t2 xor t159; 173 | t161 = t148 biimp t160; 174 | t162 = t121 and t146; 175 | t163 = t59 xor t162; 176 | t164 = t121 and t158; 177 | t165 = t59 xor t164; 178 | t166 = t163 biimp t165; 179 | t202 = not t83; 180 | t203 = t202 and t93; 181 | t204 = t73 and t203; 182 | t205 = t51 and t204; 183 | t206 = t205 and t145; 184 | t218 = t108 and t206; 185 | t219 = t67 xor t218; 186 | t209 = t205 and t157; 187 | t220 = t108 and t209; 188 | t221 = t67 xor t220; 189 | t222 = t219 biimp t221; 190 | t223 = t131 and t206; 191 | t224 = t68 xor t223; 192 | t225 = t131 and t209; 193 | t226 = t68 xor t225; 194 | t227 = t224 biimp t226; 195 | t177 = not t73; 196 | t228 = t177 and t203; 197 | t229 = t50 and t228; 198 | t230 = t229 and t145; 199 | t231 = t28 and t230; 200 | t232 = t6 xor t231; 201 | t233 = t229 and t157; 202 | t234 = t28 and t233; 203 | t235 = t6 xor t234; 204 | t236 = t232 biimp t235; 205 | t237 = t121 and t230; 206 | t238 = t42 xor t237; 207 | t239 = t121 and t233; 208 | t240 = t42 xor t239; 209 | t241 = t238 biimp t240; 210 | t242 = t108 and t230; 211 | t243 = t44 xor t242; 212 | t244 = t108 and t233; 213 | t245 = t44 xor t244; 214 | t246 = t243 biimp t245; 215 | t247 = t131 and t230; 216 | t248 = t45 xor t247; 217 | t249 = t131 and t233; 218 | t250 = t45 xor t249; 219 | t251 = t248 biimp t250; 220 | t252 = t108 and t142; 221 | t253 = t132 and t252; 222 | t254 = t228 and t51; 223 | t255 = t202 and t94; 224 | t256 = t177 and t255; 225 | t257 = t256 and t50; 226 | t258 = t73 and t255; 227 | t259 = t258 and t51; 228 | t260 = t257 or t259; 229 | t261 = t254 or t260; 230 | t178 = t177 and t95; 231 | t262 = t178 and t51; 232 | t263 = t261 or t262; 233 | t264 = t253 and t263; 234 | t265 = t83 and t264; 235 | t266 = t12 xor t265; 236 | t267 = t202 and t177; 237 | t268 = t267 and t51; 238 | t269 = t255 and t177; 239 | t270 = t255 and t51; 240 | t271 = t269 or t270; 241 | t272 = t268 or t271; 242 | t273 = t94 and t177; 243 | t274 = t273 and t51; 244 | t275 = t272 or t274; 245 | t276 = t253 and t275; 246 | t277 = t83 and t276; 247 | t278 = t12 xor t277; 248 | t279 = t266 biimp t278; 249 | t280 = t93 and t264; 250 | t281 = t13 xor t280; 251 | t282 = t93 and t276; 252 | t283 = t13 xor t282; 253 | t284 = t281 biimp t283; 254 | t285 = t73 and t264; 255 | t286 = t15 xor t285; 256 | t287 = t73 and t276; 257 | t288 = t15 xor t287; 258 | t289 = t286 biimp t288; 259 | t290 = t50 and t264; 260 | t291 = t16 xor t290; 261 | t292 = t50 and t276; 262 | t293 = t16 xor t292; 263 | t294 = t291 biimp t293; 264 | t167 = t108 and t146; 265 | t168 = t61 xor t167; 266 | t169 = t108 and t158; 267 | t170 = t61 xor t169; 268 | t171 = t168 biimp t170; 269 | t295 = t131 and t143; 270 | t296 = t295 and t263; 271 | t297 = t83 and t296; 272 | t298 = t19 xor t297; 273 | t299 = t295 and t275; 274 | t300 = t83 and t299; 275 | t301 = t19 xor t300; 276 | t302 = t298 biimp t301; 277 | t303 = t93 and t296; 278 | t304 = t20 xor t303; 279 | t305 = t93 and t299; 280 | t306 = t20 xor t305; 281 | t307 = t304 biimp t306; 282 | t308 = t73 and t296; 283 | t309 = t22 xor t308; 284 | t310 = t73 and t299; 285 | t311 = t22 xor t310; 286 | t312 = t309 biimp t311; 287 | t313 = t50 and t296; 288 | t314 = t23 xor t313; 289 | t315 = t50 and t299; 290 | t316 = t23 xor t315; 291 | t317 = t314 biimp t316; 292 | t318 = t108 and t122; 293 | t319 = t132 and t318; 294 | t320 = t319 and t263; 295 | t321 = t83 and t320; 296 | t322 = t75 xor t321; 297 | t323 = t319 and t275; 298 | t324 = t83 and t323; 299 | t325 = t75 xor t324; 300 | t326 = t322 biimp t325; 301 | t327 = t93 and t320; 302 | t328 = t85 xor t327; 303 | t329 = t93 and t323; 304 | t330 = t85 xor t329; 305 | t331 = t328 biimp t330; 306 | t332 = t73 and t320; 307 | t333 = t53 xor t332; 308 | t334 = t73 and t323; 309 | t335 = t53 xor t334; 310 | t336 = t333 biimp t335; 311 | t337 = t50 and t320; 312 | t338 = t30 xor t337; 313 | t339 = t50 and t323; 314 | t340 = t30 xor t339; 315 | t341 = t338 biimp t340; 316 | t342 = t131 and t123; 317 | t343 = t342 and t263; 318 | t344 = t83 and t343; 319 | t345 = t76 xor t344; 320 | t346 = t342 and t275; 321 | t347 = t83 and t346; 322 | t348 = t76 xor t347; 323 | t349 = t345 biimp t348; 324 | t350 = t93 and t343; 325 | t351 = t86 xor t350; 326 | t352 = t93 and t346; 327 | t353 = t86 xor t352; 328 | t354 = t351 biimp t353; 329 | t172 = t131 and t146; 330 | t173 = t62 xor t172; 331 | t174 = t131 and t158; 332 | t175 = t62 xor t174; 333 | t176 = t173 biimp t175; 334 | t355 = t73 and t343; 335 | t356 = t54 xor t355; 336 | t357 = t73 and t346; 337 | t358 = t54 xor t357; 338 | t359 = t356 biimp t358; 339 | t360 = t50 and t343; 340 | t361 = t31 xor t360; 341 | t362 = t50 and t346; 342 | t363 = t31 xor t362; 343 | t364 = t361 biimp t363; 344 | t179 = t50 and t178; 345 | t180 = t179 and t145; 346 | t181 = t28 and t180; 347 | t182 = t3 xor t181; 348 | t183 = t179 and t157; 349 | t184 = t28 and t183; 350 | t185 = t3 xor t184; 351 | t186 = t182 biimp t185; 352 | t187 = t121 and t180; 353 | t188 = t36 xor t187; 354 | t189 = t121 and t183; 355 | t190 = t36 xor t189; 356 | t191 = t188 biimp t190; 357 | t192 = t108 and t180; 358 | t193 = t38 xor t192; 359 | t194 = t108 and t183; 360 | t195 = t38 xor t194; 361 | t196 = t193 biimp t195; 362 | t197 = t131 and t180; 363 | t198 = t39 xor t197; 364 | t199 = t131 and t183; 365 | t200 = t39 xor t199; 366 | t201 = t198 biimp t200; 367 | t207 = t28 and t206; 368 | t208 = t5 xor t207; 369 | t210 = t28 and t209; 370 | t211 = t5 xor t210; 371 | t212 = t208 biimp t211; 372 | t213 = t121 and t206; 373 | t214 = t65 xor t213; 374 | t215 = t121 and t209; 375 | t216 = t65 xor t215; 376 | t217 = t214 biimp t216; 377 | 378 | tautology t161; 379 | tautology t166; 380 | tautology t222; 381 | tautology t227; 382 | tautology t236; 383 | tautology t241; 384 | tautology t246; 385 | tautology t251; 386 | tautology t279; 387 | tautology t284; 388 | tautology t289; 389 | tautology t294; 390 | tautology t171; 391 | tautology t302; 392 | tautology t307; 393 | tautology t312; 394 | tautology t317; 395 | tautology t326; 396 | tautology t331; 397 | tautology t336; 398 | tautology t341; 399 | tautology t349; 400 | tautology t354; 401 | tautology t176; 402 | tautology t359; 403 | tautology t364; 404 | tautology t186; 405 | tautology t191; 406 | tautology t196; 407 | tautology t201; 408 | tautology t212; 409 | tautology t217; 410 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CLP(B): Constraint Logic Programming over Boolean variables 2 | 3 | CLP(B), Constraint Logic Programming over Boolean variables, is 4 | available in Scryer Prolog and SWI-Prolog as 5 | [**library(clpb)**](https://www.scryer.pl/clpb.html). 6 | 7 | This repository contains usage examples and tests of the library. 8 | 9 | [**clpb.pdf**](clpb.pdf) is a _shortened version_ of the library 10 | documentation, intended as supplementary lecture material. 11 | 12 | **Project page**: 13 | 14 | [**https://www.metalevel.at/clpb/**](https://www.metalevel.at/clpb/) 15 | 16 | ## Using CLP(B) constraints 17 | 18 | Many of the examples use 19 | [**DCG notation**](https://www.metalevel.at/prolog/dcg) to 20 | describe lists of clauses. This lets you easily reason about the 21 | constraints that are being posted, change the order in which they are 22 | posted, and in general more conveniently experiment with CLP(B). 23 | In some examples, it is faster to post a single big conjunction 24 | instead of several smaller ones. 25 | 26 | I recommend you start with the following examples: 27 | 28 | 1. [**knights_and_knaves.pl**](knights_and_knaves.pl): Solution of 29 | several Boolean puzzles that appear in Raymond Smullyan's _What Is 30 | the Name of this Book_ and Maurice Kraitchik's _Mathematical 31 | Recreations_. These examples and other 32 | [**logic puzzles**](https://www.metalevel.at/prolog/puzzles) 33 | are good starting points for learning more about CLP(B). 34 | 35 | 2. [**xor.pl**](xor.pl): Verification of a digital circuit, expressing 36 | XOR with NAND gates: 37 | 38 | ![](figures/filler.png) ![XOR with NAND gates](figures/xor.png) 39 | 40 | This example uses *universally quantified* variables to express the 41 | output as a function of the input variables in residual goals. 42 | 43 | 3. [**matchsticks.pl**](matchsticks.pl): A puzzle involving 44 | matchsticks. See below for more information. 45 | 46 | 4. [**cycle_n.pl**](cycle_n.pl): Uses Boolean constraints to express 47 | independent sets and *maximal* independent sets (also called 48 | *kernels*) of the 49 | [cycle graph](https://en.wikipedia.org/wiki/Cycle_graph) CN. 50 | 51 | ![](figures/filler.png) ![Cycle graph C_7](figures/cycle7.png) ![](figures/filler20.png) ![Kernel of C_7](figures/cycle7_kernel.png) 52 | 53 | See below for more information about weighted solutions. 54 | 55 | 5. [**euler_172.pl**](euler_172.pl): CLP(B) solution of Project Euler 56 | [Problem 172](https://projecteuler.net/problem=172): How many 57 | 18-digit numbers n (without leading zeros) are there 58 | such that no digit occurs more than three times in n? 59 | 60 | 6. [**domino_tiling.pl**](domino_tiling.pl): Domino tiling of an 61 | M×N chessboard. Using CLP(B), it is easy to see 62 | that there are 12,988,816 ways to cover an 63 | 8×8 chessboard with dominoes: 64 | 65 | ![](figures/filler.png) ![Domino tiling of an 8x8 chessboard](figures/domino8x8.png) ![](figures/filler20.png) ![Domino tiling of a 2x8 chessboard](figures/domino2x8.png) 66 | 67 | Interestingly, the 68 | [Fibonacci numbers](http://mathworld.wolfram.com/FibonacciNumber.html) 69 | arise when we count the number of domino tilings of 70 | 2×N chessboards. An example is shown in the right 71 | figure. 72 | 73 | Other examples are useful as benchmarks: 74 | 75 | - [**langford.pl**](langford.pl): Count the number of [Langford pairings](https://en.wikipedia.org/wiki/Langford_pairing). 76 | - [**n_queens.pl**](n_queens.pl): CLP(B) formulation of the 77 | [N-queens puzzle](https://en.wikipedia.org/wiki/Eight_queens_puzzle). 78 | - [**pigeon.pl**](pigeon.pl): A simple allocation task. 79 | - [**schur.pl**](schur.pl): A problem related to 80 | [Schur's number](http://mathworld.wolfram.com/SchurNumber.html) as 81 | known from 82 | [Ramsey theory](http://mathworld.wolfram.com/RamseyTheory.html). 83 | 84 | The directory [**bddcalc**](bddcalc) contains a very simple calculator 85 | for BDDs. 86 | 87 | ### Matchsticks puzzle 88 | 89 | In [**matchsticks.pl**](matchsticks.pl), Boolean variables indicate 90 | whether a matchstick is placed at a specific position. The task is to 91 | eliminate all subsquares from the initial configuration in such a way 92 | that the maximum number of matchsticks is left in place: 93 | 94 | ![](figures/filler.png) ![Matchsticks initial configuration](figures/matchsticks1.png) 95 | 96 | We can use the CLP(B) predicate `weighted_maximum/3` to show that we 97 | need to remove at least 9 matchsticks to eliminate all subsquares. 98 | 99 | ![](figures/filler.png) ![Matchsticks without any subsquares](figures/matchsticks2.png) ![](figures/filler.png) ![Exactly 7 subsquares remaining](figures/matchsticks3.png) 100 | 101 | The left figure shows a sample solution, leaving the maximum number of 102 | matchsticks (31) in place. If you keep more matchsticks in place, 103 | subsquares remain. For example, the right figure contains exactly 104 | 7 subsquares, including the 4x4 outer square. 105 | 106 | CLP(B) constraints can be used to quickly generate, test and count 107 | solutions of such puzzles, among many other applications. For example, 108 | there are precisely 62,382,215,032 subsquare-free configurations that 109 | use exactly 18 matchsticks. This is the maximum number of such 110 | configurations for any fixed number of matchsticks on this grid. 111 | 112 | ### Independent sets and weighted kernels 113 | 114 | As another example, consider the following graph: 115 | 116 | ![](figures/filler20.png) ![Cycle graph with 100 nodes, C_100](figures/cycle100.png) 117 | 118 | It is the so-called 119 | [_cycle graph_](https://en.wikipedia.org/wiki/Cycle_graph) with 120 | 100 nodes, C100. Using CLP(B) constraints, it 121 | is easy to see that this graph has exactly 792,070,839,848,372,253,127 122 | _independent sets_, and exactly 1,630,580,875,002 _maximal_ 123 | independent sets, which are also called _kernels_. The gray nodes in 124 | the next picture show one such kernel: 125 | 126 | ![](figures/filler20.png) ![Maximal independent set of C_100](figures/cycle100_maximum.png) 127 | 128 | Suppose that we assign each node nj the weight 129 | wj =  (-1)νj, where νj 130 | denotes the number of ones in the binary representation 131 | of j. In the above figure, nodes with negative weight are 132 | drawn as squares, and nodes with positive weight are drawn as circles. 133 | 134 | Only 5 nodes (1, 25, 41, 73 and 97) of this kernel with 38 nodes have 135 | negative weight in this case, for a total weight of 28. In this case, 136 | the example shows a kernel with maximum weight. It is easy to 137 | find such kernels with the CLP(B) predicate `weighted_maximum/3`, and 138 | we can also compute other interesting facts: For example, there are 139 | exactly 256 kernels of maximum weight in this case. There are exactly 140 | 25,446,195,000 kernels with exactly 38 nodes. All kernels have between 141 | 34 and 50 nodes. For any fixed number of nodes, the maximum number of 142 | kernels (492,957,660,000) is attained with 41 nodes, and among these 143 | kernels, the maximum total weight is 25. 144 | 145 | By negating the coefficients of `weighted_maximum/3`, we can also find 146 | kernels with _minimum_ weight. For example: 147 | 148 | ![](figures/filler20.png) ![Kernel of C_100 with minimum weight](figures/cycle100_minimum.png) 149 | 150 | ## Implementation 151 | 152 | The implementation of `library(clpb)` is based on ordered and reduced 153 | **Binary Decision Diagrams** (BDDs). BDDs are an important data 154 | structure for representing Boolean functions and have many virtues 155 | that often allow us to solve interesting tasks efficiently. 156 | 157 | For example, the CLP(B) constraint `sat(card([2],[X,Y,Z]))` is 158 | translated to the following BDD: 159 | 160 | ![](figures/filler20.png) ![BDD for sat(card([2],[X,Y,Z]))](http://www.metalevel.at/card.svg) 161 | 162 | To inspect the BDD representation of Boolean constraints, set the 163 | Prolog flag `clpb_residuals` to `bdd`. For example: 164 | 165 | ?- set_prolog_flag(clpb_residuals, bdd). 166 | true. 167 | 168 | ?- sat(X+Y). 169 | node(2)- (v(X, 0)->true;node(1)), 170 | node(1)- (v(Y, 1)->true;false). 171 | 172 | Using `library(clpb)` is a good way to learn more about BDDs. The 173 | variable order is determined by the order in which the variables are 174 | first encountered in constraints. You can enforce arbitrary variable 175 | orders by first posting a tautology such as `+[1,V1,V2,...,Vn]`. 176 | 177 | For example: 178 | 179 |
180 | ?- sat(+[1,Y,X]), sat(X+Y).
181 | node(2)- (v(Y, 0)->true;node(1)),
182 | node(1)- (v(X, 1)->true;false).
183 | 
184 | 185 | You can render CLP(B)'s residual goals as BDDs in SWISH using the 186 | [**BDD renderer**](http://swish.swi-prolog.org/example/render_bdd.swinb). 187 | 188 | ## ZDD-based variant of `library(clpb)` 189 | 190 | There is a limited alternative version of `library(clpb)`, based on 191 | Zero-suppressed Binary Decision Diagrams (ZDDs). 192 | 193 | Please see the [**zdd**](zdd) directory for more information. Try the 194 | ZDD-based version for tasks where the BDD-based version runs out of 195 | memory. You must use `zdd_set_vars/1` before using `sat/1` though. 196 | 197 | ## Acknowledgments 198 | 199 | I am extremely grateful to: 200 | 201 | [**Jan Wielemaker**](http://eu.swi-prolog.org) for providing the 202 | Prolog system that made all this possible in the first place. 203 | 204 | [**Ulrich Neumerkel**](http://www.complang.tuwien.ac.at/ulrich/), who 205 | introduced me to constraint logic programming and CLP(B) in 206 | particular. If you are teaching Prolog, I strongly recommend you check 207 | out his 208 | [GUPU system](http://www.complang.tuwien.ac.at/ulrich/gupu/). 209 | 210 | [**Nysret Musliu**](http://dbai.tuwien.ac.at/staff/musliu/), my thesis 211 | advisor, whose interest in combinatorial tasks, constraint 212 | satisfaction and SAT solving highly motivated me to work in this 213 | area. 214 | 215 | [**Mats Carlsson**](https://www.sics.se/~matsc/), the designer and 216 | main implementor of SICStus Prolog and its visionary 217 | [CLP(B) library](https://sicstus.sics.se/sicstus/docs/latest4/html/sicstus.html/lib_002dclpb.html#lib_002dclpb). 218 | For any serious use of Prolog and constraints, make sure to check out 219 | his elegant and fast system. 220 | 221 | [**Donald Knuth**](http://www-cs-faculty.stanford.edu/~uno/) for the 222 | superb treatment of BDDs and ZDDs in his books and programs. 223 | -------------------------------------------------------------------------------- /bddcalc/c1908.cal: -------------------------------------------------------------------------------- 1 | /* BDD Calculator data file */ 2 | 3 | initial 8000 10000; 4 | 5 | inputs 6 | _101 _104 _107 _110 _113 _116 _119 _122 _125 _128 7 | _131 _134 _137 _140 _143 _146 _210 _214 _217 _221 8 | _224 _227 _234 _237 _469 _472 _475 _478 _898 _900 9 | _902 _952 _953 ; 10 | 11 | actions 12 | autoreorder 0 sift; 13 | 14 | t2 = _952; 15 | t3 = not t2; 16 | t4 = _953; 17 | t5 = not t4; 18 | t6 = _146; 19 | t7 = not t6; 20 | t8 = _143; 21 | t9 = not t8; 22 | t10 = not t9; 23 | t11 = t7 nand t10; 24 | t12 = not t7; 25 | t13 = t9 nand t12; 26 | t14 = t11 nand t13; 27 | t15 = _128; 28 | t16 = not t15; 29 | t17 = not t16; 30 | t18 = t14 nand t17; 31 | t19 = not t14; 32 | t20 = t16 nand t19; 33 | t21 = t18 nand t20; 34 | t22 = _125; 35 | t23 = not t22; 36 | t24 = not t23; 37 | t25 = t21 nand t24; 38 | t26 = not t21; 39 | t27 = t23 nand t26; 40 | t28 = t25 nand t27; 41 | t29 = _224; 42 | t30 = t29 and t5; 43 | t31 = not t30; 44 | t32 = t28 nand t31; 45 | t33 = not t28; 46 | t34 = t30 nand t33; 47 | t35 = t32 nand t34; 48 | t36 = not t35; 49 | t37 = _107; 50 | t38 = not t37; 51 | t39 = _104; 52 | t40 = not t39; 53 | t41 = not t40; 54 | t42 = t38 nand t41; 55 | t43 = not t38; 56 | t44 = t40 nand t43; 57 | t45 = t42 nand t44; 58 | t46 = _101; 59 | t47 = not t46; 60 | t48 = not t47; 61 | t49 = t45 nand t48; 62 | t50 = not t45; 63 | t51 = t47 nand t50; 64 | t52 = t49 nand t51; 65 | t53 = not t52; 66 | t54 = _119; 67 | t55 = not t54; 68 | t56 = _116; 69 | t57 = not t56; 70 | t58 = not t57; 71 | t59 = t55 nand t58; 72 | t60 = not t55; 73 | t61 = t57 nand t60; 74 | t62 = t59 nand t61; 75 | t63 = _113; 76 | t64 = not t63; 77 | t65 = not t64; 78 | t66 = t62 nand t65; 79 | t67 = not t62; 80 | t68 = t64 nand t67; 81 | t69 = t66 nand t68; 82 | t70 = not t69; 83 | t71 = t53 nand t70; 84 | t72 = not t53; 85 | t73 = t69 nand t72; 86 | t74 = t71 nand t73; 87 | t75 = _122; 88 | t76 = not t75; 89 | t77 = _110; 90 | t78 = not t77; 91 | t79 = not t78; 92 | t80 = t76 nand t79; 93 | t81 = not t76; 94 | t82 = t78 nand t81; 95 | t83 = t80 nand t82; 96 | t84 = not t83; 97 | t85 = not t84; 98 | t86 = t74 nand t85; 99 | t87 = not t74; 100 | t88 = t84 nand t87; 101 | t89 = t86 nand t88; 102 | t90 = not t89; 103 | t91 = t36 nand t90; 104 | t92 = not t36; 105 | t93 = t89 nand t92; 106 | t94 = t91 nand t93; 107 | t95 = not t94; 108 | t96 = _902; 109 | t97 = not t96; 110 | t98 = t95 nand t97; 111 | t99 = _210; 112 | t100 = _237; 113 | t101 = not t100; 114 | t102 = t101 nand t97; 115 | t103 = t99 nand t102; 116 | t104 = not t103; 117 | t105 = t98 nand t104; 118 | t106 = not t98; 119 | t107 = t103 nand t106; 120 | t108 = t105 nand t107; 121 | t109 = not t108; 122 | t110 = _140; 123 | t111 = not t110; 124 | t112 = not t111; 125 | t113 = t78 nand t112; 126 | t114 = t111 nand t79; 127 | t115 = t113 nand t114; 128 | t116 = _227; 129 | t117 = t116 and t5; 130 | t118 = not t117; 131 | t119 = t115 nand t118; 132 | t120 = not t115; 133 | t121 = t117 nand t120; 134 | t122 = t119 nand t121; 135 | t123 = not t26; 136 | t124 = t52 nand t123; 137 | t125 = t26 nand t53; 138 | t126 = t124 nand t125; 139 | t127 = _137; 140 | t128 = not t127; 141 | t129 = _134; 142 | t130 = not t129; 143 | t131 = not t130; 144 | t132 = t128 nand t131; 145 | t133 = not t128; 146 | t134 = t130 nand t133; 147 | t135 = t132 nand t134; 148 | t136 = _131; 149 | t137 = not t136; 150 | t138 = not t137; 151 | t139 = t135 nand t138; 152 | t140 = not t135; 153 | t141 = t137 nand t140; 154 | t142 = t139 nand t141; 155 | t143 = not t142; 156 | t144 = not t143; 157 | t145 = t126 nand t144; 158 | t146 = not t126; 159 | t147 = t143 nand t146; 160 | t148 = t145 nand t147; 161 | t149 = not t148; 162 | t150 = not t149; 163 | t151 = t122 nand t150; 164 | t152 = not t122; 165 | t153 = t149 nand t152; 166 | t154 = t151 nand t153; 167 | t155 = t154 nand t97; 168 | t156 = _469; 169 | t157 = not t156; 170 | t158 = not t157; 171 | t159 = t155 nand t158; 172 | t160 = not t155; 173 | t161 = t157 nand t160; 174 | t162 = t159 nand t161; 175 | t163 = not t162; 176 | t164 = _214; 177 | t165 = t164 nand t102; 178 | t166 = t99 and t101; 179 | t167 = t166 and t5; 180 | t168 = not t167; 181 | t169 = t47 nand t168; 182 | t170 = t167 nand t48; 183 | t171 = t169 nand t170; 184 | t172 = not t171; 185 | t173 = t143 nand t26; 186 | t174 = t21 nand t144; 187 | t175 = t173 nand t174; 188 | t176 = not t70; 189 | t177 = t175 nand t176; 190 | t178 = not t175; 191 | t179 = t70 nand t178; 192 | t180 = t177 nand t179; 193 | t181 = not t180; 194 | t182 = not t181; 195 | t183 = t172 nand t182; 196 | t184 = not t172; 197 | t185 = t181 nand t184; 198 | t186 = t183 nand t185; 199 | t187 = t186 nand t97; 200 | t188 = _472; 201 | t189 = not t188; 202 | t190 = not t189; 203 | t191 = t187 nand t190; 204 | t192 = not t187; 205 | t193 = t189 nand t192; 206 | t194 = t191 nand t193; 207 | t195 = not t194; 208 | t196 = t23 nand t112; 209 | t197 = t111 nand t24; 210 | t198 = t196 nand t197; 211 | t199 = t198 nand t12; 212 | t200 = not t198; 213 | t201 = t7 nand t200; 214 | t202 = t199 nand t201; 215 | t203 = t164 and t101; 216 | t204 = t203 and t5; 217 | t205 = not t204; 218 | t206 = t9 nand t205; 219 | t207 = t204 nand t10; 220 | t208 = t206 nand t207; 221 | t209 = t208 nand t138; 222 | t210 = not t208; 223 | t211 = t137 nand t210; 224 | t212 = t209 nand t211; 225 | t213 = not t212; 226 | t214 = t202 nand t213; 227 | t215 = not t202; 228 | t216 = t212 nand t215; 229 | t217 = t214 nand t216; 230 | t218 = t76 nand t65; 231 | t219 = t64 nand t81; 232 | t220 = t218 nand t219; 233 | t221 = t220 nand t41; 234 | t222 = not t220; 235 | t223 = t40 nand t222; 236 | t224 = t221 nand t223; 237 | t225 = not t224; 238 | t226 = t217 nand t225; 239 | t227 = not t217; 240 | t228 = t224 nand t227; 241 | t229 = t226 nand t228; 242 | t230 = t229 nand t97; 243 | t231 = _475; 244 | t232 = not t231; 245 | t233 = not t232; 246 | t234 = t230 nand t233; 247 | t235 = not t230; 248 | t236 = t232 nand t235; 249 | t237 = t234 nand t236; 250 | t238 = not t237; 251 | t239 = t16 nand t60; 252 | t240 = t55 nand t17; 253 | t241 = t239 nand t240; 254 | t242 = t241 nand t79; 255 | t243 = not t241; 256 | t244 = t78 nand t243; 257 | t245 = t242 nand t244; 258 | t246 = not t245; 259 | t247 = not t246; 260 | t248 = t215 nand t247; 261 | t249 = not t215; 262 | t250 = t246 nand t249; 263 | t251 = t248 nand t250; 264 | t252 = _221; 265 | t253 = _234; 266 | t254 = t252 and t253; 267 | t255 = t254 and t5; 268 | t256 = t255 nand t133; 269 | t257 = not t255; 270 | t258 = t128 nand t257; 271 | t259 = t256 nand t258; 272 | t260 = not t259; 273 | t261 = not t260; 274 | t262 = t251 nand t261; 275 | t263 = not t251; 276 | t264 = t260 nand t263; 277 | t265 = t262 nand t264; 278 | t266 = t265 nand t97; 279 | t267 = _217; 280 | t268 = t253 nand t97; 281 | t269 = t267 nand t268; 282 | t270 = not t269; 283 | t271 = t266 nand t270; 284 | t272 = not t266; 285 | t273 = t269 nand t272; 286 | t274 = t271 nand t273; 287 | t275 = not t274; 288 | t276 = t76 nand t58; 289 | t277 = t57 nand t81; 290 | t278 = t276 nand t277; 291 | t279 = t278 nand t43; 292 | t280 = not t278; 293 | t281 = t38 nand t280; 294 | t282 = t279 nand t281; 295 | t283 = t9 nand t17; 296 | t284 = t16 nand t10; 297 | t285 = t283 nand t284; 298 | t286 = t285 nand t131; 299 | t287 = not t285; 300 | t288 = t130 nand t287; 301 | t289 = t286 nand t288; 302 | t290 = not t289; 303 | t291 = t282 nand t290; 304 | t292 = not t282; 305 | t293 = t289 nand t292; 306 | t294 = t291 nand t293; 307 | t295 = t267 and t253; 308 | t296 = t295 and t5; 309 | t297 = not t296; 310 | t298 = t294 nand t297; 311 | t299 = not t294; 312 | t300 = t296 nand t299; 313 | t301 = t298 nand t300; 314 | t302 = t301 nand t97; 315 | t303 = _478; 316 | t304 = not t303; 317 | t305 = not t304; 318 | t306 = t302 nand t305; 319 | t307 = not t302; 320 | t308 = t304 nand t307; 321 | t309 = t306 nand t308; 322 | t310 = not t309; 323 | t311 = t275 and t310; 324 | t312 = t238 and t311; 325 | t313 = t195 and t312; 326 | t314 = t165 and t313; 327 | t315 = t163 and t314; 328 | t316 = t109 and t315; 329 | t317 = t252 nand t268; 330 | t318 = t316 nand t317; 331 | t319 = t5 and t318; 332 | t320 = t3 and t319; 333 | t321 = t320 and t3; 334 | t322 = t2 and t319; 335 | t323 = t310 and t238; 336 | t324 = t274 and t194; 337 | t325 = t165 and t108; 338 | t326 = t317 and t163; 339 | t327 = t325 and t326; 340 | t328 = t324 and t327; 341 | t329 = t323 and t328; 342 | t330 = _898; 343 | t331 = not t330; 344 | t332 = t331 and t96; 345 | t333 = t4 and t332; 346 | t334 = t253 nand t100; 347 | t335 = t333 nand t334; 348 | t336 = t2 and t5; 349 | t337 = t336 nand t334; 350 | t338 = t335 nand t337; 351 | t339 = t329 nand t338; 352 | t340 = t309 and t238; 353 | t341 = t275 and t194; 354 | t342 = t341 and t327; 355 | t343 = t340 and t342; 356 | t344 = t343 nand t338; 357 | t345 = t310 and t237; 358 | t346 = t345 and t342; 359 | t347 = t346 nand t338; 360 | t348 = t274 and t195; 361 | t349 = t317 and t162; 362 | t350 = t325 and t349; 363 | t351 = t348 and t350; 364 | t352 = t323 and t351; 365 | t353 = t352 nand t338; 366 | t354 = t275 and t195; 367 | t355 = t354 and t350; 368 | t356 = t340 and t355; 369 | t357 = t356 nand t338; 370 | t358 = t341 and t350; 371 | t359 = t323 and t358; 372 | t360 = t359 nand t338; 373 | t361 = t345 and t355; 374 | t362 = t361 nand t338; 375 | t363 = t360 and t362; 376 | t364 = t357 and t363; 377 | t365 = t353 and t364; 378 | t366 = t347 and t365; 379 | t367 = t344 and t366; 380 | t368 = t339 and t367; 381 | t369 = t309 and t237; 382 | t370 = t354 and t327; 383 | t371 = t369 and t370; 384 | t372 = t371 nand t338; 385 | t373 = t368 and t372; 386 | t374 = t369 and t358; 387 | t375 = _900; 388 | t376 = not t375; 389 | t377 = t376 and t96; 390 | t378 = t4 and t377; 391 | t379 = t378 nand t334; 392 | t380 = t379 nand t337; 393 | t381 = t374 nand t380; 394 | t382 = t165 and t109; 395 | t383 = t382 and t349; 396 | t384 = t348 and t383; 397 | t385 = t345 and t384; 398 | t386 = t385 nand t380; 399 | t387 = t324 and t383; 400 | t388 = t323 and t387; 401 | t389 = t388 nand t380; 402 | t390 = t341 and t383; 403 | t391 = t340 and t390; 404 | t392 = t391 nand t380; 405 | t393 = t345 and t390; 406 | t394 = t393 nand t380; 407 | t395 = t348 and t327; 408 | t396 = t345 and t395; 409 | t397 = t396 nand t380; 410 | t398 = t324 and t350; 411 | t399 = t340 and t398; 412 | t400 = t399 nand t380; 413 | t401 = t397 and t400; 414 | t402 = t394 and t401; 415 | t403 = t392 and t402; 416 | t404 = t389 and t403; 417 | t405 = t386 and t404; 418 | t406 = t381 and t405; 419 | t407 = t345 and t398; 420 | t408 = t407 nand t380; 421 | t409 = t406 and t408; 422 | t410 = t373 and t409; 423 | t411 = not t317; 424 | t412 = t411 and t163; 425 | t413 = t382 and t412; 426 | t414 = t354 and t413; 427 | t415 = t323 and t414; 428 | t416 = t336 and t334; 429 | t417 = t415 nand t416; 430 | t418 = t382 and t326; 431 | t419 = t348 and t418; 432 | t420 = t323 and t419; 433 | t421 = t420 nand t416; 434 | t422 = t354 and t418; 435 | t423 = t340 and t422; 436 | t424 = t423 nand t416; 437 | t425 = t345 and t422; 438 | t426 = t425 nand t416; 439 | t427 = t341 and t418; 440 | t428 = t323 and t427; 441 | t429 = t428 nand t416; 442 | t430 = t323 and t370; 443 | t431 = t430 nand t416; 444 | t432 = t354 and t383; 445 | t433 = t323 and t432; 446 | t434 = t433 nand t416; 447 | t435 = t431 and t434; 448 | t436 = t429 and t435; 449 | t437 = t426 and t436; 450 | t438 = t424 and t437; 451 | t439 = t421 and t438; 452 | t440 = t417 and t439; 453 | t441 = not t165; 454 | t442 = t441 and t109; 455 | t443 = t442 and t326; 456 | t444 = t354 and t443; 457 | t445 = t323 and t444; 458 | t446 = t445 nand t416; 459 | t447 = t440 and t446; 460 | t448 = t410 and t447; 461 | t449 = t322 and t448; 462 | t450 = t321 nor t449; 463 | t451 = t319 and t3; 464 | t452 = t382 and t163; 465 | t453 = t354 and t452; 466 | t454 = t323 and t453; 467 | t455 = t454 nand t334; 468 | t456 = t420 nand t334; 469 | t457 = t423 nand t334; 470 | t458 = t425 nand t334; 471 | t459 = t428 nand t334; 472 | t460 = t430 nand t334; 473 | t461 = t433 nand t334; 474 | t462 = t460 and t461; 475 | t463 = t459 and t462; 476 | t464 = t458 and t463; 477 | t465 = t457 and t464; 478 | t466 = t456 and t465; 479 | t467 = t455 and t466; 480 | t468 = t109 and t326; 481 | t469 = t354 and t468; 482 | t470 = t323 and t469; 483 | t471 = t470 nand t334; 484 | t472 = t467 and t471; 485 | t473 = t410 and t472; 486 | t474 = t319 and t473; 487 | t475 = t451 nor t474; 488 | t476 = t450 biimp t475; 489 | t477 = t35 nand t90; 490 | t478 = t89 nand t36; 491 | t479 = t477 nand t478; 492 | t480 = t99 and t102; 493 | t481 = t480 and t96; 494 | t482 = t373 nand t409; 495 | t483 = t481 and t482; 496 | t484 = not t483; 497 | t485 = t479 nand t484; 498 | t486 = not t479; 499 | t487 = t483 nand t486; 500 | t488 = t485 nand t487; 501 | t489 = t3 nand t4; 502 | t490 = t488 and t489; 503 | t491 = t99 and t96; 504 | t492 = t491 and t482; 505 | t493 = not t492; 506 | t494 = t479 nand t493; 507 | t495 = t492 nand t486; 508 | t496 = t494 nand t495; 509 | t497 = t496 and t489; 510 | t498 = t490 biimp t497; 511 | t499 = t267 and t268; 512 | t500 = t499 and t96; 513 | t501 = t500 and t482; 514 | t502 = not t501; 515 | t503 = t265 nand t502; 516 | t504 = not t265; 517 | t505 = t501 nand t504; 518 | t506 = t503 nand t505; 519 | t507 = t489 and t506; 520 | t508 = t267 and t96; 521 | t509 = t508 and t482; 522 | t510 = not t509; 523 | t511 = t265 nand t510; 524 | t512 = t509 nand t504; 525 | t513 = t511 nand t512; 526 | t514 = t489 and t513; 527 | t515 = t507 biimp t514; 528 | 529 | tautology t476; 530 | tautology t498; 531 | tautology t515; 532 | -------------------------------------------------------------------------------- /bddcalc/c1355.cal: -------------------------------------------------------------------------------- 1 | /* BDD Calculator data file */ 2 | 3 | initial 10000 10000; 4 | 5 | inputs 6 | _1gat _8gat _15gat _22gat _29gat _36gat _43gat _50gat _57gat _64gat 7 | _71gat _78gat _85gat _92gat _99gat _106gat _113gat _120gat _127gat _134gat 8 | _141gat _148gat _155gat _162gat _169gat _176gat _183gat _190gat _197gat _204gat 9 | _211gat _218gat _225gat _226gat _227gat _228gat _229gat _230gat _231gat _232gat 10 | _233gat ; 11 | 12 | actions 13 | autoreorder 0 sift; 14 | 15 | t2 = _1gat; 16 | t3 = _29gat; 17 | t4 = t2 nand t3; 18 | t5 = t2 nand t4; 19 | t6 = t3 nand t4; 20 | t7 = t5 nand t6; 21 | t8 = _57gat; 22 | t9 = _85gat; 23 | t10 = t8 nand t9; 24 | t11 = t8 nand t10; 25 | t12 = t9 nand t10; 26 | t13 = t11 nand t12; 27 | t14 = t7 nand t13; 28 | t15 = t7 nand t14; 29 | t16 = t13 nand t14; 30 | t17 = t15 nand t16; 31 | t18 = _225gat; 32 | t19 = _233gat; 33 | t20 = t18 and t19; 34 | t21 = _113gat; 35 | t22 = _120gat; 36 | t23 = t21 nand t22; 37 | t24 = t21 nand t23; 38 | t25 = t22 nand t23; 39 | t26 = t24 nand t25; 40 | t27 = _127gat; 41 | t28 = _134gat; 42 | t29 = t27 nand t28; 43 | t30 = t27 nand t29; 44 | t31 = t28 nand t29; 45 | t32 = t30 nand t31; 46 | t33 = t26 nand t32; 47 | t34 = t26 nand t33; 48 | t35 = t32 nand t33; 49 | t36 = t34 nand t35; 50 | t37 = _141gat; 51 | t38 = _148gat; 52 | t39 = t37 nand t38; 53 | t40 = t37 nand t39; 54 | t41 = t38 nand t39; 55 | t42 = t40 nand t41; 56 | t43 = _155gat; 57 | t44 = _162gat; 58 | t45 = t43 nand t44; 59 | t46 = t43 nand t45; 60 | t47 = t44 nand t45; 61 | t48 = t46 nand t47; 62 | t49 = t42 nand t48; 63 | t50 = t42 nand t49; 64 | t51 = t48 nand t49; 65 | t52 = t50 nand t51; 66 | t53 = t36 nand t52; 67 | t54 = t36 nand t53; 68 | t55 = t52 nand t53; 69 | t56 = t54 nand t55; 70 | t57 = t20 nand t56; 71 | t58 = t20 nand t57; 72 | t59 = t56 nand t57; 73 | t60 = t58 nand t59; 74 | t61 = t17 nand t60; 75 | t62 = t17 nand t61; 76 | t63 = t60 nand t61; 77 | t64 = t62 nand t63; 78 | t65 = t28 nand t44; 79 | t66 = t28 nand t65; 80 | t67 = t44 nand t65; 81 | t68 = t66 nand t67; 82 | t69 = _190gat; 83 | t70 = _218gat; 84 | t71 = t69 nand t70; 85 | t72 = t69 nand t71; 86 | t73 = t70 nand t71; 87 | t74 = t72 nand t73; 88 | t75 = t68 nand t74; 89 | t76 = t68 nand t75; 90 | t77 = t74 nand t75; 91 | t78 = t76 nand t77; 92 | t79 = _232gat; 93 | t80 = t79 and t19; 94 | t81 = _36gat; 95 | t82 = t3 nand t81; 96 | t83 = t3 nand t82; 97 | t84 = t81 nand t82; 98 | t85 = t83 nand t84; 99 | t86 = _43gat; 100 | t87 = _50gat; 101 | t88 = t86 nand t87; 102 | t89 = t86 nand t88; 103 | t90 = t87 nand t88; 104 | t91 = t89 nand t90; 105 | t92 = t85 nand t91; 106 | t93 = t85 nand t92; 107 | t94 = t91 nand t92; 108 | t95 = t93 nand t94; 109 | t96 = _92gat; 110 | t97 = t9 nand t96; 111 | t98 = t9 nand t97; 112 | t99 = t96 nand t97; 113 | t100 = t98 nand t99; 114 | t101 = _99gat; 115 | t102 = _106gat; 116 | t103 = t101 nand t102; 117 | t104 = t101 nand t103; 118 | t105 = t102 nand t103; 119 | t106 = t104 nand t105; 120 | t107 = t100 nand t106; 121 | t108 = t100 nand t107; 122 | t109 = t106 nand t107; 123 | t110 = t108 nand t109; 124 | t111 = t95 nand t110; 125 | t112 = t95 nand t111; 126 | t113 = t110 nand t111; 127 | t114 = t112 nand t113; 128 | t115 = t80 nand t114; 129 | t116 = t80 nand t115; 130 | t117 = t114 nand t115; 131 | t118 = t116 nand t117; 132 | t119 = t78 nand t118; 133 | t120 = t78 nand t119; 134 | t121 = t118 nand t119; 135 | t122 = t120 nand t121; 136 | t123 = not t122; 137 | t124 = t27 nand t43; 138 | t125 = t27 nand t124; 139 | t126 = t43 nand t124; 140 | t127 = t125 nand t126; 141 | t128 = _183gat; 142 | t129 = _211gat; 143 | t130 = t128 nand t129; 144 | t131 = t128 nand t130; 145 | t132 = t129 nand t130; 146 | t133 = t131 nand t132; 147 | t134 = t127 nand t133; 148 | t135 = t127 nand t134; 149 | t136 = t133 nand t134; 150 | t137 = t135 nand t136; 151 | t138 = _231gat; 152 | t139 = t138 and t19; 153 | t140 = _8gat; 154 | t141 = t2 nand t140; 155 | t142 = t2 nand t141; 156 | t143 = t140 nand t141; 157 | t144 = t142 nand t143; 158 | t145 = _15gat; 159 | t146 = _22gat; 160 | t147 = t145 nand t146; 161 | t148 = t145 nand t147; 162 | t149 = t146 nand t147; 163 | t150 = t148 nand t149; 164 | t151 = t144 nand t150; 165 | t152 = t144 nand t151; 166 | t153 = t150 nand t151; 167 | t154 = t152 nand t153; 168 | t155 = _64gat; 169 | t156 = t8 nand t155; 170 | t157 = t8 nand t156; 171 | t158 = t155 nand t156; 172 | t159 = t157 nand t158; 173 | t160 = _71gat; 174 | t161 = _78gat; 175 | t162 = t160 nand t161; 176 | t163 = t160 nand t162; 177 | t164 = t161 nand t162; 178 | t165 = t163 nand t164; 179 | t166 = t159 nand t165; 180 | t167 = t159 nand t166; 181 | t168 = t165 nand t166; 182 | t169 = t167 nand t168; 183 | t170 = t154 nand t169; 184 | t171 = t154 nand t170; 185 | t172 = t169 nand t170; 186 | t173 = t171 nand t172; 187 | t174 = t139 nand t173; 188 | t175 = t139 nand t174; 189 | t176 = t173 nand t174; 190 | t177 = t175 nand t176; 191 | t178 = t137 nand t177; 192 | t179 = t137 nand t178; 193 | t180 = t177 nand t178; 194 | t181 = t179 nand t180; 195 | t182 = t21 nand t37; 196 | t183 = t21 nand t182; 197 | t184 = t37 nand t182; 198 | t185 = t183 nand t184; 199 | t186 = _169gat; 200 | t187 = _197gat; 201 | t188 = t186 nand t187; 202 | t189 = t186 nand t188; 203 | t190 = t187 nand t188; 204 | t191 = t189 nand t190; 205 | t192 = t185 nand t191; 206 | t193 = t185 nand t192; 207 | t194 = t191 nand t192; 208 | t195 = t193 nand t194; 209 | t196 = _229gat; 210 | t197 = t196 and t19; 211 | t198 = t154 nand t95; 212 | t199 = t154 nand t198; 213 | t200 = t95 nand t198; 214 | t201 = t199 nand t200; 215 | t202 = t197 nand t201; 216 | t203 = t197 nand t202; 217 | t204 = t201 nand t202; 218 | t205 = t203 nand t204; 219 | t206 = t195 nand t205; 220 | t207 = t195 nand t206; 221 | t208 = t205 nand t206; 222 | t209 = t207 nand t208; 223 | t210 = t22 nand t38; 224 | t211 = t22 nand t210; 225 | t212 = t38 nand t210; 226 | t213 = t211 nand t212; 227 | t214 = _176gat; 228 | t215 = _204gat; 229 | t216 = t214 nand t215; 230 | t217 = t214 nand t216; 231 | t218 = t215 nand t216; 232 | t219 = t217 nand t218; 233 | t220 = t213 nand t219; 234 | t221 = t213 nand t220; 235 | t222 = t219 nand t220; 236 | t223 = t221 nand t222; 237 | t224 = _230gat; 238 | t225 = t224 and t19; 239 | t226 = t169 nand t110; 240 | t227 = t169 nand t226; 241 | t228 = t110 nand t226; 242 | t229 = t227 nand t228; 243 | t230 = t225 nand t229; 244 | t231 = t225 nand t230; 245 | t232 = t229 nand t230; 246 | t233 = t231 nand t232; 247 | t234 = t223 nand t233; 248 | t235 = t223 nand t234; 249 | t236 = t233 nand t234; 250 | t237 = t235 nand t236; 251 | t238 = not t237; 252 | t239 = t209 and t238; 253 | t240 = t181 and t239; 254 | t241 = t123 and t240; 255 | t242 = t145 nand t86; 256 | t243 = t145 nand t242; 257 | t244 = t86 nand t242; 258 | t245 = t243 nand t244; 259 | t246 = t160 nand t101; 260 | t247 = t160 nand t246; 261 | t248 = t101 nand t246; 262 | t249 = t247 nand t248; 263 | t250 = t245 nand t249; 264 | t251 = t245 nand t250; 265 | t252 = t249 nand t250; 266 | t253 = t251 nand t252; 267 | t254 = _227gat; 268 | t255 = t254 and t19; 269 | t256 = t186 nand t214; 270 | t257 = t186 nand t256; 271 | t258 = t214 nand t256; 272 | t259 = t257 nand t258; 273 | t260 = t128 nand t69; 274 | t261 = t128 nand t260; 275 | t262 = t69 nand t260; 276 | t263 = t261 nand t262; 277 | t264 = t259 nand t263; 278 | t265 = t259 nand t264; 279 | t266 = t263 nand t264; 280 | t267 = t265 nand t266; 281 | t268 = t36 nand t267; 282 | t269 = t36 nand t268; 283 | t270 = t267 nand t268; 284 | t271 = t269 nand t270; 285 | t272 = t255 nand t271; 286 | t273 = t255 nand t272; 287 | t274 = t271 nand t272; 288 | t275 = t273 nand t274; 289 | t276 = t253 nand t275; 290 | t277 = t253 nand t276; 291 | t278 = t275 nand t276; 292 | t279 = t277 nand t278; 293 | t280 = not t279; 294 | t281 = not t64; 295 | t282 = t140 nand t81; 296 | t283 = t140 nand t282; 297 | t284 = t81 nand t282; 298 | t285 = t283 nand t284; 299 | t286 = t155 nand t96; 300 | t287 = t155 nand t286; 301 | t288 = t96 nand t286; 302 | t289 = t287 nand t288; 303 | t290 = t285 nand t289; 304 | t291 = t285 nand t290; 305 | t292 = t289 nand t290; 306 | t293 = t291 nand t292; 307 | t294 = _226gat; 308 | t295 = t294 and t19; 309 | t296 = t187 nand t215; 310 | t297 = t187 nand t296; 311 | t298 = t215 nand t296; 312 | t299 = t297 nand t298; 313 | t300 = t129 nand t70; 314 | t301 = t129 nand t300; 315 | t302 = t70 nand t300; 316 | t303 = t301 nand t302; 317 | t304 = t299 nand t303; 318 | t305 = t299 nand t304; 319 | t306 = t303 nand t304; 320 | t307 = t305 nand t306; 321 | t308 = t267 nand t307; 322 | t309 = t267 nand t308; 323 | t310 = t307 nand t308; 324 | t311 = t309 nand t310; 325 | t312 = t295 nand t311; 326 | t313 = t295 nand t312; 327 | t314 = t311 nand t312; 328 | t315 = t313 nand t314; 329 | t316 = t293 nand t315; 330 | t317 = t293 nand t316; 331 | t318 = t315 nand t316; 332 | t319 = t317 nand t318; 333 | t320 = t281 and t319; 334 | t321 = t280 and t320; 335 | t322 = t146 nand t87; 336 | t323 = t146 nand t322; 337 | t324 = t87 nand t322; 338 | t325 = t323 nand t324; 339 | t326 = t161 nand t102; 340 | t327 = t161 nand t326; 341 | t328 = t102 nand t326; 342 | t329 = t327 nand t328; 343 | t330 = t325 nand t329; 344 | t331 = t325 nand t330; 345 | t332 = t329 nand t330; 346 | t333 = t331 nand t332; 347 | t334 = _228gat; 348 | t335 = t334 and t19; 349 | t336 = t52 nand t307; 350 | t337 = t52 nand t336; 351 | t338 = t307 nand t336; 352 | t339 = t337 nand t338; 353 | t340 = t335 nand t339; 354 | t341 = t335 nand t340; 355 | t342 = t339 nand t340; 356 | t343 = t341 nand t342; 357 | t344 = t333 nand t343; 358 | t345 = t333 nand t344; 359 | t346 = t343 nand t344; 360 | t347 = t345 nand t346; 361 | t348 = not t347; 362 | t349 = t321 and t348; 363 | t350 = not t319; 364 | t351 = t281 and t350; 365 | t352 = t280 and t351; 366 | t353 = t352 and t347; 367 | t354 = t279 and t351; 368 | t355 = t354 and t348; 369 | t356 = t353 or t355; 370 | t357 = t349 or t356; 371 | t358 = t64 and t350; 372 | t359 = t280 and t358; 373 | t360 = t359 and t348; 374 | t361 = t357 or t360; 375 | t362 = t241 and t361; 376 | t363 = t64 and t362; 377 | t364 = t2 nand t363; 378 | t365 = t2 nand t364; 379 | t366 = t363 nand t364; 380 | t367 = t365 nand t366; 381 | t368 = t281 and t280; 382 | t369 = t368 and t348; 383 | t370 = t351 and t280; 384 | t371 = t351 and t348; 385 | t372 = t370 or t371; 386 | t373 = t369 or t372; 387 | t374 = t350 and t280; 388 | t375 = t374 and t348; 389 | t376 = t373 or t375; 390 | t377 = t241 and t376; 391 | t378 = t64 and t377; 392 | t379 = t2 nand t378; 393 | t380 = t2 nand t379; 394 | t381 = t378 nand t379; 395 | t382 = t380 nand t381; 396 | t383 = t367 biimp t382; 397 | t384 = t319 and t362; 398 | t385 = t140 nand t384; 399 | t386 = t140 nand t385; 400 | t387 = t384 nand t385; 401 | t388 = t386 nand t387; 402 | t389 = t319 and t377; 403 | t390 = t140 nand t389; 404 | t391 = t140 nand t390; 405 | t392 = t389 nand t390; 406 | t393 = t391 nand t392; 407 | t394 = t388 biimp t393; 408 | t466 = not t209; 409 | t467 = t466 and t237; 410 | t468 = t181 and t467; 411 | t469 = t123 and t468; 412 | t470 = t469 and t361; 413 | t494 = t279 and t470; 414 | t495 = t160 nand t494; 415 | t496 = t160 nand t495; 416 | t497 = t494 nand t495; 417 | t498 = t496 nand t497; 418 | t476 = t469 and t376; 419 | t499 = t279 and t476; 420 | t500 = t160 nand t499; 421 | t501 = t160 nand t500; 422 | t502 = t499 nand t500; 423 | t503 = t501 nand t502; 424 | t504 = t498 biimp t503; 425 | t505 = t347 and t470; 426 | t506 = t161 nand t505; 427 | t507 = t161 nand t506; 428 | t508 = t505 nand t506; 429 | t509 = t507 nand t508; 430 | t510 = t347 and t476; 431 | t511 = t161 nand t510; 432 | t512 = t161 nand t511; 433 | t513 = t510 nand t511; 434 | t514 = t512 nand t513; 435 | t515 = t509 biimp t514; 436 | t417 = not t181; 437 | t516 = t417 and t467; 438 | t517 = t122 and t516; 439 | t518 = t517 and t361; 440 | t519 = t64 and t518; 441 | t520 = t9 nand t519; 442 | t521 = t9 nand t520; 443 | t522 = t519 nand t520; 444 | t523 = t521 nand t522; 445 | t524 = t517 and t376; 446 | t525 = t64 and t524; 447 | t526 = t9 nand t525; 448 | t527 = t9 nand t526; 449 | t528 = t525 nand t526; 450 | t529 = t527 nand t528; 451 | t530 = t523 biimp t529; 452 | t531 = t319 and t518; 453 | t532 = t96 nand t531; 454 | t533 = t96 nand t532; 455 | t534 = t531 nand t532; 456 | t535 = t533 nand t534; 457 | t536 = t319 and t524; 458 | t537 = t96 nand t536; 459 | t538 = t96 nand t537; 460 | t539 = t536 nand t537; 461 | t540 = t538 nand t539; 462 | t541 = t535 biimp t540; 463 | t542 = t279 and t518; 464 | t543 = t101 nand t542; 465 | t544 = t101 nand t543; 466 | t545 = t542 nand t543; 467 | t546 = t544 nand t545; 468 | t547 = t279 and t524; 469 | t548 = t101 nand t547; 470 | t549 = t101 nand t548; 471 | t550 = t547 nand t548; 472 | t551 = t549 nand t550; 473 | t552 = t546 biimp t551; 474 | t553 = t347 and t518; 475 | t554 = t102 nand t553; 476 | t555 = t102 nand t554; 477 | t556 = t553 nand t554; 478 | t557 = t555 nand t556; 479 | t558 = t347 and t524; 480 | t559 = t102 nand t558; 481 | t560 = t102 nand t559; 482 | t561 = t558 nand t559; 483 | t562 = t560 nand t561; 484 | t563 = t557 biimp t562; 485 | t564 = t279 and t358; 486 | t565 = t348 and t564; 487 | t566 = t516 and t123; 488 | t567 = t466 and t238; 489 | t568 = t417 and t567; 490 | t569 = t568 and t122; 491 | t570 = t181 and t567; 492 | t571 = t570 and t123; 493 | t572 = t569 or t571; 494 | t573 = t566 or t572; 495 | t418 = t417 and t239; 496 | t574 = t418 and t123; 497 | t575 = t573 or t574; 498 | t576 = t565 and t575; 499 | t577 = t209 and t576; 500 | t578 = t21 nand t577; 501 | t579 = t21 nand t578; 502 | t580 = t577 nand t578; 503 | t581 = t579 nand t580; 504 | t582 = t466 and t417; 505 | t583 = t582 and t123; 506 | t584 = t567 and t417; 507 | t585 = t567 and t123; 508 | t586 = t584 or t585; 509 | t587 = t583 or t586; 510 | t588 = t238 and t417; 511 | t589 = t588 and t123; 512 | t590 = t587 or t589; 513 | t591 = t565 and t590; 514 | t592 = t209 and t591; 515 | t593 = t21 nand t592; 516 | t594 = t21 nand t593; 517 | t595 = t592 nand t593; 518 | t596 = t594 nand t595; 519 | t597 = t581 biimp t596; 520 | t598 = t237 and t576; 521 | t599 = t22 nand t598; 522 | t600 = t22 nand t599; 523 | t601 = t598 nand t599; 524 | t602 = t600 nand t601; 525 | t603 = t237 and t591; 526 | t604 = t22 nand t603; 527 | t605 = t22 nand t604; 528 | t606 = t603 nand t604; 529 | t607 = t605 nand t606; 530 | t608 = t602 biimp t607; 531 | t609 = t181 and t576; 532 | t610 = t27 nand t609; 533 | t611 = t27 nand t610; 534 | t612 = t609 nand t610; 535 | t613 = t611 nand t612; 536 | t614 = t181 and t591; 537 | t615 = t27 nand t614; 538 | t616 = t27 nand t615; 539 | t617 = t614 nand t615; 540 | t618 = t616 nand t617; 541 | t619 = t613 biimp t618; 542 | t620 = t122 and t576; 543 | t621 = t28 nand t620; 544 | t622 = t28 nand t621; 545 | t623 = t620 nand t621; 546 | t624 = t622 nand t623; 547 | t625 = t122 and t591; 548 | t626 = t28 nand t625; 549 | t627 = t28 nand t626; 550 | t628 = t625 nand t626; 551 | t629 = t627 nand t628; 552 | t630 = t624 biimp t629; 553 | t395 = t279 and t362; 554 | t396 = t145 nand t395; 555 | t397 = t145 nand t396; 556 | t398 = t395 nand t396; 557 | t399 = t397 nand t398; 558 | t400 = t279 and t377; 559 | t401 = t145 nand t400; 560 | t402 = t145 nand t401; 561 | t403 = t400 nand t401; 562 | t404 = t402 nand t403; 563 | t405 = t399 biimp t404; 564 | t631 = t347 and t359; 565 | t632 = t631 and t575; 566 | t633 = t209 and t632; 567 | t634 = t37 nand t633; 568 | t635 = t37 nand t634; 569 | t636 = t633 nand t634; 570 | t637 = t635 nand t636; 571 | t638 = t631 and t590; 572 | t639 = t209 and t638; 573 | t640 = t37 nand t639; 574 | t641 = t37 nand t640; 575 | t642 = t639 nand t640; 576 | t643 = t641 nand t642; 577 | t644 = t637 biimp t643; 578 | t645 = t237 and t632; 579 | t646 = t38 nand t645; 580 | t647 = t38 nand t646; 581 | t648 = t645 nand t646; 582 | t649 = t647 nand t648; 583 | t650 = t237 and t638; 584 | t651 = t38 nand t650; 585 | t652 = t38 nand t651; 586 | t653 = t650 nand t651; 587 | t654 = t652 nand t653; 588 | t655 = t649 biimp t654; 589 | t656 = t181 and t632; 590 | t657 = t43 nand t656; 591 | t658 = t43 nand t657; 592 | t659 = t656 nand t657; 593 | t660 = t658 nand t659; 594 | t661 = t181 and t638; 595 | t662 = t43 nand t661; 596 | t663 = t43 nand t662; 597 | t664 = t661 nand t662; 598 | t665 = t663 nand t664; 599 | t666 = t660 biimp t665; 600 | t667 = t122 and t632; 601 | t668 = t44 nand t667; 602 | t669 = t44 nand t668; 603 | t670 = t667 nand t668; 604 | t671 = t669 nand t670; 605 | t672 = t122 and t638; 606 | t673 = t44 nand t672; 607 | t674 = t44 nand t673; 608 | t675 = t672 nand t673; 609 | t676 = t674 nand t675; 610 | t677 = t671 biimp t676; 611 | t678 = t279 and t320; 612 | t679 = t348 and t678; 613 | t680 = t679 and t575; 614 | t681 = t209 and t680; 615 | t682 = t186 nand t681; 616 | t683 = t186 nand t682; 617 | t684 = t681 nand t682; 618 | t685 = t683 nand t684; 619 | t686 = t679 and t590; 620 | t687 = t209 and t686; 621 | t688 = t186 nand t687; 622 | t689 = t186 nand t688; 623 | t690 = t687 nand t688; 624 | t691 = t689 nand t690; 625 | t692 = t685 biimp t691; 626 | t693 = t237 and t680; 627 | t694 = t214 nand t693; 628 | t695 = t214 nand t694; 629 | t696 = t693 nand t694; 630 | t697 = t695 nand t696; 631 | t698 = t237 and t686; 632 | t699 = t214 nand t698; 633 | t700 = t214 nand t699; 634 | t701 = t698 nand t699; 635 | t702 = t700 nand t701; 636 | t703 = t697 biimp t702; 637 | t704 = t181 and t680; 638 | t705 = t128 nand t704; 639 | t706 = t128 nand t705; 640 | t707 = t704 nand t705; 641 | t708 = t706 nand t707; 642 | t709 = t181 and t686; 643 | t710 = t128 nand t709; 644 | t711 = t128 nand t710; 645 | t712 = t709 nand t710; 646 | t713 = t711 nand t712; 647 | t714 = t708 biimp t713; 648 | t715 = t122 and t680; 649 | t716 = t69 nand t715; 650 | t717 = t69 nand t716; 651 | t718 = t715 nand t716; 652 | t719 = t717 nand t718; 653 | t720 = t122 and t686; 654 | t721 = t69 nand t720; 655 | t722 = t69 nand t721; 656 | t723 = t720 nand t721; 657 | t724 = t722 nand t723; 658 | t725 = t719 biimp t724; 659 | t726 = t347 and t321; 660 | t727 = t726 and t575; 661 | t728 = t209 and t727; 662 | t729 = t187 nand t728; 663 | t730 = t187 nand t729; 664 | t731 = t728 nand t729; 665 | t732 = t730 nand t731; 666 | t733 = t726 and t590; 667 | t734 = t209 and t733; 668 | t735 = t187 nand t734; 669 | t736 = t187 nand t735; 670 | t737 = t734 nand t735; 671 | t738 = t736 nand t737; 672 | t739 = t732 biimp t738; 673 | t740 = t237 and t727; 674 | t741 = t215 nand t740; 675 | t742 = t215 nand t741; 676 | t743 = t740 nand t741; 677 | t744 = t742 nand t743; 678 | t745 = t237 and t733; 679 | t746 = t215 nand t745; 680 | t747 = t215 nand t746; 681 | t748 = t745 nand t746; 682 | t749 = t747 nand t748; 683 | t750 = t744 biimp t749; 684 | t406 = t347 and t362; 685 | t407 = t146 nand t406; 686 | t408 = t146 nand t407; 687 | t409 = t406 nand t407; 688 | t410 = t408 nand t409; 689 | t411 = t347 and t377; 690 | t412 = t146 nand t411; 691 | t413 = t146 nand t412; 692 | t414 = t411 nand t412; 693 | t415 = t413 nand t414; 694 | t416 = t410 biimp t415; 695 | t751 = t181 and t727; 696 | t752 = t129 nand t751; 697 | t753 = t129 nand t752; 698 | t754 = t751 nand t752; 699 | t755 = t753 nand t754; 700 | t756 = t181 and t733; 701 | t757 = t129 nand t756; 702 | t758 = t129 nand t757; 703 | t759 = t756 nand t757; 704 | t760 = t758 nand t759; 705 | t761 = t755 biimp t760; 706 | t762 = t122 and t727; 707 | t763 = t70 nand t762; 708 | t764 = t70 nand t763; 709 | t765 = t762 nand t763; 710 | t766 = t764 nand t765; 711 | t767 = t122 and t733; 712 | t768 = t70 nand t767; 713 | t769 = t70 nand t768; 714 | t770 = t767 nand t768; 715 | t771 = t769 nand t770; 716 | t772 = t766 biimp t771; 717 | t419 = t122 and t418; 718 | t420 = t419 and t361; 719 | t421 = t64 and t420; 720 | t422 = t3 nand t421; 721 | t423 = t3 nand t422; 722 | t424 = t421 nand t422; 723 | t425 = t423 nand t424; 724 | t426 = t419 and t376; 725 | t427 = t64 and t426; 726 | t428 = t3 nand t427; 727 | t429 = t3 nand t428; 728 | t430 = t427 nand t428; 729 | t431 = t429 nand t430; 730 | t432 = t425 biimp t431; 731 | t433 = t319 and t420; 732 | t434 = t81 nand t433; 733 | t435 = t81 nand t434; 734 | t436 = t433 nand t434; 735 | t437 = t435 nand t436; 736 | t438 = t319 and t426; 737 | t439 = t81 nand t438; 738 | t440 = t81 nand t439; 739 | t441 = t438 nand t439; 740 | t442 = t440 nand t441; 741 | t443 = t437 biimp t442; 742 | t444 = t279 and t420; 743 | t445 = t86 nand t444; 744 | t446 = t86 nand t445; 745 | t447 = t444 nand t445; 746 | t448 = t446 nand t447; 747 | t449 = t279 and t426; 748 | t450 = t86 nand t449; 749 | t451 = t86 nand t450; 750 | t452 = t449 nand t450; 751 | t453 = t451 nand t452; 752 | t454 = t448 biimp t453; 753 | t455 = t347 and t420; 754 | t456 = t87 nand t455; 755 | t457 = t87 nand t456; 756 | t458 = t455 nand t456; 757 | t459 = t457 nand t458; 758 | t460 = t347 and t426; 759 | t461 = t87 nand t460; 760 | t462 = t87 nand t461; 761 | t463 = t460 nand t461; 762 | t464 = t462 nand t463; 763 | t465 = t459 biimp t464; 764 | t471 = t64 and t470; 765 | t472 = t8 nand t471; 766 | t473 = t8 nand t472; 767 | t474 = t471 nand t472; 768 | t475 = t473 nand t474; 769 | t477 = t64 and t476; 770 | t478 = t8 nand t477; 771 | t479 = t8 nand t478; 772 | t480 = t477 nand t478; 773 | t481 = t479 nand t480; 774 | t482 = t475 biimp t481; 775 | t483 = t319 and t470; 776 | t484 = t155 nand t483; 777 | t485 = t155 nand t484; 778 | t486 = t483 nand t484; 779 | t487 = t485 nand t486; 780 | t488 = t319 and t476; 781 | t489 = t155 nand t488; 782 | t490 = t155 nand t489; 783 | t491 = t488 nand t489; 784 | t492 = t490 nand t491; 785 | t493 = t487 biimp t492; 786 | 787 | tautology t383; 788 | tautology t394; 789 | tautology t504; 790 | tautology t515; 791 | tautology t530; 792 | tautology t541; 793 | tautology t552; 794 | tautology t563; 795 | tautology t597; 796 | tautology t608; 797 | tautology t619; 798 | tautology t630; 799 | tautology t405; 800 | tautology t644; 801 | tautology t655; 802 | tautology t666; 803 | tautology t677; 804 | tautology t692; 805 | tautology t703; 806 | tautology t714; 807 | tautology t725; 808 | tautology t739; 809 | tautology t750; 810 | tautology t416; 811 | tautology t761; 812 | tautology t772; 813 | tautology t432; 814 | tautology t443; 815 | tautology t454; 816 | tautology t465; 817 | tautology t482; 818 | tautology t493; 819 | -------------------------------------------------------------------------------- /bddcalc/c2670.cal: -------------------------------------------------------------------------------- 1 | /* BDD Calculator data file */ 2 | 3 | initial 41000 10000; 4 | 5 | inputs 6 | _1 _2 _3 _4 _5 _6 _7 _8 _11 _14 7 | _15 _16 _19 _20 _21 _22 _23 _24 _25 _26 8 | _27 _28 _29 _32 _33 _34 _35 _36 _37 _40 9 | _43 _44 _47 _48 _49 _50 _51 _52 _53 _54 10 | _55 _56 _57 _60 _61 _62 _63 _64 _65 _66 11 | _67 _68 _69 _72 _73 _74 _75 _76 _77 _78 12 | _79 _80 _81 _82 _85 _86 _87 _88 _89 _90 13 | _91 _92 _93 _94 _95 _96 _99 _100 _101 _102 14 | _103 _104 _105 _106 _107 _108 _111 _112 _113 _114 15 | _115 _116 _117 _118 _119 _120 _123 _124 _125 _126 16 | _127 _128 _129 _130 _131 _132 _135 _136 _137 _138 17 | _139 _140 _141 _142 _452 _483 _543 _559 _567 _651 18 | _661 _860 _868 _1083 _1341 _1348 _1384 _1956 _1961 _1966 19 | _1971 _1976 _1981 _1986 _1991 _1996 _2066 _2067 _2072 _2078 20 | _2084 _2090 _2096 _2100 _2104 _2105 _2106 _2427 _2430 _2435 21 | _2438 _2443 _2446 _2451 _2454 _2474 _2678 ; 22 | 23 | actions 24 | autoreorder 0 sift; 25 | 26 | t2 = _860; 27 | t3 = not t2; 28 | t4 = _56; 29 | t5 = _543; 30 | t6 = not t5; 31 | t7 = t4 and t6; 32 | t8 = _651; 33 | t9 = t7 and t8; 34 | t10 = _81; 35 | t11 = t10 and t6; 36 | t12 = not t8; 37 | t13 = t11 and t12; 38 | t14 = _43; 39 | t15 = t14 and t5; 40 | t16 = t15 and t12; 41 | t17 = t13 or t16; 42 | t18 = t9 or t17; 43 | t19 = _68; 44 | t20 = t19 and t5; 45 | t21 = t20 and t8; 46 | t22 = t18 or t21; 47 | t23 = t22 and t2; 48 | t24 = t3 or t23; 49 | t25 = t3 or t22; 50 | t26 = t24 biimp t25; 51 | t27 = t6 and t8; 52 | t28 = _87; 53 | t29 = t28 and t6; 54 | t30 = t29 and t12; 55 | t31 = _49; 56 | t32 = t31 and t5; 57 | t33 = t32 and t12; 58 | t34 = t30 or t33; 59 | t35 = t27 or t34; 60 | t36 = _74; 61 | t37 = t36 and t5; 62 | t38 = t37 and t8; 63 | t39 = t35 or t38; 64 | t40 = t29 or t33; 65 | t41 = t27 or t40; 66 | t42 = t36 and t8; 67 | t43 = t41 or t42; 68 | t44 = t39 biimp t43; 69 | t45 = _559; 70 | t46 = not t45; 71 | t47 = _66; 72 | t48 = t47 and t6; 73 | t49 = t48 and t8; 74 | t50 = _92; 75 | t51 = t50 and t6; 76 | t52 = t51 and t12; 77 | t53 = _54; 78 | t54 = t53 and t5; 79 | t55 = t54 and t12; 80 | t56 = t52 or t55; 81 | t57 = t49 or t56; 82 | t58 = _79; 83 | t59 = t58 and t5; 84 | t60 = t59 and t8; 85 | t61 = t57 or t60; 86 | t62 = not t61; 87 | t63 = t46 nand t62; 88 | t64 = t63 and t3; 89 | t65 = t61 and t2; 90 | t66 = t64 or t65; 91 | t67 = t64 or t61; 92 | t68 = t66 biimp t67; 93 | t69 = _2100; 94 | t70 = not t69; 95 | t71 = _2104; 96 | t72 = not t71; 97 | t73 = _2105; 98 | t74 = t72 and t73; 99 | t75 = not t73; 100 | t76 = t72 and t75; 101 | t77 = t71 and t75; 102 | t78 = t76 or t77; 103 | t79 = t74 or t78; 104 | t80 = t71 and t73; 105 | t81 = t79 or t80; 106 | t82 = t70 nand t81; 107 | t83 = t70 and t82; 108 | t84 = t82 and t81; 109 | t85 = t83 or t84; 110 | t86 = not t85; 111 | t87 = t85 and t86; 112 | t88 = t87 or t86; 113 | t89 = _2096; 114 | t90 = not t89; 115 | t91 = _123; 116 | t92 = t91 and t72; 117 | t93 = t92 and t73; 118 | t94 = _135; 119 | t95 = t94 and t72; 120 | t96 = t95 and t75; 121 | t97 = _99; 122 | t98 = t97 and t71; 123 | t99 = t98 and t75; 124 | t100 = t96 or t99; 125 | t101 = t93 or t100; 126 | t102 = _111; 127 | t103 = t102 and t71; 128 | t104 = t103 and t73; 129 | t105 = t101 or t104; 130 | t106 = t90 nand t105; 131 | t107 = t90 and t106; 132 | t108 = t106 and t105; 133 | t109 = t107 or t108; 134 | t110 = not t109; 135 | t111 = t109 and t110; 136 | t112 = t111 or t110; 137 | t113 = t88 nand t112; 138 | t114 = not t70; 139 | t115 = not t114; 140 | t116 = t115 nand t110; 141 | t117 = t113 biimp t116; 142 | t118 = _23; 143 | t119 = _16; 144 | t120 = not t119; 145 | t121 = t118 and t120; 146 | t122 = t39 and t119; 147 | t123 = t121 or t122; 148 | t124 = _1976; 149 | t125 = not t124; 150 | t126 = not t125; 151 | t127 = t123 nand t126; 152 | t128 = not t123; 153 | t129 = t125 nand t128; 154 | t130 = t127 nand t129; 155 | t131 = not t130; 156 | t132 = _6; 157 | t133 = t132 and t120; 158 | t134 = _61; 159 | t135 = t134 and t6; 160 | t136 = t135 and t8; 161 | t137 = _86; 162 | t138 = t137 and t6; 163 | t139 = t138 and t12; 164 | t140 = _48; 165 | t141 = t140 and t5; 166 | t142 = t141 and t12; 167 | t143 = t139 or t142; 168 | t144 = t136 or t143; 169 | t145 = _73; 170 | t146 = t145 and t5; 171 | t147 = t146 and t8; 172 | t148 = t144 or t147; 173 | t149 = t148 and t119; 174 | t150 = t133 or t149; 175 | t151 = _1981; 176 | t152 = not t151; 177 | t153 = not t152; 178 | t154 = t150 nand t153; 179 | t155 = not t150; 180 | t156 = t152 nand t155; 181 | t157 = t154 nand t156; 182 | t158 = not t157; 183 | t159 = _25; 184 | t160 = _29; 185 | t161 = not t160; 186 | t162 = t159 and t161; 187 | t163 = _119; 188 | t164 = t163 and t72; 189 | t165 = t164 and t73; 190 | t166 = _131; 191 | t167 = t166 and t72; 192 | t168 = t167 and t75; 193 | t169 = _95; 194 | t170 = t169 and t71; 195 | t171 = t170 and t75; 196 | t172 = t168 or t171; 197 | t173 = t165 or t172; 198 | t174 = _107; 199 | t175 = t174 and t71; 200 | t176 = t175 and t73; 201 | t177 = t173 or t176; 202 | t178 = t177 and t160; 203 | t179 = t162 or t178; 204 | t180 = _1991; 205 | t181 = not t180; 206 | t182 = not t181; 207 | t183 = t179 nand t182; 208 | t184 = not t179; 209 | t185 = t181 nand t184; 210 | t186 = t183 nand t185; 211 | t187 = not t186; 212 | t188 = _24; 213 | t189 = t188 and t120; 214 | t190 = _60; 215 | t191 = t190 and t6; 216 | t192 = t191 and t8; 217 | t193 = _85; 218 | t194 = t193 and t6; 219 | t195 = t194 and t12; 220 | t196 = _47; 221 | t197 = t196 and t5; 222 | t198 = t197 and t12; 223 | t199 = t195 or t198; 224 | t200 = t192 or t199; 225 | t201 = _72; 226 | t202 = t201 and t5; 227 | t203 = t202 and t8; 228 | t204 = t200 or t203; 229 | t205 = t204 and t119; 230 | t206 = t189 or t205; 231 | t207 = _1986; 232 | t208 = not t207; 233 | t209 = not t208; 234 | t210 = t206 nand t209; 235 | t211 = not t206; 236 | t212 = t208 nand t211; 237 | t213 = t210 nand t212; 238 | t214 = not t213; 239 | t215 = t187 and t214; 240 | t216 = t158 and t215; 241 | t217 = t131 and t216; 242 | t218 = _22; 243 | t219 = t218 and t120; 244 | t220 = _62; 245 | t221 = t220 and t6; 246 | t222 = t221 and t8; 247 | t223 = _88; 248 | t224 = t223 and t6; 249 | t225 = t224 and t12; 250 | t226 = _50; 251 | t227 = t226 and t5; 252 | t228 = t227 and t12; 253 | t229 = t225 or t228; 254 | t230 = t222 or t229; 255 | t231 = _75; 256 | t232 = t231 and t5; 257 | t233 = t232 and t8; 258 | t234 = t230 or t233; 259 | t235 = t234 and t119; 260 | t236 = t219 or t235; 261 | t237 = _1971; 262 | t238 = not t237; 263 | t239 = not t238; 264 | t240 = t236 nand t239; 265 | t241 = not t236; 266 | t242 = t238 nand t241; 267 | t243 = t240 nand t242; 268 | t244 = not t243; 269 | t245 = t217 and t244; 270 | t246 = _4; 271 | t247 = t246 and t120; 272 | t248 = t61 and t119; 273 | t249 = t247 or t248; 274 | t250 = _1348; 275 | t251 = not t250; 276 | t252 = not t251; 277 | t253 = t249 nand t252; 278 | t254 = not t249; 279 | t255 = t251 nand t254; 280 | t256 = t253 nand t255; 281 | t257 = not t256; 282 | t258 = _20; 283 | t259 = t258 and t120; 284 | t260 = _65; 285 | t261 = t260 and t6; 286 | t262 = t261 and t8; 287 | t263 = _91; 288 | t264 = t263 and t6; 289 | t265 = t264 and t12; 290 | t266 = _53; 291 | t267 = t266 and t5; 292 | t268 = t267 and t12; 293 | t269 = t265 or t268; 294 | t270 = t262 or t269; 295 | t271 = _78; 296 | t272 = t271 and t5; 297 | t273 = t272 and t8; 298 | t274 = t270 or t273; 299 | t275 = t274 and t119; 300 | t276 = t259 or t275; 301 | t277 = _1956; 302 | t278 = not t277; 303 | t279 = not t278; 304 | t280 = t276 nand t279; 305 | t281 = not t276; 306 | t282 = t278 nand t281; 307 | t283 = t280 nand t282; 308 | t284 = not t283; 309 | t285 = _21; 310 | t286 = t285 and t120; 311 | t287 = _63; 312 | t288 = t287 and t6; 313 | t289 = t288 and t8; 314 | t290 = _89; 315 | t291 = t290 and t6; 316 | t292 = t291 and t12; 317 | t293 = _51; 318 | t294 = t293 and t5; 319 | t295 = t294 and t12; 320 | t296 = t292 or t295; 321 | t297 = t289 or t296; 322 | t298 = _76; 323 | t299 = t298 and t5; 324 | t300 = t299 and t8; 325 | t301 = t297 or t300; 326 | t302 = t301 and t119; 327 | t303 = t286 or t302; 328 | t304 = _1966; 329 | t305 = not t304; 330 | t306 = not t305; 331 | t307 = t303 nand t306; 332 | t308 = not t303; 333 | t309 = t305 nand t308; 334 | t310 = t307 nand t309; 335 | t311 = not t310; 336 | t312 = _5; 337 | t313 = t312 and t120; 338 | t314 = _64; 339 | t315 = t314 and t6; 340 | t316 = t315 and t8; 341 | t317 = _90; 342 | t318 = t317 and t6; 343 | t319 = t318 and t12; 344 | t320 = _52; 345 | t321 = t320 and t5; 346 | t322 = t321 and t12; 347 | t323 = t319 or t322; 348 | t324 = t316 or t323; 349 | t325 = _77; 350 | t326 = t325 and t5; 351 | t327 = t326 and t8; 352 | t328 = t324 or t327; 353 | t329 = t328 and t119; 354 | t330 = t313 or t329; 355 | t331 = _1961; 356 | t332 = not t331; 357 | t333 = not t332; 358 | t334 = t330 nand t333; 359 | t335 = not t330; 360 | t336 = t332 nand t335; 361 | t337 = t334 nand t336; 362 | t338 = not t337; 363 | t339 = t311 and t338; 364 | t340 = t284 and t339; 365 | t341 = t257 and t340; 366 | t342 = _19; 367 | t343 = t342 and t120; 368 | t344 = t22 and t119; 369 | t345 = t343 or t344; 370 | t346 = _1341; 371 | t347 = not t346; 372 | t348 = not t347; 373 | t349 = t345 nand t348; 374 | t350 = not t345; 375 | t351 = t347 nand t350; 376 | t352 = t349 nand t351; 377 | t353 = not t352; 378 | t354 = t341 and t353; 379 | t355 = t245 and t354; 380 | t356 = _28; 381 | t357 = t356 and t161; 382 | t358 = t105 and t160; 383 | t359 = t357 or t358; 384 | t360 = _35; 385 | t361 = t360 and t161; 386 | t362 = _124; 387 | t363 = t362 and t72; 388 | t364 = t363 and t73; 389 | t365 = _136; 390 | t366 = t365 and t72; 391 | t367 = t366 and t75; 392 | t368 = _100; 393 | t369 = t368 and t71; 394 | t370 = t369 and t75; 395 | t371 = t367 or t370; 396 | t372 = t364 or t371; 397 | t373 = _112; 398 | t374 = t373 and t71; 399 | t375 = t374 and t73; 400 | t376 = t372 or t375; 401 | t377 = t376 and t160; 402 | t378 = t361 or t377; 403 | t379 = _2090; 404 | t380 = not t379; 405 | t381 = not t380; 406 | t382 = t378 nand t381; 407 | t383 = not t378; 408 | t384 = t380 nand t383; 409 | t385 = t382 nand t384; 410 | t386 = not t385; 411 | t387 = t359 and t386; 412 | t388 = _26; 413 | t389 = t388 and t161; 414 | t390 = _128; 415 | t391 = t390 and t72; 416 | t392 = t391 and t73; 417 | t393 = _140; 418 | t394 = t393 and t72; 419 | t395 = t394 and t75; 420 | t396 = _104; 421 | t397 = t396 and t71; 422 | t398 = t397 and t75; 423 | t399 = t395 or t398; 424 | t400 = t392 or t399; 425 | t401 = _116; 426 | t402 = t401 and t71; 427 | t403 = t402 and t73; 428 | t404 = t400 or t403; 429 | t405 = t404 and t160; 430 | t406 = t389 or t405; 431 | t407 = _2067; 432 | t408 = not t407; 433 | t409 = not t408; 434 | t410 = t406 nand t409; 435 | t411 = not t406; 436 | t412 = t408 nand t411; 437 | t413 = t410 nand t412; 438 | t414 = not t413; 439 | t415 = _33; 440 | t416 = t415 and t161; 441 | t417 = _127; 442 | t418 = t417 and t72; 443 | t419 = t418 and t73; 444 | t420 = _139; 445 | t421 = t420 and t72; 446 | t422 = t421 and t75; 447 | t423 = _103; 448 | t424 = t423 and t71; 449 | t425 = t424 and t75; 450 | t426 = t422 or t425; 451 | t427 = t419 or t426; 452 | t428 = _115; 453 | t429 = t428 and t71; 454 | t430 = t429 and t73; 455 | t431 = t427 or t430; 456 | t432 = t431 and t160; 457 | t433 = t416 or t432; 458 | t434 = _2072; 459 | t435 = not t434; 460 | t436 = not t435; 461 | t437 = t433 nand t436; 462 | t438 = not t433; 463 | t439 = t435 nand t438; 464 | t440 = t437 nand t439; 465 | t441 = not t440; 466 | t442 = _34; 467 | t443 = t442 and t161; 468 | t444 = _125; 469 | t445 = t444 and t72; 470 | t446 = t445 and t73; 471 | t447 = _137; 472 | t448 = t447 and t72; 473 | t449 = t448 and t75; 474 | t450 = _101; 475 | t451 = t450 and t71; 476 | t452 = t451 and t75; 477 | t453 = t449 or t452; 478 | t454 = t446 or t453; 479 | t455 = _113; 480 | t456 = t455 and t71; 481 | t457 = t456 and t73; 482 | t458 = t454 or t457; 483 | t459 = t458 and t160; 484 | t460 = t443 or t459; 485 | t461 = _2084; 486 | t462 = not t461; 487 | t463 = not t462; 488 | t464 = t460 nand t463; 489 | t465 = not t460; 490 | t466 = t462 nand t465; 491 | t467 = t464 nand t466; 492 | t468 = not t467; 493 | t469 = _27; 494 | t470 = t469 and t161; 495 | t471 = _126; 496 | t472 = t471 and t72; 497 | t473 = t472 and t73; 498 | t474 = _138; 499 | t475 = t474 and t72; 500 | t476 = t475 and t75; 501 | t477 = _102; 502 | t478 = t477 and t71; 503 | t479 = t478 and t75; 504 | t480 = t476 or t479; 505 | t481 = t473 or t480; 506 | t482 = _114; 507 | t483 = t482 and t71; 508 | t484 = t483 and t73; 509 | t485 = t481 or t484; 510 | t486 = t485 and t160; 511 | t487 = t470 or t486; 512 | t488 = _2078; 513 | t489 = not t488; 514 | t490 = not t489; 515 | t491 = t487 nand t490; 516 | t492 = not t487; 517 | t493 = t489 nand t492; 518 | t494 = t491 nand t493; 519 | t495 = not t494; 520 | t496 = t468 and t495; 521 | t497 = t441 and t496; 522 | t498 = t414 and t497; 523 | t499 = _32; 524 | t500 = t499 and t161; 525 | t501 = _129; 526 | t502 = t501 and t72; 527 | t503 = t502 and t73; 528 | t504 = _141; 529 | t505 = t504 and t72; 530 | t506 = t505 and t75; 531 | t507 = _105; 532 | t508 = t507 and t71; 533 | t509 = t508 and t75; 534 | t510 = t506 or t509; 535 | t511 = t503 or t510; 536 | t512 = _117; 537 | t513 = t512 and t71; 538 | t514 = t513 and t73; 539 | t515 = t511 or t514; 540 | t516 = t515 and t160; 541 | t517 = t500 or t516; 542 | t518 = _1996; 543 | t519 = not t518; 544 | t520 = not t519; 545 | t521 = t517 nand t520; 546 | t522 = not t517; 547 | t523 = t519 nand t522; 548 | t524 = t521 nand t523; 549 | t525 = not t524; 550 | t526 = t498 and t525; 551 | t527 = t387 and t526; 552 | t528 = t355 and t527; 553 | t529 = _11; 554 | t530 = _868; 555 | t531 = not t530; 556 | t532 = t529 and t531; 557 | t533 = t529 and t530; 558 | t534 = t532 or t533; 559 | t535 = t528 and t534; 560 | t536 = t43 and t119; 561 | t537 = t121 or t536; 562 | t538 = t537 nand t126; 563 | t539 = not t537; 564 | t540 = t125 nand t539; 565 | t541 = t538 nand t540; 566 | t542 = not t541; 567 | t543 = t542 and t216; 568 | t544 = t543 and t244; 569 | t545 = t544 and t354; 570 | t546 = t545 and t527; 571 | t547 = t546 and t529; 572 | t548 = t535 biimp t547; 573 | t549 = not t535; 574 | t550 = not t547; 575 | t551 = t549 biimp t550; 576 | t552 = not t376; 577 | t553 = t458 nand t552; 578 | t554 = not t458; 579 | t555 = t376 nand t554; 580 | t556 = t553 nand t555; 581 | t557 = not t81; 582 | t558 = t105 nand t557; 583 | t559 = not t105; 584 | t560 = t81 nand t559; 585 | t561 = t558 nand t560; 586 | t562 = not t561; 587 | t563 = t556 nand t562; 588 | t564 = not t556; 589 | t565 = t561 nand t564; 590 | t566 = t563 nand t565; 591 | t567 = _130; 592 | t568 = t567 and t72; 593 | t569 = t568 and t73; 594 | t570 = _142; 595 | t571 = t570 and t72; 596 | t572 = t571 and t75; 597 | t573 = _106; 598 | t574 = t573 and t71; 599 | t575 = t574 and t75; 600 | t576 = t572 or t575; 601 | t577 = t569 or t576; 602 | t578 = _118; 603 | t579 = t578 and t71; 604 | t580 = t579 and t73; 605 | t581 = t577 or t580; 606 | t582 = not t177; 607 | t583 = t581 nand t582; 608 | t584 = not t581; 609 | t585 = t177 nand t584; 610 | t586 = t583 nand t585; 611 | t587 = not t404; 612 | t588 = t515 nand t587; 613 | t589 = not t515; 614 | t590 = t404 nand t589; 615 | t591 = t588 nand t590; 616 | t592 = not t591; 617 | t593 = t586 and t592; 618 | t594 = not t485; 619 | t595 = t431 nand t594; 620 | t596 = not t431; 621 | t597 = t485 nand t596; 622 | t598 = t595 nand t597; 623 | t599 = not t598; 624 | t600 = t593 and t599; 625 | t601 = not t586; 626 | t602 = t592 and t601; 627 | t603 = t602 and t598; 628 | t604 = t600 nor t603; 629 | t605 = t601 and t591; 630 | t606 = t605 and t599; 631 | t607 = t591 and t586; 632 | t608 = t607 and t598; 633 | t609 = t606 nor t608; 634 | t610 = t604 nand t609; 635 | t611 = not t610; 636 | t612 = t566 nand t611; 637 | t613 = not t566; 638 | t614 = t610 nand t613; 639 | t615 = t612 nand t614; 640 | t616 = not t615; 641 | t617 = _37; 642 | t618 = not t617; 643 | t619 = t616 and t618; 644 | t620 = not t559; 645 | t621 = not t620; 646 | t622 = not t621; 647 | t623 = t556 nand t622; 648 | t624 = t621 nand t564; 649 | t625 = t623 nand t624; 650 | t626 = t625 nand t611; 651 | t627 = not t625; 652 | t628 = t610 nand t627; 653 | t629 = t626 nand t628; 654 | t630 = not t629; 655 | t631 = t630 and t618; 656 | t632 = t619 biimp t631; 657 | t633 = _67; 658 | t634 = t633 and t6; 659 | t635 = t634 and t8; 660 | t636 = _93; 661 | t637 = t636 and t6; 662 | t638 = t637 and t12; 663 | t639 = _55; 664 | t640 = t639 and t5; 665 | t641 = t640 and t12; 666 | t642 = t638 or t641; 667 | t643 = t635 or t642; 668 | t644 = _80; 669 | t645 = t644 and t5; 670 | t646 = t645 and t8; 671 | t647 = t643 or t646; 672 | t648 = t647 and t531; 673 | t649 = not t234; 674 | t650 = not t39; 675 | t651 = not t650; 676 | t652 = t649 nand t651; 677 | t653 = not t649; 678 | t654 = t650 nand t653; 679 | t655 = t652 nand t654; 680 | t656 = not t148; 681 | t657 = not t204; 682 | t658 = not t657; 683 | t659 = t656 nand t658; 684 | t660 = not t656; 685 | t661 = t657 nand t660; 686 | t662 = t659 nand t661; 687 | t663 = not t662; 688 | t664 = t655 nand t663; 689 | t665 = not t655; 690 | t666 = t662 nand t665; 691 | t667 = t664 nand t666; 692 | t668 = not t647; 693 | t669 = not t22; 694 | t670 = not t669; 695 | t671 = t668 nand t670; 696 | t672 = not t668; 697 | t673 = t669 nand t672; 698 | t674 = t671 nand t673; 699 | t675 = not t674; 700 | t676 = t63 and t675; 701 | t677 = not t274; 702 | t678 = not t677; 703 | t679 = t62 nand t678; 704 | t680 = not t62; 705 | t681 = t677 nand t680; 706 | t682 = t679 nand t681; 707 | t683 = not t682; 708 | t684 = t676 and t683; 709 | t685 = not t63; 710 | t686 = t675 and t685; 711 | t687 = t686 and t682; 712 | t688 = t684 nor t687; 713 | t689 = t685 and t674; 714 | t690 = t689 and t683; 715 | t691 = t674 and t63; 716 | t692 = t691 and t682; 717 | t693 = t690 nor t692; 718 | t694 = t688 nand t693; 719 | t695 = not t694; 720 | t696 = t667 nand t695; 721 | t697 = not t667; 722 | t698 = t694 nand t697; 723 | t699 = t696 nand t698; 724 | t700 = t699 and t530; 725 | t701 = t648 or t700; 726 | t702 = not t43; 727 | t703 = not t702; 728 | t704 = t649 nand t703; 729 | t705 = t702 nand t653; 730 | t706 = t704 nand t705; 731 | t707 = t706 nand t663; 732 | t708 = not t706; 733 | t709 = t662 nand t708; 734 | t710 = t707 nand t709; 735 | t711 = t710 nand t695; 736 | t712 = not t710; 737 | t713 = t694 nand t712; 738 | t714 = t711 nand t713; 739 | t715 = t714 and t530; 740 | t716 = t648 or t715; 741 | t717 = t701 biimp t716; 742 | t718 = t674 and t683; 743 | t719 = not t328; 744 | t720 = not t301; 745 | t721 = not t720; 746 | t722 = t719 nand t721; 747 | t723 = not t719; 748 | t724 = t720 nand t723; 749 | t725 = t722 nand t724; 750 | t726 = not t725; 751 | t727 = t718 and t726; 752 | t728 = t683 and t675; 753 | t729 = t728 and t725; 754 | t730 = t727 nor t729; 755 | t731 = t675 and t682; 756 | t732 = t731 and t726; 757 | t733 = t682 and t674; 758 | t734 = t733 and t725; 759 | t735 = t732 nor t734; 760 | t736 = t730 nand t735; 761 | t737 = not t736; 762 | t738 = t667 nand t737; 763 | t739 = t736 nand t697; 764 | t740 = t738 nand t739; 765 | t741 = not t740; 766 | t742 = t741 and t618; 767 | t743 = t710 nand t737; 768 | t744 = t736 nand t712; 769 | t745 = t743 nand t744; 770 | t746 = not t745; 771 | t747 = t746 and t618; 772 | t748 = t742 biimp t747; 773 | t749 = _1384; 774 | t750 = not t749; 775 | t751 = t485 and t750; 776 | t752 = t554 and t751; 777 | t753 = _40; 778 | t754 = t752 and t753; 779 | t755 = not t754; 780 | t756 = t515 and t755; 781 | t757 = t753 and t554; 782 | t758 = not t751; 783 | t759 = t757 and t758; 784 | t760 = t756 and t759; 785 | t761 = not t760; 786 | t762 = t519 and t755; 787 | t763 = t762 and t759; 788 | t764 = not t763; 789 | t765 = t761 nand t764; 790 | t766 = not t761; 791 | t767 = t763 nand t766; 792 | t768 = t765 nand t767; 793 | t769 = t404 and t755; 794 | t770 = t769 and t759; 795 | t771 = not t770; 796 | t772 = t408 and t755; 797 | t773 = t772 and t759; 798 | t774 = not t773; 799 | t775 = t771 nand t774; 800 | t776 = not t771; 801 | t777 = t773 nand t776; 802 | t778 = t775 nand t777; 803 | t779 = t768 and t778; 804 | t780 = t181 and t755; 805 | t781 = t780 and t759; 806 | t782 = t177 and t755; 807 | t783 = t782 and t759; 808 | t784 = not t783; 809 | t785 = t781 and t784; 810 | t786 = t779 and t785; 811 | t787 = t773 and t771; 812 | t788 = t763 and t761; 813 | t789 = t778 and t788; 814 | t790 = t787 or t789; 815 | t791 = t786 or t790; 816 | t792 = t204 and t755; 817 | t793 = t792 and t759; 818 | t794 = not t793; 819 | t795 = t208 and t755; 820 | t796 = t795 and t759; 821 | t797 = t794 and t796; 822 | t798 = not t781; 823 | t799 = t784 nand t798; 824 | t800 = not t784; 825 | t801 = t781 nand t800; 826 | t802 = t799 nand t801; 827 | t803 = t802 and t778; 828 | t804 = t797 and t803; 829 | t805 = t804 and t768; 830 | t806 = t791 or t805; 831 | t807 = not t755; 832 | t808 = t462 and t807; 833 | t809 = t305 and t755; 834 | t810 = t808 or t809; 835 | t811 = _8; 836 | t812 = t810 and t811; 837 | t813 = t301 and t755; 838 | t814 = t301 and t754; 839 | t815 = t813 or t814; 840 | t816 = t815 and t811; 841 | t817 = not t816; 842 | t818 = t812 and t817; 843 | t819 = t234 and t755; 844 | t820 = t234 and t754; 845 | t821 = t819 or t820; 846 | t822 = t821 and t811; 847 | t823 = not t822; 848 | t824 = t380 and t807; 849 | t825 = t238 and t755; 850 | t826 = t824 or t825; 851 | t827 = t826 and t811; 852 | t828 = not t827; 853 | t829 = t823 nand t828; 854 | t830 = not t823; 855 | t831 = t827 nand t830; 856 | t832 = t829 nand t831; 857 | t833 = t148 and t755; 858 | t834 = t833 and t811; 859 | t835 = not t834; 860 | t836 = t152 and t755; 861 | t837 = t836 and t811; 862 | t838 = not t837; 863 | t839 = t835 nand t838; 864 | t840 = not t835; 865 | t841 = t837 nand t840; 866 | t842 = t839 nand t841; 867 | t843 = t832 and t842; 868 | t844 = t818 and t843; 869 | t845 = t39 and t755; 870 | t846 = t845 and t811; 871 | t847 = not t846; 872 | t848 = t125 and t755; 873 | t849 = t848 and t811; 874 | t850 = not t849; 875 | t851 = t847 nand t850; 876 | t852 = not t847; 877 | t853 = t849 nand t852; 878 | t854 = t851 nand t853; 879 | t855 = t844 and t854; 880 | t856 = t854 and t842; 881 | t857 = t827 and t823; 882 | t858 = t856 and t857; 883 | t859 = t837 and t835; 884 | t860 = t849 and t847; 885 | t861 = t842 and t860; 886 | t862 = t859 or t861; 887 | t863 = t858 or t862; 888 | t864 = t855 or t863; 889 | t865 = t489 and t807; 890 | t866 = t332 and t755; 891 | t867 = t865 or t866; 892 | t868 = t867 and t719; 893 | t869 = not t812; 894 | t870 = t817 nand t869; 895 | t871 = not t817; 896 | t872 = t812 nand t871; 897 | t873 = t870 nand t872; 898 | t874 = t873 and t832; 899 | t875 = t842 and t874; 900 | t876 = t868 and t875; 901 | t877 = t876 and t854; 902 | t878 = t864 or t877; 903 | t879 = not t867; 904 | t880 = t719 nand t879; 905 | t881 = t867 nand t723; 906 | t882 = t880 nand t881; 907 | t883 = t854 and t882; 908 | t884 = t832 and t883; 909 | t885 = t842 and t884; 910 | t886 = t885 and t873; 911 | t887 = t435 and t807; 912 | t888 = t278 and t755; 913 | t889 = t887 or t888; 914 | t890 = t889 and t677; 915 | t891 = not t889; 916 | t892 = t677 nand t891; 917 | t893 = t889 nand t678; 918 | t894 = t892 nand t893; 919 | t895 = t408 and t807; 920 | t896 = t251 and t755; 921 | t897 = t895 or t896; 922 | t898 = t897 and t62; 923 | t899 = t894 and t898; 924 | t900 = t890 or t899; 925 | t901 = not t897; 926 | t902 = t62 nand t901; 927 | t903 = t897 nand t680; 928 | t904 = t902 nand t903; 929 | t905 = t904 and t894; 930 | t906 = t519 and t807; 931 | t907 = t347 and t755; 932 | t908 = t906 or t907; 933 | t909 = t908 and t669; 934 | t910 = t905 and t909; 935 | t911 = t900 or t910; 936 | t912 = t886 and t911; 937 | t913 = t878 or t912; 938 | t914 = not t913; 939 | t915 = t806 and t914; 940 | t916 = not t806; 941 | t917 = not t796; 942 | t918 = t794 nand t917; 943 | t919 = not t794; 944 | t920 = t796 nand t919; 945 | t921 = t918 nand t920; 946 | t922 = t768 and t921; 947 | t923 = t802 and t922; 948 | t924 = t923 and t778; 949 | t925 = not t924; 950 | t926 = t916 nand t925; 951 | t927 = t926 and t913; 952 | t928 = t915 or t927; 953 | t929 = t756 and t757; 954 | t930 = not t929; 955 | t931 = not t930; 956 | t932 = t762 and t757; 957 | t933 = not t932; 958 | t934 = t931 nand t933; 959 | t935 = t769 and t757; 960 | t936 = not t935; 961 | t937 = not t936; 962 | t938 = t772 and t757; 963 | t939 = not t938; 964 | t940 = t937 nand t939; 965 | t941 = t934 and t940; 966 | t942 = t780 and t757; 967 | t943 = t782 and t757; 968 | t944 = not t943; 969 | t945 = t942 and t944; 970 | t946 = t941 and t945; 971 | t947 = t938 and t936; 972 | t948 = t932 and t930; 973 | t949 = t940 and t948; 974 | t950 = t947 or t949; 975 | t951 = t946 or t950; 976 | t952 = t792 and t757; 977 | t953 = not t952; 978 | t954 = t795 and t757; 979 | t955 = t953 and t954; 980 | t956 = not t944; 981 | t957 = not t942; 982 | t958 = t956 nand t957; 983 | t959 = t958 and t940; 984 | t960 = t955 and t959; 985 | t961 = t960 and t934; 986 | t962 = t951 or t961; 987 | t963 = not t953; 988 | t964 = not t954; 989 | t965 = t963 nand t964; 990 | t966 = t934 and t965; 991 | t967 = t958 and t966; 992 | t968 = t967 and t940; 993 | t969 = not t968; 994 | t970 = not t969; 995 | t971 = t301 and t811; 996 | t972 = not t971; 997 | t973 = t812 and t972; 998 | t974 = t234 and t811; 999 | t975 = not t974; 1000 | t976 = not t975; 1001 | t977 = t976 nand t828; 1002 | t978 = t840 nand t838; 1003 | t979 = t977 and t978; 1004 | t980 = t973 and t979; 1005 | t981 = t43 and t755; 1006 | t982 = t981 and t811; 1007 | t983 = not t982; 1008 | t984 = not t983; 1009 | t985 = t984 nand t850; 1010 | t986 = t980 and t985; 1011 | t987 = t985 and t978; 1012 | t988 = t827 and t975; 1013 | t989 = t987 and t988; 1014 | t990 = t849 and t983; 1015 | t991 = t978 and t990; 1016 | t992 = t859 or t991; 1017 | t993 = t989 or t992; 1018 | t994 = t986 or t993; 1019 | t995 = not t972; 1020 | t996 = t995 nand t869; 1021 | t997 = t996 and t977; 1022 | t998 = t978 and t997; 1023 | t999 = t868 and t998; 1024 | t1000 = t999 and t985; 1025 | t1001 = t994 or t1000; 1026 | t1002 = t723 nand t879; 1027 | t1003 = t985 and t1002; 1028 | t1004 = t977 and t1003; 1029 | t1005 = t978 and t1004; 1030 | t1006 = t1005 and t996; 1031 | t1007 = t678 nand t891; 1032 | t1008 = t1007 and t898; 1033 | t1009 = t890 or t1008; 1034 | t1010 = t680 nand t901; 1035 | t1011 = t1010 and t1007; 1036 | t1012 = t1011 and t909; 1037 | t1013 = t1009 or t1012; 1038 | t1014 = t1006 and t1013; 1039 | t1015 = t1001 or t1014; 1040 | t1016 = t970 and t1015; 1041 | t1017 = t962 or t1016; 1042 | t1018 = t928 biimp t1017; 1043 | t1019 = not t619; 1044 | t1020 = not t742; 1045 | t1021 = t1019 and t1020; 1046 | t1022 = t89 nand t70; 1047 | t1023 = t69 nand t90; 1048 | t1024 = t1022 nand t1023; 1049 | t1025 = _2678; 1050 | t1026 = t1025 nand t408; 1051 | t1027 = not t1025; 1052 | t1028 = t407 nand t1027; 1053 | t1029 = t1026 nand t1028; 1054 | t1030 = t434 nand t489; 1055 | t1031 = t488 nand t435; 1056 | t1032 = t1030 nand t1031; 1057 | t1033 = not t1032; 1058 | t1034 = t1029 and t1033; 1059 | t1035 = t461 nand t380; 1060 | t1036 = t379 nand t462; 1061 | t1037 = t1035 nand t1036; 1062 | t1038 = not t1037; 1063 | t1039 = t1034 and t1038; 1064 | t1040 = not t1029; 1065 | t1041 = t1033 and t1040; 1066 | t1042 = t1041 and t1037; 1067 | t1043 = t1039 nor t1042; 1068 | t1044 = t1040 and t1032; 1069 | t1045 = t1044 and t1038; 1070 | t1046 = t1032 and t1029; 1071 | t1047 = t1046 and t1037; 1072 | t1048 = t1045 nor t1047; 1073 | t1049 = t1043 nand t1048; 1074 | t1050 = not t1049; 1075 | t1051 = t1024 nand t1050; 1076 | t1052 = not t1024; 1077 | t1053 = t1049 nand t1052; 1078 | t1054 = t1051 nand t1053; 1079 | t1055 = t1021 and t1054; 1080 | t1056 = t151 nand t208; 1081 | t1057 = t207 nand t152; 1082 | t1058 = t1056 nand t1057; 1083 | t1059 = t180 nand t519; 1084 | t1060 = t518 nand t181; 1085 | t1061 = t1059 nand t1060; 1086 | t1062 = not t1061; 1087 | t1063 = t1058 nand t1062; 1088 | t1064 = not t1058; 1089 | t1065 = t1061 nand t1064; 1090 | t1066 = t1063 nand t1065; 1091 | t1067 = _2474; 1092 | t1068 = t1067 nand t278; 1093 | t1069 = not t1067; 1094 | t1070 = t277 nand t1069; 1095 | t1071 = t1068 nand t1070; 1096 | t1072 = t331 nand t305; 1097 | t1073 = t304 nand t332; 1098 | t1074 = t1072 nand t1073; 1099 | t1075 = not t1074; 1100 | t1076 = t1071 and t1075; 1101 | t1077 = t237 nand t125; 1102 | t1078 = t124 nand t238; 1103 | t1079 = t1077 nand t1078; 1104 | t1080 = not t1079; 1105 | t1081 = t1076 and t1080; 1106 | t1082 = not t1071; 1107 | t1083 = t1075 and t1082; 1108 | t1084 = t1083 and t1079; 1109 | t1085 = t1081 nor t1084; 1110 | t1086 = t1082 and t1074; 1111 | t1087 = t1086 and t1080; 1112 | t1088 = t1074 and t1071; 1113 | t1089 = t1088 and t1079; 1114 | t1090 = t1087 nor t1089; 1115 | t1091 = t1085 nand t1090; 1116 | t1092 = not t1091; 1117 | t1093 = t1066 nand t1092; 1118 | t1094 = not t1066; 1119 | t1095 = t1091 nand t1094; 1120 | t1096 = t1093 nand t1095; 1121 | t1097 = _2454; 1122 | t1098 = _2451; 1123 | t1099 = not t1098; 1124 | t1100 = t1097 nand t1099; 1125 | t1101 = not t1097; 1126 | t1102 = t1098 nand t1101; 1127 | t1103 = t1100 nand t1102; 1128 | t1104 = t346 nand t251; 1129 | t1105 = t250 nand t347; 1130 | t1106 = t1104 nand t1105; 1131 | t1107 = not t1106; 1132 | t1108 = t1103 nand t1107; 1133 | t1109 = not t1103; 1134 | t1110 = t1106 nand t1109; 1135 | t1111 = t1108 nand t1110; 1136 | t1112 = _2430; 1137 | t1113 = _2427; 1138 | t1114 = not t1113; 1139 | t1115 = t1112 nand t1114; 1140 | t1116 = not t1112; 1141 | t1117 = t1113 nand t1116; 1142 | t1118 = t1115 nand t1117; 1143 | t1119 = _2438; 1144 | t1120 = _2435; 1145 | t1121 = not t1120; 1146 | t1122 = t1119 nand t1121; 1147 | t1123 = not t1119; 1148 | t1124 = t1120 nand t1123; 1149 | t1125 = t1122 nand t1124; 1150 | t1126 = not t1125; 1151 | t1127 = t1118 and t1126; 1152 | t1128 = _2446; 1153 | t1129 = _2443; 1154 | t1130 = not t1129; 1155 | t1131 = t1128 nand t1130; 1156 | t1132 = not t1128; 1157 | t1133 = t1129 nand t1132; 1158 | t1134 = t1131 nand t1133; 1159 | t1135 = not t1134; 1160 | t1136 = t1127 and t1135; 1161 | t1137 = not t1118; 1162 | t1138 = t1126 and t1137; 1163 | t1139 = t1138 and t1134; 1164 | t1140 = t1136 nor t1139; 1165 | t1141 = t1137 and t1125; 1166 | t1142 = t1141 and t1135; 1167 | t1143 = t1125 and t1118; 1168 | t1144 = t1143 and t1134; 1169 | t1145 = t1142 nor t1144; 1170 | t1146 = t1140 nand t1145; 1171 | t1147 = not t1146; 1172 | t1148 = t1111 nand t1147; 1173 | t1149 = not t1111; 1174 | t1150 = t1146 nand t1149; 1175 | t1151 = t1148 nand t1150; 1176 | t1152 = not t1151; 1177 | t1153 = _14; 1178 | t1154 = t1152 and t1153; 1179 | t1155 = not t1154; 1180 | t1156 = t1096 and t1155; 1181 | t1157 = not t928; 1182 | t1158 = t928 and t1157; 1183 | t1159 = t1157 and t928; 1184 | t1160 = t1158 or t1159; 1185 | t1161 = not t1160; 1186 | t1162 = t1160 and t1161; 1187 | t1163 = t1162 or t1161; 1188 | t1164 = t1156 and t1163; 1189 | t1165 = t1055 and t1164; 1190 | t1166 = _2106; 1191 | t1167 = _96; 1192 | t1168 = _132; 1193 | t1169 = _82; 1194 | t1170 = t1168 and t1169; 1195 | t1171 = t1167 and t1170; 1196 | t1172 = _44; 1197 | t1173 = t1171 and t1172; 1198 | t1174 = not t1173; 1199 | t1175 = t1166 and t1174; 1200 | t1176 = not t1175; 1201 | t1177 = _567; 1202 | t1178 = _108; 1203 | t1179 = _120; 1204 | t1180 = _57; 1205 | t1181 = t1179 and t1180; 1206 | t1182 = t1178 and t1181; 1207 | t1183 = _69; 1208 | t1184 = t1182 and t1183; 1209 | t1185 = not t1184; 1210 | t1186 = t1177 and t1185; 1211 | t1187 = not t1186; 1212 | t1188 = t1176 and t1187; 1213 | t1189 = t1165 and t1188; 1214 | t1190 = not t631; 1215 | t1191 = not t747; 1216 | t1192 = t1190 and t1191; 1217 | t1193 = t1192 and t1054; 1218 | t1194 = t1193 and t1156; 1219 | t1195 = t1194 and t1188; 1220 | t1196 = t1189 biimp t1195; 1221 | t1197 = not t1189; 1222 | t1198 = not t1195; 1223 | t1199 = t1197 biimp t1198; 1224 | 1225 | tautology t26; 1226 | tautology t44; 1227 | tautology t68; 1228 | tautology t117; 1229 | tautology t548; 1230 | tautology t551; 1231 | tautology t632; 1232 | tautology t717; 1233 | tautology t717; 1234 | tautology t748; 1235 | tautology t1018; 1236 | tautology t1196; 1237 | tautology t1199; 1238 | -------------------------------------------------------------------------------- /zdd/clpb.pl: -------------------------------------------------------------------------------- 1 | /* 2 | Author: Markus Triska 3 | E-mail: triska@metalevel.at 4 | Copyright (C): 2014-2024 Markus Triska 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 | 20 | As a special exception, if you link this library with other files, 21 | compiled with a Free Software compiler, to produce an executable, this 22 | library does not by itself cause the resulting executable to be covered 23 | by the GNU General Public License. This exception does not however 24 | invalidate any other reasons why the executable file might be covered by 25 | the GNU General Public License. 26 | */ 27 | 28 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 29 | CLP(B): Constraint Logic Programming over Boolean variables. 30 | 31 | This is like library(clpb) which ships with Scryer Prolog, except 32 | that we use Zero-suppressed Binary Decision Diagrams (ZDDs) here. 33 | 34 | ZDDs can save a lot of memory in situations where solutions have 35 | most Boolean variables equal to 0. This is the case in many 36 | covering tasks. 37 | 38 | This file is mostly a drop-in-replacement, with the following 39 | important difference: 40 | 41 | Before using sat/1, you MUST call zdd_set_vars/1 with a list of 42 | all Boolean variables that occur in your model. 43 | 44 | For example: 45 | 46 | ?- zdd_set_vars([X,Y]), sat(X+Y). 47 | 48 | yielding: 49 | 50 | sat(X=:=X), 51 | node(4)- (X->node(0);node(2)), 52 | node(2)- (Y->true;false), 53 | node(0)- (Y->true;true), 54 | sat(Y=:=Y). 55 | 56 | The current version is intended for tasks where library(clpb) runs 57 | out of memory, and mostly for counting solutions with sat_count/2. 58 | 59 | ATTENTION: sat_count/2 differs from the one in Scryer Prolog's 60 | library(clpb) if there are CLP(B) variables outside the expression! 61 | 62 | Current limitations: 63 | 64 | -) unification of CLP(B) variables is NOT yet implemented 65 | -) labeling/1 does NOT work yet 66 | -) card/2 does not yet support integer ranges 67 | 68 | Future versions may no longer require zdd_set_vars/1. 69 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 70 | 71 | :- module(clpb, [ 72 | op(300, fy, ~), 73 | op(500, yfx, #), 74 | zdd_set_vars/1, 75 | sat/1, 76 | sat_count/1, 77 | taut/2, 78 | labeling/1, 79 | sat_count/2 80 | ]). 81 | 82 | :- use_module(library(error), [domain_error/3, type_error/3]). 83 | :- use_module(library(assoc)). 84 | :- use_module(library(lists)). 85 | :- use_module(library(between)). 86 | :- use_module(library(pairs)). 87 | :- use_module(library(dcgs)). 88 | :- use_module(library(atts)). 89 | :- use_module(library(iso_ext)). 90 | :- use_module(library(debug)). 91 | 92 | :- attribute 93 | clpb/1, 94 | clpb_bdd/1, 95 | clpb_hash/1, 96 | clpb_visited/1. 97 | 98 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 99 | Compatibility predicates. 100 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 101 | 102 | must_be(What, Term) :- must_be(What, unknown(Term)-1, Term). 103 | 104 | must_be(acyclic, Where, Term) :- !, 105 | ( acyclic_term(Term) -> 106 | true 107 | ; domain_error(acyclic_term, Term, Where) 108 | ). 109 | must_be(list, Where, Term) :- !, 110 | ( acyclic_term(Term), clpz_list(Term, Where) -> true 111 | ; type_error(list, Term, Where) 112 | ). 113 | must_be(list(What), Where, Term) :- !, 114 | must_be(list, Where, Term), 115 | maplist(must_be(What, Where), Term). 116 | must_be(ground, _, Term) :- !, 117 | functor(Term, _, _). 118 | 119 | must_be(Type, _, Term) :- 120 | error:must_be(Type, Term). 121 | 122 | clpz_list(Nil, _) :- Nil == []. 123 | clpz_list(Ls, Where) :- 124 | ( var(Ls) -> 125 | instantiation_error(Ls, Where) 126 | ; Ls = [_|Rest], 127 | clpz_list(Rest, Where) 128 | ). 129 | 130 | 131 | instantiation_error(Term) :- instantiation_error(Term, unknown(Term)-1). 132 | 133 | instantiation_error(_, Goal-Arg) :- 134 | throw(error(instantiation_error, instantiation_error(Goal, Arg))). 135 | 136 | 137 | domain_error(Expectation, Term) :- 138 | domain_error(Expectation, Term, unknown(Term)-1). 139 | 140 | 141 | type_error(Expectation, Term) :- 142 | type_error(Expectation, Term, unknown(Term)-1). 143 | 144 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 145 | Compatibility predicates. 146 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 147 | 148 | :- meta_predicate(include(1, ?, ?)). 149 | 150 | include(_, [], []). 151 | include(Goal, [L|Ls0], Ls) :- 152 | ( call(Goal, L) -> 153 | Ls = [L|Rest] 154 | ; Ls = Rest 155 | ), 156 | include(Goal, Ls0, Rest). 157 | 158 | goal_expansion(get_attr(Var, Module, Value), (var(Var),get_atts(Var, Access))) :- 159 | Access =.. [Module,Value]. 160 | 161 | goal_expansion(put_attr(Var, Module, Value), put_atts(Var, Access)) :- 162 | Access =.. [Module,Value]. 163 | 164 | goal_expansion(del_attr(Var, Module), (var(Var) -> put_atts(Var, -Access);true)) :- 165 | Access =.. [Module,_]. 166 | 167 | 168 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 169 | Each CLP(B) variable belongs to exactly one BDD. Each CLP(B) 170 | variable gets an attribute (in module "clpb") of the form: 171 | 172 | index_root(Index,Root) 173 | 174 | where Index is the variable's unique integer index, and Root is the 175 | root of the BDD that the variable belongs to. 176 | 177 | Each CLP(B) variable also gets an attribute in module clpb_hash: an 178 | association table node(LID,HID) -> Node, to keep the BDD reduced. 179 | The association table of each variable must be rebuilt on occasion 180 | to remove nodes that are no longer reachable. We rebuild the 181 | association tables of involved variables after BDDs are merged to 182 | build a new root. This only serves to reclaim memory: Keeping a 183 | node in a local table even when it no longer occurs in any BDD does 184 | not affect the solver's correctness. 185 | 186 | A root is a logical variable with a single attribute ("clpb_bdd") 187 | of the form: 188 | 189 | Sat-BDD 190 | 191 | where Sat is the SAT formula (in original form) that corresponds to 192 | BDD. Sat is necessary to rebuild the BDD after variable aliasing. 193 | 194 | Finally, a BDD is either: 195 | 196 | *) The integers 0 or 1, denoting false and true, respectively, or 197 | *) A node of the form 198 | 199 | node(ID, Var, Low, High, Aux) 200 | Where ID is the node's unique integer ID, Var is the 201 | node's branching variable, and Low and High are the 202 | node's low (Var = 0) and high (Var = 1) children. Aux 203 | is a free variable, one for each node, that can be used 204 | to attach attributes and store intermediate results. 205 | 206 | Variable aliasing is treated as a conjunction of corresponding SAT 207 | formulae. 208 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 209 | 210 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 211 | Type checking. 212 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 213 | 214 | is_sat(V) :- var(V), !. 215 | is_sat(I) :- integer(I), between(0, 1, I). 216 | is_sat(~A) :- is_sat(A). 217 | is_sat(A*B) :- is_sat(A), is_sat(B). 218 | is_sat(A+B) :- is_sat(A), is_sat(B). 219 | is_sat(A#B) :- is_sat(A), is_sat(B). 220 | is_sat(A=:=B) :- is_sat(A), is_sat(B). 221 | is_sat(A=\=B) :- is_sat(A), is_sat(B). 222 | is_sat(A==B) :- is_sat(A), is_sat(B). 224 | is_sat(AB) :- is_sat(A), is_sat(B). 226 | is_sat(+(Ls)) :- must_be(list, Ls), maplist(is_sat, Ls). 227 | is_sat(*(Ls)) :- must_be(list, Ls), maplist(is_sat, Ls). 228 | is_sat(X^F) :- var(X), is_sat(F). 229 | is_sat(card(Is,Fs)) :- 230 | must_be(list(ground), Is), 231 | must_be(list, Fs), 232 | maplist(is_sat, Fs). 233 | 234 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 235 | Rewriting to canonical expressions. 236 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 237 | 238 | % elementary 239 | sat_rewrite(V, V) :- var(V), !. 240 | sat_rewrite(I, I) :- integer(I). 241 | sat_rewrite(P0*Q0, P*Q) :- sat_rewrite(P0, P), sat_rewrite(Q0, Q). 242 | sat_rewrite(P0+Q0, P+Q) :- sat_rewrite(P0, P), sat_rewrite(Q0, Q). 243 | sat_rewrite(P0#Q0, P#Q) :- sat_rewrite(P0, P), sat_rewrite(Q0, Q). 244 | sat_rewrite(X^F0, X^F) :- sat_rewrite(F0, F). 245 | sat_rewrite(card(Is,Fs0), card(Is,Fs)) :- 246 | maplist(sat_rewrite, Fs0, Fs). 247 | % synonyms 248 | sat_rewrite(~P, R) :- sat_rewrite(1 # P, R). 249 | sat_rewrite(P =:= Q, R) :- sat_rewrite(~P # Q, R). 250 | sat_rewrite(P =\= Q, R) :- sat_rewrite(P # Q, R). 251 | sat_rewrite(P =< Q, R) :- sat_rewrite(~P + Q, R). 252 | sat_rewrite(P >= Q, R) :- sat_rewrite(Q =< P, R). 253 | sat_rewrite(P < Q, R) :- sat_rewrite(~P * Q, R). 254 | sat_rewrite(P > Q, R) :- sat_rewrite(Q < P, R). 255 | sat_rewrite(+(Ls), R) :- foldl(or, Ls, 0, F), sat_rewrite(F, R). 256 | sat_rewrite(*(Ls), R) :- foldl(and, Ls, 1, F), sat_rewrite(F, R). 257 | 258 | or(A, B, B + A). 259 | 260 | and(A, B, B * A). 261 | 262 | must_be_sat(Sat) :- 263 | ( is_sat(Sat) -> true 264 | ; no_truth_value(Sat) 265 | ). 266 | 267 | no_truth_value(Term) :- domain_error(clpb_expr, Term). 268 | 269 | parse_sat(Sat0, Sat) :- 270 | must_be_sat(Sat0), 271 | sat_rewrite(Sat0, Sat), 272 | term_variables(Sat, Vs), 273 | maplist(enumerate_variable, Vs). 274 | 275 | enumerate_variable(V) :- 276 | ( var_index_root(V, _, _) -> true 277 | ; clpb_next_id('$clpb_next_var', Index), 278 | put_attr(V, clpb, index_root(Index,_)), 279 | put_empty_hash(V) 280 | ). 281 | 282 | var_index(V, I) :- var_index_root(V, I, _). 283 | 284 | var_index_root(V, I, Root) :- get_attr(V, clpb, index_root(I,Root)). 285 | 286 | put_empty_hash(V) :- 287 | empty_assoc(H0), 288 | put_attr(V, clpb_hash, H0). 289 | 290 | sat_roots(Sat, Roots) :- 291 | term_variables(Sat, Vs), 292 | maplist(var_index_root, Vs, _, Roots0), 293 | term_variables(Roots0, Roots). 294 | 295 | %% sat(+Expr) is semidet. 296 | % 297 | % True iff Expr is a satisfiable Boolean expression. 298 | 299 | sat(Sat0) :- 300 | ( phrase(sat_ands(Sat0), Ands), Ands = [_,_|_] -> 301 | maplist(sat, Ands) 302 | ; parse_sat(Sat0, Sat), 303 | sat_bdd(Sat, BDD), 304 | sat_roots(Sat, Roots), 305 | roots_and(Roots, Sat0-BDD, And-BDD1), 306 | maplist(del_bdd, Roots), 307 | maplist(=(Root), Roots), 308 | root_put_formula_bdd(Root, And, BDD1), 309 | satisfiable_bdd(BDD1) 310 | ). 311 | 312 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 313 | Posting many small sat/1 constraints is better than posting a huge 314 | conjunction (or negated disjunction), because unneeded nodes are 315 | removed from node tables after BDDs are merged. This is not 316 | possible in sat_bdd/2 because the nodes may occur in other BDDs. A 317 | better version of sat_bdd/2 or a proper implementation of a unique 318 | table including garbage collection would make this obsolete and 319 | also improve taut/2 and sat_count/2 in such cases. 320 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 321 | 322 | sat_ands(X) --> 323 | ( { var(X) } -> [X] 324 | ; { X = (A*B) } -> sat_ands(A), sat_ands(B) 325 | ; { X = *(Ls) } -> sat_ands_(Ls) 326 | ; { X = ~Y } -> not_ors(Y) 327 | ; [X] 328 | ). 329 | 330 | sat_ands_([]) --> []. 331 | sat_ands_([L|Ls]) --> [L], sat_ands_(Ls). 332 | 333 | not_ors(X) --> 334 | ( { var(X) } -> [~X] 335 | ; { X = (A+B) } -> not_ors(A), not_ors(B) 336 | ; { X = +(Ls) } -> not_ors_(Ls) 337 | ; [~X] 338 | ). 339 | 340 | not_ors_([]) --> []. 341 | not_ors_([L|Ls]) --> [~L], not_ors_(Ls). 342 | 343 | del_bdd(Root) :- del_attr(Root, clpb_bdd). 344 | 345 | root_get_formula_bdd(Root, F, BDD) :- get_attr(Root, clpb_bdd, F-BDD). 346 | 347 | root_put_formula_bdd(Root, F, BDD) :- put_attr(Root, clpb_bdd, F-BDD). 348 | 349 | roots_and(Roots, Sat0-BDD0, Sat-BDD) :- 350 | foldl(root_and, Roots, Sat0-BDD0, Sat-BDD), 351 | rebuild_hashes(BDD). 352 | 353 | root_and(Root, Sat0-BDD0, Sat-BDD) :- 354 | ( root_get_formula_bdd(Root, F, B) -> 355 | Sat = F*Sat0, 356 | bdd_and(B, BDD0, BDD) 357 | ; Sat = Sat0, 358 | BDD = BDD0 359 | ). 360 | 361 | bdd_and(NA, NB, And) :- 362 | apply(*, NA, NB, And), 363 | is_bdd(And). 364 | 365 | %% taut(+Expr, -T) is semidet 366 | % 367 | % Succeeds with T = 0 if the Boolean expression Expr cannot be 368 | % satisfied, and with T = 1 if Expr is always true with respect to the 369 | % current constraints. Fails otherwise. 370 | 371 | taut(Sat0, T) :- 372 | parse_sat(Sat0, Sat), 373 | sat_roots(Sat, Roots), 374 | catch((roots_and(Roots, _-1, _-Ands), 375 | ( T = 0, unsatisfiable_conjunction(Sat, Ands) -> true 376 | ; T = 1, unsatisfiable_conjunction(1#Sat, Ands) -> true 377 | ; false 378 | ), 379 | % reset all attributes 380 | throw(truth(T))), 381 | truth(T), 382 | true). 383 | 384 | unsatisfiable_conjunction(Sat, Ands) :- 385 | sat_bdd(Sat, BDD), 386 | bdd_and(BDD, Ands, B), 387 | B == 0. 388 | 389 | satisfiable_bdd(BDD) :- 390 | ( BDD == 0 -> false 391 | ; not_occurring_are_zero(BDD) 392 | ). 393 | 394 | not_occurring_are_zero(BDD) :- 395 | all_variables_in_index_order(AllVs), 396 | bdd_variables(BDD, Vs), 397 | maplist(put_visited, Vs), 398 | maplist(not_visited_zero, AllVs, _Zs), 399 | maplist(unvisit, Vs). 400 | % AllVs = Zs. % unification not yet supported 401 | 402 | not_visited_zero(Var, Zero) :- 403 | ( is_visited(Var) -> Zero = _Any 404 | ; Var \== 1, 405 | Zero = 0 406 | ). 407 | 408 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 409 | Node management. Always use an existing node, if there is one. 410 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 411 | 412 | make_node(Var, Low, High, Node) :- 413 | ( High == 0 -> Node = Low 414 | ; low_high_key(Low, High, Key), 415 | ( lookup_node(Var, Key, Node) -> true 416 | ; clpb_next_id('$clpb_next_node', ID), 417 | Node = node(ID,Var,Low,High,_Aux), 418 | register_node(Var, Key, Node) 419 | ) 420 | ). 421 | 422 | make_node(Var, Low, High, Node) --> 423 | % make it conveniently usable within DCGs 424 | { make_node(Var, Low, High, Node) }. 425 | 426 | 427 | low_high_key(Low, High, node(LID,HID)) :- 428 | node_id(Low, LID), 429 | node_id(High, HID). 430 | 431 | 432 | rebuild_hashes(BDD) :- 433 | bdd_nodes(put_empty_hash, BDD, Nodes), 434 | maplist(re_register_node, Nodes). 435 | 436 | re_register_node(Node) :- 437 | node_var_low_high(Node, Var, Low, High), 438 | low_high_key(Low, High, Key), 439 | register_node(Var, Key, Node). 440 | 441 | register_node(Var, Key, Node) :- 442 | get_attr(Var, clpb_hash, H0), 443 | put_assoc(Key, H0, Node, H), 444 | put_attr(Var, clpb_hash, H). 445 | 446 | lookup_node(Var, Key, Node) :- 447 | get_attr(Var, clpb_hash, H0), 448 | get_assoc(Key, H0, Node). 449 | 450 | 451 | node_id(0, false). 452 | node_id(1, true). 453 | node_id(node(ID,_,_,_,_), ID). 454 | 455 | node_aux(Node, Aux) :- arg(5, Node, Aux). 456 | 457 | node_var_low_high(Node, Var, Low, High) :- 458 | Node = node(_,Var,Low,High,_). 459 | 460 | 461 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 462 | sat_bdd/2 converts a SAT formula in canonical form to an ordered 463 | and reduced zero-suppressed BDD. 464 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 465 | 466 | sat_bdd(V, Node) :- var(V), !, var_projection(V, Node). 467 | sat_bdd(0, 0) :- !. 468 | sat_bdd(1, Node) :- !, taut(Node). 469 | sat_bdd(card(Is,Fs), Node) :- !, counter_network(Is, Fs, Node). 470 | sat_bdd(Sat, Node) :- !, 471 | Sat =.. [F,A,B], 472 | sat_bdd(A, NA), 473 | sat_bdd(B, NB), 474 | apply(F, NA, NB, Node). 475 | 476 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 477 | Counter network for card(Is,Fs). 478 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 479 | 480 | counter_network(Is, Vs, Node) :- 481 | maplist(exactly_k(Vs), Is, [N|Ns]), 482 | foldl(bdd_or, Ns, N, Node). 483 | 484 | bdd_or(A, B, Node) :- apply(+, A, B, Node). 485 | 486 | exactly_k(Vs, K, Node) :- 487 | must_be(integer, K), 488 | all_variables_in_index_order(Vars), 489 | exactly_k_(Vars, Vs, K, Node). 490 | 491 | exactly_k_([], _, K, T) :- 492 | ( K =:= 0 -> T = 1 493 | ; T = 0 494 | ). 495 | exactly_k_([V|Vs], Fs, K0, Node) :- 496 | ( K0 =:= 0 -> 497 | vs_not_in_fs([V|Vs], Fs, Vars), 498 | taut_(Vars, Node) 499 | ; member(Var, Fs), Var == V -> 500 | exactly_k_(Vs, Fs, K0, Left), 501 | K1 is K0 - 1, 502 | exactly_k_(Vs, Fs, K1, Right), 503 | make_node(V, Left, Right, Node) 504 | ; exactly_k_(Vs, Fs, K0, Node0), 505 | make_node(V, Node0, Node0, Node) 506 | ). 507 | 508 | vs_not_in_fs([], _, []). 509 | vs_not_in_fs([V|Vs], Fs, Vars) :- 510 | ( member(F, Fs), F == V -> Vars = Rest 511 | ; Vars = [V|Rest] 512 | ), 513 | vs_not_in_fs(Vs, Fs, Rest). 514 | 515 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 516 | Compute F(NA, NB). 517 | 518 | We use a DCG to thread through an implicit argument G0, an 519 | association table F(IDA,IDB) -> Node, used for memoization. 520 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 521 | 522 | apply(F, NA, NB, Node) :- 523 | empty_assoc(G0), 524 | phrase(apply(F, NA, NB, Node), [G0], _). 525 | 526 | apply(F, NA, NB, Node) --> 527 | { node_id(NA, IDA), node_id(NB, IDB), Key =.. [F,IDA,IDB] }, 528 | ( state(G0), { get_assoc(Key, G0, Node) } -> [] 529 | ; apply_(F, NA, NB, Node), 530 | state(G0, G), 531 | { put_assoc(Key, G0, Node, G) } 532 | ). 533 | 534 | apply_(*, F, G, Node) --> 535 | ( { F == 0 } -> { Node = 0 } 536 | ; { G == 0 } -> { Node = 0 } 537 | ; { F == G } -> { Node = F } 538 | ; { var_less_than(F, G) } -> 539 | { node_var_low_high(F, _, LF, _) }, 540 | apply(*, LF, G, Node) 541 | ; { var_less_than(G, F) } -> 542 | { node_var_low_high(G, _, LG, _) }, 543 | apply(*, F, LG, Node) 544 | ; { node_var_low_high(F, Var, LF, HF), 545 | node_var_low_high(G, _, LG, HG) }, 546 | apply(*, LF, LG, Low), 547 | apply(*, HF, HG, High), 548 | make_node(Var, Low, High, Node) 549 | ). 550 | 551 | 552 | apply_(+, F, G, Node) --> 553 | ( { F == 0 } -> { Node = G } 554 | ; { G == 0 } -> { Node = F } 555 | ; { F == G } -> { Node = F } 556 | ; { var_less_than(F, G) } -> 557 | { node_var_low_high(F, Var, LF, HF) }, 558 | apply(+, LF, G, Low), 559 | make_node(Var, Low, HF, Node) 560 | ; { var_less_than(G, F) } -> 561 | { node_var_low_high(G, Var, LG, HG) }, 562 | apply(+, F, LG, Low), 563 | make_node(Var, Low, HG, Node) 564 | ; { node_var_low_high(F, Var, LF, HF), 565 | node_var_low_high(G, _, LG, HG) }, 566 | apply(+, LF, LG, Low), 567 | apply(+, HF, HG, High), 568 | make_node(Var, Low, High, Node) 569 | ). 570 | 571 | apply_(#, F, G, Node) --> 572 | ( { F == 0 } -> { Node = G } 573 | ; { G == 0 } -> { Node = F } 574 | ; { F == G } -> { Node = 0 } 575 | ; { var_less_than(F, G) } -> 576 | { node_var_low_high(F, Var, LF, HF) }, 577 | apply(#, LF, G, Low), 578 | make_node(Var, Low, HF, Node) 579 | ; { var_less_than(G, F) } -> 580 | { node_var_low_high(G, Var, LG, HG) }, 581 | apply(#, F, LG, Low), 582 | make_node(Var, Low, HG, Node) 583 | ; { node_var_low_high(F, Var, LF, HF), 584 | node_var_low_high(G, _, LG, HG) }, 585 | apply(#, LF, LG, Low), 586 | apply(#, HF, HG, High), 587 | make_node(Var, Low, High, Node) 588 | ). 589 | 590 | 591 | node_varindex(Node, VI) :- 592 | node_var_low_high(Node, V, _, _), 593 | var_index(V, VI). 594 | 595 | var_less_than(NA, NB) :- 596 | ( integer(NB) -> true 597 | ; node_varindex(NA, VAI), 598 | node_varindex(NB, VBI), 599 | VAI < VBI 600 | ). 601 | 602 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 603 | Access implicit state in DCGs. 604 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 605 | 606 | state(S) --> state(S, S). 607 | 608 | state(S0, S), [S] --> [S0]. 609 | 610 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 611 | Unification. X = Expr is equivalent to sat(X =:= Expr). 612 | 613 | Current limitation: 614 | =================== 615 | 616 | Unification of variables is not yet fully implemented. 617 | 618 | If you have no simultaneous unifications, you can comment out the 619 | exception instantiation_not_yet_supported and hence use labeling/1. 620 | 621 | Aliasing is definitely not supported. 622 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 623 | 624 | verify_attributes(Var, Other, Gs) :- 625 | % can the invocations of verify_attributes/3 be reduced? 626 | %portray_clause(verify(Var=Other)), 627 | ( get_attr(Var, clpb, index_root(I,Root)) -> 628 | %portray_clause(verify(index_root(I,Root))), 629 | ( integer(Other) -> 630 | throw(instantiation_not_supported), 631 | ( between(0, 1, Other) -> 632 | restrict_in_all_bdds(I, Root, Other) 633 | ; no_truth_value(Other) 634 | ) 635 | ; throw(aliasing_not_supported), 636 | parse_sat(Other, OtherSat), 637 | root_get_formula_bdd(Root, Sat0, _), 638 | Sat = Sat0*OtherSat, 639 | sat_roots(Sat, Roots), 640 | maplist(root_rebuild_bdd, Roots), 641 | taut(True), 642 | roots_and(Roots, 1-True, And-BDD1), 643 | maplist(del_bdd, Roots), 644 | maplist(=(NewRoot), Roots), 645 | root_put_formula_bdd(NewRoot, And, BDD1), 646 | is_bdd(BDD1), 647 | satisfiable_bdd(BDD1) 648 | ) 649 | ; true 650 | ), 651 | Gs = []. 652 | 653 | restrict_in_all_bdds(VI, Root, Other) :- 654 | all_variables_in_index_order(Vs), 655 | maplist(var_index_root, Vs, _, Roots0), 656 | term_variables([Root|Roots0], Roots), 657 | maplist(restrict_vi(VI,Other), Roots, BDDs), 658 | maplist(satisfiable_bdd, BDDs). 659 | 660 | restrict_vi(VI, Other, Root, BDD) :- 661 | root_get_formula_bdd(Root, Sat, BDD0), 662 | bdd_restriction(BDD0, VI, Other, BDD), 663 | root_put_formula_bdd(Root, Sat, BDD). 664 | 665 | root_rebuild_bdd(Root) :- 666 | ( root_get_formula_bdd(Root, F0, _) -> 667 | parse_sat(F0, Sat), 668 | sat_bdd(Sat, BDD), 669 | root_put_formula_bdd(Root, F0, BDD) 670 | ; true 671 | ). 672 | 673 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 674 | BDD restriction. 675 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 676 | 677 | bdd_restriction(Node, VI, Value, Res) :- 678 | empty_assoc(G0), 679 | phrase(bdd_restriction_(Node, VI, Value, Res), [G0], _), 680 | is_bdd(Res). 681 | 682 | bdd_restriction_(Node, VI, Value, Res) --> 683 | ( { integer(Node) } -> { Res = Node } 684 | ; { node_var_low_high(Node, Var, Low, High) } -> 685 | ( { integer(Var) } -> 686 | ( { Var =:= 0 } -> bdd_restriction_(Low, VI, Value, Res) 687 | ; { Var =:= 1 } -> bdd_restriction_(High, VI, Value, Res) 688 | ; { no_truth_value(Var) } 689 | ) 690 | ; { var_index(Var, I0), 691 | node_id(Node, ID) }, 692 | ( { I0 =:= VI } -> 693 | ( { Value =:= 0 } -> { Res = Low } 694 | ; { Value =:= 1 } -> { Res = High } 695 | ; { throw(cannot_happen) } 696 | ) 697 | ; { I0 > VI } -> { Res = Node } 698 | ; state(G0), { get_assoc(ID, G0, Res) } -> [] 699 | ; bdd_restriction_(Low, VI, Value, LRes), 700 | bdd_restriction_(High, VI, Value, HRes), 701 | make_node(Var, LRes, HRes, Res), 702 | state(G0, G), 703 | { put_assoc(ID, G0, Res, G) } 704 | ) 705 | ) 706 | ; { domain_error(node, Node) } 707 | ). 708 | 709 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 710 | Relating a BDD to its elements (nodes and variables). 711 | 712 | Note that BDDs can become quite big (easily more than a million 713 | nodes), and memory space is a major bottleneck for many problems. If 714 | possible, we therefore do not duplicate the entire BDD in memory (as 715 | in bdd_ites/2), but only extract its features as needed. 716 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 717 | 718 | bdd_nodes(BDD, Ns) :- bdd_nodes(do_nothing, BDD, Ns). 719 | 720 | do_nothing(_). 721 | 722 | % VPred is a unary predicate that is called for each branching variable 723 | 724 | bdd_nodes(VPred, BDD, Ns) :- 725 | phrase(bdd_nodes_(VPred, BDD), Ns), 726 | maplist(with_aux(unvisit), Ns). 727 | 728 | bdd_nodes_(VPred, Node) --> 729 | ( { integer(Node) ; with_aux(is_visited, Node) } -> [] 730 | ; { with_aux(put_visited, Node), 731 | node_var_low_high(Node, Var, Low, High), 732 | call(VPred, Var) }, 733 | [Node], 734 | bdd_nodes_(VPred, Low), 735 | bdd_nodes_(VPred, High) 736 | ). 737 | 738 | bdd_variables(BDD, Vs) :- 739 | bdd_nodes(BDD, Nodes), 740 | nodes_variables(Nodes, Vs). 741 | 742 | nodes_variables(Nodes, Vs) :- 743 | phrase(nodes_variables_(Nodes), Vs), 744 | maplist(unvisit, Vs). 745 | 746 | nodes_variables_([]) --> []. 747 | nodes_variables_([Node|Nodes]) --> 748 | { node_var_low_high(Node, Var, _, _) }, 749 | ( { integer(Var) } -> [] 750 | ; ( { is_visited(Var) } -> [] 751 | ; { put_visited(Var) }, 752 | [Var] 753 | ) 754 | ), 755 | nodes_variables_(Nodes). 756 | 757 | unvisit(V) :- del_attr(V, clpb_visited). 758 | 759 | is_visited(V) :- get_attr(V, clpb_visited, true). 760 | 761 | put_visited(V) :- put_attr(V, clpb_visited, true). 762 | 763 | with_aux(Pred, Node) :- 764 | node_aux(Node, Aux), 765 | call(Pred, Aux). 766 | 767 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 768 | Internal consistency checks. 769 | 770 | To enable these checks, define the fact clpb_validation. 771 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 772 | 773 | :- dynamic(clpb_validation/0). 774 | 775 | %clpb_validation. 776 | 777 | is_bdd(BDD) :- 778 | ( clpb_validation -> 779 | bdd_ites(BDD, ITEs), 780 | % length(ITEs, Len), 781 | % portray_clause(Len), 782 | pairs_values(ITEs, Ls0), 783 | sort(Ls0, Ls1), 784 | ( same_length(Ls0, Ls1) -> true 785 | ; domain_error(reduced_ites, (ITEs,Ls0,Ls1)) 786 | ) 787 | % ( member(ITE, ITEs), \+ registered_node(ITE) -> 788 | % domain_error(registered_node, ITE) 789 | % ; true 790 | % ) 791 | ; true 792 | ). 793 | 794 | registered_node(Node-ite(Var,High,Low)) :- 795 | low_high_key(Low, High, Key), 796 | lookup_node(Var, Key, Node0), 797 | Node == Node0. 798 | 799 | bdd_ites(BDD, ITEs) :- 800 | bdd_nodes(BDD, Nodes), 801 | maplist(node_ite, Nodes, ITEs). 802 | 803 | node_ite(Node, Node-ite(Var,High,Low)) :- 804 | node_var_low_high(Node, Var, Low, High). 805 | 806 | %% labeling(+Vs) is nondet. 807 | % 808 | % Assigns truth values to the Boolean variables Vs such that all 809 | % stated constraints are satisfied. 810 | 811 | labeling(Vs0) :- 812 | must_be(list, Vs0), 813 | variables_in_index_order(Vs0, Vs), 814 | maplist(indomain, Vs). 815 | 816 | variables_in_index_order(Vs0, Vs) :- 817 | maplist(var_with_index, Vs0, IVs0), 818 | keysort(IVs0, IVs), 819 | pairs_values(IVs, Vs). 820 | 821 | var_with_index(V, I-V) :- 822 | ( var_index_root(V, I, _) -> true 823 | ; I = 0 824 | ). 825 | 826 | indomain(0). 827 | indomain(1). 828 | 829 | 830 | %% sat_count(+Expr, -N) is det. 831 | % 832 | % N is the number of different assignments of truth values to CLP(B) 833 | % variables, such that the Boolean expression Expr is true and all 834 | % posted constraints are satisfiable. 835 | % 836 | % Example: 837 | % 838 | % == 839 | % ?- length(Vs, 120), zdd_set_vars(Vs), sat_count(+Vs, N). 840 | % N = 1329227995784915872903807060280344575. 841 | % == 842 | 843 | sat_count(Sat0, N) :- 844 | catch((parse_sat(Sat0, Sat), 845 | sat_bdd(Sat, BDD), 846 | sat_roots(Sat, Roots), 847 | roots_and(Roots, _-BDD, _-BDD1), 848 | bdd_count(BDD1, N), 849 | % reset all attributes and Aux variables 850 | throw(count(N))), 851 | count(N), 852 | true). 853 | 854 | sat_count(N) :- 855 | catch((all_variables_in_index_order([First|_]), 856 | var_index_root(First, _, Root), 857 | root_get_formula_bdd(Root, _, BDD), 858 | bdd_count(BDD, N), 859 | throw(count(N))), 860 | count(N), 861 | true). 862 | 863 | bdd_count(Node, Count) :- 864 | ( integer(Node) -> Count = Node 865 | ; node_aux(Node, Count), 866 | ( integer(Count) -> true 867 | ; node_var_low_high(Node, _, Low, High), 868 | bdd_count(Low, LCount), 869 | bdd_count(High, HCount), 870 | Count is LCount + HCount 871 | ) 872 | ). 873 | 874 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 875 | You must enable unification if you want to generate random solutions. 876 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 877 | 878 | random_solution(Seed, Vars) :- 879 | must_be(list, Vars), 880 | set_random(seed(Seed)), 881 | ( ground(Vars) -> true 882 | ; catch((sat(+[1|Vars]), % capture all variables with a single BDD 883 | once((member(Var, Vars),var(Var))), 884 | var_index_root(Var, _, Root), 885 | root_get_formula_bdd(Root, _, BDD), 886 | phrase(random_bindings(BDD), Bs), 887 | maplist(del_attrs, Vars), 888 | % reset all attribute modifications 889 | throw(randsol(Vars, Bs))), 890 | randsol(Vars, Bs), 891 | true), 892 | maplist(call, Bs), 893 | % set remaining variables to 0 894 | include(var, Vars, Remaining), 895 | maplist(=(0), Remaining) 896 | ). 897 | 898 | random_bindings(Node) --> { Node == 1 }, !. 899 | random_bindings(Node) --> 900 | { node_var_low_high(Node, Var, Low, High), 901 | bdd_count(Node, Total), 902 | bdd_count(Low, LCount) }, 903 | ( { maybe(LCount, Total) } -> 904 | [Var=0], random_bindings(Low) 905 | ; [Var=1], random_bindings(High) 906 | ). 907 | 908 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 909 | Projection to residual goals. 910 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 911 | 912 | attribute_goals(Var) --> 913 | { var_index_root(Var, _, Root) }, 914 | boolean(Var), 915 | ( { root_get_formula_bdd(Root, _, BDD) } -> 916 | % [bdd=BDD], 917 | { del_bdd(Root), 918 | bdd_variables(BDD, Vs), 919 | maplist(del_clpb, Vs), 920 | bdd_nodes(BDD, Nodes) }, 921 | nodes(Nodes) 922 | ; [] 923 | ). 924 | 925 | boolean(V) --> [sat(V =:= V)]. 926 | 927 | nodes([]) --> []. 928 | nodes([Node|Nodes]) --> 929 | { node_var_low_high(Node, Var, Low, High), 930 | maplist(node_projection, [Node,High,Low], [ID,HID,LID]) }, 931 | [ID-(Var -> HID ; LID)], 932 | nodes(Nodes). 933 | 934 | node_projection(Node, Projection) :- 935 | node_id(Node, ID), 936 | ( integer(ID) -> Projection = node(ID) 937 | ; Projection = ID 938 | ). 939 | 940 | del_clpb(Var) :- 941 | %del_attr(Var, clpb), 942 | del_attr(Var, clpb_hash). 943 | 944 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 945 | Global variables for unique node and variable IDs. 946 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 947 | 948 | make_clpb_var('$clpb_next_var') :- bb_put('$clpb_next_var', 0). 949 | 950 | make_clpb_var('$clpb_next_node') :- bb_put('$clpb_next_node', 0). 951 | 952 | :- initialization((make_clpb_var(_),false;true)). 953 | 954 | clpb_next_id(Var, ID) :- 955 | bb_get(Var, ID), 956 | Next is ID + 1, 957 | bb_b_put(Var, Next). 958 | 959 | :- use_module(library(format)). 960 | 961 | /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 962 | ?- clpb:zdd_set_vars([X,Y]). 963 | 964 | ?- clpb:zdd_set_vars([X,Y,Z]), sat(card([2],[X,Y,Z])). 965 | 966 | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 967 | 968 | zdd_set_vars(Vars) :- 969 | must_be(list(var), Vars), 970 | bb_b_put('$clpb_vars', Vars), 971 | maplist(enumerate_variable, Vars), 972 | sat(+[1|Vars]). 973 | 974 | taut(Node) :- 975 | all_variables_in_index_order(Vars), 976 | taut_(Vars, Node). 977 | 978 | taut_([], 1). 979 | taut_([V|Vs], Taut) :- 980 | taut_(Vs, Taut0), 981 | make_node(V, Taut0, Taut0, Taut). 982 | 983 | var_projection(V, Node) :- 984 | all_variables_in_index_order(Vars), 985 | projection_(Vars, V, Node). 986 | 987 | projection_([Var|Vars], V, Proj) :- 988 | ( Var == V -> 989 | taut_(Vars, Taut), 990 | make_node(V, 0, Taut, Proj) 991 | ; projection_(Vars, V, Proj0), 992 | make_node(Var, Proj0, Proj0, Proj) 993 | ). 994 | 995 | all_variables_in_index_order(Vars) :- 996 | bb_get('$clpb_vars', Vars0), 997 | include(var, Vars0, Vars). 998 | --------------------------------------------------------------------------------