1 #include "constraint.h"
4 #include "inc_solver.h"
8 V2 Copyright (c) 2014 Ben Chambers, Eugene Goldberg, Pete Manolios,
9 Vasilis Papavasileiou, Sudarshan Srinivasan, and Daron Vroon.
11 Permission is hereby granted, free of charge, to any person obtaining
12 a copy of this software and associated documentation files (the
13 "Software"), to deal in the Software without restriction, including
14 without limitation the rights to use, copy, modify, merge, publish,
15 distribute, sublicense, and/or sell copies of the Software, and to
16 permit persons to whom the Software is furnished to do so, subject to
17 the following conditions:
19 The above copyright notice and this permission notice shall be
20 included in all copies or substantial portions of the Software. If
21 you download or use the software, send email to Pete Manolios
22 (pete@ccs.neu.edu) with your name, contact information, and a short
23 note describing what you want to use BAT for. For any reuse or
24 distribution, you must make clear to others the license terms of this
27 Contact Pete Manolios if you want any of these conditions waived.
29 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
39 C port of CNF SAT Conversion Copyright Brian Demsky 2017.
43 VectorImpl(Edge, Edge, 16)
44 Edge E_True = {(Node *)(uintptr_t) EDGE_IS_VAR_CONSTANT};
45 Edge E_False = {(Node *)(uintptr_t) (EDGE_IS_VAR_CONSTANT | NEGATE_EDGE)};
46 Edge E_BOGUS = {(Node *)0x12345673};
47 Edge E_NULL = {(Node *)NULL};
51 CNF *cnf = (CNF *) ourmalloc(sizeof(CNF));
53 cnf->capacity = DEFAULT_CNF_ARRAY_SIZE;
54 cnf->mask = cnf->capacity - 1;
55 cnf->node_array = (Node **) ourcalloc(1, sizeof(Node *) * cnf->capacity);
57 cnf->maxsize = (uint)(((double)cnf->capacity) * LOAD_FACTOR);
58 cnf->enableMatching = true;
59 initDefVectorEdge(&cnf->constraints);
60 initDefVectorEdge(&cnf->args);
61 cnf->solver = allocIncrementalSolver();
65 void deleteCNF(CNF *cnf) {
66 for (uint i = 0; i < cnf->capacity; i++) {
67 Node *n = cnf->node_array[i];
71 deleteVectorArrayEdge(&cnf->constraints);
72 deleteVectorArrayEdge(&cnf->args);
73 deleteIncrementalSolver(cnf->solver);
74 ourfree(cnf->node_array);
78 void resizeCNF(CNF *cnf, uint newCapacity) {
79 Node **old_array = cnf->node_array;
80 Node **new_array = (Node **) ourcalloc(1, sizeof(Node *) * newCapacity);
81 uint oldCapacity = cnf->capacity;
82 uint newMask = newCapacity - 1;
83 for (uint i = 0; i < oldCapacity; i++) {
84 Node *n = old_array[i];
85 uint hashCode = n->hashCode;
86 uint newindex = hashCode & newMask;
87 for (;; newindex = (newindex + 1) & newMask) {
88 if (new_array[newindex] == NULL) {
89 new_array[newindex] = n;
95 cnf->node_array = new_array;
96 cnf->capacity = newCapacity;
97 cnf->maxsize = (uint)(((double)cnf->capacity) * LOAD_FACTOR);
101 Node *allocNode(NodeType type, uint numEdges, Edge *edges, uint hashcode) {
102 Node *n = (Node *)ourmalloc(sizeof(Node) + sizeof(Edge) * numEdges);
103 memcpy(n->edges, edges, sizeof(Edge) * numEdges);
104 n->flags.type = type;
105 n->flags.wasExpanded = 0;
106 n->flags.cnfVisitedDown = 0;
107 n->flags.cnfVisitedUp = 0;
108 n->flags.varForced = 0;
109 n->numEdges = numEdges;
110 n->hashCode = hashcode;
111 n->intAnnot[0] = 0;n->intAnnot[1] = 0;
112 n->ptrAnnot[0] = NULL;n->ptrAnnot[1] = NULL;
116 Edge createNode(CNF *cnf, NodeType type, uint numEdges, Edge *edges) {
117 if (cnf->size > cnf->maxsize) {
118 resizeCNF(cnf, cnf->capacity << 1);
120 uint hashvalue = hashNode(type, numEdges, edges);
121 uint mask = cnf->mask;
122 uint index = hashvalue & mask;
124 for (;; index = (index + 1) & mask) {
125 n_ptr = &cnf->node_array[index];
126 if (*n_ptr != NULL) {
127 if ((*n_ptr)->hashCode == hashvalue) {
128 if (compareNodes(*n_ptr, type, numEdges, edges)) {
137 *n_ptr = allocNode(type, numEdges, edges, hashvalue);
142 uint hashNode(NodeType type, uint numEdges, Edge *edges) {
143 uint hashvalue = type ^ numEdges;
144 for (uint i = 0; i < numEdges; i++) {
145 hashvalue ^= (uint) ((uintptr_t) edges[i].node_ptr);
146 hashvalue = (hashvalue << 3) | (hashvalue >> 29); //rotate left by 3 bits
148 return (uint) hashvalue;
151 bool compareNodes(Node *node, NodeType type, uint numEdges, Edge *edges) {
152 if (node->flags.type != type || node->numEdges != numEdges)
154 Edge *nodeedges = node->edges;
155 for (uint i = 0; i < numEdges; i++) {
156 if (!equalsEdge(nodeedges[i], edges[i]))
162 Edge constraintOR(CNF *cnf, uint numEdges, Edge *edges) {
163 Edge edgearray[numEdges];
165 for (uint i = 0; i < numEdges; i++) {
166 edgearray[i] = constraintNegate(edges[i]);
168 Edge eand = constraintAND(cnf, numEdges, edgearray);
169 return constraintNegate(eand);
172 Edge constraintOR2(CNF *cnf, Edge left, Edge right) {
173 Edge lneg = constraintNegate(left);
174 Edge rneg = constraintNegate(right);
175 Edge eand = constraintAND2(cnf, lneg, rneg);
176 return constraintNegate(eand);
179 int comparefunction(const Edge *e1, const Edge *e2) {
180 return ((uintptr_t)e1->node_ptr) - ((uintptr_t)e2->node_ptr);
183 Edge constraintAND(CNF *cnf, uint numEdges, Edge *edges) {
184 ASSERT(numEdges != 0);
185 qsort(edges, numEdges, sizeof(Edge), (int (*)(const void *, const void *))comparefunction);
187 while (initindex < numEdges && equalsEdge(edges[initindex], E_True))
190 uint remainSize = numEdges - initindex;
194 else if (remainSize == 1)
195 return edges[initindex];
196 else if (equalsEdge(edges[initindex], E_False))
199 /** De-duplicate array */
201 edges[lowindex] = edges[initindex++];
203 for (; initindex < numEdges; initindex++) {
204 Edge e1 = edges[lowindex];
205 Edge e2 = edges[initindex];
206 if (sameNodeVarEdge(e1, e2)) {
207 if (!sameSignEdge(e1, e2)) {
211 edges[++lowindex] = edges[initindex];
213 lowindex++; //Make lowindex look like size
218 if (cnf->enableMatching && lowindex == 2 &&
219 isNegNodeEdge(edges[0]) && isNegNodeEdge(edges[1]) &&
220 getNodeType(edges[0]) == NodeType_AND &&
221 getNodeType(edges[1]) == NodeType_AND &&
222 getNodeSize(edges[0]) == 2 &&
223 getNodeSize(edges[1]) == 2) {
224 Edge *e0edges = getEdgeArray(edges[0]);
225 Edge *e1edges = getEdgeArray(edges[1]);
226 if (sameNodeOppSign(e0edges[0], e1edges[0])) {
227 return constraintNegate(constraintITE(cnf, e0edges[0], e0edges[1], e1edges[1]));
228 } else if (sameNodeOppSign(e0edges[0], e1edges[1])) {
229 return constraintNegate(constraintITE(cnf, e0edges[0], e0edges[1], e1edges[0]));
230 } else if (sameNodeOppSign(e0edges[1], e1edges[0])) {
231 return constraintNegate(constraintITE(cnf, e0edges[1], e0edges[0], e1edges[1]));
232 } else if (sameNodeOppSign(e0edges[1], e1edges[1])) {
233 return constraintNegate(constraintITE(cnf, e0edges[1], e0edges[0], e1edges[0]));
237 return createNode(cnf, NodeType_AND, lowindex, edges);
240 Edge constraintAND2(CNF *cnf, Edge left, Edge right) {
241 Edge edges[2] = {left, right};
242 return constraintAND(cnf, 2, edges);
245 Edge constraintIMPLIES(CNF *cnf, Edge left, Edge right) {
248 array[1] = constraintNegate(right);
249 Edge eand = constraintAND(cnf, 2, array);
250 return constraintNegate(eand);
253 Edge constraintIFF(CNF *cnf, Edge left, Edge right) {
254 bool negate = !sameSignEdge(left, right);
255 Edge lpos = getNonNeg(left);
256 Edge rpos = getNonNeg(right);
259 if (equalsEdge(lpos, rpos)) {
261 } else if (ltEdge(lpos, rpos)) {
262 Edge edges[] = {lpos, rpos};
263 e = (edgeIsConst(lpos)) ? rpos : createNode(cnf, NodeType_IFF, 2, edges);
265 Edge edges[] = {rpos, lpos};
266 e = (edgeIsConst(rpos)) ? lpos : createNode(cnf, NodeType_IFF, 2, edges);
269 e = constraintNegate(e);
273 Edge constraintITE(CNF *cnf, Edge cond, Edge thenedge, Edge elseedge) {
274 if (isNegEdge(cond)) {
275 cond = constraintNegate(cond);
281 bool negate = isNegEdge(thenedge);
283 thenedge = constraintNegate(thenedge);
284 elseedge = constraintNegate(elseedge);
288 if (equalsEdge(cond, E_True)) {
290 } else if (equalsEdge(thenedge, E_True) || equalsEdge(cond, thenedge)) {
291 Edge array[] = {cond, elseedge};
292 result = constraintOR(cnf, 2, array);
293 } else if (equalsEdge(elseedge, E_True) || sameNodeOppSign(cond, elseedge)) {
294 result = constraintIMPLIES(cnf, cond, thenedge);
295 } else if (equalsEdge(thenedge, E_False) || equalsEdge(cond, elseedge)) {
296 Edge array[] = {cond, thenedge};
297 result = constraintAND(cnf, 2, array);
298 } else if (equalsEdge(thenedge, elseedge)) {
300 } else if (sameNodeOppSign(thenedge, elseedge)) {
301 if (ltEdge(cond, thenedge)) {
302 Edge array[] = {cond, thenedge};
303 result = createNode(cnf, NodeType_IFF, 2, array);
305 Edge array[] = {thenedge, cond};
306 result = createNode(cnf, NodeType_IFF, 2, array);
309 Edge edges[] = {cond, thenedge, elseedge};
310 result = createNode(cnf, NodeType_ITE, 3, edges);
313 result = constraintNegate(result);
317 void addConstraintCNF(CNF *cnf, Edge constraint) {
318 pushVectorEdge(&cnf->constraints, constraint);
320 model_print("****SATC_ADDING NEW Constraint*****\n");
321 printCNF(constraint);
322 model_print("\n******************************\n");
326 Edge constraintNewVar(CNF *cnf) {
327 uint varnum = cnf->varcount++;
328 Edge e = {(Node *) ((((uintptr_t)varnum) << VAR_SHIFT) | EDGE_IS_VAR_CONSTANT) };
332 int solveCNF(CNF *cnf) {
333 long long startTime=getTimeNano();
335 convertPass(cnf, false);
336 finishedClauses(cnf->solver);
337 long long startSolve=getTimeNano();
338 int result = solve(cnf->solver);
339 long long finishTime=getTimeNano();
340 cnf->encodeTime=startSolve-startTime;
341 cnf->solveTime=finishTime-startSolve;
345 bool getValueCNF(CNF *cnf, Edge var) {
346 Literal l = getEdgeVar(var);
347 bool isneg = (l < 0);
349 return isneg ^ getValueSolver(cnf->solver, l);
352 void countPass(CNF *cnf) {
353 uint numConstraints = getSizeVectorEdge(&cnf->constraints);
354 VectorEdge *ve = allocDefVectorEdge();
355 for (uint i = 0; i < numConstraints; i++) {
356 countConstraint(cnf, ve, getVectorEdge(&cnf->constraints, i));
358 deleteVectorEdge(ve);
361 void countConstraint(CNF *cnf, VectorEdge *stack, Edge eroot) {
362 //Skip constants and variables...
363 if (edgeIsVarConst(eroot))
366 clearVectorEdge(stack);pushVectorEdge(stack, eroot);
368 bool isMatching = cnf->enableMatching;
370 while (getSizeVectorEdge(stack) != 0) {
371 Edge e = lastVectorEdge(stack); popVectorEdge(stack);
372 bool polarity = isNegEdge(e);
373 Node *n = getNodePtrFromEdge(e);
374 if (getExpanded(n, polarity)) {
375 if (n->flags.type == NodeType_IFF ||
376 n->flags.type == NodeType_ITE) {
377 Edge pExp = {(Node *)n->ptrAnnot[polarity]};
378 getNodePtrFromEdge(pExp)->intAnnot[0]++;
380 n->intAnnot[polarity]++;
383 setExpanded(n, polarity);
385 if (n->flags.type == NodeType_ITE ||
386 n->flags.type == NodeType_IFF) {
387 n->intAnnot[polarity] = 0;
388 Edge cond = n->edges[0];
389 Edge thenedge = n->edges[1];
390 Edge elseedge = n->flags.type == NodeType_IFF ? constraintNegate(thenedge) : n->edges[2];
391 thenedge = constraintNegateIf(thenedge, !polarity);
392 elseedge = constraintNegateIf(elseedge, !polarity);
393 thenedge = constraintAND2(cnf, cond, thenedge);
394 cond = constraintNegate(cond);
395 elseedge = constraintAND2(cnf, cond, elseedge);
396 thenedge = constraintNegate(thenedge);
397 elseedge = constraintNegate(elseedge);
398 cnf->enableMatching = false;
399 Edge succ1 = constraintAND2(cnf, thenedge, elseedge);
400 n->ptrAnnot[polarity] = succ1.node_ptr;
401 cnf->enableMatching = isMatching;
402 pushVectorEdge(stack, succ1);
403 if (getExpanded(n, !polarity)) {
404 Edge succ2 = {(Node *)n->ptrAnnot[!polarity]};
405 Node *n1 = getNodePtrFromEdge(succ1);
406 Node *n2 = getNodePtrFromEdge(succ2);
407 n1->ptrAnnot[0] = succ2.node_ptr;
408 n2->ptrAnnot[0] = succ1.node_ptr;
409 n1->ptrAnnot[1] = succ2.node_ptr;
410 n2->ptrAnnot[1] = succ1.node_ptr;
413 n->intAnnot[polarity] = 1;
414 for (uint i = 0; i < n->numEdges; i++) {
415 Edge succ = n->edges[i];
416 if (!edgeIsVarConst(succ)) {
417 succ = constraintNegateIf(succ, polarity);
418 pushVectorEdge(stack, succ);
426 void convertPass(CNF *cnf, bool backtrackLit) {
427 uint numConstraints = getSizeVectorEdge(&cnf->constraints);
428 VectorEdge *ve = allocDefVectorEdge();
429 for (uint i = 0; i < numConstraints; i++) {
430 convertConstraint(cnf, ve, getVectorEdge(&cnf->constraints, i), backtrackLit);
432 deleteVectorEdge(ve);
435 void convertConstraint(CNF *cnf, VectorEdge *stack, Edge root, bool backtrackLit) {
436 Node *nroot = getNodePtrFromEdge(root);
438 if (isNodeEdge(root) && (nroot->flags.type == NodeType_ITE || nroot->flags.type == NodeType_IFF)) {
439 nroot = (Node *) nroot->ptrAnnot[isNegEdge(root)];
440 root = (Edge) { nroot };
442 if (edgeIsConst(root)) {
443 if (isNegEdge(root)) {
445 Edge newvar = constraintNewVar(cnf);
446 Literal var = getEdgeVar(newvar);
447 Literal clause[] = {var};
448 addArrayClauseLiteral(cnf->solver, 1, clause);
450 addArrayClauseLiteral(cnf->solver, 1, clause);
456 } else if (edgeIsVarConst(root)) {
457 Literal clause[] = { getEdgeVar(root)};
458 addArrayClauseLiteral(cnf->solver, 1, clause);
462 clearVectorEdge(stack);pushVectorEdge(stack, root);
463 while (getSizeVectorEdge(stack) != 0) {
464 Edge e = lastVectorEdge(stack);
465 Node *n = getNodePtrFromEdge(e);
467 if (edgeIsVarConst(e)) {
468 popVectorEdge(stack);
470 } else if (n->flags.type == NodeType_ITE ||
471 n->flags.type == NodeType_IFF) {
472 popVectorEdge(stack);
473 if (n->ptrAnnot[0] != NULL)
474 pushVectorEdge(stack, (Edge) {(Node *)n->ptrAnnot[0]});
475 if (n->ptrAnnot[1] != NULL)
476 pushVectorEdge(stack, (Edge) {(Node *)n->ptrAnnot[1]});
480 bool needPos = (n->intAnnot[0] > 0);
481 bool needNeg = (n->intAnnot[1] > 0);
482 if ((!needPos || n->flags.cnfVisitedUp & 1) &&
483 (!needNeg || n->flags.cnfVisitedUp & 2)) {
484 popVectorEdge(stack);
485 } else if ((needPos && !(n->flags.cnfVisitedDown & 1)) ||
486 (needNeg && !(n->flags.cnfVisitedDown & 2))) {
488 n->flags.cnfVisitedDown |= 1;
490 n->flags.cnfVisitedDown |= 2;
491 for (uint i = 0; i < n->numEdges; i++) {
492 Edge arg = n->edges[i];
493 arg = constraintNegateIf(arg, isNegEdge(e));
494 pushVectorEdge(stack, arg); //WARNING, THIS LOOKS LIKE A BUG IN THE ORIGINAL CODE
497 popVectorEdge(stack);
501 CNFExpr *cnfExp = (CNFExpr *) nroot->ptrAnnot[isNegEdge(root)];
502 ASSERT(cnfExp != NULL);
503 if (isProxy(cnfExp)) {
504 Literal l = getProxy(cnfExp);
505 Literal clause[] = {l};
506 addArrayClauseLiteral(cnf->solver, 1, clause);
507 } else if (backtrackLit) {
508 Literal l = introProxy(cnf, root, cnfExp, isNegEdge(root));
509 Literal clause[] = {l};
510 addArrayClauseLiteral(cnf->solver, 1, clause);
512 outputCNF(cnf, cnfExp);
515 if (!((intptr_t) cnfExp & 1)) {
516 deleteCNFExpr(cnfExp);
517 nroot->ptrAnnot[isNegEdge(root)] = NULL;
522 Literal introProxy(CNF *cnf, Edge e, CNFExpr *exp, bool isNeg) {
524 Node *n = getNodePtrFromEdge(e);
526 if (n->flags.cnfVisitedUp & (1 << !isNeg)) {
527 CNFExpr *otherExp = (CNFExpr *) n->ptrAnnot[!isNeg];
528 if (isProxy(otherExp))
529 l = -getProxy(otherExp);
531 Edge semNeg = {(Node *) n->ptrAnnot[isNeg]};
532 Node *nsemNeg = getNodePtrFromEdge(semNeg);
533 if (nsemNeg != NULL) {
534 if (nsemNeg->flags.cnfVisitedUp & (1 << isNeg)) {
535 CNFExpr *otherExp = (CNFExpr *) nsemNeg->ptrAnnot[isNeg];
536 if (isProxy(otherExp))
537 l = -getProxy(otherExp);
538 } else if (nsemNeg->flags.cnfVisitedUp & (1 << !isNeg)) {
539 CNFExpr *otherExp = (CNFExpr *) nsemNeg->ptrAnnot[!isNeg];
540 if (isProxy(otherExp))
541 l = getProxy(otherExp);
547 Edge newvar = constraintNewVar(cnf);
548 l = getEdgeVar(newvar);
550 // Output the constraints on the auxiliary variable
551 constrainCNF(cnf, l, exp);
554 n->ptrAnnot[isNeg] = (void *) ((intptr_t) (l << 1) | 1);
559 void produceCNF(CNF *cnf, Edge e) {
560 CNFExpr *expPos = NULL;
561 CNFExpr *expNeg = NULL;
562 Node *n = getNodePtrFromEdge(e);
564 if (n->intAnnot[0] > 0) {
565 expPos = produceConjunction(cnf, e);
568 if (n->intAnnot[1] > 0) {
569 expNeg = produceDisjunction(cnf, e);
572 /// @todo Propagate constants across semantic negations (this can
573 /// be done similarly to the calls to propagate shown below). The
574 /// trick here is that we need to figure out how to get the
575 /// semantic negation pointers, and ensure that they can have CNF
576 /// produced for them at the right point
578 /// propagate(solver, expPos, snPos, false) || propagate(solver, expNeg, snNeg, false)
580 // propagate from positive to negative, negative to positive
581 if (!propagate(cnf, &expPos, expNeg, true))
582 propagate(cnf, &expNeg, expPos, true);
584 // The polarity heuristic entails visiting the discovery polarity first
586 saveCNF(cnf, expPos, e, false);
587 saveCNF(cnf, expNeg, e, true);
589 saveCNF(cnf, expNeg, e, true);
590 saveCNF(cnf, expPos, e, false);
594 bool propagate(CNF *cnf, CNFExpr **dest, CNFExpr *src, bool negate) {
595 if (src != NULL && !isProxy(src) && getLitSizeCNF(src) == 0) {
597 *dest = allocCNFExprBool(negate ? alwaysFalseCNF(src) : alwaysTrueCNF(src));
598 } else if (isProxy(*dest)) {
599 bool alwaysTrue = (negate ? alwaysFalseCNF(src) : alwaysTrueCNF(src));
601 Literal clause[] = {getProxy(*dest)};
602 addArrayClauseLiteral(cnf->solver, 1, clause);
604 Literal clause[] = {-getProxy(*dest)};
605 addArrayClauseLiteral(cnf->solver, 1, clause);
608 *dest = allocCNFExprBool(negate ? alwaysFalseCNF(src) : alwaysTrueCNF(src));
610 clearCNFExpr(*dest, negate ? alwaysFalseCNF(src) : alwaysTrueCNF(src));
617 void saveCNF(CNF *cnf, CNFExpr *exp, Edge e, bool sign) {
618 Node *n = getNodePtrFromEdge(e);
619 n->flags.cnfVisitedUp |= (1 << sign);
620 if (exp == NULL || isProxy(exp)) return;
622 if (exp->litSize == 1) {
623 Literal l = getLiteralLitVector(&exp->singletons, 0);
625 n->ptrAnnot[sign] = (void *) ((((intptr_t) l) << 1) | 1);
626 } else if (exp->litSize != 0 && (n->intAnnot[sign] > 1 || n->flags.varForced)) {
627 introProxy(cnf, e, exp, sign);
629 n->ptrAnnot[sign] = exp;
633 void constrainCNF(CNF *cnf, Literal lcond, CNFExpr *expr) {
634 if (alwaysTrueCNF(expr)) {
636 } else if (alwaysFalseCNF(expr)) {
637 Literal clause[] = {-lcond};
638 addArrayClauseLiteral(cnf->solver, 1, clause);
642 for (uint i = 0; i < getSizeLitVector(&expr->singletons); i++) {
643 Literal l = getLiteralLitVector(&expr->singletons,i);
644 Literal clause[] = {-lcond, l};
645 addArrayClauseLiteral(cnf->solver, 2, clause);
647 for (uint i = 0; i < getSizeVectorLitVector(&expr->clauses); i++) {
648 LitVector *lv = getVectorLitVector(&expr->clauses,i);
649 addClauseLiteral(cnf->solver, -lcond);//Add first literal
650 addArrayClauseLiteral(cnf->solver, getSizeLitVector(lv), lv->literals); //Add rest
654 void outputCNF(CNF *cnf, CNFExpr *expr) {
655 for (uint i = 0; i < getSizeLitVector(&expr->singletons); i++) {
656 Literal l = getLiteralLitVector(&expr->singletons,i);
657 Literal clause[] = {l};
658 addArrayClauseLiteral(cnf->solver, 1, clause);
660 for (uint i = 0; i < getSizeVectorLitVector(&expr->clauses); i++) {
661 LitVector *lv = getVectorLitVector(&expr->clauses,i);
662 addArrayClauseLiteral(cnf->solver, getSizeLitVector(lv), lv->literals);
666 CNFExpr *fillArgs(CNF *cnf, Edge e, bool isNeg, Edge *largestEdge) {
667 clearVectorEdge(&cnf->args);
669 *largestEdge = (Edge) {(Node *) NULL};
670 CNFExpr *largest = NULL;
671 Node *n = getNodePtrFromEdge(e);
674 Edge arg = n->edges[--i];
675 arg = constraintNegateIf(arg, isNeg);
676 Node *narg = getNodePtrFromEdge(arg);
678 if (edgeIsVarConst(arg)) {
679 pushVectorEdge(&cnf->args, arg);
683 if (narg->flags.type == NodeType_ITE || narg->flags.type == NodeType_IFF) {
684 arg = (Edge) {(Node *) narg->ptrAnnot[isNegEdge(arg)]};
687 if (narg->intAnnot[isNegEdge(arg)] == 1) {
688 CNFExpr *argExp = (CNFExpr *) narg->ptrAnnot[isNegEdge(arg)];
689 if (!isProxy(argExp)) {
690 if (largest == NULL) {
694 } else if (argExp->litSize > largest->litSize) {
695 pushVectorEdge(&cnf->args, *largestEdge);
702 pushVectorEdge(&cnf->args, arg);
705 if (largest != NULL) {
706 Node *nlargestEdge = getNodePtrFromEdge(*largestEdge);
707 nlargestEdge->ptrAnnot[isNegEdge(*largestEdge)] = NULL;
713 void printCNF(Edge e) {
714 if (edgeIsVarConst(e)) {
715 Literal l = getEdgeVar(e);
716 model_print ("%d", l);
719 bool isNeg = isNegEdge(e);
720 if (edgeIsConst(e)) {
727 Node *n = getNodePtrFromEdge(e);
729 //Pretty print things that are equivalent to OR's
730 if (getNodeType(e) == NodeType_AND) {
732 for (uint i = 0; i < n->numEdges; i++) {
733 Edge e = n->edges[i];
736 printCNF(constraintNegate(e));
744 switch (getNodeType(e)) {
756 for (uint i = 0; i < n->numEdges; i++) {
757 Edge e = n->edges[i];
765 CNFExpr *produceConjunction(CNF *cnf, Edge e) {
768 CNFExpr *accum = fillArgs(cnf, e, false, &largestEdge);
770 accum = allocCNFExprBool(true);
772 int i = getSizeVectorEdge(&cnf->args);
774 Edge arg = getVectorEdge(&cnf->args, --i);
775 if (edgeIsVarConst(arg)) {
776 conjoinCNFLit(accum, getEdgeVar(arg));
778 Node *narg = getNodePtrFromEdge(arg);
779 CNFExpr *argExp = (CNFExpr *) narg->ptrAnnot[isNegEdge(arg)];
781 bool destroy = (--narg->intAnnot[isNegEdge(arg)] == 0);
782 if (isProxy(argExp)) {// variable has been introduced
783 conjoinCNFLit(accum, getProxy(argExp));
785 conjoinCNFExpr(accum, argExp, destroy);
787 narg->ptrAnnot[isNegEdge(arg)] = NULL;
797 CNFExpr *produceDisjunction(CNF *cnf, Edge e) {
799 CNFExpr *accum = fillArgs(cnf, e, true, &largestEdge);
801 accum = allocCNFExprBool(false);
803 // This is necessary to check to make sure that we don't start out
804 // with an accumulator that is "too large".
806 /// @todo Strictly speaking, introProxy doesn't *need* to free
807 /// memory, then this wouldn't have to reallocate CNFExpr
809 /// @todo When this call to introProxy is made, the semantic
810 /// negation pointer will have been destroyed. Thus, it will not
811 /// be possible to use the correct proxy. That should be fixed.
813 // at this point, we will either have NULL, or a destructible expression
814 if (getClauseSizeCNF(accum) > CLAUSE_MAX)
815 accum = allocCNFExprLiteral(introProxy(cnf, largestEdge, accum, isNegEdge(largestEdge)));
817 int i = getSizeVectorEdge(&cnf->args);
819 Edge arg = getVectorEdge(&cnf->args, --i);
820 Node *narg = getNodePtrFromEdge(arg);
821 if (edgeIsVarConst(arg)) {
822 disjoinCNFLit(accum, getEdgeVar(arg));
824 CNFExpr *argExp = (CNFExpr *) narg->ptrAnnot[isNegEdge(arg)];
826 bool destroy = (--narg->intAnnot[isNegEdge(arg)] == 0);
827 if (isProxy(argExp)) {// variable has been introduced
828 disjoinCNFLit(accum, getProxy(argExp));
829 } else if (argExp->litSize == 0) {
830 disjoinCNFExpr(accum, argExp, destroy);
832 // check to see if we should introduce a proxy
833 int aL = accum->litSize; // lits in accum
834 int eL = argExp->litSize; // lits in argument
835 int aC = getClauseSizeCNF(accum); // clauses in accum
836 int eC = getClauseSizeCNF(argExp); // clauses in argument
838 if (eC > CLAUSE_MAX || (eL * aC + aL * eC > eL + aC + aL + aC)) {
839 disjoinCNFLit(accum, introProxy(cnf, arg, argExp, isNegEdge(arg)));
841 disjoinCNFExpr(accum, argExp, destroy);
842 if (destroy) narg->ptrAnnot[isNegEdge(arg)] = NULL;
851 Edge generateBinaryConstraint(CNF *cnf, uint numvars, Edge *vars, uint value) {
852 Edge carray[numvars];
853 for (uint j = 0; j < numvars; j++) {
854 carray[j] = ((value & 1) == 1) ? vars[j] : constraintNegate(vars[j]);
858 return constraintAND(cnf, numvars, carray);
861 /** Generates a constraint to ensure that all encodings are less than value */
862 Edge generateLTValueConstraint(CNF *cnf, uint numvars, Edge *vars, uint value) {
863 Edge orarray[numvars];
864 Edge andarray[numvars];
870 for (uint j = 0; j < numvars; j++) {
872 orarray[ori++] = constraintNegate(vars[j]);
875 //no ones to flip, so bail now...
877 return constraintAND(cnf, andi, andarray);
879 andarray[andi++] = constraintOR(cnf, ori, orarray);
881 value = value + (1 << (__builtin_ctz(value)));
886 Edge generateEquivNVConstraint(CNF *cnf, uint numvars, Edge *var1, Edge *var2) {
890 for (uint i = 0; i < numvars; i++) {
891 array[i] = constraintIFF(cnf, var1[i], var2[i]);
893 return constraintAND(cnf, numvars, array);
896 Edge generateLTConstraint(CNF *cnf, uint numvars, Edge *var1, Edge *var2) {
899 Edge result = constraintAND2(cnf, constraintNegate( var1[0]), var2[0]);
900 for (uint i = 1; i < numvars; i++) {
901 Edge lt = constraintAND2(cnf, constraintNegate( var1[i]), var2[i]);
902 Edge eq = constraintAND2(cnf, constraintIFF(cnf, var1[i], var2[i]), result);
903 result = constraintOR2(cnf, lt, eq);
908 Edge generateLTEConstraint(CNF *cnf, uint numvars, Edge *var1, Edge *var2) {
911 Edge result = constraintIMPLIES(cnf, var1[0], var2[0]);
912 for (uint i = 1; i < numvars; i++) {
913 Edge lt = constraintAND2(cnf, constraintNegate( var1[i]), var2[i]);
914 Edge eq = constraintAND2(cnf, constraintIFF(cnf, var1[i], var2[i]), result);
915 result = constraintOR2(cnf, lt, eq);