1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package org.sat4j.tools.encoding;
32
33 import org.sat4j.core.ConstrGroup;
34 import org.sat4j.core.VecInt;
35 import org.sat4j.specs.ContradictionException;
36 import org.sat4j.specs.IConstr;
37 import org.sat4j.specs.ISolver;
38 import org.sat4j.specs.IVecInt;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 public class Binary extends EncodingStrategyAdapter {
58
59
60
61
62 private static final long serialVersionUID = 1L;
63
64
65
66
67
68
69 @Override
70 public IConstr addAtMostOne(ISolver solver, IVecInt literals)
71 throws ContradictionException {
72 ConstrGroup group = new ConstrGroup(false);
73
74 final int n = literals.size();
75 final int p = (int) Math.ceil(Math.log(n) / Math.log(2));
76 final int k = (int) Math.pow(2, p) - n;
77
78 IVecInt clause = new VecInt();
79 String binary = "";
80
81 if (p == 0) {
82 return group;
83 }
84
85 int y[] = new int[p];
86 for (int i = 0; i < p; i++) {
87 y[i] = solver.nextFreeVarId(true);
88 }
89
90 for (int i = 0; i < k; i++) {
91 binary = Integer.toBinaryString(i);
92 while (binary.length() != p - 1) {
93 binary = "0" + binary;
94 }
95
96 for (int j = 0; j < p - 1; j++) {
97 clause.push(-literals.get(i));
98 if (binary.charAt(j) == '0') {
99 clause.push(-y[j]);
100 } else {
101 clause.push(y[j]);
102 }
103 group.add(solver.addClause(clause));
104 clause.clear();
105
106 }
107 }
108
109 for (int i = k; i < n; i++) {
110 binary = Integer.toBinaryString(2 * k + i - k);
111 while (binary.length() != p) {
112 binary = "0" + binary;
113 }
114 for (int j = 0; j < p; j++) {
115 clause.push(-literals.get(i));
116 if (binary.charAt(j) == '0') {
117 clause.push(-y[j]);
118 } else {
119 clause.push(y[j]);
120 }
121 group.add(solver.addClause(clause));
122 clause.clear();
123 }
124
125 }
126
127 return group;
128 }
129
130 @Override
131 public IConstr addAtMost(ISolver solver, IVecInt literals, int k)
132 throws ContradictionException {
133
134 final int n = literals.size();
135 final int p = (int) Math.ceil(Math.log(n) / Math.log(2));
136
137 ConstrGroup group = new ConstrGroup(false);
138
139 int[][] b = new int[k][p];
140
141 for (int i = 0; i < k; i++) {
142 for (int j = 0; j < p; j++) {
143 b[i][j] = solver.nextFreeVarId(true);
144 }
145 }
146
147 int[][] t = new int[k][n];
148
149 for (int i = 0; i < k; i++) {
150 for (int j = 0; j < n; j++) {
151 t[i][j] = solver.nextFreeVarId(true);
152 }
153 }
154
155 int max, min;
156 IVecInt clause1 = new VecInt();
157 IVecInt clause2 = new VecInt();
158 String binary = "";
159 for (int i = 0; i < n; i++) {
160 max = Math.max(1, k - n + i + 1);
161 min = Math.min(i + 1, k);
162 clause1.push(-literals.get(i));
163
164 binary = Integer.toBinaryString(i);
165 while (binary.length() != p) {
166 binary = "0" + binary;
167 }
168
169 for (int g = max - 1; g < min; g++) {
170 clause1.push(t[g][i]);
171 for (int j = 0; j < p; j++) {
172 clause2.push(-t[g][i]);
173 if (binary.charAt(j) == '0') {
174 clause2.push(-b[g][j]);
175 } else {
176 clause2.push(b[g][j]);
177 }
178 group.add(solver.addClause(clause2));
179 clause2.clear();
180 }
181 }
182 group.add(solver.addClause(clause1));
183 clause1.clear();
184 }
185
186 return group;
187 }
188
189 @Override
190 public IConstr addExactlyOne(ISolver solver, IVecInt literals)
191 throws ContradictionException {
192 ConstrGroup group = new ConstrGroup();
193
194 group.add(addAtLeastOne(solver, literals));
195 group.add(addAtMostOne(solver, literals));
196
197 return group;
198 }
199
200 @Override
201 public IConstr addExactly(ISolver solver, IVecInt literals, int degree)
202 throws ContradictionException {
203 ConstrGroup group = new ConstrGroup();
204
205 group.add(addAtLeast(solver, literals, degree));
206 group.add(addAtMost(solver, literals, degree));
207
208 return group;
209 }
210 }