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)
46 CNF * cnf=ourmalloc(sizeof(CNF));
48 cnf->capacity=DEFAULT_CNF_ARRAY_SIZE;
49 cnf->mask=cnf->capacity-1;
50 cnf->node_array=ourcalloc(1, sizeof(Node *)*cnf->capacity);
52 cnf->maxsize=(uint)(((double)cnf->capacity)*LOAD_FACTOR);
53 cnf->enableMatching=true;
54 allocInlineDefVectorEdge(& cnf->constraints);
55 allocInlineDefVectorEdge(& cnf->args);
56 cnf->solver=allocIncrementalSolver();
60 void deleteCNF(CNF * cnf) {
61 for(uint i=0;i<cnf->capacity;i++) {
62 Node *n=cnf->node_array[i];
66 deleteVectorArrayEdge(& cnf->constraints);
67 deleteVectorArrayEdge(& cnf->args);
68 deleteIncrementalSolver(cnf->solver);
69 ourfree(cnf->node_array);
73 void resizeCNF(CNF *cnf, uint newCapacity) {
74 Node **old_array=cnf->node_array;
75 Node **new_array=ourcalloc(1, sizeof(Node *)*newCapacity);
76 uint oldCapacity=cnf->capacity;
77 uint newMask=newCapacity-1;
78 for(uint i=0;i<oldCapacity;i++) {
80 uint hashCode=n->hashCode;
81 uint newindex=hashCode & newMask;
82 for(;;newindex=(newindex+1) & newMask) {
83 if (new_array[newindex] == NULL) {
84 new_array[newindex]=n;
90 cnf->node_array=new_array;
91 cnf->capacity=newCapacity;
92 cnf->maxsize=(uint)(((double)cnf->capacity)*LOAD_FACTOR);
96 Node * allocNode(NodeType type, uint numEdges, Edge * edges, uint hashcode) {
97 Node *n=(Node *)ourmalloc(sizeof(Node)+sizeof(Edge)*numEdges);
98 memcpy(n->edges, edges, sizeof(Edge)*numEdges);
100 n->flags.wasExpanded=0;
101 n->flags.cnfVisitedDown=0;
102 n->flags.cnfVisitedUp=0;
103 n->numEdges=numEdges;
104 n->hashCode=hashcode;
105 n->intAnnot[0]=0;n->intAnnot[1]=0;
106 n->ptrAnnot[0]=NULL;n->ptrAnnot[1]=NULL;
110 Edge createNode(CNF *cnf, NodeType type, uint numEdges, Edge * edges) {
111 if (cnf->size > cnf->maxsize) {
112 resizeCNF(cnf, cnf->capacity << 1);
114 uint hashvalue=hashNode(type, numEdges, edges);
116 uint index=hashvalue & mask;
118 for(;;index=(index+1)&mask) {
119 n_ptr=&cnf->node_array[index];
121 if ((*n_ptr)->hashCode==hashvalue) {
122 if (compareNodes(*n_ptr, type, numEdges, edges)) {
131 *n_ptr=allocNode(type, numEdges, edges, hashvalue);
136 uint hashNode(NodeType type, uint numEdges, Edge * edges) {
137 uint hashvalue=type ^ numEdges;
138 for(uint i=0;i<numEdges;i++) {
139 hashvalue ^= (uint) ((uintptr_t) edges[i].node_ptr);
140 hashvalue = (hashvalue << 3) | (hashvalue >> 29); //rotate left by 3 bits
142 return (uint) hashvalue;
145 bool compareNodes(Node * node, NodeType type, uint numEdges, Edge *edges) {
146 if (node->flags.type!=type || node->numEdges != numEdges)
148 Edge *nodeedges=node->edges;
149 for(uint i=0;i<numEdges;i++) {
150 if (!equalsEdge(nodeedges[i], edges[i]))
156 Edge constraintOR(CNF * cnf, uint numEdges, Edge *edges) {
157 Edge edgearray[numEdges];
159 for(uint i=0; i<numEdges; i++) {
160 edgearray[i]=constraintNegate(edges[i]);
162 Edge eand=constraintAND(cnf, numEdges, edgearray);
163 return constraintNegate(eand);
166 Edge constraintOR2(CNF * cnf, Edge left, Edge right) {
167 Edge lneg=constraintNegate(left);
168 Edge rneg=constraintNegate(right);
169 Edge eand=constraintAND2(cnf, left, right);
170 return constraintNegate(eand);
173 int comparefunction(const Edge * e1, const Edge * e2) {
174 return ((uintptr_t)e1->node_ptr)-((uintptr_t)e2->node_ptr);
177 Edge constraintAND(CNF * cnf, uint numEdges, Edge * edges) {
178 qsort(edges, numEdges, sizeof(Edge), (int (*)(const void *, const void *)) comparefunction);
180 while(initindex<numEdges && equalsEdge(edges[initindex], E_True))
183 uint remainSize=numEdges-initindex;
187 else if (remainSize == 1)
188 return edges[initindex];
189 else if (equalsEdge(edges[initindex], E_False))
192 /** De-duplicate array */
194 edges[lowindex++]=edges[initindex++];
196 for(;initindex<numEdges;initindex++) {
197 Edge e1=edges[lowindex];
198 Edge e2=edges[initindex];
199 if (sameNodeVarEdge(e1, e2)) {
200 if (!sameSignEdge(e1, e2)) {
204 edges[lowindex++]=edges[initindex];
209 if (cnf->enableMatching && lowindex==2 &&
210 isNegNodeEdge(edges[0]) && isNegNodeEdge(edges[1]) &&
211 getNodeType(edges[0]) == NodeType_AND &&
212 getNodeType(edges[1]) == NodeType_AND &&
213 getNodeSize(edges[0]) == 2 &&
214 getNodeSize(edges[1]) == 2) {
215 Edge * e0edges=getEdgeArray(edges[0]);
216 Edge * e1edges=getEdgeArray(edges[1]);
217 if (sameNodeOppSign(e0edges[0], e1edges[0])) {
218 return constraintNegate(constraintITE(cnf, e0edges[0], e0edges[1], e1edges[1]));
219 } else if (sameNodeOppSign(e0edges[0], e1edges[1])) {
220 return constraintNegate(constraintITE(cnf, e0edges[0], e0edges[1], e1edges[0]));
221 } else if (sameNodeOppSign(e0edges[1], e1edges[0])) {
222 return constraintNegate(constraintITE(cnf, e0edges[1], e0edges[0], e1edges[1]));
223 } else if (sameNodeOppSign(e0edges[1], e1edges[1])) {
224 return constraintNegate(constraintITE(cnf, e0edges[1], e0edges[0], e1edges[0]));
228 return createNode(cnf, NodeType_AND, numEdges, edges);
231 Edge constraintAND2(CNF * cnf, Edge left, Edge right) {
232 Edge edges[2]={left, right};
233 return constraintAND(cnf, 2, edges);
236 Edge constraintIMPLIES(CNF * cnf, Edge left, Edge right) {
239 array[1]=constraintNegate(right);
240 Edge eand=constraintAND(cnf, 2, array);
241 return constraintNegate(eand);
244 Edge constraintIFF(CNF * cnf, Edge left, Edge right) {
245 bool negate=sameSignEdge(left, right);
246 Edge lpos=getNonNeg(left);
247 Edge rpos=getNonNeg(right);
250 if (equalsEdge(lpos, rpos)) {
252 } else if (ltEdge(lpos, rpos)) {
253 Edge edges[]={lpos, rpos};
254 e=(edgeIsConst(lpos)) ? rpos : createNode(cnf, NodeType_IFF, 2, edges);
256 Edge edges[]={rpos, lpos};
257 e=(edgeIsConst(rpos)) ? lpos : createNode(cnf, NodeType_IFF, 2, edges);
260 e=constraintNegate(e);
264 Edge constraintITE(CNF * cnf, Edge cond, Edge thenedge, Edge elseedge) {
265 if (isNegEdge(cond)) {
266 cond=constraintNegate(cond);
272 bool negate = isNegEdge(thenedge);
274 thenedge=constraintNegate(thenedge);
275 elseedge=constraintNegate(elseedge);
279 if (equalsEdge(cond, E_True)) {
281 } else if (equalsEdge(thenedge, E_True) || equalsEdge(cond, thenedge)) {
282 result=constraintOR(cnf, 2, (Edge[]) {cond, elseedge});
283 } else if (equalsEdge(elseedge, E_True) || sameNodeOppSign(cond, elseedge)) {
284 result=constraintIMPLIES(cnf, cond, thenedge);
285 } else if (equalsEdge(thenedge, E_False) || equalsEdge(cond, elseedge)) {
286 result=constraintAND(cnf, 2, (Edge[]) {cond, thenedge});
287 } else if (equalsEdge(thenedge, elseedge)) {
289 } else if (sameNodeOppSign(thenedge, elseedge)) {
290 if (ltEdge(cond, thenedge)) {
291 result=createNode(cnf, NodeType_IFF, 2, (Edge[]) {cond, thenedge});
293 result=createNode(cnf, NodeType_IFF, 2, (Edge[]) {thenedge, cond});
296 Edge edges[]={cond, thenedge, elseedge};
297 result=createNode(cnf, NodeType_ITE, 3, edges);
300 result=constraintNegate(result);
304 void addConstraint(CNF *cnf, Edge constraint) {
305 pushVectorEdge(&cnf->constraints, constraint);
308 Edge constraintNewVar(CNF *cnf) {
309 uint varnum=cnf->varcount++;
310 Edge e={(Node *) ((((uintptr_t)varnum) << VAR_SHIFT) | EDGE_IS_VAR_CONSTANT) };
314 void solveCNF(CNF *cnf) {
316 convertPass(cnf, false);
321 void countPass(CNF *cnf) {
322 uint numConstraints=getSizeVectorEdge(&cnf->constraints);
323 VectorEdge *ve=allocDefVectorEdge();
324 for(uint i=0; i<numConstraints;i++) {
325 countConstraint(cnf, ve, getVectorEdge(&cnf->constraints, i));
327 deleteVectorEdge(ve);
330 void countConstraint(CNF *cnf, VectorEdge *stack, Edge e) {
331 //Skip constants and variables...
332 if (edgeIsVarConst(e))
335 clearVectorEdge(stack);pushVectorEdge(stack, e);
337 bool isMatching=cnf->enableMatching;
339 while(getSizeVectorEdge(stack) != 0) {
340 Edge e=lastVectorEdge(stack); popVectorEdge(stack);
341 bool polarity=isNegEdge(e);
342 Node *n=getNodePtrFromEdge(e);
343 if (getExpanded(n, polarity)) {
344 if (n->flags.type == NodeType_IFF ||
345 n->flags.type == NodeType_ITE) {
346 Edge pExp={n->ptrAnnot[polarity]};
347 getNodePtrFromEdge(pExp)->intAnnot[0]++;
349 n->intAnnot[polarity]++;
352 setExpanded(n, polarity);
354 if (n->flags.type == NodeType_ITE||
355 n->flags.type == NodeType_IFF) {
356 n->intAnnot[polarity]=0;
357 Edge cond=n->edges[0];
358 Edge thenedge=n->edges[1];
359 Edge elseedge=n->flags.type == NodeType_IFF? constraintNegate(thenedge): n->edges[2];
360 thenedge=constraintNegateIf(thenedge, !polarity);
361 elseedge=constraintNegateIf(elseedge, !polarity);
362 thenedge=constraintAND2(cnf, cond, thenedge);
363 cond=constraintNegate(cond);
364 elseedge=constraintAND2(cnf, cond, elseedge);
365 thenedge=constraintNegate(thenedge);
366 elseedge=constraintNegate(elseedge);
367 cnf->enableMatching=false;
368 Edge succ1=constraintAND2(cnf, thenedge, elseedge);
369 n->ptrAnnot[polarity]=succ1.node_ptr;
370 cnf->enableMatching=isMatching;
371 pushVectorEdge(stack, succ1);
372 if (getExpanded(n, !polarity)) {
373 Edge succ2={(Node *)n->ptrAnnot[!polarity]};
374 Node *n1=getNodePtrFromEdge(succ1);
375 Node *n2=getNodePtrFromEdge(succ2);
376 n1->ptrAnnot[0]=succ2.node_ptr;
377 n2->ptrAnnot[0]=succ1.node_ptr;
378 n1->ptrAnnot[1]=succ2.node_ptr;
379 n2->ptrAnnot[1]=succ1.node_ptr;
382 n->intAnnot[polarity]=1;
383 for (uint i=0;i<n->numEdges;i++) {
384 Edge succ=n->edges[i];
385 succ=constraintNegateIf(succ, polarity);
386 if(!edgeIsVarConst(succ)) {
387 pushVectorEdge(stack, succ);
395 void convertPass(CNF *cnf, bool backtrackLit) {
396 uint numConstraints=getSizeVectorEdge(&cnf->constraints);
397 VectorEdge *ve=allocDefVectorEdge();
398 for(uint i=0; i<numConstraints;i++) {
399 convertConstraint(cnf, ve, getVectorEdge(&cnf->constraints, i), backtrackLit);
401 deleteVectorEdge(ve);
404 void convertConstraint(CNF *cnf, VectorEdge *stack, Edge root, bool backtrackLit) {
405 Node *nroot=getNodePtrFromEdge(root);
407 if (isNodeEdge(root) && (nroot->flags.type == NodeType_ITE || nroot->flags.type == NodeType_IFF)) {
408 root = (Edge) { (Node *) nroot->ptrAnnot[isNegEdge(root)]};
411 if (edgeIsConst(root)) {
412 if (isNegEdge(root)) {
414 Edge newvar=constraintNewVar(cnf);
415 Literal var=getEdgeVar(newvar);
416 Literal clause[] = {var};
417 addArrayClauseLiteral(cnf->solver, 1, clause);
419 addArrayClauseLiteral(cnf->solver, 1, clause);
425 } else if (edgeIsVarConst(root)) {
426 Literal clause[] = { getEdgeVar(root)};
427 addArrayClauseLiteral(cnf->solver, 1, clause);
431 clearVectorEdge(stack);pushVectorEdge(stack, root);
432 while(getSizeVectorEdge(stack)!=0) {
433 Edge e=lastVectorEdge(stack);
434 Node *n=getNodePtrFromEdge(e);
436 if (edgeIsVarConst(e)) {
437 popVectorEdge(stack);
439 } else if (n->flags.type==NodeType_ITE ||
440 n->flags.type==NodeType_IFF) {
441 popVectorEdge(stack);
442 if (n->ptrAnnot[0]!=NULL)
443 pushVectorEdge(stack, (Edge) {(Node *)n->ptrAnnot[0]});
444 if (n->ptrAnnot[1]!=NULL)
445 pushVectorEdge(stack, (Edge) {(Node *)n->ptrAnnot[1]});
449 bool needPos = (n->intAnnot[0] > 0);
450 bool needNeg = (n->intAnnot[1] > 0);
451 if ((!needPos || n->flags.cnfVisitedUp & 1) &&
452 (!needNeg || n->flags.cnfVisitedUp & 2)) {
453 popVectorEdge(stack);
454 } else if ((needPos && !(n->flags.cnfVisitedDown & 1)) ||
455 (needNeg && !(n->flags.cnfVisitedDown & 2))) {
457 n->flags.cnfVisitedDown|=1;
459 n->flags.cnfVisitedDown|=2;
460 for(uint i=0; i<n->numEdges; i++) {
461 Edge arg=n->edges[i];
462 arg=constraintNegateIf(arg, isNegEdge(e));
463 pushVectorEdge(stack, arg); //WARNING, THIS LOOKS LIKE A BUG IN THE ORIGINAL CODE
466 popVectorEdge(stack);
470 CNFExpr * cnfExp = (CNFExpr *) nroot->ptrAnnot[isNegEdge(root)];
471 if (isProxy(cnfExp)) {
472 Literal l=getProxy(cnfExp);
473 Literal clause[] = {l};
474 addArrayClauseLiteral(cnf->solver, 1, clause);
475 } else if (backtrackLit) {
476 Literal l=introProxy(cnf, root, cnfExp, isNegEdge(root));
477 Literal clause[] = {l};
478 addArrayClauseLiteral(cnf->solver, 1, clause);
480 outputCNF(cnf, cnfExp);
483 if (!((intptr_t) cnfExp & 1)) {
484 deleteCNFExpr(cnfExp);
485 nroot->ptrAnnot[isNegEdge(root)] = NULL;
490 Literal introProxy(CNF * cnf, Edge e, CNFExpr* exp, bool isNeg) {
492 Node * n = getNodePtrFromEdge(e);
494 if (n->flags.cnfVisitedUp & (1<<!isNeg)) {
495 CNFExpr* otherExp = (CNFExpr*) n->ptrAnnot[!isNeg];
496 if (isProxy(otherExp))
497 l = -getProxy(otherExp);
499 Edge semNeg={(Node *) n->ptrAnnot[isNeg]};
500 Node * nsemNeg=getNodePtrFromEdge(semNeg);
501 if (nsemNeg != NULL) {
502 if (nsemNeg->flags.cnfVisitedUp & (1 << isNeg)) {
503 CNFExpr* otherExp = (CNFExpr*) nsemNeg->ptrAnnot[isNeg];
504 if (isProxy(otherExp))
505 l = -getProxy(otherExp);
506 } else if (nsemNeg->flags.cnfVisitedUp & (1<< !isNeg)) {
507 CNFExpr* otherExp = (CNFExpr*) nsemNeg->ptrAnnot[!isNeg];
508 if (isProxy(otherExp))
509 l = getProxy(otherExp);
515 Edge newvar = constraintNewVar(cnf);
516 l = getEdgeVar(newvar);
518 // Output the constraints on the auxiliary variable
519 constrainCNF(cnf, l, exp);
522 n->ptrAnnot[isNeg] = (void*) ((intptr_t) (l << 1) | 1);
527 void produceCNF(CNF * cnf, Edge e) {
528 CNFExpr* expPos = NULL;
529 CNFExpr* expNeg = NULL;
530 Node *n = getNodePtrFromEdge(e);
532 if (n->intAnnot[0] > 0) {
533 expPos = produceConjunction(cnf, e);
536 if (n->intAnnot[1] > 0) {
537 expNeg = produceDisjunction(cnf, e);
540 /// @todo Propagate constants across semantic negations (this can
541 /// be done similarly to the calls to propagate shown below). The
542 /// trick here is that we need to figure out how to get the
543 /// semantic negation pointers, and ensure that they can have CNF
544 /// produced for them at the right point
546 /// propagate(solver, expPos, snPos, false) || propagate(solver, expNeg, snNeg, false)
548 // propagate from positive to negative, negative to positive
549 if (!propagate(cnf, & expPos, expNeg, true))
550 propagate(cnf, & expNeg, expPos, true);
552 // The polarity heuristic entails visiting the discovery polarity first
554 saveCNF(cnf, expPos, e, false);
555 saveCNF(cnf, expNeg, e, true);
557 saveCNF(cnf, expNeg, e, true);
558 saveCNF(cnf, expPos, e, false);
562 bool propagate(CNF *cnf, CNFExpr ** dest, CNFExpr * src, bool negate) {
563 if (src != NULL && !isProxy(src) && getLitSizeCNF(src) == 0) {
565 *dest = allocCNFExprBool(negate ? alwaysFalseCNF(src) : alwaysTrueCNF(src));
566 } else if (isProxy(*dest)) {
567 bool alwaysTrue = (negate ? alwaysFalseCNF(src) : alwaysTrueCNF(src));
569 Literal clause[] = {getProxy(*dest)};
570 addArrayClauseLiteral(cnf->solver, 1, clause);
572 Literal clause[] = {-getProxy(*dest)};
573 addArrayClauseLiteral(cnf->solver, 1, clause);
576 *dest = allocCNFExprBool(negate ? alwaysFalseCNF(src) : alwaysTrueCNF(src));
578 clearCNFExpr(*dest, negate ? alwaysFalseCNF(src) : alwaysTrueCNF(src));
585 void saveCNF(CNF *cnf, CNFExpr* exp, Edge e, bool sign) {
586 Node *n=getNodePtrFromEdge(e);
587 n->flags.cnfVisitedUp |= (1 << sign);
588 if (exp == NULL || isProxy(exp)) return;
590 if (exp->litSize == 1) {
591 Literal l = getLiteralLitVector(&exp->singletons, 0);
593 n->ptrAnnot[sign] = (void*) ((intptr_t) (l << 1) | 1);
594 } else if (exp->litSize != 0 && (n->intAnnot[sign] > 1 || n->flags.varForced)) {
595 introProxy(cnf, e, exp, sign);
597 n->ptrAnnot[sign] = exp;
601 void constrainCNF(CNF * cnf, Literal lcond, CNFExpr *expr) {
602 if (alwaysTrueCNF(expr)) {
604 } else if (alwaysFalseCNF(expr)) {
605 Literal clause[] = {-lcond};
606 addArrayClauseLiteral(cnf->solver, 1, clause);
610 for(uint i=0;i<getSizeLitVector(&expr->singletons);i++) {
611 Literal l=getLiteralLitVector(&expr->singletons,i);
612 Literal clause[] = {-lcond, l};
613 addArrayClauseLiteral(cnf->solver, 1, clause);
615 for(uint i=0;i<getSizeVectorLitVector(&expr->clauses);i++) {
616 LitVector *lv=getVectorLitVector(&expr->clauses,i);
617 addClauseLiteral(cnf->solver, -lcond); //Add first literal
618 addArrayClauseLiteral(cnf->solver, getSizeLitVector(lv), lv->literals); //Add rest
622 void outputCNF(CNF *cnf, CNFExpr *expr) {
623 for(uint i=0;i<getSizeLitVector(&expr->singletons);i++) {
624 Literal l=getLiteralLitVector(&expr->singletons,i);
625 Literal clause[] = {l};
626 addArrayClauseLiteral(cnf->solver, 1, clause);
628 for(uint i=0;i<getSizeVectorLitVector(&expr->clauses);i++) {
629 LitVector *lv=getVectorLitVector(&expr->clauses,i);
630 addArrayClauseLiteral(cnf->solver, getSizeLitVector(lv), lv->literals);
634 CNFExpr* fillArgs(CNF *cnf, Edge e, bool isNeg, Edge * largestEdge) {
635 clearVectorEdge(&cnf->args);
637 *largestEdge = (Edge) {(Node*) NULL};
638 CNFExpr* largest = NULL;
639 Node *n=getNodePtrFromEdge(e);
642 Edge arg = n->edges[--i]; arg=constraintNegateIf(arg, isNeg);
643 Node * narg = getNodePtrFromEdge(arg);
645 if (edgeIsVarConst(arg)) {
646 pushVectorEdge(&cnf->args, arg);
650 if (narg->flags.type == NodeType_ITE || narg->flags.type == NodeType_IFF) {
651 arg = (Edge) {(Node *) narg->ptrAnnot[isNegEdge(arg)]};
654 if (narg->intAnnot[isNegEdge(arg)] == 1) {
655 CNFExpr* argExp = (CNFExpr*) narg->ptrAnnot[isNegEdge(arg)];
656 if (!isProxy(argExp)) {
657 if (largest == NULL) {
661 } else if (argExp->litSize > largest->litSize) {
662 pushVectorEdge(&cnf->args, *largestEdge);
669 pushVectorEdge(&cnf->args, arg);
672 if (largest != NULL) {
673 Node *nlargestEdge=getNodePtrFromEdge(*largestEdge);
674 nlargestEdge->ptrAnnot[isNegEdge(*largestEdge)] = NULL;
681 CNFExpr * produceConjunction(CNF * cnf, Edge e) {
684 CNFExpr* accum = fillArgs(cnf, e, false, &largestEdge);
685 if (accum == NULL) accum = allocCNFExprBool(true);
687 int i = getSizeVectorEdge(&cnf->args);
689 Edge arg = getVectorEdge(&cnf->args, --i);
690 if (edgeIsVarConst(arg)) {
691 conjoinCNFLit(accum, getEdgeVar(arg));
693 Node *narg=getNodePtrFromEdge(arg);
694 CNFExpr* argExp = (CNFExpr*) narg->ptrAnnot[isNegEdge(arg)];
696 bool destroy = (--narg->intAnnot[isNegEdge(arg)] == 0);
697 if (isProxy(argExp)) { // variable has been introduced
698 conjoinCNFLit(accum, getProxy(argExp));
700 conjoinCNFExpr(accum, argExp, destroy);
701 if (destroy) narg->ptrAnnot[isNegEdge(arg)] = NULL;
711 CNFExpr* produceDisjunction(CNF *cnf, Edge e) {
713 CNFExpr* accum = fillArgs(cnf, e, true, &largestEdge);
715 accum = allocCNFExprBool(false);
717 // This is necessary to check to make sure that we don't start out
718 // with an accumulator that is "too large".
720 /// @todo Strictly speaking, introProxy doesn't *need* to free
721 /// memory, then this wouldn't have to reallocate CNFExpr
723 /// @todo When this call to introProxy is made, the semantic
724 /// negation pointer will have been destroyed. Thus, it will not
725 /// be possible to use the correct proxy. That should be fixed.
727 // at this point, we will either have NULL, or a destructible expression
728 if (getClauseSizeCNF(accum) > CLAUSE_MAX)
729 accum = allocCNFExprLiteral(introProxy(cnf, largestEdge, accum, isNegEdge(largestEdge)));
731 int i = getSizeVectorEdge(&cnf->args);
733 Edge arg=getVectorEdge(&cnf->args, --i);
734 Node *narg=getNodePtrFromEdge(arg);
735 if (edgeIsVarConst(arg)) {
736 disjoinCNFLit(accum, getEdgeVar(arg));
738 CNFExpr* argExp = (CNFExpr*) narg->ptrAnnot[isNegEdge(arg)];
740 bool destroy = (--narg->intAnnot[isNegEdge(arg)] == 0);
741 if (isProxy(argExp)) { // variable has been introduced
742 disjoinCNFLit(accum, getProxy(argExp));
743 } else if (argExp->litSize == 0) {
744 disjoinCNFExpr(accum, argExp, destroy);
746 // check to see if we should introduce a proxy
747 int aL = accum->litSize; // lits in accum
748 int eL = argExp->litSize; // lits in argument
749 int aC = getClauseSizeCNF(accum); // clauses in accum
750 int eC = getClauseSizeCNF(argExp); // clauses in argument
752 if (eC > CLAUSE_MAX || (eL * aC + aL * eC > eL + aC + aL + aC)) {
753 disjoinCNFLit(accum, introProxy(cnf, arg, argExp, isNegEdge(arg)));
755 disjoinCNFExpr(accum, argExp, destroy);
756 if (destroy) narg->ptrAnnot[isNegEdge(arg)] = NULL;