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 package org.sat4j.minisat.constraints.cnf;
31
32 import static org.sat4j.core.LiteralsUtils.neg;
33
34 import java.io.Serializable;
35
36 import org.sat4j.minisat.core.Constr;
37 import org.sat4j.minisat.core.ILits;
38 import org.sat4j.minisat.core.Propagatable;
39 import org.sat4j.specs.IVecInt;
40 import org.sat4j.specs.UnitPropagationListener;
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 public abstract class HTClause implements Propagatable, Constr, Serializable {
57
58 private static final long serialVersionUID = 1L;
59
60 protected double activity;
61
62 protected final int[] middleLits;
63
64 protected final ILits voc;
65
66 protected int head;
67
68 protected int tail;
69
70
71
72
73
74
75
76
77
78 public HTClause(IVecInt ps, ILits voc) {
79 assert ps.size() > 1;
80 this.head = ps.get(0);
81 this.tail = ps.last();
82 final int size = ps.size() - 2;
83 assert size > 0;
84 this.middleLits = new int[size];
85 System.arraycopy(ps.toArray(), 1, this.middleLits, 0, size);
86 ps.clear();
87 assert ps.size() == 0;
88 this.voc = voc;
89 this.activity = 0;
90 }
91
92
93
94
95
96
97 public void calcReason(int p, IVecInt outReason) {
98 if (this.voc.isFalsified(this.head)) {
99 outReason.push(neg(this.head));
100 }
101 final int[] mylits = this.middleLits;
102 for (int mylit : mylits) {
103 if (this.voc.isFalsified(mylit)) {
104 outReason.push(neg(mylit));
105 }
106 }
107 if (this.voc.isFalsified(this.tail)) {
108 outReason.push(neg(this.tail));
109 }
110 }
111
112
113
114
115
116
117 public void remove(UnitPropagationListener upl) {
118 this.voc.watches(neg(this.head)).remove(this);
119 this.voc.watches(neg(this.tail)).remove(this);
120 }
121
122
123
124
125
126
127 public boolean simplify() {
128 if (this.voc.isSatisfied(this.head) || this.voc.isSatisfied(this.tail)) {
129 return true;
130 }
131 for (int middleLit : this.middleLits) {
132 if (this.voc.isSatisfied(middleLit)) {
133 return true;
134 }
135 }
136 return false;
137 }
138
139 public boolean propagate(UnitPropagationListener s, int p) {
140
141 if (this.head == neg(p)) {
142 final int[] mylits = this.middleLits;
143 int temphead = 0;
144
145 while (temphead < mylits.length
146 && this.voc.isFalsified(mylits[temphead])) {
147 temphead++;
148 }
149 assert temphead <= mylits.length;
150 if (temphead == mylits.length) {
151 this.voc.watch(p, this);
152 return s.enqueue(this.tail, this);
153 }
154 this.head = mylits[temphead];
155 mylits[temphead] = neg(p);
156 this.voc.watch(neg(this.head), this);
157 return true;
158 }
159 assert this.tail == neg(p);
160 final int[] mylits = this.middleLits;
161 int temptail = mylits.length - 1;
162
163 while (temptail >= 0 && this.voc.isFalsified(mylits[temptail])) {
164 temptail--;
165 }
166 assert -1 <= temptail;
167 if (-1 == temptail) {
168 this.voc.watch(p, this);
169 return s.enqueue(this.head, this);
170 }
171 this.tail = mylits[temptail];
172 mylits[temptail] = neg(p);
173 this.voc.watch(neg(this.tail), this);
174 return true;
175 }
176
177
178
179
180 public boolean locked() {
181 return this.voc.getReason(this.head) == this
182 || this.voc.getReason(this.tail) == this;
183 }
184
185
186
187
188 public double getActivity() {
189 return this.activity;
190 }
191
192 @Override
193 public String toString() {
194 StringBuffer stb = new StringBuffer();
195 stb.append(Lits.toString(this.head));
196 stb.append("[");
197 stb.append(this.voc.valueToString(this.head));
198 stb.append("]");
199 stb.append(" ");
200 for (int middleLit : this.middleLits) {
201 stb.append(Lits.toString(middleLit));
202 stb.append("[");
203 stb.append(this.voc.valueToString(middleLit));
204 stb.append("]");
205 stb.append(" ");
206 }
207 stb.append(Lits.toString(this.tail));
208 stb.append("[");
209 stb.append(this.voc.valueToString(this.tail));
210 stb.append("]");
211 return stb.toString();
212 }
213
214
215
216
217
218
219
220
221
222 public int get(int i) {
223 if (i == 0) {
224 return this.head;
225 }
226 if (i == this.middleLits.length + 1) {
227 return this.tail;
228 }
229 return this.middleLits[i - 1];
230 }
231
232
233
234
235 public void rescaleBy(double d) {
236 this.activity *= d;
237 }
238
239 public int size() {
240 return this.middleLits.length + 2;
241 }
242
243 public void assertConstraint(UnitPropagationListener s) {
244 assert this.voc.isUnassigned(this.head);
245 boolean ret = s.enqueue(this.head, this);
246 assert ret;
247 }
248
249 public void assertConstraintIfNeeded(UnitPropagationListener s) {
250 if (voc.isFalsified(this.tail)) {
251 boolean ret = s.enqueue(this.head, this);
252 assert ret;
253 }
254 }
255
256 public ILits getVocabulary() {
257 return this.voc;
258 }
259
260 public int[] getLits() {
261 int[] tmp = new int[size()];
262 System.arraycopy(this.middleLits, 0, tmp, 1, this.middleLits.length);
263 tmp[0] = this.head;
264 tmp[tmp.length - 1] = this.tail;
265 return tmp;
266 }
267
268 @Override
269 public boolean equals(Object obj) {
270 if (obj == null) {
271 return false;
272 }
273 try {
274 HTClause wcl = (HTClause) obj;
275 if (wcl.head != this.head || wcl.tail != this.tail) {
276 return false;
277 }
278 if (this.middleLits.length != wcl.middleLits.length) {
279 return false;
280 }
281 boolean ok;
282 for (int lit : this.middleLits) {
283 ok = false;
284 for (int lit2 : wcl.middleLits) {
285 if (lit == lit2) {
286 ok = true;
287 break;
288 }
289 }
290 if (!ok) {
291 return false;
292 }
293 }
294 return true;
295 } catch (ClassCastException e) {
296 return false;
297 }
298 }
299
300 @Override
301 public int hashCode() {
302 long sum = this.head + this.tail;
303 for (int p : this.middleLits) {
304 sum += p;
305 }
306 return (int) sum / this.middleLits.length;
307 }
308
309 public boolean canBePropagatedMultipleTimes() {
310 return false;
311 }
312
313 public Constr toConstraint() {
314 return this;
315 }
316
317 public void calcReasonOnTheFly(int p, IVecInt trail, IVecInt outReason) {
318 calcReason(p, outReason);
319 }
320 }