From: bdemsky Date: Thu, 24 Aug 2017 23:49:49 +0000 (-0700) Subject: Rename everything X-Git-Url: http://plrg.eecs.uci.edu/git/?p=satune.git;a=commitdiff_plain;h=4216901871798182a3574865d6aa4f3ff3130a54 Rename everything --- diff --git a/src/AST/boolean.c b/src/AST/boolean.c deleted file mode 100644 index 2987217..0000000 --- a/src/AST/boolean.c +++ /dev/null @@ -1,78 +0,0 @@ -#include "boolean.h" -#include "structs.h" -#include "csolver.h" -#include "element.h" -#include "order.h" - -Boolean *allocBooleanVar(VarType t) { - BooleanVar *This = (BooleanVar *) ourmalloc(sizeof (BooleanVar)); - GETBOOLEANTYPE(This) = BOOLEANVAR; - GETBOOLEANVALUE(This) = BV_UNDEFINED; - GETBOOLEANPOLARITY(This) = P_UNDEFINED; - This->vtype = t; - This->var = E_NULL; - initDefVectorBoolean(GETBOOLEANPARENTS(This)); - return &This->base; -} - -Boolean *allocBooleanOrder(Order *order, uint64_t first, uint64_t second) { - BooleanOrder *This = (BooleanOrder *) ourmalloc(sizeof (BooleanOrder)); - GETBOOLEANTYPE(This) = ORDERCONST; - GETBOOLEANVALUE(This) = BV_UNDEFINED; - GETBOOLEANPOLARITY(This) = P_UNDEFINED; - This->order = order; - This->first = first; - This->second = second; - pushVectorBooleanOrder(&order->constraints, This); - initDefVectorBoolean(GETBOOLEANPARENTS(This)); - return &This->base; -} - -Boolean *allocBooleanPredicate(Predicate *predicate, Element **inputs, uint numInputs, Boolean *undefinedStatus) { - BooleanPredicate *This = (BooleanPredicate *) ourmalloc(sizeof(BooleanPredicate)); - GETBOOLEANTYPE(This) = PREDICATEOP; - GETBOOLEANVALUE(This) = BV_UNDEFINED; - GETBOOLEANPOLARITY(This) = P_UNDEFINED; - This->predicate = predicate; - initArrayInitElement(&This->inputs, inputs, numInputs); - initDefVectorBoolean(GETBOOLEANPARENTS(This)); - - for (uint i = 0; i < numInputs; i++) { - pushVectorASTNode(GETELEMENTPARENTS(inputs[i]), (ASTNode *)This); - } - initPredicateEncoding(&This->encoding, (Boolean *) This); - This->undefStatus = undefinedStatus; - return &This->base; -} - -Boolean *allocBooleanLogicArray(CSolver *solver, LogicOp op, Boolean **array, uint asize) { - BooleanLogic *This = ourmalloc(sizeof(BooleanLogic)); - GETBOOLEANTYPE(This) = LOGICOP; - GETBOOLEANVALUE(This) = BV_UNDEFINED; - GETBOOLEANPOLARITY(This) = P_UNDEFINED; - This->op = op; - initDefVectorBoolean(GETBOOLEANPARENTS(This)); - initArrayInitBoolean(&This->inputs, array, asize); - pushVectorBoolean(solver->allBooleans, (Boolean *) This); - return &This->base; -} - -void deleteBoolean(Boolean *This) { - switch (GETBOOLEANTYPE(This)) { - case PREDICATEOP: { - BooleanPredicate *bp = (BooleanPredicate *)This; - deleteInlineArrayElement(&bp->inputs ); - deleteFunctionEncoding(&bp->encoding); - break; - } - case LOGICOP: { - BooleanLogic *bl = (BooleanLogic *) This; - deleteInlineArrayBoolean(&bl->inputs); - break; - } - default: - break; - } - deleteVectorArrayBoolean(GETBOOLEANPARENTS(This)); - ourfree(This); -} diff --git a/src/AST/boolean.cc b/src/AST/boolean.cc new file mode 100644 index 0000000..256ab5a --- /dev/null +++ b/src/AST/boolean.cc @@ -0,0 +1,78 @@ +#include "boolean.h" +#include "structs.h" +#include "csolver.h" +#include "element.h" +#include "order.h" + +Boolean *allocBooleanVar(VarType t) { + BooleanVar *This = (BooleanVar *) ourmalloc(sizeof (BooleanVar)); + GETBOOLEANTYPE(This) = BOOLEANVAR; + GETBOOLEANVALUE(This) = BV_UNDEFINED; + GETBOOLEANPOLARITY(This) = P_UNDEFINED; + This->vtype = t; + This->var = E_NULL; + initDefVectorBoolean(GETBOOLEANPARENTS(This)); + return &This->base; +} + +Boolean *allocBooleanOrder(Order *order, uint64_t first, uint64_t second) { + BooleanOrder *This = (BooleanOrder *) ourmalloc(sizeof (BooleanOrder)); + GETBOOLEANTYPE(This) = ORDERCONST; + GETBOOLEANVALUE(This) = BV_UNDEFINED; + GETBOOLEANPOLARITY(This) = P_UNDEFINED; + This->order = order; + This->first = first; + This->second = second; + pushVectorBooleanOrder(&order->constraints, This); + initDefVectorBoolean(GETBOOLEANPARENTS(This)); + return &This->base; +} + +Boolean *allocBooleanPredicate(Predicate *predicate, Element **inputs, uint numInputs, Boolean *undefinedStatus) { + BooleanPredicate *This = (BooleanPredicate *) ourmalloc(sizeof(BooleanPredicate)); + GETBOOLEANTYPE(This) = PREDICATEOP; + GETBOOLEANVALUE(This) = BV_UNDEFINED; + GETBOOLEANPOLARITY(This) = P_UNDEFINED; + This->predicate = predicate; + initArrayInitElement(&This->inputs, inputs, numInputs); + initDefVectorBoolean(GETBOOLEANPARENTS(This)); + + for (uint i = 0; i < numInputs; i++) { + pushVectorASTNode(GETELEMENTPARENTS(inputs[i]), (ASTNode *)This); + } + initPredicateEncoding(&This->encoding, (Boolean *) This); + This->undefStatus = undefinedStatus; + return &This->base; +} + +Boolean *allocBooleanLogicArray(CSolver *solver, LogicOp op, Boolean **array, uint asize) { + BooleanLogic *This = (BooleanLogic *) ourmalloc(sizeof(BooleanLogic)); + GETBOOLEANTYPE(This) = LOGICOP; + GETBOOLEANVALUE(This) = BV_UNDEFINED; + GETBOOLEANPOLARITY(This) = P_UNDEFINED; + This->op = op; + initDefVectorBoolean(GETBOOLEANPARENTS(This)); + initArrayInitBoolean(&This->inputs, array, asize); + pushVectorBoolean(solver->allBooleans, (Boolean *) This); + return &This->base; +} + +void deleteBoolean(Boolean *This) { + switch (GETBOOLEANTYPE(This)) { + case PREDICATEOP: { + BooleanPredicate *bp = (BooleanPredicate *)This; + deleteInlineArrayElement(&bp->inputs ); + deleteFunctionEncoding(&bp->encoding); + break; + } + case LOGICOP: { + BooleanLogic *bl = (BooleanLogic *) This; + deleteInlineArrayBoolean(&bl->inputs); + break; + } + default: + break; + } + deleteVectorArrayBoolean(GETBOOLEANPARENTS(This)); + ourfree(This); +} diff --git a/src/AST/element.c b/src/AST/element.c deleted file mode 100644 index 5d126c7..0000000 --- a/src/AST/element.c +++ /dev/null @@ -1,91 +0,0 @@ -#include "element.h" -#include "structs.h" -#include "set.h" -#include "constraint.h" -#include "function.h" -#include "table.h" - -Element *allocElementSet(Set *s) { - ElementSet *This = (ElementSet *)ourmalloc(sizeof(ElementSet)); - GETELEMENTTYPE(This) = ELEMSET; - This->set = s; - initDefVectorASTNode(GETELEMENTPARENTS(This)); - initElementEncoding(&This->encoding, (Element *) This); - return &This->base; -} - -Element *allocElementFunction(Function *function, Element **array, uint numArrays, Boolean *overflowstatus) { - ElementFunction *This = (ElementFunction *) ourmalloc(sizeof(ElementFunction)); - GETELEMENTTYPE(This) = ELEMFUNCRETURN; - This->function = function; - ASSERT(GETBOOLEANTYPE(overflowstatus) == BOOLEANVAR); - This->overflowstatus = overflowstatus; - initArrayInitElement(&This->inputs, array, numArrays); - initDefVectorASTNode(GETELEMENTPARENTS(This)); - for (uint i = 0; i < numArrays; i++) - pushVectorASTNode(GETELEMENTPARENTS(array[i]), (ASTNode *) This); - initElementEncoding(&This->rangeencoding, (Element *) This); - initFunctionEncoding(&This->functionencoding, (Element *) This); - return &This->base; -} - -Element *allocElementConst(uint64_t value, VarType type) { - ElementConst *This = (ElementConst *)ourmalloc(sizeof(ElementConst)); - GETELEMENTTYPE(This) = ELEMCONST; - This->value = value; - This->set = allocSet(type, (uint64_t[]) {value}, 1); - initDefVectorASTNode(GETELEMENTPARENTS(This)); - initElementEncoding(&This->encoding, (Element *) This); - return &This->base; -} - -Set *getElementSet(Element *This) { - switch (GETELEMENTTYPE(This)) { - case ELEMSET: - return ((ElementSet *)This)->set; - case ELEMCONST: - return ((ElementConst *)This)->set; - case ELEMFUNCRETURN: { - Function *func = ((ElementFunction *)This)->function; - switch (GETFUNCTIONTYPE(func)) { - case TABLEFUNC: - return ((FunctionTable *)func)->table->range; - case OPERATORFUNC: - return ((FunctionOperator *)func)->range; - default: - ASSERT(0); - } - } - default: - ASSERT(0); - } - ASSERT(0); - return NULL; -} - -void deleteElement(Element *This) { - switch (GETELEMENTTYPE(This)) { - case ELEMFUNCRETURN: { - ElementFunction *ef = (ElementFunction *) This; - deleteInlineArrayElement(&ef->inputs); - deleteElementEncoding(&ef->rangeencoding); - deleteFunctionEncoding(&ef->functionencoding); - break; - } - case ELEMSET: { - ElementSet *es = (ElementSet *) This; - deleteElementEncoding(&es->encoding); - break; - } - case ELEMCONST: { - ElementConst *ec = (ElementConst *) This; - deleteSet(ec->set);//Client did not create, so we free it - deleteElementEncoding(&ec->encoding); - break; - } - default: - ASSERT(0); - } - deleteVectorArrayASTNode(GETELEMENTPARENTS(This)); - ourfree(This); -} diff --git a/src/AST/element.cc b/src/AST/element.cc new file mode 100644 index 0000000..5d126c7 --- /dev/null +++ b/src/AST/element.cc @@ -0,0 +1,91 @@ +#include "element.h" +#include "structs.h" +#include "set.h" +#include "constraint.h" +#include "function.h" +#include "table.h" + +Element *allocElementSet(Set *s) { + ElementSet *This = (ElementSet *)ourmalloc(sizeof(ElementSet)); + GETELEMENTTYPE(This) = ELEMSET; + This->set = s; + initDefVectorASTNode(GETELEMENTPARENTS(This)); + initElementEncoding(&This->encoding, (Element *) This); + return &This->base; +} + +Element *allocElementFunction(Function *function, Element **array, uint numArrays, Boolean *overflowstatus) { + ElementFunction *This = (ElementFunction *) ourmalloc(sizeof(ElementFunction)); + GETELEMENTTYPE(This) = ELEMFUNCRETURN; + This->function = function; + ASSERT(GETBOOLEANTYPE(overflowstatus) == BOOLEANVAR); + This->overflowstatus = overflowstatus; + initArrayInitElement(&This->inputs, array, numArrays); + initDefVectorASTNode(GETELEMENTPARENTS(This)); + for (uint i = 0; i < numArrays; i++) + pushVectorASTNode(GETELEMENTPARENTS(array[i]), (ASTNode *) This); + initElementEncoding(&This->rangeencoding, (Element *) This); + initFunctionEncoding(&This->functionencoding, (Element *) This); + return &This->base; +} + +Element *allocElementConst(uint64_t value, VarType type) { + ElementConst *This = (ElementConst *)ourmalloc(sizeof(ElementConst)); + GETELEMENTTYPE(This) = ELEMCONST; + This->value = value; + This->set = allocSet(type, (uint64_t[]) {value}, 1); + initDefVectorASTNode(GETELEMENTPARENTS(This)); + initElementEncoding(&This->encoding, (Element *) This); + return &This->base; +} + +Set *getElementSet(Element *This) { + switch (GETELEMENTTYPE(This)) { + case ELEMSET: + return ((ElementSet *)This)->set; + case ELEMCONST: + return ((ElementConst *)This)->set; + case ELEMFUNCRETURN: { + Function *func = ((ElementFunction *)This)->function; + switch (GETFUNCTIONTYPE(func)) { + case TABLEFUNC: + return ((FunctionTable *)func)->table->range; + case OPERATORFUNC: + return ((FunctionOperator *)func)->range; + default: + ASSERT(0); + } + } + default: + ASSERT(0); + } + ASSERT(0); + return NULL; +} + +void deleteElement(Element *This) { + switch (GETELEMENTTYPE(This)) { + case ELEMFUNCRETURN: { + ElementFunction *ef = (ElementFunction *) This; + deleteInlineArrayElement(&ef->inputs); + deleteElementEncoding(&ef->rangeencoding); + deleteFunctionEncoding(&ef->functionencoding); + break; + } + case ELEMSET: { + ElementSet *es = (ElementSet *) This; + deleteElementEncoding(&es->encoding); + break; + } + case ELEMCONST: { + ElementConst *ec = (ElementConst *) This; + deleteSet(ec->set);//Client did not create, so we free it + deleteElementEncoding(&ec->encoding); + break; + } + default: + ASSERT(0); + } + deleteVectorArrayASTNode(GETELEMENTPARENTS(This)); + ourfree(This); +} diff --git a/src/AST/function.c b/src/AST/function.c deleted file mode 100644 index 3a32139..0000000 --- a/src/AST/function.c +++ /dev/null @@ -1,53 +0,0 @@ -#include "function.h" -#include "table.h" -#include "set.h" - - -Function *allocFunctionOperator(ArithOp op, Set **domain, uint numDomain, Set *range, OverFlowBehavior overflowbehavior) { - FunctionOperator *This = (FunctionOperator *) ourmalloc(sizeof(FunctionOperator)); - GETFUNCTIONTYPE(This) = OPERATORFUNC; - initArrayInitSet(&This->domains, domain, numDomain); - This->op = op; - This->overflowbehavior = overflowbehavior; - This->range = range; - return &This->base; -} - -Function *allocFunctionTable (Table *table, UndefinedBehavior undefBehavior) { - FunctionTable *This = (FunctionTable *) ourmalloc(sizeof(FunctionTable)); - GETFUNCTIONTYPE(This) = TABLEFUNC; - This->table = table; - This->undefBehavior = undefBehavior; - return &This->base; -} - -uint64_t applyFunctionOperator(FunctionOperator *This, uint numVals, uint64_t *values) { - ASSERT(numVals == 2); - switch (This->op) { - case ADD: - return values[0] + values[1]; - break; - case SUB: - return values[0] - values[1]; - break; - default: - ASSERT(0); - } -} - -bool isInRangeFunction(FunctionOperator *This, uint64_t val) { - return existsInSet(This->range, val); -} - -void deleteFunction(Function *This) { - switch (GETFUNCTIONTYPE(This)) { - case TABLEFUNC: - break; - case OPERATORFUNC: - deleteInlineArraySet(&((FunctionOperator *) This)->domains); - break; - default: - ASSERT(0); - } - ourfree(This); -} diff --git a/src/AST/function.cc b/src/AST/function.cc new file mode 100644 index 0000000..3a32139 --- /dev/null +++ b/src/AST/function.cc @@ -0,0 +1,53 @@ +#include "function.h" +#include "table.h" +#include "set.h" + + +Function *allocFunctionOperator(ArithOp op, Set **domain, uint numDomain, Set *range, OverFlowBehavior overflowbehavior) { + FunctionOperator *This = (FunctionOperator *) ourmalloc(sizeof(FunctionOperator)); + GETFUNCTIONTYPE(This) = OPERATORFUNC; + initArrayInitSet(&This->domains, domain, numDomain); + This->op = op; + This->overflowbehavior = overflowbehavior; + This->range = range; + return &This->base; +} + +Function *allocFunctionTable (Table *table, UndefinedBehavior undefBehavior) { + FunctionTable *This = (FunctionTable *) ourmalloc(sizeof(FunctionTable)); + GETFUNCTIONTYPE(This) = TABLEFUNC; + This->table = table; + This->undefBehavior = undefBehavior; + return &This->base; +} + +uint64_t applyFunctionOperator(FunctionOperator *This, uint numVals, uint64_t *values) { + ASSERT(numVals == 2); + switch (This->op) { + case ADD: + return values[0] + values[1]; + break; + case SUB: + return values[0] - values[1]; + break; + default: + ASSERT(0); + } +} + +bool isInRangeFunction(FunctionOperator *This, uint64_t val) { + return existsInSet(This->range, val); +} + +void deleteFunction(Function *This) { + switch (GETFUNCTIONTYPE(This)) { + case TABLEFUNC: + break; + case OPERATORFUNC: + deleteInlineArraySet(&((FunctionOperator *) This)->domains); + break; + default: + ASSERT(0); + } + ourfree(This); +} diff --git a/src/AST/mutableset.c b/src/AST/mutableset.c deleted file mode 100644 index 19552f6..0000000 --- a/src/AST/mutableset.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "mutableset.h" - -MutableSet *allocMutableSet(VarType t) { - MutableSet *This = (MutableSet *)ourmalloc(sizeof(MutableSet)); - This->type = t; - This->isRange = false; - This->low = 0; - This->high = 0; - This->members = allocDefVectorInt(); - return This; -} - -void addElementMSet(MutableSet *set, uint64_t element) { - pushVectorInt(set->members, element); -} diff --git a/src/AST/mutableset.cc b/src/AST/mutableset.cc new file mode 100644 index 0000000..19552f6 --- /dev/null +++ b/src/AST/mutableset.cc @@ -0,0 +1,15 @@ +#include "mutableset.h" + +MutableSet *allocMutableSet(VarType t) { + MutableSet *This = (MutableSet *)ourmalloc(sizeof(MutableSet)); + This->type = t; + This->isRange = false; + This->low = 0; + This->high = 0; + This->members = allocDefVectorInt(); + return This; +} + +void addElementMSet(MutableSet *set, uint64_t element) { + pushVectorInt(set->members, element); +} diff --git a/src/AST/order.c b/src/AST/order.c deleted file mode 100644 index 92bb557..0000000 --- a/src/AST/order.c +++ /dev/null @@ -1,49 +0,0 @@ -#include "order.h" -#include "structs.h" -#include "set.h" -#include "boolean.h" -#include "ordergraph.h" - -Order *allocOrder(OrderType type, Set *set) { - Order *This = (Order *)ourmalloc(sizeof(Order)); - This->set = set; - initDefVectorBooleanOrder(&This->constraints); - This->type = type; - initOrderEncoding(&This->order, This); - This->orderPairTable = NULL; - This->elementTable = NULL; - This->graph = NULL; - return This; -} - -void initializeOrderHashTable(Order *This) { - This->orderPairTable = allocHashTableOrderPair(HT_INITIAL_CAPACITY, HT_DEFAULT_FACTOR); -} - -void initializeOrderElementsHashTable(Order *This){ - This->elementTable = allocHashSetOrderElement(HT_INITIAL_CAPACITY, HT_DEFAULT_FACTOR); -} - -void addOrderConstraint(Order *This, BooleanOrder *constraint) { - pushVectorBooleanOrder( &This->constraints, constraint); -} - -void setOrderEncodingType(Order *This, OrderEncodingType type) { - This->order.type = type; -} - -void deleteOrder(Order *This) { - deleteVectorArrayBooleanOrder(&This->constraints); - deleteOrderEncoding(&This->order); - if (This->orderPairTable != NULL) { - resetAndDeleteHashTableOrderPair(This->orderPairTable); - deleteHashTableOrderPair(This->orderPairTable); - } - if(This->elementTable != NULL){ - deleteHashSetOrderElement(This->elementTable); - } - if (This->graph != NULL) { - deleteOrderGraph(This->graph); - } - ourfree(This); -} diff --git a/src/AST/order.cc b/src/AST/order.cc new file mode 100644 index 0000000..92bb557 --- /dev/null +++ b/src/AST/order.cc @@ -0,0 +1,49 @@ +#include "order.h" +#include "structs.h" +#include "set.h" +#include "boolean.h" +#include "ordergraph.h" + +Order *allocOrder(OrderType type, Set *set) { + Order *This = (Order *)ourmalloc(sizeof(Order)); + This->set = set; + initDefVectorBooleanOrder(&This->constraints); + This->type = type; + initOrderEncoding(&This->order, This); + This->orderPairTable = NULL; + This->elementTable = NULL; + This->graph = NULL; + return This; +} + +void initializeOrderHashTable(Order *This) { + This->orderPairTable = allocHashTableOrderPair(HT_INITIAL_CAPACITY, HT_DEFAULT_FACTOR); +} + +void initializeOrderElementsHashTable(Order *This){ + This->elementTable = allocHashSetOrderElement(HT_INITIAL_CAPACITY, HT_DEFAULT_FACTOR); +} + +void addOrderConstraint(Order *This, BooleanOrder *constraint) { + pushVectorBooleanOrder( &This->constraints, constraint); +} + +void setOrderEncodingType(Order *This, OrderEncodingType type) { + This->order.type = type; +} + +void deleteOrder(Order *This) { + deleteVectorArrayBooleanOrder(&This->constraints); + deleteOrderEncoding(&This->order); + if (This->orderPairTable != NULL) { + resetAndDeleteHashTableOrderPair(This->orderPairTable); + deleteHashTableOrderPair(This->orderPairTable); + } + if(This->elementTable != NULL){ + deleteHashSetOrderElement(This->elementTable); + } + if (This->graph != NULL) { + deleteOrderGraph(This->graph); + } + ourfree(This); +} diff --git a/src/AST/predicate.c b/src/AST/predicate.c deleted file mode 100644 index 0e0238a..0000000 --- a/src/AST/predicate.c +++ /dev/null @@ -1,53 +0,0 @@ -#include "predicate.h" -#include "boolean.h" -#include "set.h" -#include "table.h" - -Predicate *allocPredicateOperator(CompOp op, Set **domain, uint numDomain) { - PredicateOperator *This = ourmalloc(sizeof(PredicateOperator)); - GETPREDICATETYPE(This) = OPERATORPRED; - initArrayInitSet(&This->domains, domain, numDomain); - This->op = op; - return &This->base; -} - -Predicate *allocPredicateTable(Table *table, UndefinedBehavior undefBehavior) { - ASSERT(table->range == NULL); - PredicateTable *This = ourmalloc(sizeof(PredicateTable)); - GETPREDICATETYPE(This) = TABLEPRED; - This->table = table; - This->undefinedbehavior = undefBehavior; - return &This->base; -} - -void deletePredicate(Predicate *This) { - switch (GETPREDICATETYPE(This)) { - case OPERATORPRED: { - PredicateOperator *operpred = (PredicateOperator *) This; - deleteInlineArraySet(&operpred->domains); - break; - } - case TABLEPRED: { - break; - } - } - //need to handle freeing array... - ourfree(This); -} - -bool evalPredicateOperator(PredicateOperator *This, uint64_t *inputs) { - switch (This->op) { - case EQUALS: - return inputs[0] == inputs[1]; - case LT: - return inputs[0] < inputs[1]; - case GT: - return inputs[0] > inputs[1]; - case LTE: - return inputs[0] <= inputs[1]; - case GTE: - return inputs[0] >= inputs[1]; - } - ASSERT(0); - return false; -} diff --git a/src/AST/predicate.cc b/src/AST/predicate.cc new file mode 100644 index 0000000..dfc8596 --- /dev/null +++ b/src/AST/predicate.cc @@ -0,0 +1,53 @@ +#include "predicate.h" +#include "boolean.h" +#include "set.h" +#include "table.h" + +Predicate *allocPredicateOperator(CompOp op, Set **domain, uint numDomain) { + PredicateOperator *This = (PredicateOperator *)ourmalloc(sizeof(PredicateOperator)); + GETPREDICATETYPE(This) = OPERATORPRED; + initArrayInitSet(&This->domains, domain, numDomain); + This->op = op; + return &This->base; +} + +Predicate *allocPredicateTable(Table *table, UndefinedBehavior undefBehavior) { + ASSERT(table->range == NULL); + PredicateTable *This = (PredicateTable *) ourmalloc(sizeof(PredicateTable)); + GETPREDICATETYPE(This) = TABLEPRED; + This->table = table; + This->undefinedbehavior = undefBehavior; + return &This->base; +} + +void deletePredicate(Predicate *This) { + switch (GETPREDICATETYPE(This)) { + case OPERATORPRED: { + PredicateOperator *operpred = (PredicateOperator *) This; + deleteInlineArraySet(&operpred->domains); + break; + } + case TABLEPRED: { + break; + } + } + //need to handle freeing array... + ourfree(This); +} + +bool evalPredicateOperator(PredicateOperator *This, uint64_t *inputs) { + switch (This->op) { + case EQUALS: + return inputs[0] == inputs[1]; + case LT: + return inputs[0] < inputs[1]; + case GT: + return inputs[0] > inputs[1]; + case LTE: + return inputs[0] <= inputs[1]; + case GTE: + return inputs[0] >= inputs[1]; + } + ASSERT(0); + return false; +} diff --git a/src/AST/rewriter.c b/src/AST/rewriter.c deleted file mode 100644 index 5e24051..0000000 --- a/src/AST/rewriter.c +++ /dev/null @@ -1,164 +0,0 @@ -#include "rewriter.h" -#include "boolean.h" -#include "csolver.h" - -void replaceBooleanWithTrue(CSolver * This, Boolean *bexpr) { - if (containsHashSetBoolean(This->constraints, bexpr)) { - removeHashSetBoolean(This->constraints, bexpr); - } - - uint size = getSizeVectorBoolean(&bexpr->parents); - for (uint i = 0; i < size; i++) { - Boolean *parent = getVectorBoolean(&bexpr->parents, i); - BooleanLogic *logicop = (BooleanLogic *) parent; - switch (logicop->op) { - case L_AND: - handleANDTrue(This, logicop, bexpr); - break; - case L_OR: - replaceBooleanWithTrue(This, parent); - break; - case L_NOT: - replaceBooleanWithFalse(This, parent); - break; - case L_XOR: - handleXORTrue(logicop, bexpr); - break; - case L_IMPLIES: - handleIMPLIESTrue(This, logicop, bexpr); - break; - } - } -} - -void replaceBooleanWithBoolean(CSolver * This, Boolean *oldb, Boolean *newb) { - if (containsHashSetBoolean(This->constraints, oldb)) { - removeHashSetBoolean(This->constraints, oldb); - addHashSetBoolean(This->constraints, newb); - } - - uint size = getSizeVectorBoolean(&oldb->parents); - for (uint i = 0; i < size; i++) { - Boolean *parent = getVectorBoolean(&oldb->parents, i); - BooleanLogic *logicop = (BooleanLogic *) parent; - - uint parentsize = getSizeArrayBoolean(&logicop->inputs); - - for (uint j = 0; j < parentsize; j++) { - Boolean *b = getArrayBoolean(&logicop->inputs, i); - if (b == oldb) { - setArrayBoolean(&logicop->inputs, i, newb); - pushVectorBoolean(&newb->parents, parent); - } - } - } -} - -void handleXORTrue(BooleanLogic *bexpr, Boolean *child) { - uint size = getSizeArrayBoolean(&bexpr->inputs); - Boolean *b = getArrayBoolean(&bexpr->inputs, 0); - uint childindex = (b == child) ? 0 : 1; - removeElementArrayBoolean(&bexpr->inputs, childindex); - bexpr->op = L_NOT; -} - -void handleXORFalse(CSolver * This, BooleanLogic *bexpr, Boolean *child) { - uint size = getSizeArrayBoolean(&bexpr->inputs); - Boolean *b = getArrayBoolean(&bexpr->inputs, 0); - uint otherindex = (b == child) ? 1 : 0; - replaceBooleanWithBoolean(This, (Boolean *)bexpr, getArrayBoolean(&bexpr->inputs, otherindex)); -} - -void handleIMPLIESTrue(CSolver * This, BooleanLogic *bexpr, Boolean *child) { - uint size = getSizeArrayBoolean(&bexpr->inputs); - Boolean *b = getArrayBoolean(&bexpr->inputs, 0); - if (b == child) { - //Replace with other term - replaceBooleanWithBoolean(This, (Boolean *)bexpr, getArrayBoolean(&bexpr->inputs, 1)); - } else { - //Statement is true... - replaceBooleanWithTrue(This, (Boolean *)bexpr); - } -} - -void handleIMPLIESFalse(CSolver * This, BooleanLogic *bexpr, Boolean *child) { - uint size = getSizeArrayBoolean(&bexpr->inputs); - Boolean *b = getArrayBoolean(&bexpr->inputs, 0); - if (b == child) { - //Statement is true... - replaceBooleanWithTrue(This, (Boolean *)bexpr); - } else { - //Make into negation of first term - removeElementArrayBoolean(&bexpr->inputs, 1); - bexpr->op = L_NOT; - } -} - -void handleANDTrue(CSolver * This, BooleanLogic *bexpr, Boolean *child) { - uint size = getSizeArrayBoolean(&bexpr->inputs); - - if (size == 1) { - replaceBooleanWithTrue(This, (Boolean *)bexpr); - return; - } - - for (uint i = 0; i < size; i++) { - Boolean *b = getArrayBoolean(&bexpr->inputs, i); - if (b == child) { - removeElementArrayBoolean(&bexpr->inputs, i); - } - } - - if (size == 2) { - replaceBooleanWithBoolean(This, (Boolean *)bexpr, getArrayBoolean(&bexpr->inputs, 0)); - } -} - -void handleORFalse(CSolver * This, BooleanLogic *bexpr, Boolean *child) { - uint size = getSizeArrayBoolean(&bexpr->inputs); - - if (size == 1) { - replaceBooleanWithFalse(This, (Boolean *) bexpr); - } - - for (uint i = 0; i < size; i++) { - Boolean *b = getArrayBoolean(&bexpr->inputs, i); - if (b == child) { - removeElementArrayBoolean(&bexpr->inputs, i); - } - } - - if (size == 2) { - replaceBooleanWithBoolean(This, (Boolean *)bexpr, getArrayBoolean(&bexpr->inputs, 0)); - } -} - -void replaceBooleanWithFalse(CSolver * This, Boolean *bexpr) { - if (containsHashSetBoolean(This->constraints, bexpr)) { - This->unsat=true; - removeHashSetBoolean(This->constraints, bexpr); - } - - uint size = getSizeVectorBoolean(&bexpr->parents); - for (uint i = 0; i < size; i++) { - Boolean *parent = getVectorBoolean(&bexpr->parents, i); - BooleanLogic *logicop = (BooleanLogic *) parent; - switch (logicop->op) { - case L_AND: - replaceBooleanWithFalse(This, parent); - break; - case L_OR: - handleORFalse(This, logicop, bexpr); - break; - case L_NOT: - replaceBooleanWithTrue(This, parent); - break; - case L_XOR: - handleXORFalse(This, logicop, bexpr); - break; - case L_IMPLIES: - handleIMPLIESFalse(This, logicop, bexpr); - break; - } - } -} diff --git a/src/AST/rewriter.cc b/src/AST/rewriter.cc new file mode 100644 index 0000000..5e24051 --- /dev/null +++ b/src/AST/rewriter.cc @@ -0,0 +1,164 @@ +#include "rewriter.h" +#include "boolean.h" +#include "csolver.h" + +void replaceBooleanWithTrue(CSolver * This, Boolean *bexpr) { + if (containsHashSetBoolean(This->constraints, bexpr)) { + removeHashSetBoolean(This->constraints, bexpr); + } + + uint size = getSizeVectorBoolean(&bexpr->parents); + for (uint i = 0; i < size; i++) { + Boolean *parent = getVectorBoolean(&bexpr->parents, i); + BooleanLogic *logicop = (BooleanLogic *) parent; + switch (logicop->op) { + case L_AND: + handleANDTrue(This, logicop, bexpr); + break; + case L_OR: + replaceBooleanWithTrue(This, parent); + break; + case L_NOT: + replaceBooleanWithFalse(This, parent); + break; + case L_XOR: + handleXORTrue(logicop, bexpr); + break; + case L_IMPLIES: + handleIMPLIESTrue(This, logicop, bexpr); + break; + } + } +} + +void replaceBooleanWithBoolean(CSolver * This, Boolean *oldb, Boolean *newb) { + if (containsHashSetBoolean(This->constraints, oldb)) { + removeHashSetBoolean(This->constraints, oldb); + addHashSetBoolean(This->constraints, newb); + } + + uint size = getSizeVectorBoolean(&oldb->parents); + for (uint i = 0; i < size; i++) { + Boolean *parent = getVectorBoolean(&oldb->parents, i); + BooleanLogic *logicop = (BooleanLogic *) parent; + + uint parentsize = getSizeArrayBoolean(&logicop->inputs); + + for (uint j = 0; j < parentsize; j++) { + Boolean *b = getArrayBoolean(&logicop->inputs, i); + if (b == oldb) { + setArrayBoolean(&logicop->inputs, i, newb); + pushVectorBoolean(&newb->parents, parent); + } + } + } +} + +void handleXORTrue(BooleanLogic *bexpr, Boolean *child) { + uint size = getSizeArrayBoolean(&bexpr->inputs); + Boolean *b = getArrayBoolean(&bexpr->inputs, 0); + uint childindex = (b == child) ? 0 : 1; + removeElementArrayBoolean(&bexpr->inputs, childindex); + bexpr->op = L_NOT; +} + +void handleXORFalse(CSolver * This, BooleanLogic *bexpr, Boolean *child) { + uint size = getSizeArrayBoolean(&bexpr->inputs); + Boolean *b = getArrayBoolean(&bexpr->inputs, 0); + uint otherindex = (b == child) ? 1 : 0; + replaceBooleanWithBoolean(This, (Boolean *)bexpr, getArrayBoolean(&bexpr->inputs, otherindex)); +} + +void handleIMPLIESTrue(CSolver * This, BooleanLogic *bexpr, Boolean *child) { + uint size = getSizeArrayBoolean(&bexpr->inputs); + Boolean *b = getArrayBoolean(&bexpr->inputs, 0); + if (b == child) { + //Replace with other term + replaceBooleanWithBoolean(This, (Boolean *)bexpr, getArrayBoolean(&bexpr->inputs, 1)); + } else { + //Statement is true... + replaceBooleanWithTrue(This, (Boolean *)bexpr); + } +} + +void handleIMPLIESFalse(CSolver * This, BooleanLogic *bexpr, Boolean *child) { + uint size = getSizeArrayBoolean(&bexpr->inputs); + Boolean *b = getArrayBoolean(&bexpr->inputs, 0); + if (b == child) { + //Statement is true... + replaceBooleanWithTrue(This, (Boolean *)bexpr); + } else { + //Make into negation of first term + removeElementArrayBoolean(&bexpr->inputs, 1); + bexpr->op = L_NOT; + } +} + +void handleANDTrue(CSolver * This, BooleanLogic *bexpr, Boolean *child) { + uint size = getSizeArrayBoolean(&bexpr->inputs); + + if (size == 1) { + replaceBooleanWithTrue(This, (Boolean *)bexpr); + return; + } + + for (uint i = 0; i < size; i++) { + Boolean *b = getArrayBoolean(&bexpr->inputs, i); + if (b == child) { + removeElementArrayBoolean(&bexpr->inputs, i); + } + } + + if (size == 2) { + replaceBooleanWithBoolean(This, (Boolean *)bexpr, getArrayBoolean(&bexpr->inputs, 0)); + } +} + +void handleORFalse(CSolver * This, BooleanLogic *bexpr, Boolean *child) { + uint size = getSizeArrayBoolean(&bexpr->inputs); + + if (size == 1) { + replaceBooleanWithFalse(This, (Boolean *) bexpr); + } + + for (uint i = 0; i < size; i++) { + Boolean *b = getArrayBoolean(&bexpr->inputs, i); + if (b == child) { + removeElementArrayBoolean(&bexpr->inputs, i); + } + } + + if (size == 2) { + replaceBooleanWithBoolean(This, (Boolean *)bexpr, getArrayBoolean(&bexpr->inputs, 0)); + } +} + +void replaceBooleanWithFalse(CSolver * This, Boolean *bexpr) { + if (containsHashSetBoolean(This->constraints, bexpr)) { + This->unsat=true; + removeHashSetBoolean(This->constraints, bexpr); + } + + uint size = getSizeVectorBoolean(&bexpr->parents); + for (uint i = 0; i < size; i++) { + Boolean *parent = getVectorBoolean(&bexpr->parents, i); + BooleanLogic *logicop = (BooleanLogic *) parent; + switch (logicop->op) { + case L_AND: + replaceBooleanWithFalse(This, parent); + break; + case L_OR: + handleORFalse(This, logicop, bexpr); + break; + case L_NOT: + replaceBooleanWithTrue(This, parent); + break; + case L_XOR: + handleXORFalse(This, logicop, bexpr); + break; + case L_IMPLIES: + handleIMPLIESFalse(This, logicop, bexpr); + break; + } + } +} diff --git a/src/AST/set.c b/src/AST/set.c deleted file mode 100644 index 003379e..0000000 --- a/src/AST/set.c +++ /dev/null @@ -1,56 +0,0 @@ -#include "set.h" -#include - -Set *allocSet(VarType t, uint64_t *elements, uint num) { - Set *This = (Set *)ourmalloc(sizeof(Set)); - This->type = t; - This->isRange = false; - This->low = 0; - This->high = 0; - This->members = allocVectorArrayInt(num, elements); - return This; -} - -Set *allocSetRange(VarType t, uint64_t lowrange, uint64_t highrange) { - Set *This = (Set *)ourmalloc(sizeof(Set)); - This->type = t; - This->isRange = true; - This->low = lowrange; - This->high = highrange; - This->members = NULL; - return This; -} - -bool existsInSet(Set *This, uint64_t element) { - if (This->isRange) { - return element >= This->low && element <= This->high; - } else { - uint size = getSizeVectorInt(This->members); - for (uint i = 0; i < size; i++) { - if (element == getVectorInt(This->members, i)) - return true; - } - return false; - } -} - -uint64_t getSetElement(Set *This, uint index) { - if (This->isRange) - return This->low + index; - else - return getVectorInt(This->members, index); -} - -uint getSetSize(Set *This) { - if (This->isRange) { - return This->high - This->low + 1; - } else { - return getSizeVectorInt(This->members); - } -} - -void deleteSet(Set *This) { - if (!This->isRange) - deleteVectorInt(This->members); - ourfree(This); -} diff --git a/src/AST/set.cc b/src/AST/set.cc new file mode 100644 index 0000000..003379e --- /dev/null +++ b/src/AST/set.cc @@ -0,0 +1,56 @@ +#include "set.h" +#include + +Set *allocSet(VarType t, uint64_t *elements, uint num) { + Set *This = (Set *)ourmalloc(sizeof(Set)); + This->type = t; + This->isRange = false; + This->low = 0; + This->high = 0; + This->members = allocVectorArrayInt(num, elements); + return This; +} + +Set *allocSetRange(VarType t, uint64_t lowrange, uint64_t highrange) { + Set *This = (Set *)ourmalloc(sizeof(Set)); + This->type = t; + This->isRange = true; + This->low = lowrange; + This->high = highrange; + This->members = NULL; + return This; +} + +bool existsInSet(Set *This, uint64_t element) { + if (This->isRange) { + return element >= This->low && element <= This->high; + } else { + uint size = getSizeVectorInt(This->members); + for (uint i = 0; i < size; i++) { + if (element == getVectorInt(This->members, i)) + return true; + } + return false; + } +} + +uint64_t getSetElement(Set *This, uint index) { + if (This->isRange) + return This->low + index; + else + return getVectorInt(This->members, index); +} + +uint getSetSize(Set *This) { + if (This->isRange) { + return This->high - This->low + 1; + } else { + return getSizeVectorInt(This->members); + } +} + +void deleteSet(Set *This) { + if (!This->isRange) + deleteVectorInt(This->members); + ourfree(This); +} diff --git a/src/AST/table.c b/src/AST/table.c deleted file mode 100644 index b903744..0000000 --- a/src/AST/table.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "table.h" -#include "common.h" -#include "structs.h" -#include "tableentry.h" -#include "set.h" -#include "mutableset.h" - -Table *allocTable(Set **domains, uint numDomain, Set *range) { - Table *This = (Table *) ourmalloc(sizeof(Table)); - initArrayInitSet(&This->domains, domains, numDomain); - This->entries = allocHashSetTableEntry(HT_INITIAL_CAPACITY, HT_DEFAULT_FACTOR); - This->range = range; - return This; -} - -void addNewTableEntry(Table *This, uint64_t *inputs, uint inputSize, uint64_t result) { - ASSERT(getSizeArraySet( &This->domains) == inputSize); -#ifdef CONFIG_ASSERT - if (This->range == NULL) - ASSERT(result == true || result == false); -#endif - TableEntry *tb = allocTableEntry(inputs, inputSize, result); - ASSERT(!containsHashSetTableEntry(This->entries, tb)); - bool status = addHashSetTableEntry(This->entries, tb); - ASSERT(status); -} - -TableEntry *getTableEntryFromTable(Table *table, uint64_t *inputs, uint inputSize) { - TableEntry *temp = allocTableEntry(inputs, inputSize, -1); - TableEntry *result = getHashSetTableEntry(table->entries, temp); - deleteTableEntry(temp); - return result; -} - -void deleteTable(Table *This) { - deleteInlineArraySet(&This->domains); - HSIteratorTableEntry *iterator = iteratorTableEntry(This->entries); - while (hasNextTableEntry(iterator)) { - deleteTableEntry( nextTableEntry(iterator) ); - } - deleteIterTableEntry(iterator); - deleteHashSetTableEntry(This->entries); - ourfree(This); -} - diff --git a/src/AST/table.cc b/src/AST/table.cc new file mode 100644 index 0000000..b903744 --- /dev/null +++ b/src/AST/table.cc @@ -0,0 +1,45 @@ +#include "table.h" +#include "common.h" +#include "structs.h" +#include "tableentry.h" +#include "set.h" +#include "mutableset.h" + +Table *allocTable(Set **domains, uint numDomain, Set *range) { + Table *This = (Table *) ourmalloc(sizeof(Table)); + initArrayInitSet(&This->domains, domains, numDomain); + This->entries = allocHashSetTableEntry(HT_INITIAL_CAPACITY, HT_DEFAULT_FACTOR); + This->range = range; + return This; +} + +void addNewTableEntry(Table *This, uint64_t *inputs, uint inputSize, uint64_t result) { + ASSERT(getSizeArraySet( &This->domains) == inputSize); +#ifdef CONFIG_ASSERT + if (This->range == NULL) + ASSERT(result == true || result == false); +#endif + TableEntry *tb = allocTableEntry(inputs, inputSize, result); + ASSERT(!containsHashSetTableEntry(This->entries, tb)); + bool status = addHashSetTableEntry(This->entries, tb); + ASSERT(status); +} + +TableEntry *getTableEntryFromTable(Table *table, uint64_t *inputs, uint inputSize) { + TableEntry *temp = allocTableEntry(inputs, inputSize, -1); + TableEntry *result = getHashSetTableEntry(table->entries, temp); + deleteTableEntry(temp); + return result; +} + +void deleteTable(Table *This) { + deleteInlineArraySet(&This->domains); + HSIteratorTableEntry *iterator = iteratorTableEntry(This->entries); + while (hasNextTableEntry(iterator)) { + deleteTableEntry( nextTableEntry(iterator) ); + } + deleteIterTableEntry(iterator); + deleteHashSetTableEntry(This->entries); + ourfree(This); +} + diff --git a/src/AST/tableentry.c b/src/AST/tableentry.c deleted file mode 100644 index 64aae20..0000000 --- a/src/AST/tableentry.c +++ /dev/null @@ -1,14 +0,0 @@ -#include "tableentry.h" -#include - -TableEntry *allocTableEntry(uint64_t *inputs, uint inputSize, uint64_t result) { - TableEntry *te = (TableEntry *) ourmalloc(sizeof(TableEntry) + inputSize * sizeof(uint64_t)); - te->output = result; - te->inputSize = inputSize; - memcpy(te->inputs, inputs, inputSize * sizeof(uint64_t)); - return te; -} - -void deleteTableEntry(TableEntry *tableEntry) { - ourfree(tableEntry); -} diff --git a/src/AST/tableentry.cc b/src/AST/tableentry.cc new file mode 100644 index 0000000..64aae20 --- /dev/null +++ b/src/AST/tableentry.cc @@ -0,0 +1,14 @@ +#include "tableentry.h" +#include + +TableEntry *allocTableEntry(uint64_t *inputs, uint inputSize, uint64_t result) { + TableEntry *te = (TableEntry *) ourmalloc(sizeof(TableEntry) + inputSize * sizeof(uint64_t)); + te->output = result; + te->inputSize = inputSize; + memcpy(te->inputs, inputs, inputSize * sizeof(uint64_t)); + return te; +} + +void deleteTableEntry(TableEntry *tableEntry) { + ourfree(tableEntry); +} diff --git a/src/Backend/cnfexpr.c b/src/Backend/cnfexpr.c deleted file mode 100644 index ae1104f..0000000 --- a/src/Backend/cnfexpr.c +++ /dev/null @@ -1,465 +0,0 @@ -#include "cnfexpr.h" -#include -/* - V2 Copyright (c) 2014 Ben Chambers, Eugene Goldberg, Pete Manolios, - Vasilis Papavasileiou, Sudarshan Srinivasan, and Daron Vroon. - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. If - you download or use the software, send email to Pete Manolios - (pete@ccs.neu.edu) with your name, contact information, and a short - note describing what you want to use BAT for. For any reuse or - distribution, you must make clear to others the license terms of this - work. - - Contact Pete Manolios if you want any of these conditions waived. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - C port of CNF SAT Conversion Copyright Brian Demsky 2017. - */ - -#define LITCAPACITY 4 -#define MERGESIZE 5 - -VectorImpl(LitVector, LitVector *, 4) - -static inline uint boundedSize(uint x) { return (x > MERGESIZE) ? MERGESIZE : x; } - -LitVector *allocLitVector() { - LitVector *This = ourmalloc(sizeof(LitVector)); - initLitVector(This); - return This; -} - -void initLitVector(LitVector *This) { - This->size = 0; - This->capacity = LITCAPACITY; - This->literals = ourmalloc(This->capacity * sizeof(Literal)); -} - -LitVector *cloneLitVector(LitVector *orig) { - LitVector *This = ourmalloc(sizeof(LitVector)); - This->size = orig->size; - This->capacity = orig->capacity; - This->literals = ourmalloc(This->capacity * sizeof(Literal)); - memcpy(This->literals, orig->literals, sizeof(Literal) * This->size); - return This; -} - -void clearLitVector(LitVector *This) { - This->size = 0; -} - -void freeLitVector(LitVector *This) { - ourfree(This->literals); -} - -void deleteLitVector(LitVector *This) { - freeLitVector(This); - ourfree(This); -} - -Literal getLiteralLitVector(LitVector *This, uint index) { - return This->literals[index]; -} - -void setLiteralLitVector(LitVector *This, uint index, Literal l) { - This->literals[index] = l; -} - -void addLiteralLitVector(LitVector *This, Literal l) { - Literal labs = abs(l); - uint vec_size = This->size; - uint searchsize = boundedSize(vec_size); - uint i = 0; - for (; i < searchsize; i++) { - Literal curr = This->literals[i]; - Literal currabs = abs(curr); - if (currabs > labs) - break; - if (currabs == labs) { - if (curr == -l) - This->size = 0; //either true or false now depending on whether this is a conj or disj - return; - } - } - if ((++This->size) >= This->capacity) { - This->capacity <<= 1; - This->literals = ourrealloc(This->literals, This->capacity * sizeof(Literal)); - } - - if (vec_size < MERGESIZE) { - memmove(&This->literals[i + 1], &This->literals[i], (vec_size - i) * sizeof(Literal)); - This->literals[i] = l; - } else { - This->literals[vec_size] = l; - } -} - -CNFExpr *allocCNFExprBool(bool isTrue) { - CNFExpr *This = ourmalloc(sizeof(CNFExpr)); - This->litSize = 0; - This->isTrue = isTrue; - initVectorLitVector(&This->clauses, 2); - initLitVector(&This->singletons); - return This; -} - -CNFExpr *allocCNFExprLiteral(Literal l) { - CNFExpr *This = ourmalloc(sizeof(CNFExpr)); - This->litSize = 1; - This->isTrue = false; - initVectorLitVector(&This->clauses, 2); - initLitVector(&This->singletons); - addLiteralLitVector(&This->singletons, l); - return This; -} - -void clearCNFExpr(CNFExpr *This, bool isTrue) { - for (uint i = 0; i < getSizeVectorLitVector(&This->clauses); i++) { - deleteLitVector(getVectorLitVector(&This->clauses, i)); - } - clearVectorLitVector(&This->clauses); - clearLitVector(&This->singletons); - This->litSize = 0; - This->isTrue = isTrue; -} - -void deleteCNFExpr(CNFExpr *This) { - for (uint i = 0; i < getSizeVectorLitVector(&This->clauses); i++) { - deleteLitVector(getVectorLitVector(&This->clauses, i)); - } - deleteVectorArrayLitVector(&This->clauses); - freeLitVector(&This->singletons); - ourfree(This); -} - -void conjoinCNFLit(CNFExpr *This, Literal l) { - if (This->litSize == 0 && !This->isTrue)//Handle False - return; - - This->litSize -= getSizeLitVector(&This->singletons); - addLiteralLitVector(&This->singletons, l); - uint newsize = getSizeLitVector(&This->singletons); - if (newsize == 0) - clearCNFExpr(This, false);//We found a conflict - else - This->litSize += getSizeLitVector(&This->singletons); -} - -void copyCNF(CNFExpr *This, CNFExpr *expr, bool destroy) { - if (destroy) { - ourfree(This->singletons.literals); - ourfree(This->clauses.array); - This->litSize = expr->litSize; - This->singletons.literals = expr->singletons.literals; - This->singletons.capacity = expr->singletons.capacity; - This->clauses.size = expr->clauses.size; - This->clauses.array = expr->clauses.array; - This->clauses.capacity = expr->clauses.capacity; - ourfree(expr); - } else { - for (uint i = 0; i < getSizeLitVector(&expr->singletons); i++) { - Literal l = getLiteralLitVector(&expr->singletons,i); - addLiteralLitVector(&This->singletons, l); - } - for (uint i = 0; i < getSizeVectorLitVector(&expr->clauses); i++) { - LitVector *lv = getVectorLitVector(&expr->clauses,i); - pushVectorLitVector(&This->clauses, cloneLitVector(lv)); - } - This->litSize = expr->litSize; - } -} - -void conjoinCNFExpr(CNFExpr *This, CNFExpr *expr, bool destroy) { - if (expr->litSize == 0) { - if (!This->isTrue) { - clearCNFExpr(This, false); - } - if (destroy) { - deleteCNFExpr(expr); - } - return; - } - if (This->litSize == 0) { - if (This->isTrue) { - copyCNF(This, expr, destroy); - } else if (destroy) { - deleteCNFExpr(expr); - } - return; - } - uint litSize = This->litSize; - litSize -= getSizeLitVector(&expr->singletons); - for (uint i = 0; i < getSizeLitVector(&expr->singletons); i++) { - Literal l = getLiteralLitVector(&expr->singletons,i); - addLiteralLitVector(&This->singletons, l); - if (getSizeLitVector(&This->singletons) == 0) { - //Found conflict... - clearCNFExpr(This, false); - if (destroy) { - deleteCNFExpr(expr); - } - return; - } - } - litSize += getSizeLitVector(&expr->singletons); - if (destroy) { - for (uint i = 0; i < getSizeVectorLitVector(&expr->clauses); i++) { - LitVector *lv = getVectorLitVector(&expr->clauses,i); - litSize += getSizeLitVector(lv); - pushVectorLitVector(&This->clauses, lv); - } - clearVectorLitVector(&expr->clauses); - deleteCNFExpr(expr); - } else { - for (uint i = 0; i < getSizeVectorLitVector(&expr->clauses); i++) { - LitVector *lv = getVectorLitVector(&expr->clauses,i); - litSize += getSizeLitVector(lv); - pushVectorLitVector(&This->clauses, cloneLitVector(lv)); - } - } - This->litSize = litSize; -} - -void disjoinCNFLit(CNFExpr *This, Literal l) { - if (This->litSize == 0) { - if (!This->isTrue) { - This->litSize++; - addLiteralLitVector(&This->singletons, l); - } - return; - } - - uint litSize = 0; - uint newindex = 0; - for (uint i = 0; i < getSizeVectorLitVector(&This->clauses); i++) { - LitVector *lv = getVectorLitVector(&This->clauses, i); - addLiteralLitVector(lv, l); - uint newSize = getSizeLitVector(lv); - if (newSize != 0) { - setVectorLitVector(&This->clauses, newindex++, lv); - } else { - deleteLitVector(lv); - } - litSize += newSize; - } - setSizeVectorLitVector(&This->clauses, newindex); - - bool hasSameSingleton = false; - for (uint i = 0; i < getSizeLitVector(&This->singletons); i++) { - Literal lsing = getLiteralLitVector(&This->singletons, i); - if (lsing == l) { - hasSameSingleton = true; - } else if (lsing != -l) { - //Create new LitVector with both l and lsing - LitVector *newlitvec = allocLitVector(); - addLiteralLitVector(newlitvec, l); - addLiteralLitVector(newlitvec, lsing); - litSize += 2; - pushVectorLitVector(&This->clauses, newlitvec); - } - } - clearLitVector(&This->singletons); - if (hasSameSingleton) { - addLiteralLitVector(&This->singletons, l); - litSize++; - } else if (litSize == 0) { - This->isTrue = true;//we are true - } - This->litSize = litSize; -} - -#define MERGETHRESHOLD 2 -LitVector *mergeLitVectors(LitVector *This, LitVector *expr) { - uint maxsize = This->size + expr->size + MERGETHRESHOLD; - LitVector *merged = ourmalloc(sizeof(LitVector)); - merged->literals = ourmalloc(sizeof(Literal) * maxsize); - merged->capacity = maxsize; - uint thisSize = boundedSize(This->size); - uint exprSize = boundedSize(expr->size); - uint iThis = 0, iExpr = 0, iMerge = 0; - Literal lThis = This->literals[iThis]; - Literal lExpr = expr->literals[iExpr]; - Literal thisAbs = abs(lThis); - Literal exprAbs = abs(lExpr); - - while (iThis < thisSize && iExpr < exprSize) { - if (thisAbs < exprAbs) { - merged->literals[iMerge++] = lThis; - lThis = This->literals[++iThis]; - thisAbs = abs(lThis); - } else if (thisAbs > exprAbs) { - merged->literals[iMerge++] = lExpr; - lExpr = expr->literals[++iExpr]; - exprAbs = abs(lExpr); - } else if (lThis == lExpr) { - merged->literals[iMerge++] = lExpr; - lExpr = expr->literals[++iExpr]; - exprAbs = abs(lExpr); - lThis = This->literals[++iThis]; - thisAbs = abs(lThis); - } else if (lThis == -lExpr) { - merged->size = 0; - return merged; - } - } - if (iThis < thisSize) { - memcpy(&merged->literals[iMerge], &This->literals[iThis], (thisSize - iThis) * sizeof(Literal)); - iMerge += (thisSize - iThis); - } - if (iExpr < exprSize) { - memcpy(&merged->literals[iMerge], &expr->literals[iExpr], (exprSize - iExpr) * sizeof(Literal)); - iMerge += (exprSize - iExpr); - } - merged->size = iMerge; - return merged; -} - -LitVector *mergeLitVectorLiteral(LitVector *This, Literal l) { - LitVector *copy = cloneLitVector(This); - addLiteralLitVector(copy, l); - return copy; -} - -void disjoinCNFExpr(CNFExpr *This, CNFExpr *expr, bool destroy) { - /** Handle the special cases */ - if (expr->litSize == 0) { - if (expr->isTrue) { - clearCNFExpr(This, true); - } - if (destroy) { - deleteCNFExpr(expr); - } - return; - } else if (This->litSize == 0) { - if (!This->isTrue) { - copyCNF(This, expr, destroy); - } else if (destroy) { - deleteCNFExpr(expr); - } - return; - } else if (expr->litSize == 1) { - disjoinCNFLit(This, getLiteralLitVector(&expr->singletons,0)); - if (destroy) { - deleteCNFExpr(expr); - } - return; - } else if (destroy && This->litSize == 1) { - Literal l = getLiteralLitVector(&This->singletons,0); - copyCNF(This, expr, true); - disjoinCNFLit(This, l); - return; - } - - /** Handle the full cross product */ - uint mergeIndex = 0; - uint newCapacity = getClauseSizeCNF(This) * getClauseSizeCNF(expr); - LitVector **mergeArray = ourmalloc(newCapacity * sizeof(LitVector *)); - uint singleIndex = 0; - /** First do the singleton, clause pairs */ - for (uint i = 0; i < getSizeLitVector(&This->singletons); i++) { - Literal lThis = getLiteralLitVector(&This->singletons, i); - for (uint j = 0; j < getSizeVectorLitVector(&expr->clauses); j++) { - LitVector *lExpr = getVectorLitVector(&expr->clauses, j); - LitVector *copy = cloneLitVector(lExpr); - addLiteralLitVector(copy, lThis); - if (getSizeLitVector(copy) == 0) { - deleteLitVector(copy); - } else { - mergeArray[mergeIndex++] = copy; - } - } - } - - /** Next do the clause, singleton pairs */ - for (uint i = 0; i < getSizeLitVector(&expr->singletons); i++) { - Literal lExpr = getLiteralLitVector(&expr->singletons, i); - for (uint j = 0; j < getSizeVectorLitVector(&This->clauses); j++) { - LitVector *lThis = getVectorLitVector(&This->clauses, j); - LitVector *copy = cloneLitVector(lThis); - addLiteralLitVector(copy, lExpr); - if (getSizeLitVector(copy) == 0) { - deleteLitVector(copy); - } else { - mergeArray[mergeIndex++] = copy; - } - } - } - - /** Next do the clause, clause pairs */ - for (uint i = 0; i < getSizeVectorLitVector(&This->clauses); i++) { - LitVector *lThis = getVectorLitVector(&This->clauses, i); - for (uint j = 0; j < getSizeVectorLitVector(&expr->clauses); j++) { - LitVector *lExpr = getVectorLitVector(&expr->clauses, j); - LitVector *merge = mergeLitVectors(lThis, lExpr); - if (getSizeLitVector(merge) == 0) { - deleteLitVector(merge); - } else { - mergeArray[mergeIndex++] = merge; - } - } - deleteLitVector(lThis);//Done with this litVector - } - - /** Finally do the singleton, singleton pairs */ - for (uint i = 0; i < getSizeLitVector(&This->singletons); i++) { - Literal lThis = getLiteralLitVector(&This->singletons, i); - for (uint j = 0; j < getSizeLitVector(&expr->singletons); j++) { - Literal lExpr = getLiteralLitVector(&expr->singletons, j); - if (lThis == lExpr) { - //We have a singleton still in the final result - setLiteralLitVector(&This->singletons, singleIndex++, lThis); - } else if (lThis != -lExpr) { - LitVector *mergeLV = allocLitVector(); - addLiteralLitVector(mergeLV, lThis); - addLiteralLitVector(mergeLV, lExpr); - mergeArray[mergeIndex++] = mergeLV; - } - } - } - - ourfree(This->clauses.array); - setSizeLitVector(&This->singletons, singleIndex); - This->clauses.capacity = newCapacity; - This->clauses.array = mergeArray; - This->clauses.size = mergeIndex; - if (destroy) - deleteCNFExpr(expr); -} - -void printCNFExpr(CNFExpr *This) { - for (uint i = 0; i < getSizeLitVector(&This->singletons); i++) { - if (i != 0) - printf(" ^ "); - Literal l = getLiteralLitVector(&This->singletons,i); - printf ("%d",l); - } - for (uint i = 0; i < getSizeVectorLitVector(&This->clauses); i++) { - LitVector *lv = getVectorLitVector(&This->clauses,i); - printf(" ^ ("); - for (uint j = 0; j < getSizeLitVector(lv); j++) { - if (j != 0) - printf(" v "); - printf("%d", getLiteralLitVector(lv, j)); - } - printf(")"); - } -} diff --git a/src/Backend/cnfexpr.cc b/src/Backend/cnfexpr.cc new file mode 100644 index 0000000..1aa6cf0 --- /dev/null +++ b/src/Backend/cnfexpr.cc @@ -0,0 +1,465 @@ +#include "cnfexpr.h" +#include +/* + V2 Copyright (c) 2014 Ben Chambers, Eugene Goldberg, Pete Manolios, + Vasilis Papavasileiou, Sudarshan Srinivasan, and Daron Vroon. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. If + you download or use the software, send email to Pete Manolios + (pete@ccs.neu.edu) with your name, contact information, and a short + note describing what you want to use BAT for. For any reuse or + distribution, you must make clear to others the license terms of this + work. + + Contact Pete Manolios if you want any of these conditions waived. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + C port of CNF SAT Conversion Copyright Brian Demsky 2017. + */ + +#define LITCAPACITY 4 +#define MERGESIZE 5 + +VectorImpl(LitVector, LitVector *, 4) + +static inline uint boundedSize(uint x) { return (x > MERGESIZE) ? MERGESIZE : x; } + +LitVector *allocLitVector() { + LitVector *This = (LitVector *)ourmalloc(sizeof(LitVector)); + initLitVector(This); + return This; +} + +void initLitVector(LitVector *This) { + This->size = 0; + This->capacity = LITCAPACITY; + This->literals = (Literal *)ourmalloc(This->capacity * sizeof(Literal)); +} + +LitVector *cloneLitVector(LitVector *orig) { + LitVector *This = (LitVector *)ourmalloc(sizeof(LitVector)); + This->size = orig->size; + This->capacity = orig->capacity; + This->literals = (Literal *)ourmalloc(This->capacity * sizeof(Literal)); + memcpy(This->literals, orig->literals, sizeof(Literal) * This->size); + return This; +} + +void clearLitVector(LitVector *This) { + This->size = 0; +} + +void freeLitVector(LitVector *This) { + ourfree(This->literals); +} + +void deleteLitVector(LitVector *This) { + freeLitVector(This); + ourfree(This); +} + +Literal getLiteralLitVector(LitVector *This, uint index) { + return This->literals[index]; +} + +void setLiteralLitVector(LitVector *This, uint index, Literal l) { + This->literals[index] = l; +} + +void addLiteralLitVector(LitVector *This, Literal l) { + Literal labs = abs(l); + uint vec_size = This->size; + uint searchsize = boundedSize(vec_size); + uint i = 0; + for (; i < searchsize; i++) { + Literal curr = This->literals[i]; + Literal currabs = abs(curr); + if (currabs > labs) + break; + if (currabs == labs) { + if (curr == -l) + This->size = 0; //either true or false now depending on whether this is a conj or disj + return; + } + } + if ((++This->size) >= This->capacity) { + This->capacity <<= 1; + This->literals = (Literal *) ourrealloc(This->literals, This->capacity * sizeof(Literal)); + } + + if (vec_size < MERGESIZE) { + memmove(&This->literals[i + 1], &This->literals[i], (vec_size - i) * sizeof(Literal)); + This->literals[i] = l; + } else { + This->literals[vec_size] = l; + } +} + +CNFExpr *allocCNFExprBool(bool isTrue) { + CNFExpr *This = (CNFExpr *)ourmalloc(sizeof(CNFExpr)); + This->litSize = 0; + This->isTrue = isTrue; + initVectorLitVector(&This->clauses, 2); + initLitVector(&This->singletons); + return This; +} + +CNFExpr *allocCNFExprLiteral(Literal l) { + CNFExpr *This = (CNFExpr *)ourmalloc(sizeof(CNFExpr)); + This->litSize = 1; + This->isTrue = false; + initVectorLitVector(&This->clauses, 2); + initLitVector(&This->singletons); + addLiteralLitVector(&This->singletons, l); + return This; +} + +void clearCNFExpr(CNFExpr *This, bool isTrue) { + for (uint i = 0; i < getSizeVectorLitVector(&This->clauses); i++) { + deleteLitVector(getVectorLitVector(&This->clauses, i)); + } + clearVectorLitVector(&This->clauses); + clearLitVector(&This->singletons); + This->litSize = 0; + This->isTrue = isTrue; +} + +void deleteCNFExpr(CNFExpr *This) { + for (uint i = 0; i < getSizeVectorLitVector(&This->clauses); i++) { + deleteLitVector(getVectorLitVector(&This->clauses, i)); + } + deleteVectorArrayLitVector(&This->clauses); + freeLitVector(&This->singletons); + ourfree(This); +} + +void conjoinCNFLit(CNFExpr *This, Literal l) { + if (This->litSize == 0 && !This->isTrue)//Handle False + return; + + This->litSize -= getSizeLitVector(&This->singletons); + addLiteralLitVector(&This->singletons, l); + uint newsize = getSizeLitVector(&This->singletons); + if (newsize == 0) + clearCNFExpr(This, false);//We found a conflict + else + This->litSize += getSizeLitVector(&This->singletons); +} + +void copyCNF(CNFExpr *This, CNFExpr *expr, bool destroy) { + if (destroy) { + ourfree(This->singletons.literals); + ourfree(This->clauses.array); + This->litSize = expr->litSize; + This->singletons.literals = expr->singletons.literals; + This->singletons.capacity = expr->singletons.capacity; + This->clauses.size = expr->clauses.size; + This->clauses.array = expr->clauses.array; + This->clauses.capacity = expr->clauses.capacity; + ourfree(expr); + } else { + for (uint i = 0; i < getSizeLitVector(&expr->singletons); i++) { + Literal l = getLiteralLitVector(&expr->singletons,i); + addLiteralLitVector(&This->singletons, l); + } + for (uint i = 0; i < getSizeVectorLitVector(&expr->clauses); i++) { + LitVector *lv = getVectorLitVector(&expr->clauses,i); + pushVectorLitVector(&This->clauses, cloneLitVector(lv)); + } + This->litSize = expr->litSize; + } +} + +void conjoinCNFExpr(CNFExpr *This, CNFExpr *expr, bool destroy) { + if (expr->litSize == 0) { + if (!This->isTrue) { + clearCNFExpr(This, false); + } + if (destroy) { + deleteCNFExpr(expr); + } + return; + } + if (This->litSize == 0) { + if (This->isTrue) { + copyCNF(This, expr, destroy); + } else if (destroy) { + deleteCNFExpr(expr); + } + return; + } + uint litSize = This->litSize; + litSize -= getSizeLitVector(&expr->singletons); + for (uint i = 0; i < getSizeLitVector(&expr->singletons); i++) { + Literal l = getLiteralLitVector(&expr->singletons,i); + addLiteralLitVector(&This->singletons, l); + if (getSizeLitVector(&This->singletons) == 0) { + //Found conflict... + clearCNFExpr(This, false); + if (destroy) { + deleteCNFExpr(expr); + } + return; + } + } + litSize += getSizeLitVector(&expr->singletons); + if (destroy) { + for (uint i = 0; i < getSizeVectorLitVector(&expr->clauses); i++) { + LitVector *lv = getVectorLitVector(&expr->clauses,i); + litSize += getSizeLitVector(lv); + pushVectorLitVector(&This->clauses, lv); + } + clearVectorLitVector(&expr->clauses); + deleteCNFExpr(expr); + } else { + for (uint i = 0; i < getSizeVectorLitVector(&expr->clauses); i++) { + LitVector *lv = getVectorLitVector(&expr->clauses,i); + litSize += getSizeLitVector(lv); + pushVectorLitVector(&This->clauses, cloneLitVector(lv)); + } + } + This->litSize = litSize; +} + +void disjoinCNFLit(CNFExpr *This, Literal l) { + if (This->litSize == 0) { + if (!This->isTrue) { + This->litSize++; + addLiteralLitVector(&This->singletons, l); + } + return; + } + + uint litSize = 0; + uint newindex = 0; + for (uint i = 0; i < getSizeVectorLitVector(&This->clauses); i++) { + LitVector *lv = getVectorLitVector(&This->clauses, i); + addLiteralLitVector(lv, l); + uint newSize = getSizeLitVector(lv); + if (newSize != 0) { + setVectorLitVector(&This->clauses, newindex++, lv); + } else { + deleteLitVector(lv); + } + litSize += newSize; + } + setSizeVectorLitVector(&This->clauses, newindex); + + bool hasSameSingleton = false; + for (uint i = 0; i < getSizeLitVector(&This->singletons); i++) { + Literal lsing = getLiteralLitVector(&This->singletons, i); + if (lsing == l) { + hasSameSingleton = true; + } else if (lsing != -l) { + //Create new LitVector with both l and lsing + LitVector *newlitvec = allocLitVector(); + addLiteralLitVector(newlitvec, l); + addLiteralLitVector(newlitvec, lsing); + litSize += 2; + pushVectorLitVector(&This->clauses, newlitvec); + } + } + clearLitVector(&This->singletons); + if (hasSameSingleton) { + addLiteralLitVector(&This->singletons, l); + litSize++; + } else if (litSize == 0) { + This->isTrue = true;//we are true + } + This->litSize = litSize; +} + +#define MERGETHRESHOLD 2 +LitVector *mergeLitVectors(LitVector *This, LitVector *expr) { + uint maxsize = This->size + expr->size + MERGETHRESHOLD; + LitVector *merged = (LitVector *)ourmalloc(sizeof(LitVector)); + merged->literals = (Literal *)ourmalloc(sizeof(Literal) * maxsize); + merged->capacity = maxsize; + uint thisSize = boundedSize(This->size); + uint exprSize = boundedSize(expr->size); + uint iThis = 0, iExpr = 0, iMerge = 0; + Literal lThis = This->literals[iThis]; + Literal lExpr = expr->literals[iExpr]; + Literal thisAbs = abs(lThis); + Literal exprAbs = abs(lExpr); + + while (iThis < thisSize && iExpr < exprSize) { + if (thisAbs < exprAbs) { + merged->literals[iMerge++] = lThis; + lThis = This->literals[++iThis]; + thisAbs = abs(lThis); + } else if (thisAbs > exprAbs) { + merged->literals[iMerge++] = lExpr; + lExpr = expr->literals[++iExpr]; + exprAbs = abs(lExpr); + } else if (lThis == lExpr) { + merged->literals[iMerge++] = lExpr; + lExpr = expr->literals[++iExpr]; + exprAbs = abs(lExpr); + lThis = This->literals[++iThis]; + thisAbs = abs(lThis); + } else if (lThis == -lExpr) { + merged->size = 0; + return merged; + } + } + if (iThis < thisSize) { + memcpy(&merged->literals[iMerge], &This->literals[iThis], (thisSize - iThis) * sizeof(Literal)); + iMerge += (thisSize - iThis); + } + if (iExpr < exprSize) { + memcpy(&merged->literals[iMerge], &expr->literals[iExpr], (exprSize - iExpr) * sizeof(Literal)); + iMerge += (exprSize - iExpr); + } + merged->size = iMerge; + return merged; +} + +LitVector *mergeLitVectorLiteral(LitVector *This, Literal l) { + LitVector *copy = cloneLitVector(This); + addLiteralLitVector(copy, l); + return copy; +} + +void disjoinCNFExpr(CNFExpr *This, CNFExpr *expr, bool destroy) { + /** Handle the special cases */ + if (expr->litSize == 0) { + if (expr->isTrue) { + clearCNFExpr(This, true); + } + if (destroy) { + deleteCNFExpr(expr); + } + return; + } else if (This->litSize == 0) { + if (!This->isTrue) { + copyCNF(This, expr, destroy); + } else if (destroy) { + deleteCNFExpr(expr); + } + return; + } else if (expr->litSize == 1) { + disjoinCNFLit(This, getLiteralLitVector(&expr->singletons,0)); + if (destroy) { + deleteCNFExpr(expr); + } + return; + } else if (destroy && This->litSize == 1) { + Literal l = getLiteralLitVector(&This->singletons,0); + copyCNF(This, expr, true); + disjoinCNFLit(This, l); + return; + } + + /** Handle the full cross product */ + uint mergeIndex = 0; + uint newCapacity = getClauseSizeCNF(This) * getClauseSizeCNF(expr); + LitVector **mergeArray = (LitVector **)ourmalloc(newCapacity * sizeof(LitVector *)); + uint singleIndex = 0; + /** First do the singleton, clause pairs */ + for (uint i = 0; i < getSizeLitVector(&This->singletons); i++) { + Literal lThis = getLiteralLitVector(&This->singletons, i); + for (uint j = 0; j < getSizeVectorLitVector(&expr->clauses); j++) { + LitVector *lExpr = getVectorLitVector(&expr->clauses, j); + LitVector *copy = cloneLitVector(lExpr); + addLiteralLitVector(copy, lThis); + if (getSizeLitVector(copy) == 0) { + deleteLitVector(copy); + } else { + mergeArray[mergeIndex++] = copy; + } + } + } + + /** Next do the clause, singleton pairs */ + for (uint i = 0; i < getSizeLitVector(&expr->singletons); i++) { + Literal lExpr = getLiteralLitVector(&expr->singletons, i); + for (uint j = 0; j < getSizeVectorLitVector(&This->clauses); j++) { + LitVector *lThis = getVectorLitVector(&This->clauses, j); + LitVector *copy = cloneLitVector(lThis); + addLiteralLitVector(copy, lExpr); + if (getSizeLitVector(copy) == 0) { + deleteLitVector(copy); + } else { + mergeArray[mergeIndex++] = copy; + } + } + } + + /** Next do the clause, clause pairs */ + for (uint i = 0; i < getSizeVectorLitVector(&This->clauses); i++) { + LitVector *lThis = getVectorLitVector(&This->clauses, i); + for (uint j = 0; j < getSizeVectorLitVector(&expr->clauses); j++) { + LitVector *lExpr = getVectorLitVector(&expr->clauses, j); + LitVector *merge = mergeLitVectors(lThis, lExpr); + if (getSizeLitVector(merge) == 0) { + deleteLitVector(merge); + } else { + mergeArray[mergeIndex++] = merge; + } + } + deleteLitVector(lThis);//Done with this litVector + } + + /** Finally do the singleton, singleton pairs */ + for (uint i = 0; i < getSizeLitVector(&This->singletons); i++) { + Literal lThis = getLiteralLitVector(&This->singletons, i); + for (uint j = 0; j < getSizeLitVector(&expr->singletons); j++) { + Literal lExpr = getLiteralLitVector(&expr->singletons, j); + if (lThis == lExpr) { + //We have a singleton still in the final result + setLiteralLitVector(&This->singletons, singleIndex++, lThis); + } else if (lThis != -lExpr) { + LitVector *mergeLV = allocLitVector(); + addLiteralLitVector(mergeLV, lThis); + addLiteralLitVector(mergeLV, lExpr); + mergeArray[mergeIndex++] = mergeLV; + } + } + } + + ourfree(This->clauses.array); + setSizeLitVector(&This->singletons, singleIndex); + This->clauses.capacity = newCapacity; + This->clauses.array = mergeArray; + This->clauses.size = mergeIndex; + if (destroy) + deleteCNFExpr(expr); +} + +void printCNFExpr(CNFExpr *This) { + for (uint i = 0; i < getSizeLitVector(&This->singletons); i++) { + if (i != 0) + printf(" ^ "); + Literal l = getLiteralLitVector(&This->singletons,i); + printf ("%d",l); + } + for (uint i = 0; i < getSizeVectorLitVector(&This->clauses); i++) { + LitVector *lv = getVectorLitVector(&This->clauses,i); + printf(" ^ ("); + for (uint j = 0; j < getSizeLitVector(lv); j++) { + if (j != 0) + printf(" v "); + printf("%d", getLiteralLitVector(lv, j)); + } + printf(")"); + } +} diff --git a/src/Backend/constraint.c b/src/Backend/constraint.c deleted file mode 100644 index c7cac98..0000000 --- a/src/Backend/constraint.c +++ /dev/null @@ -1,906 +0,0 @@ -#include "constraint.h" -#include -#include -#include "inc_solver.h" -#include "cnfexpr.h" -#include "common.h" -/* - V2 Copyright (c) 2014 Ben Chambers, Eugene Goldberg, Pete Manolios, - Vasilis Papavasileiou, Sudarshan Srinivasan, and Daron Vroon. - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. If - you download or use the software, send email to Pete Manolios - (pete@ccs.neu.edu) with your name, contact information, and a short - note describing what you want to use BAT for. For any reuse or - distribution, you must make clear to others the license terms of this - work. - - Contact Pete Manolios if you want any of these conditions waived. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - C port of CNF SAT Conversion Copyright Brian Demsky 2017. - */ - - -VectorImpl(Edge, Edge, 16) -Edge E_True = {(Node *)(uintptr_t) EDGE_IS_VAR_CONSTANT}; -Edge E_False = {(Node *)(uintptr_t) (EDGE_IS_VAR_CONSTANT | NEGATE_EDGE)}; -Edge E_BOGUS = {(Node *)0x12345673}; -Edge E_NULL = {(Node *)NULL}; - - -CNF *createCNF() { - CNF *cnf = ourmalloc(sizeof(CNF)); - cnf->varcount = 1; - cnf->capacity = DEFAULT_CNF_ARRAY_SIZE; - cnf->mask = cnf->capacity - 1; - cnf->node_array = ourcalloc(1, sizeof(Node *) * cnf->capacity); - cnf->size = 0; - cnf->maxsize = (uint)(((double)cnf->capacity) * LOAD_FACTOR); - cnf->enableMatching = true; - initDefVectorEdge(&cnf->constraints); - initDefVectorEdge(&cnf->args); - cnf->solver = allocIncrementalSolver(); - return cnf; -} - -void deleteCNF(CNF *cnf) { - for (uint i = 0; i < cnf->capacity; i++) { - Node *n = cnf->node_array[i]; - if (n != NULL) - ourfree(n); - } - deleteVectorArrayEdge(&cnf->constraints); - deleteVectorArrayEdge(&cnf->args); - deleteIncrementalSolver(cnf->solver); - ourfree(cnf->node_array); - ourfree(cnf); -} - -void resizeCNF(CNF *cnf, uint newCapacity) { - Node **old_array = cnf->node_array; - Node **new_array = ourcalloc(1, sizeof(Node *) * newCapacity); - uint oldCapacity = cnf->capacity; - uint newMask = newCapacity - 1; - for (uint i = 0; i < oldCapacity; i++) { - Node *n = old_array[i]; - uint hashCode = n->hashCode; - uint newindex = hashCode & newMask; - for (;; newindex = (newindex + 1) & newMask) { - if (new_array[newindex] == NULL) { - new_array[newindex] = n; - break; - } - } - } - ourfree(old_array); - cnf->node_array = new_array; - cnf->capacity = newCapacity; - cnf->maxsize = (uint)(((double)cnf->capacity) * LOAD_FACTOR); - cnf->mask = newMask; -} - -Node *allocNode(NodeType type, uint numEdges, Edge *edges, uint hashcode) { - Node *n = (Node *)ourmalloc(sizeof(Node) + sizeof(Edge) * numEdges); - memcpy(n->edges, edges, sizeof(Edge) * numEdges); - n->flags.type = type; - n->flags.wasExpanded = 0; - n->flags.cnfVisitedDown = 0; - n->flags.cnfVisitedUp = 0; - n->flags.varForced = 0; - n->numEdges = numEdges; - n->hashCode = hashcode; - n->intAnnot[0] = 0;n->intAnnot[1] = 0; - n->ptrAnnot[0] = NULL;n->ptrAnnot[1] = NULL; - return n; -} - -Edge createNode(CNF *cnf, NodeType type, uint numEdges, Edge *edges) { - if (cnf->size > cnf->maxsize) { - resizeCNF(cnf, cnf->capacity << 1); - } - uint hashvalue = hashNode(type, numEdges, edges); - uint mask = cnf->mask; - uint index = hashvalue & mask; - Node **n_ptr; - for (;; index = (index + 1) & mask) { - n_ptr = &cnf->node_array[index]; - if (*n_ptr != NULL) { - if ((*n_ptr)->hashCode == hashvalue) { - if (compareNodes(*n_ptr, type, numEdges, edges)) { - Edge e = {*n_ptr}; - return e; - } - } - } else { - break; - } - } - *n_ptr = allocNode(type, numEdges, edges, hashvalue); - Edge e = {*n_ptr}; - return e; -} - -uint hashNode(NodeType type, uint numEdges, Edge *edges) { - uint hashvalue = type ^ numEdges; - for (uint i = 0; i < numEdges; i++) { - hashvalue ^= (uint) ((uintptr_t) edges[i].node_ptr); - hashvalue = (hashvalue << 3) | (hashvalue >> 29); //rotate left by 3 bits - } - return (uint) hashvalue; -} - -bool compareNodes(Node *node, NodeType type, uint numEdges, Edge *edges) { - if (node->flags.type != type || node->numEdges != numEdges) - return false; - Edge *nodeedges = node->edges; - for (uint i = 0; i < numEdges; i++) { - if (!equalsEdge(nodeedges[i], edges[i])) - return false; - } - return true; -} - -Edge constraintOR(CNF *cnf, uint numEdges, Edge *edges) { - Edge edgearray[numEdges]; - - for (uint i = 0; i < numEdges; i++) { - edgearray[i] = constraintNegate(edges[i]); - } - Edge eand = constraintAND(cnf, numEdges, edgearray); - return constraintNegate(eand); -} - -Edge constraintOR2(CNF *cnf, Edge left, Edge right) { - Edge lneg = constraintNegate(left); - Edge rneg = constraintNegate(right); - Edge eand = constraintAND2(cnf, lneg, rneg); - return constraintNegate(eand); -} - -int comparefunction(const Edge *e1, const Edge *e2) { - return ((uintptr_t)e1->node_ptr) - ((uintptr_t)e2->node_ptr); -} - -Edge constraintAND(CNF *cnf, uint numEdges, Edge *edges) { - ASSERT(numEdges != 0); - qsort(edges, numEdges, sizeof(Edge), (int (*)(const void *, const void *))comparefunction); - int initindex = 0; - while (initindex < numEdges && equalsEdge(edges[initindex], E_True)) - initindex++; - - uint remainSize = numEdges - initindex; - - if (remainSize == 0) - return E_True; - else if (remainSize == 1) - return edges[initindex]; - else if (equalsEdge(edges[initindex], E_False)) - return E_False; - - /** De-duplicate array */ - uint lowindex = 0; - edges[lowindex] = edges[initindex++]; - - for (; initindex < numEdges; initindex++) { - Edge e1 = edges[lowindex]; - Edge e2 = edges[initindex]; - if (sameNodeVarEdge(e1, e2)) { - if (!sameSignEdge(e1, e2)) { - return E_False; - } - } else - edges[++lowindex] = edges[initindex]; - } - lowindex++; //Make lowindex look like size - - if (lowindex == 1) - return edges[0]; - - if (cnf->enableMatching && lowindex == 2 && - isNegNodeEdge(edges[0]) && isNegNodeEdge(edges[1]) && - getNodeType(edges[0]) == NodeType_AND && - getNodeType(edges[1]) == NodeType_AND && - getNodeSize(edges[0]) == 2 && - getNodeSize(edges[1]) == 2) { - Edge *e0edges = getEdgeArray(edges[0]); - Edge *e1edges = getEdgeArray(edges[1]); - if (sameNodeOppSign(e0edges[0], e1edges[0])) { - return constraintNegate(constraintITE(cnf, e0edges[0], e0edges[1], e1edges[1])); - } else if (sameNodeOppSign(e0edges[0], e1edges[1])) { - return constraintNegate(constraintITE(cnf, e0edges[0], e0edges[1], e1edges[0])); - } else if (sameNodeOppSign(e0edges[1], e1edges[0])) { - return constraintNegate(constraintITE(cnf, e0edges[1], e0edges[0], e1edges[1])); - } else if (sameNodeOppSign(e0edges[1], e1edges[1])) { - return constraintNegate(constraintITE(cnf, e0edges[1], e0edges[0], e1edges[0])); - } - } - - return createNode(cnf, NodeType_AND, lowindex, edges); -} - -Edge constraintAND2(CNF *cnf, Edge left, Edge right) { - Edge edges[2] = {left, right}; - return constraintAND(cnf, 2, edges); -} - -Edge constraintIMPLIES(CNF *cnf, Edge left, Edge right) { - Edge array[2]; - array[0] = left; - array[1] = constraintNegate(right); - Edge eand = constraintAND(cnf, 2, array); - return constraintNegate(eand); -} - -Edge constraintIFF(CNF *cnf, Edge left, Edge right) { - bool negate = !sameSignEdge(left, right); - Edge lpos = getNonNeg(left); - Edge rpos = getNonNeg(right); - - Edge e; - if (equalsEdge(lpos, rpos)) { - e = E_True; - } else if (ltEdge(lpos, rpos)) { - Edge edges[] = {lpos, rpos}; - e = (edgeIsConst(lpos)) ? rpos : createNode(cnf, NodeType_IFF, 2, edges); - } else { - Edge edges[] = {rpos, lpos}; - e = (edgeIsConst(rpos)) ? lpos : createNode(cnf, NodeType_IFF, 2, edges); - } - if (negate) - e = constraintNegate(e); - return e; -} - -Edge constraintITE(CNF *cnf, Edge cond, Edge thenedge, Edge elseedge) { - if (isNegEdge(cond)) { - cond = constraintNegate(cond); - Edge tmp = thenedge; - thenedge = elseedge; - elseedge = tmp; - } - - bool negate = isNegEdge(thenedge); - if (negate) { - thenedge = constraintNegate(thenedge); - elseedge = constraintNegate(elseedge); - } - - Edge result; - if (equalsEdge(cond, E_True)) { - result = thenedge; - } else if (equalsEdge(thenedge, E_True) || equalsEdge(cond, thenedge)) { - result = constraintOR(cnf, 2, (Edge[]) {cond, elseedge}); - } else if (equalsEdge(elseedge, E_True) || sameNodeOppSign(cond, elseedge)) { - result = constraintIMPLIES(cnf, cond, thenedge); - } else if (equalsEdge(thenedge, E_False) || equalsEdge(cond, elseedge)) { - result = constraintAND(cnf, 2, (Edge[]) {cond, thenedge}); - } else if (equalsEdge(thenedge, elseedge)) { - result = thenedge; - } else if (sameNodeOppSign(thenedge, elseedge)) { - if (ltEdge(cond, thenedge)) { - result = createNode(cnf, NodeType_IFF, 2, (Edge[]) {cond, thenedge}); - } else { - result = createNode(cnf, NodeType_IFF, 2, (Edge[]) {thenedge, cond}); - } - } else { - Edge edges[] = {cond, thenedge, elseedge}; - result = createNode(cnf, NodeType_ITE, 3, edges); - } - if (negate) - result = constraintNegate(result); - return result; -} - -void addConstraintCNF(CNF *cnf, Edge constraint) { - pushVectorEdge(&cnf->constraints, constraint); - model_print("****ADDING NEW Constraint*****\n"); - printCNF(constraint); - model_print("\n******************************\n"); -} - -Edge constraintNewVar(CNF *cnf) { - uint varnum = cnf->varcount++; - Edge e = {(Node *) ((((uintptr_t)varnum) << VAR_SHIFT) | EDGE_IS_VAR_CONSTANT) }; - return e; -} - -int solveCNF(CNF *cnf) { - countPass(cnf); - convertPass(cnf, false); - finishedClauses(cnf->solver); - return solve(cnf->solver); -} - -bool getValueCNF(CNF *cnf, Edge var) { - Literal l = getEdgeVar(var); - bool isneg = (l < 0); - l = abs(l); - return isneg ^ getValueSolver(cnf->solver, l); -} - -void countPass(CNF *cnf) { - uint numConstraints = getSizeVectorEdge(&cnf->constraints); - VectorEdge *ve = allocDefVectorEdge(); - for (uint i = 0; i < numConstraints; i++) { - countConstraint(cnf, ve, getVectorEdge(&cnf->constraints, i)); - } - deleteVectorEdge(ve); -} - -void countConstraint(CNF *cnf, VectorEdge *stack, Edge eroot) { - //Skip constants and variables... - if (edgeIsVarConst(eroot)) - return; - - clearVectorEdge(stack);pushVectorEdge(stack, eroot); - - bool isMatching = cnf->enableMatching; - - while (getSizeVectorEdge(stack) != 0) { - Edge e = lastVectorEdge(stack); popVectorEdge(stack); - bool polarity = isNegEdge(e); - Node *n = getNodePtrFromEdge(e); - if (getExpanded(n, polarity)) { - if (n->flags.type == NodeType_IFF || - n->flags.type == NodeType_ITE) { - Edge pExp = {n->ptrAnnot[polarity]}; - getNodePtrFromEdge(pExp)->intAnnot[0]++; - } else { - n->intAnnot[polarity]++; - } - } else { - setExpanded(n, polarity); - - if (n->flags.type == NodeType_ITE || - n->flags.type == NodeType_IFF) { - n->intAnnot[polarity] = 0; - Edge cond = n->edges[0]; - Edge thenedge = n->edges[1]; - Edge elseedge = n->flags.type == NodeType_IFF ? constraintNegate(thenedge) : n->edges[2]; - thenedge = constraintNegateIf(thenedge, !polarity); - elseedge = constraintNegateIf(elseedge, !polarity); - thenedge = constraintAND2(cnf, cond, thenedge); - cond = constraintNegate(cond); - elseedge = constraintAND2(cnf, cond, elseedge); - thenedge = constraintNegate(thenedge); - elseedge = constraintNegate(elseedge); - cnf->enableMatching = false; - Edge succ1 = constraintAND2(cnf, thenedge, elseedge); - n->ptrAnnot[polarity] = succ1.node_ptr; - cnf->enableMatching = isMatching; - pushVectorEdge(stack, succ1); - if (getExpanded(n, !polarity)) { - Edge succ2 = {(Node *)n->ptrAnnot[!polarity]}; - Node *n1 = getNodePtrFromEdge(succ1); - Node *n2 = getNodePtrFromEdge(succ2); - n1->ptrAnnot[0] = succ2.node_ptr; - n2->ptrAnnot[0] = succ1.node_ptr; - n1->ptrAnnot[1] = succ2.node_ptr; - n2->ptrAnnot[1] = succ1.node_ptr; - } - } else { - n->intAnnot[polarity] = 1; - for (uint i = 0; i < n->numEdges; i++) { - Edge succ = n->edges[i]; - if (!edgeIsVarConst(succ)) { - succ = constraintNegateIf(succ, polarity); - pushVectorEdge(stack, succ); - } - } - } - } - } -} - -void convertPass(CNF *cnf, bool backtrackLit) { - uint numConstraints = getSizeVectorEdge(&cnf->constraints); - VectorEdge *ve = allocDefVectorEdge(); - for (uint i = 0; i < numConstraints; i++) { - convertConstraint(cnf, ve, getVectorEdge(&cnf->constraints, i), backtrackLit); - } - deleteVectorEdge(ve); -} - -void convertConstraint(CNF *cnf, VectorEdge *stack, Edge root, bool backtrackLit) { - Node *nroot = getNodePtrFromEdge(root); - - if (isNodeEdge(root) && (nroot->flags.type == NodeType_ITE || nroot->flags.type == NodeType_IFF)) { - nroot = (Node *) nroot->ptrAnnot[isNegEdge(root)]; - root = (Edge) { nroot }; - } - if (edgeIsConst(root)) { - if (isNegEdge(root)) { - //trivally unsat - Edge newvar = constraintNewVar(cnf); - Literal var = getEdgeVar(newvar); - Literal clause[] = {var}; - addArrayClauseLiteral(cnf->solver, 1, clause); - clause[0] = -var; - addArrayClauseLiteral(cnf->solver, 1, clause); - return; - } else { - //trivially true - return; - } - } else if (edgeIsVarConst(root)) { - Literal clause[] = { getEdgeVar(root)}; - addArrayClauseLiteral(cnf->solver, 1, clause); - return; - } - - clearVectorEdge(stack);pushVectorEdge(stack, root); - while (getSizeVectorEdge(stack) != 0) { - Edge e = lastVectorEdge(stack); - Node *n = getNodePtrFromEdge(e); - - if (edgeIsVarConst(e)) { - popVectorEdge(stack); - continue; - } else if (n->flags.type == NodeType_ITE || - n->flags.type == NodeType_IFF) { - popVectorEdge(stack); - if (n->ptrAnnot[0] != NULL) - pushVectorEdge(stack, (Edge) {(Node *)n->ptrAnnot[0]}); - if (n->ptrAnnot[1] != NULL) - pushVectorEdge(stack, (Edge) {(Node *)n->ptrAnnot[1]}); - continue; - } - - bool needPos = (n->intAnnot[0] > 0); - bool needNeg = (n->intAnnot[1] > 0); - if ((!needPos || n->flags.cnfVisitedUp & 1) && - (!needNeg || n->flags.cnfVisitedUp & 2)) { - popVectorEdge(stack); - } else if ((needPos && !(n->flags.cnfVisitedDown & 1)) || - (needNeg && !(n->flags.cnfVisitedDown & 2))) { - if (needPos) - n->flags.cnfVisitedDown |= 1; - if (needNeg) - n->flags.cnfVisitedDown |= 2; - for (uint i = 0; i < n->numEdges; i++) { - Edge arg = n->edges[i]; - arg = constraintNegateIf(arg, isNegEdge(e)); - pushVectorEdge(stack, arg); //WARNING, THIS LOOKS LIKE A BUG IN THE ORIGINAL CODE - } - } else { - popVectorEdge(stack); - produceCNF(cnf, e); - } - } - CNFExpr *cnfExp = (CNFExpr *) nroot->ptrAnnot[isNegEdge(root)]; - ASSERT(cnfExp != NULL); - if (isProxy(cnfExp)) { - Literal l = getProxy(cnfExp); - Literal clause[] = {l}; - addArrayClauseLiteral(cnf->solver, 1, clause); - } else if (backtrackLit) { - Literal l = introProxy(cnf, root, cnfExp, isNegEdge(root)); - Literal clause[] = {l}; - addArrayClauseLiteral(cnf->solver, 1, clause); - } else { - outputCNF(cnf, cnfExp); - } - - if (!((intptr_t) cnfExp & 1)) { - deleteCNFExpr(cnfExp); - nroot->ptrAnnot[isNegEdge(root)] = NULL; - } -} - - -Literal introProxy(CNF *cnf, Edge e, CNFExpr *exp, bool isNeg) { - Literal l = 0; - Node *n = getNodePtrFromEdge(e); - - if (n->flags.cnfVisitedUp & (1 << !isNeg)) { - CNFExpr *otherExp = (CNFExpr *) n->ptrAnnot[!isNeg]; - if (isProxy(otherExp)) - l = -getProxy(otherExp); - } else { - Edge semNeg = {(Node *) n->ptrAnnot[isNeg]}; - Node *nsemNeg = getNodePtrFromEdge(semNeg); - if (nsemNeg != NULL) { - if (nsemNeg->flags.cnfVisitedUp & (1 << isNeg)) { - CNFExpr *otherExp = (CNFExpr *) nsemNeg->ptrAnnot[isNeg]; - if (isProxy(otherExp)) - l = -getProxy(otherExp); - } else if (nsemNeg->flags.cnfVisitedUp & (1 << !isNeg)) { - CNFExpr *otherExp = (CNFExpr *) nsemNeg->ptrAnnot[!isNeg]; - if (isProxy(otherExp)) - l = getProxy(otherExp); - } - } - } - - if (l == 0) { - Edge newvar = constraintNewVar(cnf); - l = getEdgeVar(newvar); - } - // Output the constraints on the auxiliary variable - constrainCNF(cnf, l, exp); - deleteCNFExpr(exp); - - n->ptrAnnot[isNeg] = (void *) ((intptr_t) (l << 1) | 1); - - return l; -} - -void produceCNF(CNF *cnf, Edge e) { - CNFExpr *expPos = NULL; - CNFExpr *expNeg = NULL; - Node *n = getNodePtrFromEdge(e); - - if (n->intAnnot[0] > 0) { - expPos = produceConjunction(cnf, e); - } - - if (n->intAnnot[1] > 0) { - expNeg = produceDisjunction(cnf, e); - } - - /// @todo Propagate constants across semantic negations (this can - /// be done similarly to the calls to propagate shown below). The - /// trick here is that we need to figure out how to get the - /// semantic negation pointers, and ensure that they can have CNF - /// produced for them at the right point - /// - /// propagate(solver, expPos, snPos, false) || propagate(solver, expNeg, snNeg, false) - - // propagate from positive to negative, negative to positive - if (!propagate(cnf, &expPos, expNeg, true)) - propagate(cnf, &expNeg, expPos, true); - - // The polarity heuristic entails visiting the discovery polarity first - if (isPosEdge(e)) { - saveCNF(cnf, expPos, e, false); - saveCNF(cnf, expNeg, e, true); - } else { - saveCNF(cnf, expNeg, e, true); - saveCNF(cnf, expPos, e, false); - } -} - -bool propagate(CNF *cnf, CNFExpr **dest, CNFExpr *src, bool negate) { - if (src != NULL && !isProxy(src) && getLitSizeCNF(src) == 0) { - if (*dest == NULL) { - *dest = allocCNFExprBool(negate ? alwaysFalseCNF(src) : alwaysTrueCNF(src)); - } else if (isProxy(*dest)) { - bool alwaysTrue = (negate ? alwaysFalseCNF(src) : alwaysTrueCNF(src)); - if (alwaysTrue) { - Literal clause[] = {getProxy(*dest)}; - addArrayClauseLiteral(cnf->solver, 1, clause); - } else { - Literal clause[] = {-getProxy(*dest)}; - addArrayClauseLiteral(cnf->solver, 1, clause); - } - - *dest = allocCNFExprBool(negate ? alwaysFalseCNF(src) : alwaysTrueCNF(src)); - } else { - clearCNFExpr(*dest, negate ? alwaysFalseCNF(src) : alwaysTrueCNF(src)); - } - return true; - } - return false; -} - -void saveCNF(CNF *cnf, CNFExpr *exp, Edge e, bool sign) { - Node *n = getNodePtrFromEdge(e); - n->flags.cnfVisitedUp |= (1 << sign); - if (exp == NULL || isProxy(exp)) return; - - if (exp->litSize == 1) { - Literal l = getLiteralLitVector(&exp->singletons, 0); - deleteCNFExpr(exp); - n->ptrAnnot[sign] = (void *) ((((intptr_t) l) << 1) | 1); - } else if (exp->litSize != 0 && (n->intAnnot[sign] > 1 || n->flags.varForced)) { - introProxy(cnf, e, exp, sign); - } else { - n->ptrAnnot[sign] = exp; - } -} - -void constrainCNF(CNF *cnf, Literal lcond, CNFExpr *expr) { - if (alwaysTrueCNF(expr)) { - return; - } else if (alwaysFalseCNF(expr)) { - Literal clause[] = {-lcond}; - addArrayClauseLiteral(cnf->solver, 1, clause); - return; - } - - for (uint i = 0; i < getSizeLitVector(&expr->singletons); i++) { - Literal l = getLiteralLitVector(&expr->singletons,i); - Literal clause[] = {-lcond, l}; - addArrayClauseLiteral(cnf->solver, 2, clause); - } - for (uint i = 0; i < getSizeVectorLitVector(&expr->clauses); i++) { - LitVector *lv = getVectorLitVector(&expr->clauses,i); - addClauseLiteral(cnf->solver, -lcond);//Add first literal - addArrayClauseLiteral(cnf->solver, getSizeLitVector(lv), lv->literals); //Add rest - } -} - -void outputCNF(CNF *cnf, CNFExpr *expr) { - for (uint i = 0; i < getSizeLitVector(&expr->singletons); i++) { - Literal l = getLiteralLitVector(&expr->singletons,i); - Literal clause[] = {l}; - addArrayClauseLiteral(cnf->solver, 1, clause); - } - for (uint i = 0; i < getSizeVectorLitVector(&expr->clauses); i++) { - LitVector *lv = getVectorLitVector(&expr->clauses,i); - addArrayClauseLiteral(cnf->solver, getSizeLitVector(lv), lv->literals); - } -} - -CNFExpr *fillArgs(CNF *cnf, Edge e, bool isNeg, Edge *largestEdge) { - clearVectorEdge(&cnf->args); - - *largestEdge = (Edge) {(Node *) NULL}; - CNFExpr *largest = NULL; - Node *n = getNodePtrFromEdge(e); - int i = n->numEdges; - while (i != 0) { - Edge arg = n->edges[--i]; - arg = constraintNegateIf(arg, isNeg); - Node *narg = getNodePtrFromEdge(arg); - - if (edgeIsVarConst(arg)) { - pushVectorEdge(&cnf->args, arg); - continue; - } - - if (narg->flags.type == NodeType_ITE || narg->flags.type == NodeType_IFF) { - arg = (Edge) {(Node *) narg->ptrAnnot[isNegEdge(arg)]}; - } - - if (narg->intAnnot[isNegEdge(arg)] == 1) { - CNFExpr *argExp = (CNFExpr *) narg->ptrAnnot[isNegEdge(arg)]; - if (!isProxy(argExp)) { - if (largest == NULL) { - largest = argExp; - *largestEdge = arg; - continue; - } else if (argExp->litSize > largest->litSize) { - pushVectorEdge(&cnf->args, *largestEdge); - largest = argExp; - *largestEdge = arg; - continue; - } - } - } - pushVectorEdge(&cnf->args, arg); - } - - if (largest != NULL) { - Node *nlargestEdge = getNodePtrFromEdge(*largestEdge); - nlargestEdge->ptrAnnot[isNegEdge(*largestEdge)] = NULL; - } - - return largest; -} - -void printCNF(Edge e) { - if (edgeIsVarConst(e)) { - Literal l = getEdgeVar(e); - model_print ("%d", l); - return; - } - bool isNeg = isNegEdge(e); - if (edgeIsConst(e)) { - if (isNeg) - model_print("T"); - else - model_print("F"); - return; - } - Node *n = getNodePtrFromEdge(e); - if (isNeg) { - //Pretty print things that are equivalent to OR's - if (getNodeType(e) == NodeType_AND) { - model_print("or("); - for (uint i = 0; i < n->numEdges; i++) { - Edge e = n->edges[i]; - if (i != 0) - model_print(" "); - printCNF(constraintNegate(e)); - } - model_print(")"); - return; - } - - model_print("!"); - } - switch (getNodeType(e)) { - case NodeType_AND: - model_print("and"); - break; - case NodeType_ITE: - model_print("ite"); - break; - case NodeType_IFF: - model_print("iff"); - break; - } - model_print("("); - for (uint i = 0; i < n->numEdges; i++) { - Edge e = n->edges[i]; - if (i != 0) - model_print(" "); - printCNF(e); - } - model_print(")"); -} - -CNFExpr *produceConjunction(CNF *cnf, Edge e) { - Edge largestEdge; - - CNFExpr *accum = fillArgs(cnf, e, false, &largestEdge); - if (accum == NULL) - accum = allocCNFExprBool(true); - - int i = getSizeVectorEdge(&cnf->args); - while (i != 0) { - Edge arg = getVectorEdge(&cnf->args, --i); - if (edgeIsVarConst(arg)) { - conjoinCNFLit(accum, getEdgeVar(arg)); - } else { - Node *narg = getNodePtrFromEdge(arg); - CNFExpr *argExp = (CNFExpr *) narg->ptrAnnot[isNegEdge(arg)]; - - bool destroy = (--narg->intAnnot[isNegEdge(arg)] == 0); - if (isProxy(argExp)) {// variable has been introduced - conjoinCNFLit(accum, getProxy(argExp)); - } else { - conjoinCNFExpr(accum, argExp, destroy); - if (destroy) - narg->ptrAnnot[isNegEdge(arg)] = NULL; - } - } - } - - return accum; -} - -#define CLAUSE_MAX 3 - -CNFExpr *produceDisjunction(CNF *cnf, Edge e) { - Edge largestEdge; - CNFExpr *accum = fillArgs(cnf, e, true, &largestEdge); - if (accum == NULL) - accum = allocCNFExprBool(false); - - // This is necessary to check to make sure that we don't start out - // with an accumulator that is "too large". - - /// @todo Strictly speaking, introProxy doesn't *need* to free - /// memory, then this wouldn't have to reallocate CNFExpr - - /// @todo When this call to introProxy is made, the semantic - /// negation pointer will have been destroyed. Thus, it will not - /// be possible to use the correct proxy. That should be fixed. - - // at this point, we will either have NULL, or a destructible expression - if (getClauseSizeCNF(accum) > CLAUSE_MAX) - accum = allocCNFExprLiteral(introProxy(cnf, largestEdge, accum, isNegEdge(largestEdge))); - - int i = getSizeVectorEdge(&cnf->args); - while (i != 0) { - Edge arg = getVectorEdge(&cnf->args, --i); - Node *narg = getNodePtrFromEdge(arg); - if (edgeIsVarConst(arg)) { - disjoinCNFLit(accum, getEdgeVar(arg)); - } else { - CNFExpr *argExp = (CNFExpr *) narg->ptrAnnot[isNegEdge(arg)]; - - bool destroy = (--narg->intAnnot[isNegEdge(arg)] == 0); - if (isProxy(argExp)) {// variable has been introduced - disjoinCNFLit(accum, getProxy(argExp)); - } else if (argExp->litSize == 0) { - disjoinCNFExpr(accum, argExp, destroy); - } else { - // check to see if we should introduce a proxy - int aL = accum->litSize; // lits in accum - int eL = argExp->litSize; // lits in argument - int aC = getClauseSizeCNF(accum); // clauses in accum - int eC = getClauseSizeCNF(argExp); // clauses in argument - - if (eC > CLAUSE_MAX || (eL * aC + aL * eC > eL + aC + aL + aC)) { - disjoinCNFLit(accum, introProxy(cnf, arg, argExp, isNegEdge(arg))); - } else { - disjoinCNFExpr(accum, argExp, destroy); - if (destroy) narg->ptrAnnot[isNegEdge(arg)] = NULL; - } - } - } - } - - return accum; -} - -Edge generateBinaryConstraint(CNF *cnf, uint numvars, Edge *vars, uint value) { - Edge carray[numvars]; - for (uint j = 0; j < numvars; j++) { - carray[j] = ((value & 1) == 1) ? vars[j] : constraintNegate(vars[j]); - value = value >> 1; - } - - return constraintAND(cnf, numvars, carray); -} - -/** Generates a constraint to ensure that all encodings are less than value */ -Edge generateLTValueConstraint(CNF *cnf, uint numvars, Edge *vars, uint value) { - Edge orarray[numvars]; - Edge andarray[numvars]; - uint andi = 0; - - while (true) { - uint val = value; - uint ori = 0; - for (uint j = 0; j < numvars; j++) { - if ((val & 1) == 1) - orarray[ori++] = constraintNegate(vars[j]); - val = val >> 1; - } - //no ones to flip, so bail now... - if (ori == 0) { - return constraintAND(cnf, andi, andarray); - } - andarray[andi++] = constraintOR(cnf, ori, orarray); - - value = value + (1 << (__builtin_ctz(value))); - //flip the last one - } -} - -Edge generateEquivNVConstraint(CNF *cnf, uint numvars, Edge *var1, Edge *var2) { - if (numvars == 0) - return E_True; - Edge array[numvars]; - for (uint i = 0; i < numvars; i++) { - array[i] = constraintIFF(cnf, var1[i], var2[i]); - } - return constraintAND(cnf, numvars, array); -} - -Edge generateLTConstraint(CNF *cnf, uint numvars, Edge *var1, Edge *var2){ - if(numvars == 0 ) - return E_False; - Edge result =constraintAND2(cnf, constraintNegate( var1[0]), var2[0]); - for (uint i = 1; i < numvars; i++) { - Edge lt = constraintAND2(cnf, constraintNegate( var1[i]), var2[i]); - Edge eq = constraintAND2(cnf, constraintIFF(cnf, var1[i], var2[i]), result); - result = constraintOR2(cnf, lt, eq); - } - return result; -} - -Edge generateLTEConstraint(CNF *cnf, uint numvars, Edge *var1, Edge *var2){ - if(numvars == 0 ) - return E_True; - Edge result =constraintIMPLIES(cnf, var1[0], var2[0]); - for (uint i = 1; i < numvars; i++) { - Edge lt = constraintAND2(cnf, constraintNegate( var1[i]), var2[i]); - Edge eq = constraintAND2(cnf, constraintIFF(cnf, var1[i], var2[i]), result); - result = constraintOR2(cnf, lt, eq); - } - return result; -} diff --git a/src/Backend/constraint.cc b/src/Backend/constraint.cc new file mode 100644 index 0000000..a339988 --- /dev/null +++ b/src/Backend/constraint.cc @@ -0,0 +1,906 @@ +#include "constraint.h" +#include +#include +#include "inc_solver.h" +#include "cnfexpr.h" +#include "common.h" +/* + V2 Copyright (c) 2014 Ben Chambers, Eugene Goldberg, Pete Manolios, + Vasilis Papavasileiou, Sudarshan Srinivasan, and Daron Vroon. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. If + you download or use the software, send email to Pete Manolios + (pete@ccs.neu.edu) with your name, contact information, and a short + note describing what you want to use BAT for. For any reuse or + distribution, you must make clear to others the license terms of this + work. + + Contact Pete Manolios if you want any of these conditions waived. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + C port of CNF SAT Conversion Copyright Brian Demsky 2017. + */ + + +VectorImpl(Edge, Edge, 16) +Edge E_True = {(Node *)(uintptr_t) EDGE_IS_VAR_CONSTANT}; +Edge E_False = {(Node *)(uintptr_t) (EDGE_IS_VAR_CONSTANT | NEGATE_EDGE)}; +Edge E_BOGUS = {(Node *)0x12345673}; +Edge E_NULL = {(Node *)NULL}; + + +CNF *createCNF() { + CNF *cnf = (CNF *) ourmalloc(sizeof(CNF)); + cnf->varcount = 1; + cnf->capacity = DEFAULT_CNF_ARRAY_SIZE; + cnf->mask = cnf->capacity - 1; + cnf->node_array = (Node **) ourcalloc(1, sizeof(Node *) * cnf->capacity); + cnf->size = 0; + cnf->maxsize = (uint)(((double)cnf->capacity) * LOAD_FACTOR); + cnf->enableMatching = true; + initDefVectorEdge(&cnf->constraints); + initDefVectorEdge(&cnf->args); + cnf->solver = allocIncrementalSolver(); + return cnf; +} + +void deleteCNF(CNF *cnf) { + for (uint i = 0; i < cnf->capacity; i++) { + Node *n = cnf->node_array[i]; + if (n != NULL) + ourfree(n); + } + deleteVectorArrayEdge(&cnf->constraints); + deleteVectorArrayEdge(&cnf->args); + deleteIncrementalSolver(cnf->solver); + ourfree(cnf->node_array); + ourfree(cnf); +} + +void resizeCNF(CNF *cnf, uint newCapacity) { + Node **old_array = cnf->node_array; + Node **new_array = (Node **) ourcalloc(1, sizeof(Node *) * newCapacity); + uint oldCapacity = cnf->capacity; + uint newMask = newCapacity - 1; + for (uint i = 0; i < oldCapacity; i++) { + Node *n = old_array[i]; + uint hashCode = n->hashCode; + uint newindex = hashCode & newMask; + for (;; newindex = (newindex + 1) & newMask) { + if (new_array[newindex] == NULL) { + new_array[newindex] = n; + break; + } + } + } + ourfree(old_array); + cnf->node_array = new_array; + cnf->capacity = newCapacity; + cnf->maxsize = (uint)(((double)cnf->capacity) * LOAD_FACTOR); + cnf->mask = newMask; +} + +Node *allocNode(NodeType type, uint numEdges, Edge *edges, uint hashcode) { + Node *n = (Node *)ourmalloc(sizeof(Node) + sizeof(Edge) * numEdges); + memcpy(n->edges, edges, sizeof(Edge) * numEdges); + n->flags.type = type; + n->flags.wasExpanded = 0; + n->flags.cnfVisitedDown = 0; + n->flags.cnfVisitedUp = 0; + n->flags.varForced = 0; + n->numEdges = numEdges; + n->hashCode = hashcode; + n->intAnnot[0] = 0;n->intAnnot[1] = 0; + n->ptrAnnot[0] = NULL;n->ptrAnnot[1] = NULL; + return n; +} + +Edge createNode(CNF *cnf, NodeType type, uint numEdges, Edge *edges) { + if (cnf->size > cnf->maxsize) { + resizeCNF(cnf, cnf->capacity << 1); + } + uint hashvalue = hashNode(type, numEdges, edges); + uint mask = cnf->mask; + uint index = hashvalue & mask; + Node **n_ptr; + for (;; index = (index + 1) & mask) { + n_ptr = &cnf->node_array[index]; + if (*n_ptr != NULL) { + if ((*n_ptr)->hashCode == hashvalue) { + if (compareNodes(*n_ptr, type, numEdges, edges)) { + Edge e = {*n_ptr}; + return e; + } + } + } else { + break; + } + } + *n_ptr = allocNode(type, numEdges, edges, hashvalue); + Edge e = {*n_ptr}; + return e; +} + +uint hashNode(NodeType type, uint numEdges, Edge *edges) { + uint hashvalue = type ^ numEdges; + for (uint i = 0; i < numEdges; i++) { + hashvalue ^= (uint) ((uintptr_t) edges[i].node_ptr); + hashvalue = (hashvalue << 3) | (hashvalue >> 29); //rotate left by 3 bits + } + return (uint) hashvalue; +} + +bool compareNodes(Node *node, NodeType type, uint numEdges, Edge *edges) { + if (node->flags.type != type || node->numEdges != numEdges) + return false; + Edge *nodeedges = node->edges; + for (uint i = 0; i < numEdges; i++) { + if (!equalsEdge(nodeedges[i], edges[i])) + return false; + } + return true; +} + +Edge constraintOR(CNF *cnf, uint numEdges, Edge *edges) { + Edge edgearray[numEdges]; + + for (uint i = 0; i < numEdges; i++) { + edgearray[i] = constraintNegate(edges[i]); + } + Edge eand = constraintAND(cnf, numEdges, edgearray); + return constraintNegate(eand); +} + +Edge constraintOR2(CNF *cnf, Edge left, Edge right) { + Edge lneg = constraintNegate(left); + Edge rneg = constraintNegate(right); + Edge eand = constraintAND2(cnf, lneg, rneg); + return constraintNegate(eand); +} + +int comparefunction(const Edge *e1, const Edge *e2) { + return ((uintptr_t)e1->node_ptr) - ((uintptr_t)e2->node_ptr); +} + +Edge constraintAND(CNF *cnf, uint numEdges, Edge *edges) { + ASSERT(numEdges != 0); + qsort(edges, numEdges, sizeof(Edge), (int (*)(const void *, const void *))comparefunction); + int initindex = 0; + while (initindex < numEdges && equalsEdge(edges[initindex], E_True)) + initindex++; + + uint remainSize = numEdges - initindex; + + if (remainSize == 0) + return E_True; + else if (remainSize == 1) + return edges[initindex]; + else if (equalsEdge(edges[initindex], E_False)) + return E_False; + + /** De-duplicate array */ + uint lowindex = 0; + edges[lowindex] = edges[initindex++]; + + for (; initindex < numEdges; initindex++) { + Edge e1 = edges[lowindex]; + Edge e2 = edges[initindex]; + if (sameNodeVarEdge(e1, e2)) { + if (!sameSignEdge(e1, e2)) { + return E_False; + } + } else + edges[++lowindex] = edges[initindex]; + } + lowindex++; //Make lowindex look like size + + if (lowindex == 1) + return edges[0]; + + if (cnf->enableMatching && lowindex == 2 && + isNegNodeEdge(edges[0]) && isNegNodeEdge(edges[1]) && + getNodeType(edges[0]) == NodeType_AND && + getNodeType(edges[1]) == NodeType_AND && + getNodeSize(edges[0]) == 2 && + getNodeSize(edges[1]) == 2) { + Edge *e0edges = getEdgeArray(edges[0]); + Edge *e1edges = getEdgeArray(edges[1]); + if (sameNodeOppSign(e0edges[0], e1edges[0])) { + return constraintNegate(constraintITE(cnf, e0edges[0], e0edges[1], e1edges[1])); + } else if (sameNodeOppSign(e0edges[0], e1edges[1])) { + return constraintNegate(constraintITE(cnf, e0edges[0], e0edges[1], e1edges[0])); + } else if (sameNodeOppSign(e0edges[1], e1edges[0])) { + return constraintNegate(constraintITE(cnf, e0edges[1], e0edges[0], e1edges[1])); + } else if (sameNodeOppSign(e0edges[1], e1edges[1])) { + return constraintNegate(constraintITE(cnf, e0edges[1], e0edges[0], e1edges[0])); + } + } + + return createNode(cnf, NodeType_AND, lowindex, edges); +} + +Edge constraintAND2(CNF *cnf, Edge left, Edge right) { + Edge edges[2] = {left, right}; + return constraintAND(cnf, 2, edges); +} + +Edge constraintIMPLIES(CNF *cnf, Edge left, Edge right) { + Edge array[2]; + array[0] = left; + array[1] = constraintNegate(right); + Edge eand = constraintAND(cnf, 2, array); + return constraintNegate(eand); +} + +Edge constraintIFF(CNF *cnf, Edge left, Edge right) { + bool negate = !sameSignEdge(left, right); + Edge lpos = getNonNeg(left); + Edge rpos = getNonNeg(right); + + Edge e; + if (equalsEdge(lpos, rpos)) { + e = E_True; + } else if (ltEdge(lpos, rpos)) { + Edge edges[] = {lpos, rpos}; + e = (edgeIsConst(lpos)) ? rpos : createNode(cnf, NodeType_IFF, 2, edges); + } else { + Edge edges[] = {rpos, lpos}; + e = (edgeIsConst(rpos)) ? lpos : createNode(cnf, NodeType_IFF, 2, edges); + } + if (negate) + e = constraintNegate(e); + return e; +} + +Edge constraintITE(CNF *cnf, Edge cond, Edge thenedge, Edge elseedge) { + if (isNegEdge(cond)) { + cond = constraintNegate(cond); + Edge tmp = thenedge; + thenedge = elseedge; + elseedge = tmp; + } + + bool negate = isNegEdge(thenedge); + if (negate) { + thenedge = constraintNegate(thenedge); + elseedge = constraintNegate(elseedge); + } + + Edge result; + if (equalsEdge(cond, E_True)) { + result = thenedge; + } else if (equalsEdge(thenedge, E_True) || equalsEdge(cond, thenedge)) { + result = constraintOR(cnf, 2, (Edge[]) {cond, elseedge}); + } else if (equalsEdge(elseedge, E_True) || sameNodeOppSign(cond, elseedge)) { + result = constraintIMPLIES(cnf, cond, thenedge); + } else if (equalsEdge(thenedge, E_False) || equalsEdge(cond, elseedge)) { + result = constraintAND(cnf, 2, (Edge[]) {cond, thenedge}); + } else if (equalsEdge(thenedge, elseedge)) { + result = thenedge; + } else if (sameNodeOppSign(thenedge, elseedge)) { + if (ltEdge(cond, thenedge)) { + result = createNode(cnf, NodeType_IFF, 2, (Edge[]) {cond, thenedge}); + } else { + result = createNode(cnf, NodeType_IFF, 2, (Edge[]) {thenedge, cond}); + } + } else { + Edge edges[] = {cond, thenedge, elseedge}; + result = createNode(cnf, NodeType_ITE, 3, edges); + } + if (negate) + result = constraintNegate(result); + return result; +} + +void addConstraintCNF(CNF *cnf, Edge constraint) { + pushVectorEdge(&cnf->constraints, constraint); + model_print("****ADDING NEW Constraint*****\n"); + printCNF(constraint); + model_print("\n******************************\n"); +} + +Edge constraintNewVar(CNF *cnf) { + uint varnum = cnf->varcount++; + Edge e = {(Node *) ((((uintptr_t)varnum) << VAR_SHIFT) | EDGE_IS_VAR_CONSTANT) }; + return e; +} + +int solveCNF(CNF *cnf) { + countPass(cnf); + convertPass(cnf, false); + finishedClauses(cnf->solver); + return solve(cnf->solver); +} + +bool getValueCNF(CNF *cnf, Edge var) { + Literal l = getEdgeVar(var); + bool isneg = (l < 0); + l = abs(l); + return isneg ^ getValueSolver(cnf->solver, l); +} + +void countPass(CNF *cnf) { + uint numConstraints = getSizeVectorEdge(&cnf->constraints); + VectorEdge *ve = allocDefVectorEdge(); + for (uint i = 0; i < numConstraints; i++) { + countConstraint(cnf, ve, getVectorEdge(&cnf->constraints, i)); + } + deleteVectorEdge(ve); +} + +void countConstraint(CNF *cnf, VectorEdge *stack, Edge eroot) { + //Skip constants and variables... + if (edgeIsVarConst(eroot)) + return; + + clearVectorEdge(stack);pushVectorEdge(stack, eroot); + + bool isMatching = cnf->enableMatching; + + while (getSizeVectorEdge(stack) != 0) { + Edge e = lastVectorEdge(stack); popVectorEdge(stack); + bool polarity = isNegEdge(e); + Node *n = getNodePtrFromEdge(e); + if (getExpanded(n, polarity)) { + if (n->flags.type == NodeType_IFF || + n->flags.type == NodeType_ITE) { + Edge pExp = {(Node *)n->ptrAnnot[polarity]}; + getNodePtrFromEdge(pExp)->intAnnot[0]++; + } else { + n->intAnnot[polarity]++; + } + } else { + setExpanded(n, polarity); + + if (n->flags.type == NodeType_ITE || + n->flags.type == NodeType_IFF) { + n->intAnnot[polarity] = 0; + Edge cond = n->edges[0]; + Edge thenedge = n->edges[1]; + Edge elseedge = n->flags.type == NodeType_IFF ? constraintNegate(thenedge) : n->edges[2]; + thenedge = constraintNegateIf(thenedge, !polarity); + elseedge = constraintNegateIf(elseedge, !polarity); + thenedge = constraintAND2(cnf, cond, thenedge); + cond = constraintNegate(cond); + elseedge = constraintAND2(cnf, cond, elseedge); + thenedge = constraintNegate(thenedge); + elseedge = constraintNegate(elseedge); + cnf->enableMatching = false; + Edge succ1 = constraintAND2(cnf, thenedge, elseedge); + n->ptrAnnot[polarity] = succ1.node_ptr; + cnf->enableMatching = isMatching; + pushVectorEdge(stack, succ1); + if (getExpanded(n, !polarity)) { + Edge succ2 = {(Node *)n->ptrAnnot[!polarity]}; + Node *n1 = getNodePtrFromEdge(succ1); + Node *n2 = getNodePtrFromEdge(succ2); + n1->ptrAnnot[0] = succ2.node_ptr; + n2->ptrAnnot[0] = succ1.node_ptr; + n1->ptrAnnot[1] = succ2.node_ptr; + n2->ptrAnnot[1] = succ1.node_ptr; + } + } else { + n->intAnnot[polarity] = 1; + for (uint i = 0; i < n->numEdges; i++) { + Edge succ = n->edges[i]; + if (!edgeIsVarConst(succ)) { + succ = constraintNegateIf(succ, polarity); + pushVectorEdge(stack, succ); + } + } + } + } + } +} + +void convertPass(CNF *cnf, bool backtrackLit) { + uint numConstraints = getSizeVectorEdge(&cnf->constraints); + VectorEdge *ve = allocDefVectorEdge(); + for (uint i = 0; i < numConstraints; i++) { + convertConstraint(cnf, ve, getVectorEdge(&cnf->constraints, i), backtrackLit); + } + deleteVectorEdge(ve); +} + +void convertConstraint(CNF *cnf, VectorEdge *stack, Edge root, bool backtrackLit) { + Node *nroot = getNodePtrFromEdge(root); + + if (isNodeEdge(root) && (nroot->flags.type == NodeType_ITE || nroot->flags.type == NodeType_IFF)) { + nroot = (Node *) nroot->ptrAnnot[isNegEdge(root)]; + root = (Edge) { nroot }; + } + if (edgeIsConst(root)) { + if (isNegEdge(root)) { + //trivally unsat + Edge newvar = constraintNewVar(cnf); + Literal var = getEdgeVar(newvar); + Literal clause[] = {var}; + addArrayClauseLiteral(cnf->solver, 1, clause); + clause[0] = -var; + addArrayClauseLiteral(cnf->solver, 1, clause); + return; + } else { + //trivially true + return; + } + } else if (edgeIsVarConst(root)) { + Literal clause[] = { getEdgeVar(root)}; + addArrayClauseLiteral(cnf->solver, 1, clause); + return; + } + + clearVectorEdge(stack);pushVectorEdge(stack, root); + while (getSizeVectorEdge(stack) != 0) { + Edge e = lastVectorEdge(stack); + Node *n = getNodePtrFromEdge(e); + + if (edgeIsVarConst(e)) { + popVectorEdge(stack); + continue; + } else if (n->flags.type == NodeType_ITE || + n->flags.type == NodeType_IFF) { + popVectorEdge(stack); + if (n->ptrAnnot[0] != NULL) + pushVectorEdge(stack, (Edge) {(Node *)n->ptrAnnot[0]}); + if (n->ptrAnnot[1] != NULL) + pushVectorEdge(stack, (Edge) {(Node *)n->ptrAnnot[1]}); + continue; + } + + bool needPos = (n->intAnnot[0] > 0); + bool needNeg = (n->intAnnot[1] > 0); + if ((!needPos || n->flags.cnfVisitedUp & 1) && + (!needNeg || n->flags.cnfVisitedUp & 2)) { + popVectorEdge(stack); + } else if ((needPos && !(n->flags.cnfVisitedDown & 1)) || + (needNeg && !(n->flags.cnfVisitedDown & 2))) { + if (needPos) + n->flags.cnfVisitedDown |= 1; + if (needNeg) + n->flags.cnfVisitedDown |= 2; + for (uint i = 0; i < n->numEdges; i++) { + Edge arg = n->edges[i]; + arg = constraintNegateIf(arg, isNegEdge(e)); + pushVectorEdge(stack, arg); //WARNING, THIS LOOKS LIKE A BUG IN THE ORIGINAL CODE + } + } else { + popVectorEdge(stack); + produceCNF(cnf, e); + } + } + CNFExpr *cnfExp = (CNFExpr *) nroot->ptrAnnot[isNegEdge(root)]; + ASSERT(cnfExp != NULL); + if (isProxy(cnfExp)) { + Literal l = getProxy(cnfExp); + Literal clause[] = {l}; + addArrayClauseLiteral(cnf->solver, 1, clause); + } else if (backtrackLit) { + Literal l = introProxy(cnf, root, cnfExp, isNegEdge(root)); + Literal clause[] = {l}; + addArrayClauseLiteral(cnf->solver, 1, clause); + } else { + outputCNF(cnf, cnfExp); + } + + if (!((intptr_t) cnfExp & 1)) { + deleteCNFExpr(cnfExp); + nroot->ptrAnnot[isNegEdge(root)] = NULL; + } +} + + +Literal introProxy(CNF *cnf, Edge e, CNFExpr *exp, bool isNeg) { + Literal l = 0; + Node *n = getNodePtrFromEdge(e); + + if (n->flags.cnfVisitedUp & (1 << !isNeg)) { + CNFExpr *otherExp = (CNFExpr *) n->ptrAnnot[!isNeg]; + if (isProxy(otherExp)) + l = -getProxy(otherExp); + } else { + Edge semNeg = {(Node *) n->ptrAnnot[isNeg]}; + Node *nsemNeg = getNodePtrFromEdge(semNeg); + if (nsemNeg != NULL) { + if (nsemNeg->flags.cnfVisitedUp & (1 << isNeg)) { + CNFExpr *otherExp = (CNFExpr *) nsemNeg->ptrAnnot[isNeg]; + if (isProxy(otherExp)) + l = -getProxy(otherExp); + } else if (nsemNeg->flags.cnfVisitedUp & (1 << !isNeg)) { + CNFExpr *otherExp = (CNFExpr *) nsemNeg->ptrAnnot[!isNeg]; + if (isProxy(otherExp)) + l = getProxy(otherExp); + } + } + } + + if (l == 0) { + Edge newvar = constraintNewVar(cnf); + l = getEdgeVar(newvar); + } + // Output the constraints on the auxiliary variable + constrainCNF(cnf, l, exp); + deleteCNFExpr(exp); + + n->ptrAnnot[isNeg] = (void *) ((intptr_t) (l << 1) | 1); + + return l; +} + +void produceCNF(CNF *cnf, Edge e) { + CNFExpr *expPos = NULL; + CNFExpr *expNeg = NULL; + Node *n = getNodePtrFromEdge(e); + + if (n->intAnnot[0] > 0) { + expPos = produceConjunction(cnf, e); + } + + if (n->intAnnot[1] > 0) { + expNeg = produceDisjunction(cnf, e); + } + + /// @todo Propagate constants across semantic negations (this can + /// be done similarly to the calls to propagate shown below). The + /// trick here is that we need to figure out how to get the + /// semantic negation pointers, and ensure that they can have CNF + /// produced for them at the right point + /// + /// propagate(solver, expPos, snPos, false) || propagate(solver, expNeg, snNeg, false) + + // propagate from positive to negative, negative to positive + if (!propagate(cnf, &expPos, expNeg, true)) + propagate(cnf, &expNeg, expPos, true); + + // The polarity heuristic entails visiting the discovery polarity first + if (isPosEdge(e)) { + saveCNF(cnf, expPos, e, false); + saveCNF(cnf, expNeg, e, true); + } else { + saveCNF(cnf, expNeg, e, true); + saveCNF(cnf, expPos, e, false); + } +} + +bool propagate(CNF *cnf, CNFExpr **dest, CNFExpr *src, bool negate) { + if (src != NULL && !isProxy(src) && getLitSizeCNF(src) == 0) { + if (*dest == NULL) { + *dest = allocCNFExprBool(negate ? alwaysFalseCNF(src) : alwaysTrueCNF(src)); + } else if (isProxy(*dest)) { + bool alwaysTrue = (negate ? alwaysFalseCNF(src) : alwaysTrueCNF(src)); + if (alwaysTrue) { + Literal clause[] = {getProxy(*dest)}; + addArrayClauseLiteral(cnf->solver, 1, clause); + } else { + Literal clause[] = {-getProxy(*dest)}; + addArrayClauseLiteral(cnf->solver, 1, clause); + } + + *dest = allocCNFExprBool(negate ? alwaysFalseCNF(src) : alwaysTrueCNF(src)); + } else { + clearCNFExpr(*dest, negate ? alwaysFalseCNF(src) : alwaysTrueCNF(src)); + } + return true; + } + return false; +} + +void saveCNF(CNF *cnf, CNFExpr *exp, Edge e, bool sign) { + Node *n = getNodePtrFromEdge(e); + n->flags.cnfVisitedUp |= (1 << sign); + if (exp == NULL || isProxy(exp)) return; + + if (exp->litSize == 1) { + Literal l = getLiteralLitVector(&exp->singletons, 0); + deleteCNFExpr(exp); + n->ptrAnnot[sign] = (void *) ((((intptr_t) l) << 1) | 1); + } else if (exp->litSize != 0 && (n->intAnnot[sign] > 1 || n->flags.varForced)) { + introProxy(cnf, e, exp, sign); + } else { + n->ptrAnnot[sign] = exp; + } +} + +void constrainCNF(CNF *cnf, Literal lcond, CNFExpr *expr) { + if (alwaysTrueCNF(expr)) { + return; + } else if (alwaysFalseCNF(expr)) { + Literal clause[] = {-lcond}; + addArrayClauseLiteral(cnf->solver, 1, clause); + return; + } + + for (uint i = 0; i < getSizeLitVector(&expr->singletons); i++) { + Literal l = getLiteralLitVector(&expr->singletons,i); + Literal clause[] = {-lcond, l}; + addArrayClauseLiteral(cnf->solver, 2, clause); + } + for (uint i = 0; i < getSizeVectorLitVector(&expr->clauses); i++) { + LitVector *lv = getVectorLitVector(&expr->clauses,i); + addClauseLiteral(cnf->solver, -lcond);//Add first literal + addArrayClauseLiteral(cnf->solver, getSizeLitVector(lv), lv->literals); //Add rest + } +} + +void outputCNF(CNF *cnf, CNFExpr *expr) { + for (uint i = 0; i < getSizeLitVector(&expr->singletons); i++) { + Literal l = getLiteralLitVector(&expr->singletons,i); + Literal clause[] = {l}; + addArrayClauseLiteral(cnf->solver, 1, clause); + } + for (uint i = 0; i < getSizeVectorLitVector(&expr->clauses); i++) { + LitVector *lv = getVectorLitVector(&expr->clauses,i); + addArrayClauseLiteral(cnf->solver, getSizeLitVector(lv), lv->literals); + } +} + +CNFExpr *fillArgs(CNF *cnf, Edge e, bool isNeg, Edge *largestEdge) { + clearVectorEdge(&cnf->args); + + *largestEdge = (Edge) {(Node *) NULL}; + CNFExpr *largest = NULL; + Node *n = getNodePtrFromEdge(e); + int i = n->numEdges; + while (i != 0) { + Edge arg = n->edges[--i]; + arg = constraintNegateIf(arg, isNeg); + Node *narg = getNodePtrFromEdge(arg); + + if (edgeIsVarConst(arg)) { + pushVectorEdge(&cnf->args, arg); + continue; + } + + if (narg->flags.type == NodeType_ITE || narg->flags.type == NodeType_IFF) { + arg = (Edge) {(Node *) narg->ptrAnnot[isNegEdge(arg)]}; + } + + if (narg->intAnnot[isNegEdge(arg)] == 1) { + CNFExpr *argExp = (CNFExpr *) narg->ptrAnnot[isNegEdge(arg)]; + if (!isProxy(argExp)) { + if (largest == NULL) { + largest = argExp; + *largestEdge = arg; + continue; + } else if (argExp->litSize > largest->litSize) { + pushVectorEdge(&cnf->args, *largestEdge); + largest = argExp; + *largestEdge = arg; + continue; + } + } + } + pushVectorEdge(&cnf->args, arg); + } + + if (largest != NULL) { + Node *nlargestEdge = getNodePtrFromEdge(*largestEdge); + nlargestEdge->ptrAnnot[isNegEdge(*largestEdge)] = NULL; + } + + return largest; +} + +void printCNF(Edge e) { + if (edgeIsVarConst(e)) { + Literal l = getEdgeVar(e); + model_print ("%d", l); + return; + } + bool isNeg = isNegEdge(e); + if (edgeIsConst(e)) { + if (isNeg) + model_print("T"); + else + model_print("F"); + return; + } + Node *n = getNodePtrFromEdge(e); + if (isNeg) { + //Pretty print things that are equivalent to OR's + if (getNodeType(e) == NodeType_AND) { + model_print("or("); + for (uint i = 0; i < n->numEdges; i++) { + Edge e = n->edges[i]; + if (i != 0) + model_print(" "); + printCNF(constraintNegate(e)); + } + model_print(")"); + return; + } + + model_print("!"); + } + switch (getNodeType(e)) { + case NodeType_AND: + model_print("and"); + break; + case NodeType_ITE: + model_print("ite"); + break; + case NodeType_IFF: + model_print("iff"); + break; + } + model_print("("); + for (uint i = 0; i < n->numEdges; i++) { + Edge e = n->edges[i]; + if (i != 0) + model_print(" "); + printCNF(e); + } + model_print(")"); +} + +CNFExpr *produceConjunction(CNF *cnf, Edge e) { + Edge largestEdge; + + CNFExpr *accum = fillArgs(cnf, e, false, &largestEdge); + if (accum == NULL) + accum = allocCNFExprBool(true); + + int i = getSizeVectorEdge(&cnf->args); + while (i != 0) { + Edge arg = getVectorEdge(&cnf->args, --i); + if (edgeIsVarConst(arg)) { + conjoinCNFLit(accum, getEdgeVar(arg)); + } else { + Node *narg = getNodePtrFromEdge(arg); + CNFExpr *argExp = (CNFExpr *) narg->ptrAnnot[isNegEdge(arg)]; + + bool destroy = (--narg->intAnnot[isNegEdge(arg)] == 0); + if (isProxy(argExp)) {// variable has been introduced + conjoinCNFLit(accum, getProxy(argExp)); + } else { + conjoinCNFExpr(accum, argExp, destroy); + if (destroy) + narg->ptrAnnot[isNegEdge(arg)] = NULL; + } + } + } + + return accum; +} + +#define CLAUSE_MAX 3 + +CNFExpr *produceDisjunction(CNF *cnf, Edge e) { + Edge largestEdge; + CNFExpr *accum = fillArgs(cnf, e, true, &largestEdge); + if (accum == NULL) + accum = allocCNFExprBool(false); + + // This is necessary to check to make sure that we don't start out + // with an accumulator that is "too large". + + /// @todo Strictly speaking, introProxy doesn't *need* to free + /// memory, then this wouldn't have to reallocate CNFExpr + + /// @todo When this call to introProxy is made, the semantic + /// negation pointer will have been destroyed. Thus, it will not + /// be possible to use the correct proxy. That should be fixed. + + // at this point, we will either have NULL, or a destructible expression + if (getClauseSizeCNF(accum) > CLAUSE_MAX) + accum = allocCNFExprLiteral(introProxy(cnf, largestEdge, accum, isNegEdge(largestEdge))); + + int i = getSizeVectorEdge(&cnf->args); + while (i != 0) { + Edge arg = getVectorEdge(&cnf->args, --i); + Node *narg = getNodePtrFromEdge(arg); + if (edgeIsVarConst(arg)) { + disjoinCNFLit(accum, getEdgeVar(arg)); + } else { + CNFExpr *argExp = (CNFExpr *) narg->ptrAnnot[isNegEdge(arg)]; + + bool destroy = (--narg->intAnnot[isNegEdge(arg)] == 0); + if (isProxy(argExp)) {// variable has been introduced + disjoinCNFLit(accum, getProxy(argExp)); + } else if (argExp->litSize == 0) { + disjoinCNFExpr(accum, argExp, destroy); + } else { + // check to see if we should introduce a proxy + int aL = accum->litSize; // lits in accum + int eL = argExp->litSize; // lits in argument + int aC = getClauseSizeCNF(accum); // clauses in accum + int eC = getClauseSizeCNF(argExp); // clauses in argument + + if (eC > CLAUSE_MAX || (eL * aC + aL * eC > eL + aC + aL + aC)) { + disjoinCNFLit(accum, introProxy(cnf, arg, argExp, isNegEdge(arg))); + } else { + disjoinCNFExpr(accum, argExp, destroy); + if (destroy) narg->ptrAnnot[isNegEdge(arg)] = NULL; + } + } + } + } + + return accum; +} + +Edge generateBinaryConstraint(CNF *cnf, uint numvars, Edge *vars, uint value) { + Edge carray[numvars]; + for (uint j = 0; j < numvars; j++) { + carray[j] = ((value & 1) == 1) ? vars[j] : constraintNegate(vars[j]); + value = value >> 1; + } + + return constraintAND(cnf, numvars, carray); +} + +/** Generates a constraint to ensure that all encodings are less than value */ +Edge generateLTValueConstraint(CNF *cnf, uint numvars, Edge *vars, uint value) { + Edge orarray[numvars]; + Edge andarray[numvars]; + uint andi = 0; + + while (true) { + uint val = value; + uint ori = 0; + for (uint j = 0; j < numvars; j++) { + if ((val & 1) == 1) + orarray[ori++] = constraintNegate(vars[j]); + val = val >> 1; + } + //no ones to flip, so bail now... + if (ori == 0) { + return constraintAND(cnf, andi, andarray); + } + andarray[andi++] = constraintOR(cnf, ori, orarray); + + value = value + (1 << (__builtin_ctz(value))); + //flip the last one + } +} + +Edge generateEquivNVConstraint(CNF *cnf, uint numvars, Edge *var1, Edge *var2) { + if (numvars == 0) + return E_True; + Edge array[numvars]; + for (uint i = 0; i < numvars; i++) { + array[i] = constraintIFF(cnf, var1[i], var2[i]); + } + return constraintAND(cnf, numvars, array); +} + +Edge generateLTConstraint(CNF *cnf, uint numvars, Edge *var1, Edge *var2){ + if(numvars == 0 ) + return E_False; + Edge result =constraintAND2(cnf, constraintNegate( var1[0]), var2[0]); + for (uint i = 1; i < numvars; i++) { + Edge lt = constraintAND2(cnf, constraintNegate( var1[i]), var2[i]); + Edge eq = constraintAND2(cnf, constraintIFF(cnf, var1[i], var2[i]), result); + result = constraintOR2(cnf, lt, eq); + } + return result; +} + +Edge generateLTEConstraint(CNF *cnf, uint numvars, Edge *var1, Edge *var2){ + if(numvars == 0 ) + return E_True; + Edge result =constraintIMPLIES(cnf, var1[0], var2[0]); + for (uint i = 1; i < numvars; i++) { + Edge lt = constraintAND2(cnf, constraintNegate( var1[i]), var2[i]); + Edge eq = constraintAND2(cnf, constraintIFF(cnf, var1[i], var2[i]), result); + result = constraintOR2(cnf, lt, eq); + } + return result; +} diff --git a/src/Backend/inc_solver.c b/src/Backend/inc_solver.c deleted file mode 100644 index 85528dc..0000000 --- a/src/Backend/inc_solver.c +++ /dev/null @@ -1,209 +0,0 @@ -/* Copyright (c) 2015 Regents of the University of California - * - * Author: Brian Demsky - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - */ - -#include "inc_solver.h" -#define SATSOLVER "sat_solver" -#include -#include "common.h" -#include - -IncrementalSolver *allocIncrementalSolver() { - IncrementalSolver *This = (IncrementalSolver *)ourmalloc(sizeof(IncrementalSolver)); - This->buffer = ((int *)ourmalloc(sizeof(int) * IS_BUFFERSIZE)); - This->solution = NULL; - This->solutionsize = 0; - This->offset = 0; - createSolver(This); - return This; -} - -void deleteIncrementalSolver(IncrementalSolver *This) { - killSolver(This); - ourfree(This->buffer); - if (This->solution != NULL) - ourfree(This->solution); - ourfree(This); -} - -void resetSolver(IncrementalSolver *This) { - killSolver(This); - This->offset = 0; - createSolver(This); -} - -void addClauseLiteral(IncrementalSolver *This, int literal) { - This->buffer[This->offset++] = literal; - if (This->offset == IS_BUFFERSIZE) { - flushBufferSolver(This); - } -} - -void addArrayClauseLiteral(IncrementalSolver *This, uint numliterals, int *literals) { - uint index = 0; - while (true) { - uint bufferspace = IS_BUFFERSIZE - This->offset; - uint numtowrite = numliterals - index; - if (bufferspace > numtowrite) { - memcpy(&This->buffer[This->offset], &literals[index], numtowrite * sizeof(int)); - This->offset += numtowrite; - This->buffer[This->offset++] = 0; //have one extra spot always - if (This->offset == IS_BUFFERSIZE) {//Check if full - flushBufferSolver(This); - } - return; - } else { - memcpy(&This->buffer[This->offset], &literals[index], bufferspace * sizeof(int)); - This->offset += bufferspace; - index += bufferspace; - flushBufferSolver(This); - } - } -} - -void finishedClauses(IncrementalSolver *This) { - addClauseLiteral(This, 0); -} - -void freeze(IncrementalSolver *This, int variable) { - addClauseLiteral(This, IS_FREEZE); - addClauseLiteral(This, variable); -} - -int solve(IncrementalSolver *This) { - //add an empty clause - startSolve(This); - return getSolution(This); -} - -void startSolve(IncrementalSolver *This) { - addClauseLiteral(This, IS_RUNSOLVER); - flushBufferSolver(This); -} - -int getSolution(IncrementalSolver *This) { - int result = readIntSolver(This); - if (result == IS_SAT) { - int numVars = readIntSolver(This); - if (numVars > This->solutionsize) { - if (This->solution != NULL) - ourfree(This->solution); - This->solution = (int *) ourmalloc((numVars + 1) * sizeof(int)); - This->solution[0] = 0; - } - readSolver(This, &This->solution[1], numVars * sizeof(int)); - This->solutionsize = numVars; - } - return result; -} - -int readIntSolver(IncrementalSolver *This) { - int value; - readSolver(This, &value, 4); - return value; -} - -void readSolver(IncrementalSolver *This, void *tmp, ssize_t size) { - char *result = (char *) tmp; - ssize_t bytestoread = size; - ssize_t bytesread = 0; - do { - ssize_t n = read(This->from_solver_fd, &((char *)result)[bytesread], bytestoread); - if (n == -1) { - model_print("Read failure\n"); - exit(-1); - } - bytestoread -= n; - bytesread += n; - } while (bytestoread != 0); -} - -bool getValueSolver(IncrementalSolver *This, int variable) { - return This->solution[variable]; -} - -void createSolver(IncrementalSolver *This) { - int to_pipe[2]; - int from_pipe[2]; - if (pipe(to_pipe) || pipe(from_pipe)) { - model_print("Error creating pipe.\n"); - exit(-1); - } - if ((This->solver_pid = fork()) == -1) { - model_print("Error forking.\n"); - exit(-1); - } - if (This->solver_pid == 0) { - //Solver process - close(to_pipe[1]); - close(from_pipe[0]); - int fd = open("log_file", O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU); - - if ((dup2(to_pipe[0], 0) == -1) || - (dup2(from_pipe[1], IS_OUT_FD) == -1) || - (dup2(fd, 1) == -1)) { - model_print("Error duplicating pipes\n"); - } - // setsid(); - execlp(SATSOLVER, SATSOLVER, NULL); - model_print("execlp Failed\n"); - close(fd); - } else { - //Our process - This->to_solver_fd = to_pipe[1]; - This->from_solver_fd = from_pipe[0]; - close(to_pipe[0]); - close(from_pipe[1]); - } -} - -void killSolver(IncrementalSolver *This) { - close(This->to_solver_fd); - close(This->from_solver_fd); - //Stop the solver - if (This->solver_pid > 0) { - int status; - kill(This->solver_pid, SIGKILL); - waitpid(This->solver_pid, &status, 0); - } -} - -//DEBUGGING CODE STARTS -bool first = true; -//DEBUGGING CODE ENDS - -void flushBufferSolver(IncrementalSolver *This) { - ssize_t bytestowrite = sizeof(int) * This->offset; - ssize_t byteswritten = 0; - //DEBUGGING CODE STARTS - for (uint i = 0; i < This->offset; i++) { - if (first) - printf("("); - if (This->buffer[i] == 0) { - printf(")\n"); - first = true; - } else { - if (!first) - printf(" + "); - first = false; - printf("%d", This->buffer[i]); - } - } - //DEBUGGING CODE ENDS - do { - ssize_t n = write(This->to_solver_fd, &((char *)This->buffer)[byteswritten], bytestowrite); - if (n == -1) { - perror("Write failure\n"); - model_print("to_solver_fd=%d\n",This->to_solver_fd); - exit(-1); - } - bytestowrite -= n; - byteswritten += n; - } while (bytestowrite != 0); - This->offset = 0; -} diff --git a/src/Backend/inc_solver.cc b/src/Backend/inc_solver.cc new file mode 100644 index 0000000..85528dc --- /dev/null +++ b/src/Backend/inc_solver.cc @@ -0,0 +1,209 @@ +/* Copyright (c) 2015 Regents of the University of California + * + * Author: Brian Demsky + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include "inc_solver.h" +#define SATSOLVER "sat_solver" +#include +#include "common.h" +#include + +IncrementalSolver *allocIncrementalSolver() { + IncrementalSolver *This = (IncrementalSolver *)ourmalloc(sizeof(IncrementalSolver)); + This->buffer = ((int *)ourmalloc(sizeof(int) * IS_BUFFERSIZE)); + This->solution = NULL; + This->solutionsize = 0; + This->offset = 0; + createSolver(This); + return This; +} + +void deleteIncrementalSolver(IncrementalSolver *This) { + killSolver(This); + ourfree(This->buffer); + if (This->solution != NULL) + ourfree(This->solution); + ourfree(This); +} + +void resetSolver(IncrementalSolver *This) { + killSolver(This); + This->offset = 0; + createSolver(This); +} + +void addClauseLiteral(IncrementalSolver *This, int literal) { + This->buffer[This->offset++] = literal; + if (This->offset == IS_BUFFERSIZE) { + flushBufferSolver(This); + } +} + +void addArrayClauseLiteral(IncrementalSolver *This, uint numliterals, int *literals) { + uint index = 0; + while (true) { + uint bufferspace = IS_BUFFERSIZE - This->offset; + uint numtowrite = numliterals - index; + if (bufferspace > numtowrite) { + memcpy(&This->buffer[This->offset], &literals[index], numtowrite * sizeof(int)); + This->offset += numtowrite; + This->buffer[This->offset++] = 0; //have one extra spot always + if (This->offset == IS_BUFFERSIZE) {//Check if full + flushBufferSolver(This); + } + return; + } else { + memcpy(&This->buffer[This->offset], &literals[index], bufferspace * sizeof(int)); + This->offset += bufferspace; + index += bufferspace; + flushBufferSolver(This); + } + } +} + +void finishedClauses(IncrementalSolver *This) { + addClauseLiteral(This, 0); +} + +void freeze(IncrementalSolver *This, int variable) { + addClauseLiteral(This, IS_FREEZE); + addClauseLiteral(This, variable); +} + +int solve(IncrementalSolver *This) { + //add an empty clause + startSolve(This); + return getSolution(This); +} + +void startSolve(IncrementalSolver *This) { + addClauseLiteral(This, IS_RUNSOLVER); + flushBufferSolver(This); +} + +int getSolution(IncrementalSolver *This) { + int result = readIntSolver(This); + if (result == IS_SAT) { + int numVars = readIntSolver(This); + if (numVars > This->solutionsize) { + if (This->solution != NULL) + ourfree(This->solution); + This->solution = (int *) ourmalloc((numVars + 1) * sizeof(int)); + This->solution[0] = 0; + } + readSolver(This, &This->solution[1], numVars * sizeof(int)); + This->solutionsize = numVars; + } + return result; +} + +int readIntSolver(IncrementalSolver *This) { + int value; + readSolver(This, &value, 4); + return value; +} + +void readSolver(IncrementalSolver *This, void *tmp, ssize_t size) { + char *result = (char *) tmp; + ssize_t bytestoread = size; + ssize_t bytesread = 0; + do { + ssize_t n = read(This->from_solver_fd, &((char *)result)[bytesread], bytestoread); + if (n == -1) { + model_print("Read failure\n"); + exit(-1); + } + bytestoread -= n; + bytesread += n; + } while (bytestoread != 0); +} + +bool getValueSolver(IncrementalSolver *This, int variable) { + return This->solution[variable]; +} + +void createSolver(IncrementalSolver *This) { + int to_pipe[2]; + int from_pipe[2]; + if (pipe(to_pipe) || pipe(from_pipe)) { + model_print("Error creating pipe.\n"); + exit(-1); + } + if ((This->solver_pid = fork()) == -1) { + model_print("Error forking.\n"); + exit(-1); + } + if (This->solver_pid == 0) { + //Solver process + close(to_pipe[1]); + close(from_pipe[0]); + int fd = open("log_file", O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU); + + if ((dup2(to_pipe[0], 0) == -1) || + (dup2(from_pipe[1], IS_OUT_FD) == -1) || + (dup2(fd, 1) == -1)) { + model_print("Error duplicating pipes\n"); + } + // setsid(); + execlp(SATSOLVER, SATSOLVER, NULL); + model_print("execlp Failed\n"); + close(fd); + } else { + //Our process + This->to_solver_fd = to_pipe[1]; + This->from_solver_fd = from_pipe[0]; + close(to_pipe[0]); + close(from_pipe[1]); + } +} + +void killSolver(IncrementalSolver *This) { + close(This->to_solver_fd); + close(This->from_solver_fd); + //Stop the solver + if (This->solver_pid > 0) { + int status; + kill(This->solver_pid, SIGKILL); + waitpid(This->solver_pid, &status, 0); + } +} + +//DEBUGGING CODE STARTS +bool first = true; +//DEBUGGING CODE ENDS + +void flushBufferSolver(IncrementalSolver *This) { + ssize_t bytestowrite = sizeof(int) * This->offset; + ssize_t byteswritten = 0; + //DEBUGGING CODE STARTS + for (uint i = 0; i < This->offset; i++) { + if (first) + printf("("); + if (This->buffer[i] == 0) { + printf(")\n"); + first = true; + } else { + if (!first) + printf(" + "); + first = false; + printf("%d", This->buffer[i]); + } + } + //DEBUGGING CODE ENDS + do { + ssize_t n = write(This->to_solver_fd, &((char *)This->buffer)[byteswritten], bytestowrite); + if (n == -1) { + perror("Write failure\n"); + model_print("to_solver_fd=%d\n",This->to_solver_fd); + exit(-1); + } + bytestowrite -= n; + byteswritten += n; + } while (bytestowrite != 0); + This->offset = 0; +} diff --git a/src/Backend/orderelement.c b/src/Backend/orderelement.c deleted file mode 100644 index 1355011..0000000 --- a/src/Backend/orderelement.c +++ /dev/null @@ -1,13 +0,0 @@ -#include "orderelement.h" - - -OrderElement *allocOrderElement(uint64_t item, Element* elem) { - OrderElement *This = (OrderElement *) ourmalloc(sizeof(OrderElement)); - This->elem = elem; - This->item = item; - return This; -} - -void deleteOrderElement(OrderElement *pair) { - ourfree(pair); -} diff --git a/src/Backend/orderelement.cc b/src/Backend/orderelement.cc new file mode 100644 index 0000000..1355011 --- /dev/null +++ b/src/Backend/orderelement.cc @@ -0,0 +1,13 @@ +#include "orderelement.h" + + +OrderElement *allocOrderElement(uint64_t item, Element* elem) { + OrderElement *This = (OrderElement *) ourmalloc(sizeof(OrderElement)); + This->elem = elem; + This->item = item; + return This; +} + +void deleteOrderElement(OrderElement *pair) { + ourfree(pair); +} diff --git a/src/Backend/orderpair.c b/src/Backend/orderpair.c deleted file mode 100644 index 9501af5..0000000 --- a/src/Backend/orderpair.c +++ /dev/null @@ -1,14 +0,0 @@ -#include "orderpair.h" - - -OrderPair *allocOrderPair(uint64_t first, uint64_t second, Edge constraint) { - OrderPair *pair = (OrderPair *) ourmalloc(sizeof(OrderPair)); - pair->first = first; - pair->second = second; - pair->constraint = constraint; - return pair; -} - -void deleteOrderPair(OrderPair *pair) { - ourfree(pair); -} diff --git a/src/Backend/orderpair.cc b/src/Backend/orderpair.cc new file mode 100644 index 0000000..9501af5 --- /dev/null +++ b/src/Backend/orderpair.cc @@ -0,0 +1,14 @@ +#include "orderpair.h" + + +OrderPair *allocOrderPair(uint64_t first, uint64_t second, Edge constraint) { + OrderPair *pair = (OrderPair *) ourmalloc(sizeof(OrderPair)); + pair->first = first; + pair->second = second; + pair->constraint = constraint; + return pair; +} + +void deleteOrderPair(OrderPair *pair) { + ourfree(pair); +} diff --git a/src/Backend/satelemencoder.c b/src/Backend/satelemencoder.c deleted file mode 100644 index 5beae4f..0000000 --- a/src/Backend/satelemencoder.c +++ /dev/null @@ -1,150 +0,0 @@ -#include "satencoder.h" -#include "structs.h" -#include "common.h" -#include "ops.h" -#include "element.h" -#include "set.h" - -Edge getElementValueConstraint(SATEncoder *This, Element *elem, uint64_t value) { - switch (getElementEncoding(elem)->type) { - case ONEHOT: - return getElementValueOneHotConstraint(This, elem, value); - case UNARY: - return getElementValueUnaryConstraint(This, elem, value); - case BINARYINDEX: - return getElementValueBinaryIndexConstraint(This, elem, value); - case ONEHOTBINARY: - ASSERT(0); - break; - case BINARYVAL: - return getElementValueBinaryValueConstraint(This, elem, value); - break; - default: - ASSERT(0); - break; - } - return E_BOGUS; -} - -Edge getElementValueBinaryIndexConstraint(SATEncoder *This, Element *elem, uint64_t value) { - ASTNodeType type = GETELEMENTTYPE(elem); - ASSERT(type == ELEMSET || type == ELEMFUNCRETURN || type == ELEMCONST); - ElementEncoding *elemEnc = getElementEncoding(elem); - for (uint i = 0; i < elemEnc->encArraySize; i++) { - if (isinUseElement(elemEnc, i) && elemEnc->encodingArray[i] == value) { - return (elemEnc->numVars == 0) ? E_True : generateBinaryConstraint(This->cnf, elemEnc->numVars, elemEnc->variables, i); - } - } - return E_False; -} - -Edge getElementValueOneHotConstraint(SATEncoder *This, Element *elem, uint64_t value) { - ASTNodeType type = GETELEMENTTYPE(elem); - ASSERT(type == ELEMSET || type == ELEMFUNCRETURN || type == ELEMCONST); - ElementEncoding *elemEnc = getElementEncoding(elem); - for (uint i = 0; i < elemEnc->encArraySize; i++) { - if (isinUseElement(elemEnc, i) && elemEnc->encodingArray[i] == value) { - return (elemEnc->numVars == 0) ? E_True : elemEnc->variables[i]; - } - } - return E_False; -} - -Edge getElementValueUnaryConstraint(SATEncoder *This, Element *elem, uint64_t value) { - ASTNodeType type = GETELEMENTTYPE(elem); - ASSERT(type == ELEMSET || type == ELEMFUNCRETURN || type == ELEMCONST); - ElementEncoding *elemEnc = getElementEncoding(elem); - for (uint i = 0; i < elemEnc->encArraySize; i++) { - if (isinUseElement(elemEnc, i) && elemEnc->encodingArray[i] == value) { - if (elemEnc->numVars == 0) - return E_True; - if (i == 0) - return constraintNegate(elemEnc->variables[0]); - else if ((i + 1) == elemEnc->encArraySize) - return elemEnc->variables[i - 1]; - else - return constraintAND2(This->cnf, elemEnc->variables[i - 1], constraintNegate(elemEnc->variables[i])); - } - } - return E_False; -} - -Edge getElementValueBinaryValueConstraint(SATEncoder *This, Element *element, uint64_t value) { - ASTNodeType type = GETELEMENTTYPE(element); - ASSERT(type == ELEMSET || type == ELEMFUNCRETURN); - ElementEncoding *elemEnc = getElementEncoding(element); - if (elemEnc->low <= elemEnc->high) { - if (value < elemEnc->low || value > elemEnc->high) - return E_False; - } else { - //Range wraps around 0 - if (value < elemEnc->low && value > elemEnc->high) - return E_False; - } - - uint64_t valueminusoffset = value - elemEnc->offset; - return generateBinaryConstraint(This->cnf, elemEnc->numVars, elemEnc->variables, valueminusoffset); -} - -void allocElementConstraintVariables(ElementEncoding *This, uint numVars) { - This->numVars = numVars; - This->variables = ourmalloc(sizeof(Edge) * numVars); -} - -void generateBinaryValueEncodingVars(SATEncoder *This, ElementEncoding *encoding) { - ASSERT(encoding->type == BINARYVAL); - allocElementConstraintVariables(encoding, encoding->numBits); - getArrayNewVarsSATEncoder(This, encoding->numVars, encoding->variables); -} - -void generateBinaryIndexEncodingVars(SATEncoder *This, ElementEncoding *encoding) { - ASSERT(encoding->type == BINARYINDEX); - allocElementConstraintVariables(encoding, NUMBITS(encoding->encArraySize - 1)); - getArrayNewVarsSATEncoder(This, encoding->numVars, encoding->variables); -} - -void generateOneHotEncodingVars(SATEncoder *This, ElementEncoding *encoding) { - allocElementConstraintVariables(encoding, encoding->encArraySize); - getArrayNewVarsSATEncoder(This, encoding->numVars, encoding->variables); - for (uint i = 0; i < encoding->numVars; i++) { - for (uint j = i + 1; j < encoding->numVars; j++) { - addConstraintCNF(This->cnf, constraintNegate(constraintAND2(This->cnf, encoding->variables[i], encoding->variables[j]))); - } - } - addConstraintCNF(This->cnf, constraintOR(This->cnf, encoding->numVars, encoding->variables)); -} - -void generateUnaryEncodingVars(SATEncoder *This, ElementEncoding *encoding) { - allocElementConstraintVariables(encoding, encoding->encArraySize - 1); - getArrayNewVarsSATEncoder(This, encoding->numVars, encoding->variables); - //Add unary constraint - for (uint i = 1; i < encoding->numVars; i++) { - addConstraintCNF(This->cnf, constraintOR2(This->cnf, encoding->variables[i - 1], constraintNegate(encoding->variables[i]))); - } -} - -void generateElementEncoding(SATEncoder *This, Element *element) { - ElementEncoding *encoding = getElementEncoding(element); - ASSERT(encoding->type != ELEM_UNASSIGNED); - if (encoding->variables != NULL) - return; - switch (encoding->type) { - case ONEHOT: - generateOneHotEncodingVars(This, encoding); - return; - case BINARYINDEX: - generateBinaryIndexEncodingVars(This, encoding); - return; - case UNARY: - generateUnaryEncodingVars(This, encoding); - return; - case ONEHOTBINARY: - return; - case BINARYVAL: - generateBinaryValueEncodingVars(This, encoding); - return; - default: - ASSERT(0); - } -} - diff --git a/src/Backend/satelemencoder.cc b/src/Backend/satelemencoder.cc new file mode 100644 index 0000000..5aaa162 --- /dev/null +++ b/src/Backend/satelemencoder.cc @@ -0,0 +1,150 @@ +#include "satencoder.h" +#include "structs.h" +#include "common.h" +#include "ops.h" +#include "element.h" +#include "set.h" + +Edge getElementValueConstraint(SATEncoder *This, Element *elem, uint64_t value) { + switch (getElementEncoding(elem)->type) { + case ONEHOT: + return getElementValueOneHotConstraint(This, elem, value); + case UNARY: + return getElementValueUnaryConstraint(This, elem, value); + case BINARYINDEX: + return getElementValueBinaryIndexConstraint(This, elem, value); + case ONEHOTBINARY: + ASSERT(0); + break; + case BINARYVAL: + return getElementValueBinaryValueConstraint(This, elem, value); + break; + default: + ASSERT(0); + break; + } + return E_BOGUS; +} + +Edge getElementValueBinaryIndexConstraint(SATEncoder *This, Element *elem, uint64_t value) { + ASTNodeType type = GETELEMENTTYPE(elem); + ASSERT(type == ELEMSET || type == ELEMFUNCRETURN || type == ELEMCONST); + ElementEncoding *elemEnc = getElementEncoding(elem); + for (uint i = 0; i < elemEnc->encArraySize; i++) { + if (isinUseElement(elemEnc, i) && elemEnc->encodingArray[i] == value) { + return (elemEnc->numVars == 0) ? E_True : generateBinaryConstraint(This->cnf, elemEnc->numVars, elemEnc->variables, i); + } + } + return E_False; +} + +Edge getElementValueOneHotConstraint(SATEncoder *This, Element *elem, uint64_t value) { + ASTNodeType type = GETELEMENTTYPE(elem); + ASSERT(type == ELEMSET || type == ELEMFUNCRETURN || type == ELEMCONST); + ElementEncoding *elemEnc = getElementEncoding(elem); + for (uint i = 0; i < elemEnc->encArraySize; i++) { + if (isinUseElement(elemEnc, i) && elemEnc->encodingArray[i] == value) { + return (elemEnc->numVars == 0) ? E_True : elemEnc->variables[i]; + } + } + return E_False; +} + +Edge getElementValueUnaryConstraint(SATEncoder *This, Element *elem, uint64_t value) { + ASTNodeType type = GETELEMENTTYPE(elem); + ASSERT(type == ELEMSET || type == ELEMFUNCRETURN || type == ELEMCONST); + ElementEncoding *elemEnc = getElementEncoding(elem); + for (uint i = 0; i < elemEnc->encArraySize; i++) { + if (isinUseElement(elemEnc, i) && elemEnc->encodingArray[i] == value) { + if (elemEnc->numVars == 0) + return E_True; + if (i == 0) + return constraintNegate(elemEnc->variables[0]); + else if ((i + 1) == elemEnc->encArraySize) + return elemEnc->variables[i - 1]; + else + return constraintAND2(This->cnf, elemEnc->variables[i - 1], constraintNegate(elemEnc->variables[i])); + } + } + return E_False; +} + +Edge getElementValueBinaryValueConstraint(SATEncoder *This, Element *element, uint64_t value) { + ASTNodeType type = GETELEMENTTYPE(element); + ASSERT(type == ELEMSET || type == ELEMFUNCRETURN); + ElementEncoding *elemEnc = getElementEncoding(element); + if (elemEnc->low <= elemEnc->high) { + if (value < elemEnc->low || value > elemEnc->high) + return E_False; + } else { + //Range wraps around 0 + if (value < elemEnc->low && value > elemEnc->high) + return E_False; + } + + uint64_t valueminusoffset = value - elemEnc->offset; + return generateBinaryConstraint(This->cnf, elemEnc->numVars, elemEnc->variables, valueminusoffset); +} + +void allocElementConstraintVariables(ElementEncoding *This, uint numVars) { + This->numVars = numVars; + This->variables = (Edge *)ourmalloc(sizeof(Edge) * numVars); +} + +void generateBinaryValueEncodingVars(SATEncoder *This, ElementEncoding *encoding) { + ASSERT(encoding->type == BINARYVAL); + allocElementConstraintVariables(encoding, encoding->numBits); + getArrayNewVarsSATEncoder(This, encoding->numVars, encoding->variables); +} + +void generateBinaryIndexEncodingVars(SATEncoder *This, ElementEncoding *encoding) { + ASSERT(encoding->type == BINARYINDEX); + allocElementConstraintVariables(encoding, NUMBITS(encoding->encArraySize - 1)); + getArrayNewVarsSATEncoder(This, encoding->numVars, encoding->variables); +} + +void generateOneHotEncodingVars(SATEncoder *This, ElementEncoding *encoding) { + allocElementConstraintVariables(encoding, encoding->encArraySize); + getArrayNewVarsSATEncoder(This, encoding->numVars, encoding->variables); + for (uint i = 0; i < encoding->numVars; i++) { + for (uint j = i + 1; j < encoding->numVars; j++) { + addConstraintCNF(This->cnf, constraintNegate(constraintAND2(This->cnf, encoding->variables[i], encoding->variables[j]))); + } + } + addConstraintCNF(This->cnf, constraintOR(This->cnf, encoding->numVars, encoding->variables)); +} + +void generateUnaryEncodingVars(SATEncoder *This, ElementEncoding *encoding) { + allocElementConstraintVariables(encoding, encoding->encArraySize - 1); + getArrayNewVarsSATEncoder(This, encoding->numVars, encoding->variables); + //Add unary constraint + for (uint i = 1; i < encoding->numVars; i++) { + addConstraintCNF(This->cnf, constraintOR2(This->cnf, encoding->variables[i - 1], constraintNegate(encoding->variables[i]))); + } +} + +void generateElementEncoding(SATEncoder *This, Element *element) { + ElementEncoding *encoding = getElementEncoding(element); + ASSERT(encoding->type != ELEM_UNASSIGNED); + if (encoding->variables != NULL) + return; + switch (encoding->type) { + case ONEHOT: + generateOneHotEncodingVars(This, encoding); + return; + case BINARYINDEX: + generateBinaryIndexEncodingVars(This, encoding); + return; + case UNARY: + generateUnaryEncodingVars(This, encoding); + return; + case ONEHOTBINARY: + return; + case BINARYVAL: + generateBinaryValueEncodingVars(This, encoding); + return; + default: + ASSERT(0); + } +} + diff --git a/src/Backend/satencoder.c b/src/Backend/satencoder.c deleted file mode 100644 index f5362b8..0000000 --- a/src/Backend/satencoder.c +++ /dev/null @@ -1,166 +0,0 @@ -#include "satencoder.h" -#include "structs.h" -#include "csolver.h" -#include "boolean.h" -#include "constraint.h" -#include "common.h" -#include "element.h" -#include "function.h" -#include "tableentry.h" -#include "table.h" -#include "order.h" -#include "predicate.h" -#include "set.h" -#include "satfuncopencoder.h" - -//TODO: Should handle sharing of AST Nodes without recoding them a second time - -SATEncoder *allocSATEncoder(CSolver *solver) { - SATEncoder *This = ourmalloc(sizeof (SATEncoder)); - This->solver = solver; - This->varcount = 1; - This->cnf = createCNF(); - return This; -} - -void deleteSATEncoder(SATEncoder *This) { - deleteCNF(This->cnf); - ourfree(This); -} - -void encodeAllSATEncoder(CSolver *csolver, SATEncoder *This) { - HSIteratorBoolean *iterator=iteratorBoolean(csolver->constraints); - while(hasNextBoolean(iterator)) { - Boolean *constraint = nextBoolean(iterator); - model_print("Encoding All ...\n\n"); - Edge c = encodeConstraintSATEncoder(This, constraint); - model_print("Returned Constraint in EncodingAll:\n"); - addConstraintCNF(This->cnf, c); - } - deleteIterBoolean(iterator); -} - -Edge encodeConstraintSATEncoder(SATEncoder *This, Boolean *constraint) { - switch (GETBOOLEANTYPE(constraint)) { - case ORDERCONST: - return encodeOrderSATEncoder(This, (BooleanOrder *) constraint); - case BOOLEANVAR: - return encodeVarSATEncoder(This, (BooleanVar *) constraint); - case LOGICOP: - return encodeLogicSATEncoder(This, (BooleanLogic *) constraint); - case PREDICATEOP: - return encodePredicateSATEncoder(This, (BooleanPredicate *) constraint); - default: - model_print("Unhandled case in encodeConstraintSATEncoder %u", GETBOOLEANTYPE(constraint)); - exit(-1); - } -} - -void getArrayNewVarsSATEncoder(SATEncoder *encoder, uint num, Edge *carray) { - for (uint i = 0; i < num; i++) - carray[i] = getNewVarSATEncoder(encoder); -} - -Edge getNewVarSATEncoder(SATEncoder *This) { - return constraintNewVar(This->cnf); -} - -Edge encodeVarSATEncoder(SATEncoder *This, BooleanVar *constraint) { - if (edgeIsNull(constraint->var)) { - constraint->var = getNewVarSATEncoder(This); - } - return constraint->var; -} - -Edge encodeLogicSATEncoder(SATEncoder *This, BooleanLogic *constraint) { - Edge array[getSizeArrayBoolean(&constraint->inputs)]; - for (uint i = 0; i < getSizeArrayBoolean(&constraint->inputs); i++) - array[i] = encodeConstraintSATEncoder(This, getArrayBoolean(&constraint->inputs, i)); - - switch (constraint->op) { - case L_AND: - return constraintAND(This->cnf, getSizeArrayBoolean(&constraint->inputs), array); - case L_OR: - return constraintOR(This->cnf, getSizeArrayBoolean(&constraint->inputs), array); - case L_NOT: - ASSERT( getSizeArrayBoolean(&constraint->inputs) == 1); - return constraintNegate(array[0]); - case L_XOR: - ASSERT( getSizeArrayBoolean(&constraint->inputs) == 2); - return constraintXOR(This->cnf, array[0], array[1]); - case L_IMPLIES: - ASSERT( getSizeArrayBoolean( &constraint->inputs) == 2); - return constraintIMPLIES(This->cnf, array[0], array[1]); - default: - model_print("Unhandled case in encodeLogicSATEncoder %u", constraint->op); - exit(-1); - } -} - -Edge encodePredicateSATEncoder(SATEncoder *This, BooleanPredicate *constraint) { - switch (GETPREDICATETYPE(constraint->predicate) ) { - case TABLEPRED: - return encodeTablePredicateSATEncoder(This, constraint); - case OPERATORPRED: - return encodeOperatorPredicateSATEncoder(This, constraint); - default: - ASSERT(0); - } - return E_BOGUS; -} - -Edge encodeTablePredicateSATEncoder(SATEncoder *This, BooleanPredicate *constraint) { - switch (constraint->encoding.type) { - case ENUMERATEIMPLICATIONS: - case ENUMERATEIMPLICATIONSNEGATE: - return encodeEnumTablePredicateSATEncoder(This, constraint); - case CIRCUIT: - ASSERT(0); - break; - default: - ASSERT(0); - } - return E_BOGUS; -} - -void encodeElementSATEncoder(SATEncoder *encoder, Element *This) { - switch ( GETELEMENTTYPE(This) ) { - case ELEMFUNCRETURN: - generateElementEncoding(encoder, This); - encodeElementFunctionSATEncoder(encoder, (ElementFunction *) This); - break; - case ELEMSET: - generateElementEncoding(encoder, This); - return; - case ELEMCONST: - return; - default: - ASSERT(0); - } -} - -void encodeElementFunctionSATEncoder(SATEncoder *encoder, ElementFunction *This) { - switch (GETFUNCTIONTYPE(This->function)) { - case TABLEFUNC: - encodeTableElementFunctionSATEncoder(encoder, This); - break; - case OPERATORFUNC: - encodeOperatorElementFunctionSATEncoder(encoder, This); - break; - default: - ASSERT(0); - } -} - -void encodeTableElementFunctionSATEncoder(SATEncoder *encoder, ElementFunction *This) { - switch (getElementFunctionEncoding(This)->type) { - case ENUMERATEIMPLICATIONS: - encodeEnumTableElemFunctionSATEncoder(encoder, This); - break; - case CIRCUIT: - ASSERT(0); - break; - default: - ASSERT(0); - } -} diff --git a/src/Backend/satencoder.cc b/src/Backend/satencoder.cc new file mode 100644 index 0000000..73998a6 --- /dev/null +++ b/src/Backend/satencoder.cc @@ -0,0 +1,166 @@ +#include "satencoder.h" +#include "structs.h" +#include "csolver.h" +#include "boolean.h" +#include "constraint.h" +#include "common.h" +#include "element.h" +#include "function.h" +#include "tableentry.h" +#include "table.h" +#include "order.h" +#include "predicate.h" +#include "set.h" +#include "satfuncopencoder.h" + +//TODO: Should handle sharing of AST Nodes without recoding them a second time + +SATEncoder *allocSATEncoder(CSolver *solver) { + SATEncoder *This = (SATEncoder *)ourmalloc(sizeof (SATEncoder)); + This->solver = solver; + This->varcount = 1; + This->cnf = createCNF(); + return This; +} + +void deleteSATEncoder(SATEncoder *This) { + deleteCNF(This->cnf); + ourfree(This); +} + +void encodeAllSATEncoder(CSolver *csolver, SATEncoder *This) { + HSIteratorBoolean *iterator=iteratorBoolean(csolver->constraints); + while(hasNextBoolean(iterator)) { + Boolean *constraint = nextBoolean(iterator); + model_print("Encoding All ...\n\n"); + Edge c = encodeConstraintSATEncoder(This, constraint); + model_print("Returned Constraint in EncodingAll:\n"); + addConstraintCNF(This->cnf, c); + } + deleteIterBoolean(iterator); +} + +Edge encodeConstraintSATEncoder(SATEncoder *This, Boolean *constraint) { + switch (GETBOOLEANTYPE(constraint)) { + case ORDERCONST: + return encodeOrderSATEncoder(This, (BooleanOrder *) constraint); + case BOOLEANVAR: + return encodeVarSATEncoder(This, (BooleanVar *) constraint); + case LOGICOP: + return encodeLogicSATEncoder(This, (BooleanLogic *) constraint); + case PREDICATEOP: + return encodePredicateSATEncoder(This, (BooleanPredicate *) constraint); + default: + model_print("Unhandled case in encodeConstraintSATEncoder %u", GETBOOLEANTYPE(constraint)); + exit(-1); + } +} + +void getArrayNewVarsSATEncoder(SATEncoder *encoder, uint num, Edge *carray) { + for (uint i = 0; i < num; i++) + carray[i] = getNewVarSATEncoder(encoder); +} + +Edge getNewVarSATEncoder(SATEncoder *This) { + return constraintNewVar(This->cnf); +} + +Edge encodeVarSATEncoder(SATEncoder *This, BooleanVar *constraint) { + if (edgeIsNull(constraint->var)) { + constraint->var = getNewVarSATEncoder(This); + } + return constraint->var; +} + +Edge encodeLogicSATEncoder(SATEncoder *This, BooleanLogic *constraint) { + Edge array[getSizeArrayBoolean(&constraint->inputs)]; + for (uint i = 0; i < getSizeArrayBoolean(&constraint->inputs); i++) + array[i] = encodeConstraintSATEncoder(This, getArrayBoolean(&constraint->inputs, i)); + + switch (constraint->op) { + case L_AND: + return constraintAND(This->cnf, getSizeArrayBoolean(&constraint->inputs), array); + case L_OR: + return constraintOR(This->cnf, getSizeArrayBoolean(&constraint->inputs), array); + case L_NOT: + ASSERT( getSizeArrayBoolean(&constraint->inputs) == 1); + return constraintNegate(array[0]); + case L_XOR: + ASSERT( getSizeArrayBoolean(&constraint->inputs) == 2); + return constraintXOR(This->cnf, array[0], array[1]); + case L_IMPLIES: + ASSERT( getSizeArrayBoolean( &constraint->inputs) == 2); + return constraintIMPLIES(This->cnf, array[0], array[1]); + default: + model_print("Unhandled case in encodeLogicSATEncoder %u", constraint->op); + exit(-1); + } +} + +Edge encodePredicateSATEncoder(SATEncoder *This, BooleanPredicate *constraint) { + switch (GETPREDICATETYPE(constraint->predicate) ) { + case TABLEPRED: + return encodeTablePredicateSATEncoder(This, constraint); + case OPERATORPRED: + return encodeOperatorPredicateSATEncoder(This, constraint); + default: + ASSERT(0); + } + return E_BOGUS; +} + +Edge encodeTablePredicateSATEncoder(SATEncoder *This, BooleanPredicate *constraint) { + switch (constraint->encoding.type) { + case ENUMERATEIMPLICATIONS: + case ENUMERATEIMPLICATIONSNEGATE: + return encodeEnumTablePredicateSATEncoder(This, constraint); + case CIRCUIT: + ASSERT(0); + break; + default: + ASSERT(0); + } + return E_BOGUS; +} + +void encodeElementSATEncoder(SATEncoder *encoder, Element *This) { + switch ( GETELEMENTTYPE(This) ) { + case ELEMFUNCRETURN: + generateElementEncoding(encoder, This); + encodeElementFunctionSATEncoder(encoder, (ElementFunction *) This); + break; + case ELEMSET: + generateElementEncoding(encoder, This); + return; + case ELEMCONST: + return; + default: + ASSERT(0); + } +} + +void encodeElementFunctionSATEncoder(SATEncoder *encoder, ElementFunction *This) { + switch (GETFUNCTIONTYPE(This->function)) { + case TABLEFUNC: + encodeTableElementFunctionSATEncoder(encoder, This); + break; + case OPERATORFUNC: + encodeOperatorElementFunctionSATEncoder(encoder, This); + break; + default: + ASSERT(0); + } +} + +void encodeTableElementFunctionSATEncoder(SATEncoder *encoder, ElementFunction *This) { + switch (getElementFunctionEncoding(This)->type) { + case ENUMERATEIMPLICATIONS: + encodeEnumTableElemFunctionSATEncoder(encoder, This); + break; + case CIRCUIT: + ASSERT(0); + break; + default: + ASSERT(0); + } +} diff --git a/src/Backend/satfuncopencoder.c b/src/Backend/satfuncopencoder.c deleted file mode 100644 index 8dd7532..0000000 --- a/src/Backend/satfuncopencoder.c +++ /dev/null @@ -1,221 +0,0 @@ -#include "satencoder.h" -#include "common.h" -#include "function.h" -#include "ops.h" -#include "predicate.h" -#include "boolean.h" -#include "table.h" -#include "tableentry.h" -#include "set.h" -#include "element.h" -#include "common.h" -#include "satfuncopencoder.h" - -Edge encodeOperatorPredicateSATEncoder(SATEncoder *This, BooleanPredicate *constraint) { - switch (constraint->encoding.type) { - case ENUMERATEIMPLICATIONS: - return encodeEnumOperatorPredicateSATEncoder(This, constraint); - case CIRCUIT: - return encodeCircuitOperatorPredicateEncoder(This, constraint); - default: - ASSERT(0); - } - exit(-1); -} - -Edge encodeEnumOperatorPredicateSATEncoder(SATEncoder *This, BooleanPredicate *constraint) { - PredicateOperator *predicate = (PredicateOperator *)constraint->predicate; - uint numDomains = getSizeArraySet(&predicate->domains); - - FunctionEncodingType encType = constraint->encoding.type; - bool generateNegation = encType == ENUMERATEIMPLICATIONSNEGATE; - - /* Call base encoders for children */ - for (uint i = 0; i < numDomains; i++) { - Element *elem = getArrayElement( &constraint->inputs, i); - encodeElementSATEncoder(This, elem); - } - VectorEdge *clauses = allocDefVectorEdge(); // Setup array of clauses - - uint indices[numDomains]; //setup indices - bzero(indices, sizeof(uint) * numDomains); - - uint64_t vals[numDomains];//setup value array - for (uint i = 0; i < numDomains; i++) { - Set *set = getArraySet(&predicate->domains, i); - vals[i] = getSetElement(set, indices[i]); - } - - bool notfinished = true; - while (notfinished) { - Edge carray[numDomains]; - - if (evalPredicateOperator(predicate, vals) ^ generateNegation) { - //Include this in the set of terms - for (uint i = 0; i < numDomains; i++) { - Element *elem = getArrayElement(&constraint->inputs, i); - carray[i] = getElementValueConstraint(This, elem, vals[i]); - } - Edge term = constraintAND(This->cnf, numDomains, carray); - pushVectorEdge(clauses, term); - } - - notfinished = false; - for (uint i = 0; i < numDomains; i++) { - uint index = ++indices[i]; - Set *set = getArraySet(&predicate->domains, i); - - if (index < getSetSize(set)) { - vals[i] = getSetElement(set, index); - notfinished = true; - break; - } else { - indices[i] = 0; - vals[i] = getSetElement(set, 0); - } - } - } - if (getSizeVectorEdge(clauses) == 0) { - deleteVectorEdge(clauses); - return E_False; - } - Edge cor = constraintOR(This->cnf, getSizeVectorEdge(clauses), exposeArrayEdge(clauses)); - deleteVectorEdge(clauses); - return generateNegation ? constraintNegate(cor) : cor; -} - - -void encodeOperatorElementFunctionSATEncoder(SATEncoder *This, ElementFunction *func) { -#ifdef TRACE_DEBUG - model_print("Operator Function ...\n"); -#endif - FunctionOperator *function = (FunctionOperator *) func->function; - uint numDomains = getSizeArrayElement(&func->inputs); - - /* Call base encoders for children */ - for (uint i = 0; i < numDomains; i++) { - Element *elem = getArrayElement( &func->inputs, i); - encodeElementSATEncoder(This, elem); - } - - VectorEdge *clauses = allocDefVectorEdge(); // Setup array of clauses - - uint indices[numDomains]; //setup indices - bzero(indices, sizeof(uint) * numDomains); - - uint64_t vals[numDomains];//setup value array - for (uint i = 0; i < numDomains; i++) { - Set *set = getElementSet(getArrayElement(&func->inputs, i)); - vals[i] = getSetElement(set, indices[i]); - } - - Edge overFlowConstraint = ((BooleanVar *) func->overflowstatus)->var; - - bool notfinished = true; - while (notfinished) { - Edge carray[numDomains + 1]; - - uint64_t result = applyFunctionOperator(function, numDomains, vals); - bool isInRange = isInRangeFunction((FunctionOperator *)func->function, result); - bool needClause = isInRange; - if (function->overflowbehavior == OVERFLOWSETSFLAG || function->overflowbehavior == FLAGIFFOVERFLOW) { - needClause = true; - } - - if (needClause) { - //Include this in the set of terms - for (uint i = 0; i < numDomains; i++) { - Element *elem = getArrayElement(&func->inputs, i); - carray[i] = getElementValueConstraint(This, elem, vals[i]); - } - if (isInRange) { - carray[numDomains] = getElementValueConstraint(This, &func->base, result); - } - - Edge clause; - switch (function->overflowbehavior) { - case IGNORE: - case NOOVERFLOW: - case WRAPAROUND: { - clause = constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), carray[numDomains]); - break; - } - case FLAGFORCESOVERFLOW: { - clause = constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), constraintAND2(This->cnf, carray[numDomains], constraintNegate(overFlowConstraint))); - break; - } - case OVERFLOWSETSFLAG: { - if (isInRange) { - clause = constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), carray[numDomains]); - } else { - clause = constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), overFlowConstraint); - } - break; - } - case FLAGIFFOVERFLOW: { - if (isInRange) { - clause = constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), constraintAND2(This->cnf, carray[numDomains], constraintNegate(overFlowConstraint))); - } else { - clause = constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), overFlowConstraint); - } - break; - } - default: - ASSERT(0); - } -#ifdef TRACE_DEBUG - model_print("added clause in operator function\n"); - printCNF(clause); - model_print("\n"); -#endif - pushVectorEdge(clauses, clause); - } - - notfinished = false; - for (uint i = 0; i < numDomains; i++) { - uint index = ++indices[i]; - Set *set = getElementSet(getArrayElement(&func->inputs, i)); - - if (index < getSetSize(set)) { - vals[i] = getSetElement(set, index); - notfinished = true; - break; - } else { - indices[i] = 0; - vals[i] = getSetElement(set, 0); - } - } - } - if (getSizeVectorEdge(clauses) == 0) { - deleteVectorEdge(clauses); - return; - } - Edge cor = constraintAND(This->cnf, getSizeVectorEdge(clauses), exposeArrayEdge(clauses)); - addConstraintCNF(This->cnf, cor); - deleteVectorEdge(clauses); -} - -Edge encodeCircuitOperatorPredicateEncoder(SATEncoder *This, BooleanPredicate *constraint) { - PredicateOperator *predicate = (PredicateOperator *) constraint->predicate; - ASSERT(getSizeArraySet(&predicate->domains) == 2); - Element *elem0 = getArrayElement( &constraint->inputs, 0); - encodeElementSATEncoder(This, elem0); - Element *elem1 = getArrayElement( &constraint->inputs, 1); - encodeElementSATEncoder(This, elem1); - ElementEncoding *ee0 = getElementEncoding(elem0); - ElementEncoding *ee1 = getElementEncoding(elem1); - ASSERT(ee0->numVars == ee1->numVars); - uint numVars = ee0->numVars; - switch (predicate->op) { - case EQUALS: - return generateEquivNVConstraint(This->cnf, numVars, ee0->variables, ee1->variables); - case LT: - return generateLTConstraint(This->cnf, numVars, ee0->variables, ee1->variables); - case GT: - return generateLTConstraint(This->cnf, numVars, ee1->variables, ee0->variables); - default: - ASSERT(0); - } - exit(-1); -} - diff --git a/src/Backend/satfuncopencoder.cc b/src/Backend/satfuncopencoder.cc new file mode 100644 index 0000000..8dd7532 --- /dev/null +++ b/src/Backend/satfuncopencoder.cc @@ -0,0 +1,221 @@ +#include "satencoder.h" +#include "common.h" +#include "function.h" +#include "ops.h" +#include "predicate.h" +#include "boolean.h" +#include "table.h" +#include "tableentry.h" +#include "set.h" +#include "element.h" +#include "common.h" +#include "satfuncopencoder.h" + +Edge encodeOperatorPredicateSATEncoder(SATEncoder *This, BooleanPredicate *constraint) { + switch (constraint->encoding.type) { + case ENUMERATEIMPLICATIONS: + return encodeEnumOperatorPredicateSATEncoder(This, constraint); + case CIRCUIT: + return encodeCircuitOperatorPredicateEncoder(This, constraint); + default: + ASSERT(0); + } + exit(-1); +} + +Edge encodeEnumOperatorPredicateSATEncoder(SATEncoder *This, BooleanPredicate *constraint) { + PredicateOperator *predicate = (PredicateOperator *)constraint->predicate; + uint numDomains = getSizeArraySet(&predicate->domains); + + FunctionEncodingType encType = constraint->encoding.type; + bool generateNegation = encType == ENUMERATEIMPLICATIONSNEGATE; + + /* Call base encoders for children */ + for (uint i = 0; i < numDomains; i++) { + Element *elem = getArrayElement( &constraint->inputs, i); + encodeElementSATEncoder(This, elem); + } + VectorEdge *clauses = allocDefVectorEdge(); // Setup array of clauses + + uint indices[numDomains]; //setup indices + bzero(indices, sizeof(uint) * numDomains); + + uint64_t vals[numDomains];//setup value array + for (uint i = 0; i < numDomains; i++) { + Set *set = getArraySet(&predicate->domains, i); + vals[i] = getSetElement(set, indices[i]); + } + + bool notfinished = true; + while (notfinished) { + Edge carray[numDomains]; + + if (evalPredicateOperator(predicate, vals) ^ generateNegation) { + //Include this in the set of terms + for (uint i = 0; i < numDomains; i++) { + Element *elem = getArrayElement(&constraint->inputs, i); + carray[i] = getElementValueConstraint(This, elem, vals[i]); + } + Edge term = constraintAND(This->cnf, numDomains, carray); + pushVectorEdge(clauses, term); + } + + notfinished = false; + for (uint i = 0; i < numDomains; i++) { + uint index = ++indices[i]; + Set *set = getArraySet(&predicate->domains, i); + + if (index < getSetSize(set)) { + vals[i] = getSetElement(set, index); + notfinished = true; + break; + } else { + indices[i] = 0; + vals[i] = getSetElement(set, 0); + } + } + } + if (getSizeVectorEdge(clauses) == 0) { + deleteVectorEdge(clauses); + return E_False; + } + Edge cor = constraintOR(This->cnf, getSizeVectorEdge(clauses), exposeArrayEdge(clauses)); + deleteVectorEdge(clauses); + return generateNegation ? constraintNegate(cor) : cor; +} + + +void encodeOperatorElementFunctionSATEncoder(SATEncoder *This, ElementFunction *func) { +#ifdef TRACE_DEBUG + model_print("Operator Function ...\n"); +#endif + FunctionOperator *function = (FunctionOperator *) func->function; + uint numDomains = getSizeArrayElement(&func->inputs); + + /* Call base encoders for children */ + for (uint i = 0; i < numDomains; i++) { + Element *elem = getArrayElement( &func->inputs, i); + encodeElementSATEncoder(This, elem); + } + + VectorEdge *clauses = allocDefVectorEdge(); // Setup array of clauses + + uint indices[numDomains]; //setup indices + bzero(indices, sizeof(uint) * numDomains); + + uint64_t vals[numDomains];//setup value array + for (uint i = 0; i < numDomains; i++) { + Set *set = getElementSet(getArrayElement(&func->inputs, i)); + vals[i] = getSetElement(set, indices[i]); + } + + Edge overFlowConstraint = ((BooleanVar *) func->overflowstatus)->var; + + bool notfinished = true; + while (notfinished) { + Edge carray[numDomains + 1]; + + uint64_t result = applyFunctionOperator(function, numDomains, vals); + bool isInRange = isInRangeFunction((FunctionOperator *)func->function, result); + bool needClause = isInRange; + if (function->overflowbehavior == OVERFLOWSETSFLAG || function->overflowbehavior == FLAGIFFOVERFLOW) { + needClause = true; + } + + if (needClause) { + //Include this in the set of terms + for (uint i = 0; i < numDomains; i++) { + Element *elem = getArrayElement(&func->inputs, i); + carray[i] = getElementValueConstraint(This, elem, vals[i]); + } + if (isInRange) { + carray[numDomains] = getElementValueConstraint(This, &func->base, result); + } + + Edge clause; + switch (function->overflowbehavior) { + case IGNORE: + case NOOVERFLOW: + case WRAPAROUND: { + clause = constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), carray[numDomains]); + break; + } + case FLAGFORCESOVERFLOW: { + clause = constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), constraintAND2(This->cnf, carray[numDomains], constraintNegate(overFlowConstraint))); + break; + } + case OVERFLOWSETSFLAG: { + if (isInRange) { + clause = constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), carray[numDomains]); + } else { + clause = constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), overFlowConstraint); + } + break; + } + case FLAGIFFOVERFLOW: { + if (isInRange) { + clause = constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), constraintAND2(This->cnf, carray[numDomains], constraintNegate(overFlowConstraint))); + } else { + clause = constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), overFlowConstraint); + } + break; + } + default: + ASSERT(0); + } +#ifdef TRACE_DEBUG + model_print("added clause in operator function\n"); + printCNF(clause); + model_print("\n"); +#endif + pushVectorEdge(clauses, clause); + } + + notfinished = false; + for (uint i = 0; i < numDomains; i++) { + uint index = ++indices[i]; + Set *set = getElementSet(getArrayElement(&func->inputs, i)); + + if (index < getSetSize(set)) { + vals[i] = getSetElement(set, index); + notfinished = true; + break; + } else { + indices[i] = 0; + vals[i] = getSetElement(set, 0); + } + } + } + if (getSizeVectorEdge(clauses) == 0) { + deleteVectorEdge(clauses); + return; + } + Edge cor = constraintAND(This->cnf, getSizeVectorEdge(clauses), exposeArrayEdge(clauses)); + addConstraintCNF(This->cnf, cor); + deleteVectorEdge(clauses); +} + +Edge encodeCircuitOperatorPredicateEncoder(SATEncoder *This, BooleanPredicate *constraint) { + PredicateOperator *predicate = (PredicateOperator *) constraint->predicate; + ASSERT(getSizeArraySet(&predicate->domains) == 2); + Element *elem0 = getArrayElement( &constraint->inputs, 0); + encodeElementSATEncoder(This, elem0); + Element *elem1 = getArrayElement( &constraint->inputs, 1); + encodeElementSATEncoder(This, elem1); + ElementEncoding *ee0 = getElementEncoding(elem0); + ElementEncoding *ee1 = getElementEncoding(elem1); + ASSERT(ee0->numVars == ee1->numVars); + uint numVars = ee0->numVars; + switch (predicate->op) { + case EQUALS: + return generateEquivNVConstraint(This->cnf, numVars, ee0->variables, ee1->variables); + case LT: + return generateLTConstraint(This->cnf, numVars, ee0->variables, ee1->variables); + case GT: + return generateLTConstraint(This->cnf, numVars, ee1->variables, ee0->variables); + default: + ASSERT(0); + } + exit(-1); +} + diff --git a/src/Backend/satfunctableencoder.c b/src/Backend/satfunctableencoder.c deleted file mode 100644 index d37e6dc..0000000 --- a/src/Backend/satfunctableencoder.c +++ /dev/null @@ -1,323 +0,0 @@ -#include "satencoder.h" -#include "common.h" -#include "function.h" -#include "ops.h" -#include "predicate.h" -#include "boolean.h" -#include "table.h" -#include "tableentry.h" -#include "set.h" -#include "element.h" -#include "common.h" - -Edge encodeEnumEntriesTablePredicateSATEncoder(SATEncoder *This, BooleanPredicate *constraint) { - ASSERT(GETPREDICATETYPE(constraint->predicate) == TABLEPRED); - UndefinedBehavior undefStatus = ((PredicateTable *)constraint->predicate)->undefinedbehavior; - ASSERT(undefStatus == IGNOREBEHAVIOR || undefStatus == FLAGFORCEUNDEFINED); - Table *table = ((PredicateTable *)constraint->predicate)->table; - FunctionEncodingType encType = constraint->encoding.type; - ArrayElement *inputs = &constraint->inputs; - uint inputNum = getSizeArrayElement(inputs); - uint size = getSizeHashSetTableEntry(table->entries); - bool generateNegation = encType == ENUMERATEIMPLICATIONSNEGATE; - Edge constraints[size]; - Edge undefConst = encodeConstraintSATEncoder(This, constraint->undefStatus); - printCNF(undefConst); - model_print("**\n"); - HSIteratorTableEntry *iterator = iteratorTableEntry(table->entries); - uint i = 0; - while (hasNextTableEntry(iterator)) { - TableEntry *entry = nextTableEntry(iterator); - if (generateNegation == entry->output && undefStatus == IGNOREBEHAVIOR) { - //Skip the irrelevant entries - continue; - } - Edge carray[inputNum]; - for (uint j = 0; j < inputNum; j++) { - Element *el = getArrayElement(inputs, j); - carray[j] = getElementValueConstraint(This, el, entry->inputs[j]); - printCNF(carray[j]); - model_print("\n"); - } - Edge row; - switch (undefStatus) { - case IGNOREBEHAVIOR: - row = constraintAND(This->cnf, inputNum, carray); - break; - case FLAGFORCEUNDEFINED: { - addConstraintCNF(This->cnf, constraintIMPLIES(This->cnf,constraintAND(This->cnf, inputNum, carray), constraintNegate(undefConst))); - if (generateNegation == entry->output) { - continue; - } - row = constraintAND(This->cnf, inputNum, carray); - break; - } - default: - ASSERT(0); - } - constraints[i++] = row; - printCNF(row); - - model_print("\n\n"); - } - deleteIterTableEntry(iterator); - ASSERT(i != 0); - Edge result = generateNegation ? constraintNegate(constraintOR(This->cnf, i, constraints)) - : constraintOR(This->cnf, i, constraints); - printCNF(result); - return result; -} -Edge encodeEnumTablePredicateSATEncoder(SATEncoder *This, BooleanPredicate *constraint) { -#ifdef TRACE_DEBUG - model_print("Enumeration Table Predicate ...\n"); -#endif - ASSERT(GETPREDICATETYPE(constraint->predicate) == TABLEPRED); - //First encode children - ArrayElement *inputs = &constraint->inputs; - uint inputNum = getSizeArrayElement(inputs); - //Encode all the inputs first ... - for (uint i = 0; i < inputNum; i++) { - encodeElementSATEncoder(This, getArrayElement(inputs, i)); - } - PredicateTable *predicate = (PredicateTable *)constraint->predicate; - switch (predicate->undefinedbehavior) { - case IGNOREBEHAVIOR: - case FLAGFORCEUNDEFINED: - return encodeEnumEntriesTablePredicateSATEncoder(This, constraint); - default: - break; - } - bool generateNegation = constraint->encoding.type == ENUMERATEIMPLICATIONSNEGATE; - uint numDomains = getSizeArraySet(&predicate->table->domains); - - VectorEdge *clauses = allocDefVectorEdge(); - - uint indices[numDomains]; //setup indices - bzero(indices, sizeof(uint) * numDomains); - - uint64_t vals[numDomains];//setup value array - for (uint i = 0; i < numDomains; i++) { - Set *set = getArraySet(&predicate->table->domains, i); - vals[i] = getSetElement(set, indices[i]); - } - bool hasOverflow = false; - Edge undefConstraint = encodeConstraintSATEncoder (This, constraint->undefStatus); - printCNF(undefConstraint); - bool notfinished = true; - while (notfinished) { - Edge carray[numDomains]; - TableEntry *tableEntry = getTableEntryFromTable(predicate->table, vals, numDomains); - bool isInRange = tableEntry != NULL; - if (!isInRange && !hasOverflow) { - hasOverflow = true; - } - Edge clause; - for (uint i = 0; i < numDomains; i++) { - Element *elem = getArrayElement(&constraint->inputs, i); - carray[i] = getElementValueConstraint(This, elem, vals[i]); - } - - switch (predicate->undefinedbehavior) { - case UNDEFINEDSETSFLAG: - if (isInRange) { - clause = constraintAND(This->cnf, numDomains, carray); - } else { - addConstraintCNF(This->cnf, constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), undefConstraint) ); - } - break; - case FLAGIFFUNDEFINED: - if (isInRange) { - clause = constraintAND(This->cnf, numDomains, carray); - addConstraintCNF(This->cnf, constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), constraintNegate(undefConstraint))); - } else { - addConstraintCNF(This->cnf, constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), undefConstraint) ); - } - break; - - default: - ASSERT(0); - } - - if (isInRange) { -#ifdef TRACE_DEBUG - model_print("added clause in predicate table enumeration ...\n"); - printCNF(clause); - model_print("\n"); -#endif - pushVectorEdge(clauses, clause); - } - - notfinished = false; - for (uint i = 0; i < numDomains; i++) { - uint index = ++indices[i]; - Set *set = getArraySet(&predicate->table->domains, i); - - if (index < getSetSize(set)) { - vals[i] = getSetElement(set, index); - notfinished = true; - break; - } else { - indices[i] = 0; - vals[i] = getSetElement(set, 0); - } - } - } - Edge result = E_NULL; - ASSERT(getSizeVectorEdge(clauses) != 0); - result = constraintOR(This->cnf, getSizeVectorEdge(clauses), exposeArrayEdge(clauses)); - if (hasOverflow) { - result = constraintOR2(This->cnf, result, undefConstraint); - } - if (generateNegation) { - ASSERT(!hasOverflow); - result = constraintNegate(result); - } - deleteVectorEdge(clauses); - return result; -} - -void encodeEnumEntriesTableElemFuncSATEncoder(SATEncoder *This, ElementFunction *func) { - UndefinedBehavior undefStatus = ((FunctionTable *) func->function)->undefBehavior; - ASSERT(undefStatus == IGNOREBEHAVIOR || undefStatus == FLAGFORCEUNDEFINED); - ArrayElement *elements = &func->inputs; - Table *table = ((FunctionTable *) (func->function))->table; - uint size = getSizeHashSetTableEntry(table->entries); - Edge constraints[size]; - HSIteratorTableEntry *iterator = iteratorTableEntry(table->entries); - uint i = 0; - while (hasNextTableEntry(iterator)) { - TableEntry *entry = nextTableEntry(iterator); - ASSERT(entry != NULL); - uint inputNum = getSizeArrayElement(elements); - Edge carray[inputNum]; - for (uint j = 0; j < inputNum; j++) { - Element *el = getArrayElement(elements, j); - carray[j] = getElementValueConstraint(This, el, entry->inputs[j]); - } - Edge output = getElementValueConstraint(This, (Element *)func, entry->output); - Edge row; - switch (undefStatus ) { - case IGNOREBEHAVIOR: { - row = constraintIMPLIES(This->cnf,constraintAND(This->cnf, inputNum, carray), output); - break; - } - case FLAGFORCEUNDEFINED: { - Edge undefConst = encodeConstraintSATEncoder(This, func->overflowstatus); - row = constraintIMPLIES(This->cnf,constraintAND(This->cnf, inputNum, carray), constraintAND2(This->cnf, output, constraintNegate(undefConst))); - break; - } - default: - ASSERT(0); - - } - constraints[i++] = row; - } - deleteIterTableEntry(iterator); - addConstraintCNF(This->cnf, constraintAND(This->cnf, size, constraints)); -} - -void encodeEnumTableElemFunctionSATEncoder(SATEncoder *This, ElementFunction *elemFunc) { -#ifdef TRACE_DEBUG - model_print("Enumeration Table functions ...\n"); -#endif - ASSERT(GETFUNCTIONTYPE(elemFunc->function) == TABLEFUNC); - //First encode children - ArrayElement *elements = &elemFunc->inputs; - for (uint i = 0; i < getSizeArrayElement(elements); i++) { - Element *elem = getArrayElement( elements, i); - encodeElementSATEncoder(This, elem); - } - - FunctionTable *function = (FunctionTable *)elemFunc->function; - switch (function->undefBehavior) { - case IGNOREBEHAVIOR: - case FLAGFORCEUNDEFINED: - return encodeEnumEntriesTableElemFuncSATEncoder(This, elemFunc); - default: - break; - } - - uint numDomains = getSizeArraySet(&function->table->domains); - - VectorEdge *clauses = allocDefVectorEdge(); // Setup array of clauses - - uint indices[numDomains]; //setup indices - bzero(indices, sizeof(uint) * numDomains); - - uint64_t vals[numDomains];//setup value array - for (uint i = 0; i < numDomains; i++) { - Set *set = getArraySet(&function->table->domains, i); - vals[i] = getSetElement(set, indices[i]); - } - - Edge undefConstraint = encodeConstraintSATEncoder(This, elemFunc->overflowstatus); - bool notfinished = true; - while (notfinished) { - Edge carray[numDomains + 1]; - TableEntry *tableEntry = getTableEntryFromTable(function->table, vals, numDomains); - bool isInRange = tableEntry != NULL; - ASSERT(function->undefBehavior == UNDEFINEDSETSFLAG || function->undefBehavior == FLAGIFFUNDEFINED); - for (uint i = 0; i < numDomains; i++) { - Element *elem = getArrayElement(&elemFunc->inputs, i); - carray[i] = getElementValueConstraint(This, elem, vals[i]); - } - if (isInRange) { - carray[numDomains] = getElementValueConstraint(This, (Element *)elemFunc, tableEntry->output); - } - - Edge clause; - switch (function->undefBehavior) { - case UNDEFINEDSETSFLAG: { - if (isInRange) { - //FIXME: Talk to Brian, It should be IFF not only IMPLY. --HG - clause = constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), carray[numDomains]); - } else { - addConstraintCNF(This->cnf, constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), undefConstraint)); - } - break; - } - case FLAGIFFUNDEFINED: { - if (isInRange) { - clause = constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), carray[numDomains]); - addConstraintCNF(This->cnf, constraintIMPLIES(This->cnf, constraintAND(This->cnf, numDomains, carray), constraintNegate(undefConstraint) )); - } else { - addConstraintCNF(This->cnf,constraintIMPLIES(This->cnf, constraintAND(This->cnf, numDomains, carray), undefConstraint)); - } - break; - } - default: - ASSERT(0); - } - if (isInRange) { -#ifdef TRACE_DEBUG - model_print("added clause in function table enumeration ...\n"); - printCNF(clause); - model_print("\n"); -#endif - pushVectorEdge(clauses, clause); - } - - notfinished = false; - for (uint i = 0; i < numDomains; i++) { - uint index = ++indices[i]; - Set *set = getArraySet(&function->table->domains, i); - - if (index < getSetSize(set)) { - vals[i] = getSetElement(set, index); - notfinished = true; - break; - } else { - indices[i] = 0; - vals[i] = getSetElement(set, 0); - } - } - } - if (getSizeVectorEdge(clauses) == 0) { - deleteVectorEdge(clauses); - return; - } - Edge cor = constraintAND(This->cnf, getSizeVectorEdge(clauses), exposeArrayEdge(clauses)); - addConstraintCNF(This->cnf, cor); - deleteVectorEdge(clauses); - -} diff --git a/src/Backend/satfunctableencoder.cc b/src/Backend/satfunctableencoder.cc new file mode 100644 index 0000000..d37e6dc --- /dev/null +++ b/src/Backend/satfunctableencoder.cc @@ -0,0 +1,323 @@ +#include "satencoder.h" +#include "common.h" +#include "function.h" +#include "ops.h" +#include "predicate.h" +#include "boolean.h" +#include "table.h" +#include "tableentry.h" +#include "set.h" +#include "element.h" +#include "common.h" + +Edge encodeEnumEntriesTablePredicateSATEncoder(SATEncoder *This, BooleanPredicate *constraint) { + ASSERT(GETPREDICATETYPE(constraint->predicate) == TABLEPRED); + UndefinedBehavior undefStatus = ((PredicateTable *)constraint->predicate)->undefinedbehavior; + ASSERT(undefStatus == IGNOREBEHAVIOR || undefStatus == FLAGFORCEUNDEFINED); + Table *table = ((PredicateTable *)constraint->predicate)->table; + FunctionEncodingType encType = constraint->encoding.type; + ArrayElement *inputs = &constraint->inputs; + uint inputNum = getSizeArrayElement(inputs); + uint size = getSizeHashSetTableEntry(table->entries); + bool generateNegation = encType == ENUMERATEIMPLICATIONSNEGATE; + Edge constraints[size]; + Edge undefConst = encodeConstraintSATEncoder(This, constraint->undefStatus); + printCNF(undefConst); + model_print("**\n"); + HSIteratorTableEntry *iterator = iteratorTableEntry(table->entries); + uint i = 0; + while (hasNextTableEntry(iterator)) { + TableEntry *entry = nextTableEntry(iterator); + if (generateNegation == entry->output && undefStatus == IGNOREBEHAVIOR) { + //Skip the irrelevant entries + continue; + } + Edge carray[inputNum]; + for (uint j = 0; j < inputNum; j++) { + Element *el = getArrayElement(inputs, j); + carray[j] = getElementValueConstraint(This, el, entry->inputs[j]); + printCNF(carray[j]); + model_print("\n"); + } + Edge row; + switch (undefStatus) { + case IGNOREBEHAVIOR: + row = constraintAND(This->cnf, inputNum, carray); + break; + case FLAGFORCEUNDEFINED: { + addConstraintCNF(This->cnf, constraintIMPLIES(This->cnf,constraintAND(This->cnf, inputNum, carray), constraintNegate(undefConst))); + if (generateNegation == entry->output) { + continue; + } + row = constraintAND(This->cnf, inputNum, carray); + break; + } + default: + ASSERT(0); + } + constraints[i++] = row; + printCNF(row); + + model_print("\n\n"); + } + deleteIterTableEntry(iterator); + ASSERT(i != 0); + Edge result = generateNegation ? constraintNegate(constraintOR(This->cnf, i, constraints)) + : constraintOR(This->cnf, i, constraints); + printCNF(result); + return result; +} +Edge encodeEnumTablePredicateSATEncoder(SATEncoder *This, BooleanPredicate *constraint) { +#ifdef TRACE_DEBUG + model_print("Enumeration Table Predicate ...\n"); +#endif + ASSERT(GETPREDICATETYPE(constraint->predicate) == TABLEPRED); + //First encode children + ArrayElement *inputs = &constraint->inputs; + uint inputNum = getSizeArrayElement(inputs); + //Encode all the inputs first ... + for (uint i = 0; i < inputNum; i++) { + encodeElementSATEncoder(This, getArrayElement(inputs, i)); + } + PredicateTable *predicate = (PredicateTable *)constraint->predicate; + switch (predicate->undefinedbehavior) { + case IGNOREBEHAVIOR: + case FLAGFORCEUNDEFINED: + return encodeEnumEntriesTablePredicateSATEncoder(This, constraint); + default: + break; + } + bool generateNegation = constraint->encoding.type == ENUMERATEIMPLICATIONSNEGATE; + uint numDomains = getSizeArraySet(&predicate->table->domains); + + VectorEdge *clauses = allocDefVectorEdge(); + + uint indices[numDomains]; //setup indices + bzero(indices, sizeof(uint) * numDomains); + + uint64_t vals[numDomains];//setup value array + for (uint i = 0; i < numDomains; i++) { + Set *set = getArraySet(&predicate->table->domains, i); + vals[i] = getSetElement(set, indices[i]); + } + bool hasOverflow = false; + Edge undefConstraint = encodeConstraintSATEncoder (This, constraint->undefStatus); + printCNF(undefConstraint); + bool notfinished = true; + while (notfinished) { + Edge carray[numDomains]; + TableEntry *tableEntry = getTableEntryFromTable(predicate->table, vals, numDomains); + bool isInRange = tableEntry != NULL; + if (!isInRange && !hasOverflow) { + hasOverflow = true; + } + Edge clause; + for (uint i = 0; i < numDomains; i++) { + Element *elem = getArrayElement(&constraint->inputs, i); + carray[i] = getElementValueConstraint(This, elem, vals[i]); + } + + switch (predicate->undefinedbehavior) { + case UNDEFINEDSETSFLAG: + if (isInRange) { + clause = constraintAND(This->cnf, numDomains, carray); + } else { + addConstraintCNF(This->cnf, constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), undefConstraint) ); + } + break; + case FLAGIFFUNDEFINED: + if (isInRange) { + clause = constraintAND(This->cnf, numDomains, carray); + addConstraintCNF(This->cnf, constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), constraintNegate(undefConstraint))); + } else { + addConstraintCNF(This->cnf, constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), undefConstraint) ); + } + break; + + default: + ASSERT(0); + } + + if (isInRange) { +#ifdef TRACE_DEBUG + model_print("added clause in predicate table enumeration ...\n"); + printCNF(clause); + model_print("\n"); +#endif + pushVectorEdge(clauses, clause); + } + + notfinished = false; + for (uint i = 0; i < numDomains; i++) { + uint index = ++indices[i]; + Set *set = getArraySet(&predicate->table->domains, i); + + if (index < getSetSize(set)) { + vals[i] = getSetElement(set, index); + notfinished = true; + break; + } else { + indices[i] = 0; + vals[i] = getSetElement(set, 0); + } + } + } + Edge result = E_NULL; + ASSERT(getSizeVectorEdge(clauses) != 0); + result = constraintOR(This->cnf, getSizeVectorEdge(clauses), exposeArrayEdge(clauses)); + if (hasOverflow) { + result = constraintOR2(This->cnf, result, undefConstraint); + } + if (generateNegation) { + ASSERT(!hasOverflow); + result = constraintNegate(result); + } + deleteVectorEdge(clauses); + return result; +} + +void encodeEnumEntriesTableElemFuncSATEncoder(SATEncoder *This, ElementFunction *func) { + UndefinedBehavior undefStatus = ((FunctionTable *) func->function)->undefBehavior; + ASSERT(undefStatus == IGNOREBEHAVIOR || undefStatus == FLAGFORCEUNDEFINED); + ArrayElement *elements = &func->inputs; + Table *table = ((FunctionTable *) (func->function))->table; + uint size = getSizeHashSetTableEntry(table->entries); + Edge constraints[size]; + HSIteratorTableEntry *iterator = iteratorTableEntry(table->entries); + uint i = 0; + while (hasNextTableEntry(iterator)) { + TableEntry *entry = nextTableEntry(iterator); + ASSERT(entry != NULL); + uint inputNum = getSizeArrayElement(elements); + Edge carray[inputNum]; + for (uint j = 0; j < inputNum; j++) { + Element *el = getArrayElement(elements, j); + carray[j] = getElementValueConstraint(This, el, entry->inputs[j]); + } + Edge output = getElementValueConstraint(This, (Element *)func, entry->output); + Edge row; + switch (undefStatus ) { + case IGNOREBEHAVIOR: { + row = constraintIMPLIES(This->cnf,constraintAND(This->cnf, inputNum, carray), output); + break; + } + case FLAGFORCEUNDEFINED: { + Edge undefConst = encodeConstraintSATEncoder(This, func->overflowstatus); + row = constraintIMPLIES(This->cnf,constraintAND(This->cnf, inputNum, carray), constraintAND2(This->cnf, output, constraintNegate(undefConst))); + break; + } + default: + ASSERT(0); + + } + constraints[i++] = row; + } + deleteIterTableEntry(iterator); + addConstraintCNF(This->cnf, constraintAND(This->cnf, size, constraints)); +} + +void encodeEnumTableElemFunctionSATEncoder(SATEncoder *This, ElementFunction *elemFunc) { +#ifdef TRACE_DEBUG + model_print("Enumeration Table functions ...\n"); +#endif + ASSERT(GETFUNCTIONTYPE(elemFunc->function) == TABLEFUNC); + //First encode children + ArrayElement *elements = &elemFunc->inputs; + for (uint i = 0; i < getSizeArrayElement(elements); i++) { + Element *elem = getArrayElement( elements, i); + encodeElementSATEncoder(This, elem); + } + + FunctionTable *function = (FunctionTable *)elemFunc->function; + switch (function->undefBehavior) { + case IGNOREBEHAVIOR: + case FLAGFORCEUNDEFINED: + return encodeEnumEntriesTableElemFuncSATEncoder(This, elemFunc); + default: + break; + } + + uint numDomains = getSizeArraySet(&function->table->domains); + + VectorEdge *clauses = allocDefVectorEdge(); // Setup array of clauses + + uint indices[numDomains]; //setup indices + bzero(indices, sizeof(uint) * numDomains); + + uint64_t vals[numDomains];//setup value array + for (uint i = 0; i < numDomains; i++) { + Set *set = getArraySet(&function->table->domains, i); + vals[i] = getSetElement(set, indices[i]); + } + + Edge undefConstraint = encodeConstraintSATEncoder(This, elemFunc->overflowstatus); + bool notfinished = true; + while (notfinished) { + Edge carray[numDomains + 1]; + TableEntry *tableEntry = getTableEntryFromTable(function->table, vals, numDomains); + bool isInRange = tableEntry != NULL; + ASSERT(function->undefBehavior == UNDEFINEDSETSFLAG || function->undefBehavior == FLAGIFFUNDEFINED); + for (uint i = 0; i < numDomains; i++) { + Element *elem = getArrayElement(&elemFunc->inputs, i); + carray[i] = getElementValueConstraint(This, elem, vals[i]); + } + if (isInRange) { + carray[numDomains] = getElementValueConstraint(This, (Element *)elemFunc, tableEntry->output); + } + + Edge clause; + switch (function->undefBehavior) { + case UNDEFINEDSETSFLAG: { + if (isInRange) { + //FIXME: Talk to Brian, It should be IFF not only IMPLY. --HG + clause = constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), carray[numDomains]); + } else { + addConstraintCNF(This->cnf, constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), undefConstraint)); + } + break; + } + case FLAGIFFUNDEFINED: { + if (isInRange) { + clause = constraintIMPLIES(This->cnf,constraintAND(This->cnf, numDomains, carray), carray[numDomains]); + addConstraintCNF(This->cnf, constraintIMPLIES(This->cnf, constraintAND(This->cnf, numDomains, carray), constraintNegate(undefConstraint) )); + } else { + addConstraintCNF(This->cnf,constraintIMPLIES(This->cnf, constraintAND(This->cnf, numDomains, carray), undefConstraint)); + } + break; + } + default: + ASSERT(0); + } + if (isInRange) { +#ifdef TRACE_DEBUG + model_print("added clause in function table enumeration ...\n"); + printCNF(clause); + model_print("\n"); +#endif + pushVectorEdge(clauses, clause); + } + + notfinished = false; + for (uint i = 0; i < numDomains; i++) { + uint index = ++indices[i]; + Set *set = getArraySet(&function->table->domains, i); + + if (index < getSetSize(set)) { + vals[i] = getSetElement(set, index); + notfinished = true; + break; + } else { + indices[i] = 0; + vals[i] = getSetElement(set, 0); + } + } + } + if (getSizeVectorEdge(clauses) == 0) { + deleteVectorEdge(clauses); + return; + } + Edge cor = constraintAND(This->cnf, getSizeVectorEdge(clauses), exposeArrayEdge(clauses)); + addConstraintCNF(This->cnf, cor); + deleteVectorEdge(clauses); + +} diff --git a/src/Backend/satorderencoder.c b/src/Backend/satorderencoder.c deleted file mode 100644 index 64f414c..0000000 --- a/src/Backend/satorderencoder.c +++ /dev/null @@ -1,208 +0,0 @@ -#include "satencoder.h" -#include "structs.h" -#include "common.h" -#include "order.h" -#include "csolver.h" -#include "orderpair.h" -#include "set.h" -#include "tunable.h" -#include "orderencoder.h" -#include "ordergraph.h" -#include "orderedge.h" -#include "element.h" -#include "predicate.h" -#include "orderelement.h" - -Edge encodeOrderSATEncoder(SATEncoder *This, BooleanOrder *constraint) { - if(constraint->order->order.type == INTEGERENCODING){ - return orderIntegerEncodingSATEncoder(This, constraint); - } - switch ( constraint->order->type) { - case PARTIAL: - return encodePartialOrderSATEncoder(This, constraint); - case TOTAL: - return encodeTotalOrderSATEncoder(This, constraint); - default: - ASSERT(0); - } - return E_BOGUS; -} - -Edge orderIntegerEncodingSATEncoder(SATEncoder *This, BooleanOrder *boolOrder){ - if(boolOrder->order->graph == NULL){ - bool doOptOrderStructure=GETVARTUNABLE(This->solver->tuner, boolOrder->order->type, - OPTIMIZEORDERSTRUCTURE, &onoff); - if (doOptOrderStructure ) { - boolOrder->order->graph = buildMustOrderGraph(boolOrder->order); - reachMustAnalysis(This->solver, boolOrder->order->graph, true); - } - } - Order* order = boolOrder->order; - Edge gvalue = inferOrderConstraintFromGraph(order, boolOrder->first, boolOrder->second); - if(!edgeIsNull(gvalue)) - return gvalue; - - if (boolOrder->order->elementTable == NULL) { - initializeOrderElementsHashTable(boolOrder->order); - } - //getting two elements and using LT predicate ... - Element* elem1 = getOrderIntegerElement(This, order, boolOrder->first); - ElementEncoding *encoding = getElementEncoding(elem1); - if (getElementEncodingType(encoding) == ELEM_UNASSIGNED) { - setElementEncodingType(encoding, BINARYINDEX); - encodingArrayInitialization(encoding); - } - Element* elem2 = getOrderIntegerElement(This, order, boolOrder->second); - encoding = getElementEncoding(elem2); - if (getElementEncodingType(encoding) == ELEM_UNASSIGNED) { - setElementEncodingType(encoding, BINARYINDEX); - encodingArrayInitialization(encoding); - } - Predicate *predicate =allocPredicateOperator(LT, (Set*[]){order->set, order->set}, 2); - Boolean * boolean=allocBooleanPredicate(predicate, (Element *[]){elem1,elem2}, 2, NULL); - setFunctionEncodingType(getPredicateFunctionEncoding((BooleanPredicate*)boolean), CIRCUIT); - {//Adding new elements and boolean/predicate to solver regarding memory management - pushVectorBoolean(This->solver->allBooleans, boolean); - pushVectorPredicate(This->solver->allPredicates, predicate); - pushVectorElement(This->solver->allElements, elem1); - pushVectorElement(This->solver->allElements, elem2); - } - return encodeConstraintSATEncoder(This, boolean); -} - -Edge inferOrderConstraintFromGraph(Order* order, uint64_t _first, uint64_t _second){ - if (order->graph != NULL) { - OrderGraph *graph=order->graph; - OrderNode *first=lookupOrderNodeFromOrderGraph(graph, _first); - OrderNode *second=lookupOrderNodeFromOrderGraph(graph, _second); - if ((first != NULL) && (second != NULL)) { - OrderEdge *edge=lookupOrderEdgeFromOrderGraph(graph, first, second); - if (edge != NULL) { - if (edge->mustPos) - return E_True; - else if (edge->mustNeg) - return E_False; - } - OrderEdge *invedge=getOrderEdgeFromOrderGraph(graph, second, first); - if (invedge != NULL) { - if (invedge->mustPos) - return E_False; - else if (invedge->mustNeg) - return E_True; - } - } - } - return E_NULL; -} - -Element* getOrderIntegerElement(SATEncoder* This,Order *order, uint64_t item) { - HashSetOrderElement* eset = order->elementTable; - OrderElement oelement ={item, NULL}; - if( !containsHashSetOrderElement(eset, &oelement)){ - Element* elem = allocElementSet(order->set); - ElementEncoding* encoding = getElementEncoding(elem); - setElementEncodingType(encoding, BINARYINDEX); - encodingArrayInitialization(encoding); - encodeElementSATEncoder(This, elem); - addHashSetOrderElement(eset, allocOrderElement(item, elem)); - return elem; - }else - return getHashSetOrderElement(eset, &oelement)->elem; -} -Edge getPairConstraint(SATEncoder *This, Order *order, OrderPair *pair) { - Edge gvalue = inferOrderConstraintFromGraph(order, pair->first, pair->second); - if(!edgeIsNull(gvalue)) - return gvalue; - - HashTableOrderPair *table = order->orderPairTable; - bool negate = false; - OrderPair flipped; - if (pair->first < pair->second) { - negate = true; - flipped.first = pair->second; - flipped.second = pair->first; - pair = &flipped; - } - Edge constraint; - if (!containsOrderPair(table, pair)) { - constraint = getNewVarSATEncoder(This); - OrderPair *paircopy = allocOrderPair(pair->first, pair->second, constraint); - putOrderPair(table, paircopy, paircopy); - } else - constraint = getOrderPair(table, pair)->constraint; - - return negate ? constraintNegate(constraint) : constraint; -} - -Edge encodeTotalOrderSATEncoder(SATEncoder *This, BooleanOrder *boolOrder) { - ASSERT(boolOrder->order->type == TOTAL); - if (boolOrder->order->orderPairTable == NULL) { - initializeOrderHashTable(boolOrder->order); - bool doOptOrderStructure=GETVARTUNABLE(This->solver->tuner, boolOrder->order->type, OPTIMIZEORDERSTRUCTURE, &onoff); - if (doOptOrderStructure) { - boolOrder->order->graph = buildMustOrderGraph(boolOrder->order); - reachMustAnalysis(This->solver, boolOrder->order->graph, true); - } - createAllTotalOrderConstraintsSATEncoder(This, boolOrder->order); - } - OrderPair pair = {boolOrder->first, boolOrder->second, E_NULL}; - Edge constraint = getPairConstraint(This, boolOrder->order, &pair); - return constraint; -} - - -void createAllTotalOrderConstraintsSATEncoder(SATEncoder *This, Order *order) { -#ifdef TRACE_DEBUG - model_print("in total order ...\n"); -#endif - ASSERT(order->type == TOTAL); - VectorInt *mems = order->set->members; - uint size = getSizeVectorInt(mems); - for (uint i = 0; i < size; i++) { - uint64_t valueI = getVectorInt(mems, i); - for (uint j = i + 1; j < size; j++) { - uint64_t valueJ = getVectorInt(mems, j); - OrderPair pairIJ = {valueI, valueJ}; - Edge constIJ = getPairConstraint(This, order, &pairIJ); - for (uint k = j + 1; k < size; k++) { - uint64_t valueK = getVectorInt(mems, k); - OrderPair pairJK = {valueJ, valueK}; - OrderPair pairIK = {valueI, valueK}; - Edge constIK = getPairConstraint(This, order, &pairIK); - Edge constJK = getPairConstraint(This, order, &pairJK); - addConstraintCNF(This->cnf, generateTransOrderConstraintSATEncoder(This, constIJ, constJK, constIK)); - } - } - } -} - -Edge getOrderConstraint(HashTableOrderPair *table, OrderPair *pair) { - ASSERT(pair->first != pair->second); - bool negate = false; - OrderPair flipped; - if (pair->first < pair->second) { - negate = true; - flipped.first = pair->second; - flipped.second = pair->first; - pair = &flipped; - } - if (!containsOrderPair(table, pair)) { - return E_NULL; - } - Edge constraint = getOrderPair(table, pair)->constraint; - ASSERT(!edgeIsNull(constraint)); - return negate ? constraintNegate(constraint) : constraint; -} - -Edge generateTransOrderConstraintSATEncoder(SATEncoder *This, Edge constIJ,Edge constJK,Edge constIK) { - Edge carray[] = {constIJ, constJK, constraintNegate(constIK)}; - Edge loop1 = constraintOR(This->cnf, 3, carray); - Edge carray2[] = {constraintNegate(constIJ), constraintNegate(constJK), constIK}; - Edge loop2 = constraintOR(This->cnf, 3, carray2 ); - return constraintAND2(This->cnf, loop1, loop2); -} - -Edge encodePartialOrderSATEncoder(SATEncoder *This, BooleanOrder *constraint) { - ASSERT(constraint->order->type == PARTIAL); - return E_BOGUS; -} diff --git a/src/Backend/satorderencoder.cc b/src/Backend/satorderencoder.cc new file mode 100644 index 0000000..64f414c --- /dev/null +++ b/src/Backend/satorderencoder.cc @@ -0,0 +1,208 @@ +#include "satencoder.h" +#include "structs.h" +#include "common.h" +#include "order.h" +#include "csolver.h" +#include "orderpair.h" +#include "set.h" +#include "tunable.h" +#include "orderencoder.h" +#include "ordergraph.h" +#include "orderedge.h" +#include "element.h" +#include "predicate.h" +#include "orderelement.h" + +Edge encodeOrderSATEncoder(SATEncoder *This, BooleanOrder *constraint) { + if(constraint->order->order.type == INTEGERENCODING){ + return orderIntegerEncodingSATEncoder(This, constraint); + } + switch ( constraint->order->type) { + case PARTIAL: + return encodePartialOrderSATEncoder(This, constraint); + case TOTAL: + return encodeTotalOrderSATEncoder(This, constraint); + default: + ASSERT(0); + } + return E_BOGUS; +} + +Edge orderIntegerEncodingSATEncoder(SATEncoder *This, BooleanOrder *boolOrder){ + if(boolOrder->order->graph == NULL){ + bool doOptOrderStructure=GETVARTUNABLE(This->solver->tuner, boolOrder->order->type, + OPTIMIZEORDERSTRUCTURE, &onoff); + if (doOptOrderStructure ) { + boolOrder->order->graph = buildMustOrderGraph(boolOrder->order); + reachMustAnalysis(This->solver, boolOrder->order->graph, true); + } + } + Order* order = boolOrder->order; + Edge gvalue = inferOrderConstraintFromGraph(order, boolOrder->first, boolOrder->second); + if(!edgeIsNull(gvalue)) + return gvalue; + + if (boolOrder->order->elementTable == NULL) { + initializeOrderElementsHashTable(boolOrder->order); + } + //getting two elements and using LT predicate ... + Element* elem1 = getOrderIntegerElement(This, order, boolOrder->first); + ElementEncoding *encoding = getElementEncoding(elem1); + if (getElementEncodingType(encoding) == ELEM_UNASSIGNED) { + setElementEncodingType(encoding, BINARYINDEX); + encodingArrayInitialization(encoding); + } + Element* elem2 = getOrderIntegerElement(This, order, boolOrder->second); + encoding = getElementEncoding(elem2); + if (getElementEncodingType(encoding) == ELEM_UNASSIGNED) { + setElementEncodingType(encoding, BINARYINDEX); + encodingArrayInitialization(encoding); + } + Predicate *predicate =allocPredicateOperator(LT, (Set*[]){order->set, order->set}, 2); + Boolean * boolean=allocBooleanPredicate(predicate, (Element *[]){elem1,elem2}, 2, NULL); + setFunctionEncodingType(getPredicateFunctionEncoding((BooleanPredicate*)boolean), CIRCUIT); + {//Adding new elements and boolean/predicate to solver regarding memory management + pushVectorBoolean(This->solver->allBooleans, boolean); + pushVectorPredicate(This->solver->allPredicates, predicate); + pushVectorElement(This->solver->allElements, elem1); + pushVectorElement(This->solver->allElements, elem2); + } + return encodeConstraintSATEncoder(This, boolean); +} + +Edge inferOrderConstraintFromGraph(Order* order, uint64_t _first, uint64_t _second){ + if (order->graph != NULL) { + OrderGraph *graph=order->graph; + OrderNode *first=lookupOrderNodeFromOrderGraph(graph, _first); + OrderNode *second=lookupOrderNodeFromOrderGraph(graph, _second); + if ((first != NULL) && (second != NULL)) { + OrderEdge *edge=lookupOrderEdgeFromOrderGraph(graph, first, second); + if (edge != NULL) { + if (edge->mustPos) + return E_True; + else if (edge->mustNeg) + return E_False; + } + OrderEdge *invedge=getOrderEdgeFromOrderGraph(graph, second, first); + if (invedge != NULL) { + if (invedge->mustPos) + return E_False; + else if (invedge->mustNeg) + return E_True; + } + } + } + return E_NULL; +} + +Element* getOrderIntegerElement(SATEncoder* This,Order *order, uint64_t item) { + HashSetOrderElement* eset = order->elementTable; + OrderElement oelement ={item, NULL}; + if( !containsHashSetOrderElement(eset, &oelement)){ + Element* elem = allocElementSet(order->set); + ElementEncoding* encoding = getElementEncoding(elem); + setElementEncodingType(encoding, BINARYINDEX); + encodingArrayInitialization(encoding); + encodeElementSATEncoder(This, elem); + addHashSetOrderElement(eset, allocOrderElement(item, elem)); + return elem; + }else + return getHashSetOrderElement(eset, &oelement)->elem; +} +Edge getPairConstraint(SATEncoder *This, Order *order, OrderPair *pair) { + Edge gvalue = inferOrderConstraintFromGraph(order, pair->first, pair->second); + if(!edgeIsNull(gvalue)) + return gvalue; + + HashTableOrderPair *table = order->orderPairTable; + bool negate = false; + OrderPair flipped; + if (pair->first < pair->second) { + negate = true; + flipped.first = pair->second; + flipped.second = pair->first; + pair = &flipped; + } + Edge constraint; + if (!containsOrderPair(table, pair)) { + constraint = getNewVarSATEncoder(This); + OrderPair *paircopy = allocOrderPair(pair->first, pair->second, constraint); + putOrderPair(table, paircopy, paircopy); + } else + constraint = getOrderPair(table, pair)->constraint; + + return negate ? constraintNegate(constraint) : constraint; +} + +Edge encodeTotalOrderSATEncoder(SATEncoder *This, BooleanOrder *boolOrder) { + ASSERT(boolOrder->order->type == TOTAL); + if (boolOrder->order->orderPairTable == NULL) { + initializeOrderHashTable(boolOrder->order); + bool doOptOrderStructure=GETVARTUNABLE(This->solver->tuner, boolOrder->order->type, OPTIMIZEORDERSTRUCTURE, &onoff); + if (doOptOrderStructure) { + boolOrder->order->graph = buildMustOrderGraph(boolOrder->order); + reachMustAnalysis(This->solver, boolOrder->order->graph, true); + } + createAllTotalOrderConstraintsSATEncoder(This, boolOrder->order); + } + OrderPair pair = {boolOrder->first, boolOrder->second, E_NULL}; + Edge constraint = getPairConstraint(This, boolOrder->order, &pair); + return constraint; +} + + +void createAllTotalOrderConstraintsSATEncoder(SATEncoder *This, Order *order) { +#ifdef TRACE_DEBUG + model_print("in total order ...\n"); +#endif + ASSERT(order->type == TOTAL); + VectorInt *mems = order->set->members; + uint size = getSizeVectorInt(mems); + for (uint i = 0; i < size; i++) { + uint64_t valueI = getVectorInt(mems, i); + for (uint j = i + 1; j < size; j++) { + uint64_t valueJ = getVectorInt(mems, j); + OrderPair pairIJ = {valueI, valueJ}; + Edge constIJ = getPairConstraint(This, order, &pairIJ); + for (uint k = j + 1; k < size; k++) { + uint64_t valueK = getVectorInt(mems, k); + OrderPair pairJK = {valueJ, valueK}; + OrderPair pairIK = {valueI, valueK}; + Edge constIK = getPairConstraint(This, order, &pairIK); + Edge constJK = getPairConstraint(This, order, &pairJK); + addConstraintCNF(This->cnf, generateTransOrderConstraintSATEncoder(This, constIJ, constJK, constIK)); + } + } + } +} + +Edge getOrderConstraint(HashTableOrderPair *table, OrderPair *pair) { + ASSERT(pair->first != pair->second); + bool negate = false; + OrderPair flipped; + if (pair->first < pair->second) { + negate = true; + flipped.first = pair->second; + flipped.second = pair->first; + pair = &flipped; + } + if (!containsOrderPair(table, pair)) { + return E_NULL; + } + Edge constraint = getOrderPair(table, pair)->constraint; + ASSERT(!edgeIsNull(constraint)); + return negate ? constraintNegate(constraint) : constraint; +} + +Edge generateTransOrderConstraintSATEncoder(SATEncoder *This, Edge constIJ,Edge constJK,Edge constIK) { + Edge carray[] = {constIJ, constJK, constraintNegate(constIK)}; + Edge loop1 = constraintOR(This->cnf, 3, carray); + Edge carray2[] = {constraintNegate(constIJ), constraintNegate(constJK), constIK}; + Edge loop2 = constraintOR(This->cnf, 3, carray2 ); + return constraintAND2(This->cnf, loop1, loop2); +} + +Edge encodePartialOrderSATEncoder(SATEncoder *This, BooleanOrder *constraint) { + ASSERT(constraint->order->type == PARTIAL); + return E_BOGUS; +} diff --git a/src/Backend/sattranslator.c b/src/Backend/sattranslator.c deleted file mode 100644 index ca0fdae..0000000 --- a/src/Backend/sattranslator.c +++ /dev/null @@ -1,96 +0,0 @@ -#include "sattranslator.h" -#include "element.h" -#include "csolver.h" -#include "satencoder.h" -#include "set.h" -#include "order.h" -#include "orderpair.h" - -uint64_t getElementValueBinaryIndexSATTranslator(CSolver *This, ElementEncoding *elemEnc) { - uint index = 0; - for (int i = elemEnc->numVars - 1; i >= 0; i--) { - index = index << 1; - if (getValueSolver(This->satEncoder->cnf->solver, getEdgeVar( elemEnc->variables[i] ))) - index |= 1; - } - model_print("index:%u\tencArraySize:%u\tisInUseElement:%u\n", index, elemEnc->encArraySize, isinUseElement(elemEnc, index)); - ASSERT(elemEnc->encArraySize > index && isinUseElement(elemEnc, index)); - return elemEnc->encodingArray[index]; -} - -uint64_t getElementValueBinaryValueSATTranslator(CSolver *This, ElementEncoding *elemEnc) { - uint64_t value = 0; - for (int i = elemEnc->numVars - 1; i >= 0; i--) { - value = value << 1; - if (getValueSolver(This->satEncoder->cnf->solver, getEdgeVar( elemEnc->variables[i] )) ) - value |= 1; - } - if (elemEnc->isBinaryValSigned && - This->satEncoder->cnf->solver->solution[ getEdgeVar( elemEnc->variables[elemEnc->numVars - 1])]) { - //Do sign extension of negative number - uint64_t highbits = 0xffffffffffffffff - ((1 << (elemEnc->numVars)) - 1); - value += highbits; - } - value += elemEnc->offset; - return value; -} - -uint64_t getElementValueOneHotSATTranslator(CSolver *This, ElementEncoding *elemEnc) { - uint index = 0; - for (uint i = 0; i < elemEnc->numVars; i++) { - if (getValueSolver(This->satEncoder->cnf->solver, getEdgeVar( elemEnc->variables[i] ))) - index = i; - } - ASSERT(elemEnc->encArraySize > index && isinUseElement(elemEnc, index)); - return elemEnc->encodingArray[index]; -} - -uint64_t getElementValueUnarySATTranslator(CSolver *This, ElementEncoding *elemEnc) { - uint i; - for (i = 0; i < elemEnc->numVars; i++) { - if (!getValueSolver(This->satEncoder->cnf->solver, getEdgeVar( elemEnc->variables[i] )) ) { - break; - } - } - - return elemEnc->encodingArray[i]; -} - -uint64_t getElementValueSATTranslator(CSolver *This, Element *element) { - ElementEncoding *elemEnc = getElementEncoding(element); - if (elemEnc->numVars == 0)//case when the set has only one item - return getSetElement(getElementSet(element), 0); - switch (elemEnc->type) { - case ONEHOT: - return getElementValueOneHotSATTranslator(This, elemEnc); - case UNARY: - return getElementValueUnarySATTranslator(This, elemEnc); - case BINARYINDEX: - return getElementValueBinaryIndexSATTranslator(This, elemEnc); - case ONEHOTBINARY: - ASSERT(0); - break; - case BINARYVAL: - ASSERT(0); - break; - default: - ASSERT(0); - break; - } - return -1; -} - -bool getBooleanVariableValueSATTranslator( CSolver *This, Boolean *boolean) { - int index = getEdgeVar( ((BooleanVar *) boolean)->var ); - return getValueSolver(This->satEncoder->cnf->solver, index); -} - -HappenedBefore getOrderConstraintValueSATTranslator(CSolver *This, Order *order, uint64_t first, uint64_t second) { - ASSERT(order->orderPairTable != NULL); - OrderPair pair = {first, second, E_NULL}; - Edge var = getOrderConstraint(order->orderPairTable, &pair); - if (edgeIsNull(var)) - return UNORDERED; - return getValueCNF(This->satEncoder->cnf, var) ? FIRST : SECOND; -} - diff --git a/src/Backend/sattranslator.cc b/src/Backend/sattranslator.cc new file mode 100644 index 0000000..ca0fdae --- /dev/null +++ b/src/Backend/sattranslator.cc @@ -0,0 +1,96 @@ +#include "sattranslator.h" +#include "element.h" +#include "csolver.h" +#include "satencoder.h" +#include "set.h" +#include "order.h" +#include "orderpair.h" + +uint64_t getElementValueBinaryIndexSATTranslator(CSolver *This, ElementEncoding *elemEnc) { + uint index = 0; + for (int i = elemEnc->numVars - 1; i >= 0; i--) { + index = index << 1; + if (getValueSolver(This->satEncoder->cnf->solver, getEdgeVar( elemEnc->variables[i] ))) + index |= 1; + } + model_print("index:%u\tencArraySize:%u\tisInUseElement:%u\n", index, elemEnc->encArraySize, isinUseElement(elemEnc, index)); + ASSERT(elemEnc->encArraySize > index && isinUseElement(elemEnc, index)); + return elemEnc->encodingArray[index]; +} + +uint64_t getElementValueBinaryValueSATTranslator(CSolver *This, ElementEncoding *elemEnc) { + uint64_t value = 0; + for (int i = elemEnc->numVars - 1; i >= 0; i--) { + value = value << 1; + if (getValueSolver(This->satEncoder->cnf->solver, getEdgeVar( elemEnc->variables[i] )) ) + value |= 1; + } + if (elemEnc->isBinaryValSigned && + This->satEncoder->cnf->solver->solution[ getEdgeVar( elemEnc->variables[elemEnc->numVars - 1])]) { + //Do sign extension of negative number + uint64_t highbits = 0xffffffffffffffff - ((1 << (elemEnc->numVars)) - 1); + value += highbits; + } + value += elemEnc->offset; + return value; +} + +uint64_t getElementValueOneHotSATTranslator(CSolver *This, ElementEncoding *elemEnc) { + uint index = 0; + for (uint i = 0; i < elemEnc->numVars; i++) { + if (getValueSolver(This->satEncoder->cnf->solver, getEdgeVar( elemEnc->variables[i] ))) + index = i; + } + ASSERT(elemEnc->encArraySize > index && isinUseElement(elemEnc, index)); + return elemEnc->encodingArray[index]; +} + +uint64_t getElementValueUnarySATTranslator(CSolver *This, ElementEncoding *elemEnc) { + uint i; + for (i = 0; i < elemEnc->numVars; i++) { + if (!getValueSolver(This->satEncoder->cnf->solver, getEdgeVar( elemEnc->variables[i] )) ) { + break; + } + } + + return elemEnc->encodingArray[i]; +} + +uint64_t getElementValueSATTranslator(CSolver *This, Element *element) { + ElementEncoding *elemEnc = getElementEncoding(element); + if (elemEnc->numVars == 0)//case when the set has only one item + return getSetElement(getElementSet(element), 0); + switch (elemEnc->type) { + case ONEHOT: + return getElementValueOneHotSATTranslator(This, elemEnc); + case UNARY: + return getElementValueUnarySATTranslator(This, elemEnc); + case BINARYINDEX: + return getElementValueBinaryIndexSATTranslator(This, elemEnc); + case ONEHOTBINARY: + ASSERT(0); + break; + case BINARYVAL: + ASSERT(0); + break; + default: + ASSERT(0); + break; + } + return -1; +} + +bool getBooleanVariableValueSATTranslator( CSolver *This, Boolean *boolean) { + int index = getEdgeVar( ((BooleanVar *) boolean)->var ); + return getValueSolver(This->satEncoder->cnf->solver, index); +} + +HappenedBefore getOrderConstraintValueSATTranslator(CSolver *This, Order *order, uint64_t first, uint64_t second) { + ASSERT(order->orderPairTable != NULL); + OrderPair pair = {first, second, E_NULL}; + Edge var = getOrderConstraint(order->orderPairTable, &pair); + if (edgeIsNull(var)) + return UNORDERED; + return getValueCNF(This->satEncoder->cnf, var) ? FIRST : SECOND; +} + diff --git a/src/Collections/structs.c b/src/Collections/structs.c deleted file mode 100644 index d6cdd16..0000000 --- a/src/Collections/structs.c +++ /dev/null @@ -1,91 +0,0 @@ -#include "structs.h" -#include "mymemory.h" -#include "orderpair.h" -#include "tableentry.h" -#include "ordernode.h" -#include "orderedge.h" -#include "ordergraph.h" -#include "orderelement.h" - -VectorImpl(Table, Table *, 4); -VectorImpl(Set, Set *, 4); -VectorImpl(Boolean, Boolean *, 4); -VectorImpl(BooleanOrder, BooleanOrder *, 4); -VectorImpl(Function, Function *, 4); -VectorImpl(Predicate, Predicate *, 4); -VectorImpl(Element, Element *, 4); -VectorImpl(Order, Order *, 4); -VectorImpl(TableEntry, TableEntry *, 4); -VectorImpl(ASTNode, ASTNode *, 4); -VectorImpl(Int, uint64_t, 4); -VectorImpl(OrderNode, OrderNode *, 4); -VectorImpl(OrderGraph, OrderGraph *, 4); - -static inline unsigned int Ptr_hash_function(void *hash) { - return (unsigned int)((int64)hash >> 4); -} - -static inline bool Ptr_equals(void *key1, void *key2) { - return key1 == key2; -} - -static inline unsigned int order_pair_hash_function(OrderPair *This) { - return (uint) (This->first << 2) ^ This->second; -} - -static inline unsigned int order_pair_equals(OrderPair *key1, OrderPair *key2) { - return key1->first == key2->first && key1->second == key2->second; -} - -static inline unsigned int table_entry_hash_function(TableEntry *This) { - unsigned int h = 0; - for (uint i = 0; i < This->inputSize; i++) { - h += This->inputs[i]; - h *= 31; - } - return h; -} - -static inline bool table_entry_equals(TableEntry *key1, TableEntry *key2) { - if (key1->inputSize != key2->inputSize) - return false; - for (uint i = 0; i < key1->inputSize; i++) - if (key1->inputs[i] != key2->inputs[i]) - return false; - return true; -} - -static inline unsigned int order_node_hash_function(OrderNode *This) { - return (uint) This->id; - -} - -static inline bool order_node_equals(OrderNode *key1, OrderNode *key2) { - return key1->id == key2->id; -} - -static inline unsigned int order_edge_hash_function(OrderEdge *This) { - return (uint) (((uintptr_t)This->sink) ^ ((uintptr_t)This->source << 4)); -} - -static inline bool order_edge_equals(OrderEdge *key1, OrderEdge *key2) { - return key1->sink == key2->sink && key1->source == key2->source; -} - -static inline unsigned int order_element_hash_function(OrderElement* This) { - return (uint)This->item; -} - -static inline bool order_element_equals(OrderElement* key1, OrderElement* key2) { - return key1->item == key2->item; -} - - -HashSetImpl(Boolean, Boolean *, Ptr_hash_function, Ptr_equals); -HashSetImpl(TableEntry, TableEntry *, table_entry_hash_function, table_entry_equals); -HashSetImpl(OrderNode, OrderNode *, order_node_hash_function, order_node_equals); -HashSetImpl(OrderEdge, OrderEdge *, order_edge_hash_function, order_edge_equals); -HashSetImpl(OrderElement, OrderElement *, order_element_hash_function, order_element_equals); - -HashTableImpl(NodeToNodeSet, OrderNode *, HashSetOrderNode *, Ptr_hash_function, Ptr_equals, deleteHashSetOrderNode); -HashTableImpl(OrderPair, OrderPair *, OrderPair *, order_pair_hash_function, order_pair_equals, ourfree); diff --git a/src/Collections/structs.cc b/src/Collections/structs.cc new file mode 100644 index 0000000..d6cdd16 --- /dev/null +++ b/src/Collections/structs.cc @@ -0,0 +1,91 @@ +#include "structs.h" +#include "mymemory.h" +#include "orderpair.h" +#include "tableentry.h" +#include "ordernode.h" +#include "orderedge.h" +#include "ordergraph.h" +#include "orderelement.h" + +VectorImpl(Table, Table *, 4); +VectorImpl(Set, Set *, 4); +VectorImpl(Boolean, Boolean *, 4); +VectorImpl(BooleanOrder, BooleanOrder *, 4); +VectorImpl(Function, Function *, 4); +VectorImpl(Predicate, Predicate *, 4); +VectorImpl(Element, Element *, 4); +VectorImpl(Order, Order *, 4); +VectorImpl(TableEntry, TableEntry *, 4); +VectorImpl(ASTNode, ASTNode *, 4); +VectorImpl(Int, uint64_t, 4); +VectorImpl(OrderNode, OrderNode *, 4); +VectorImpl(OrderGraph, OrderGraph *, 4); + +static inline unsigned int Ptr_hash_function(void *hash) { + return (unsigned int)((int64)hash >> 4); +} + +static inline bool Ptr_equals(void *key1, void *key2) { + return key1 == key2; +} + +static inline unsigned int order_pair_hash_function(OrderPair *This) { + return (uint) (This->first << 2) ^ This->second; +} + +static inline unsigned int order_pair_equals(OrderPair *key1, OrderPair *key2) { + return key1->first == key2->first && key1->second == key2->second; +} + +static inline unsigned int table_entry_hash_function(TableEntry *This) { + unsigned int h = 0; + for (uint i = 0; i < This->inputSize; i++) { + h += This->inputs[i]; + h *= 31; + } + return h; +} + +static inline bool table_entry_equals(TableEntry *key1, TableEntry *key2) { + if (key1->inputSize != key2->inputSize) + return false; + for (uint i = 0; i < key1->inputSize; i++) + if (key1->inputs[i] != key2->inputs[i]) + return false; + return true; +} + +static inline unsigned int order_node_hash_function(OrderNode *This) { + return (uint) This->id; + +} + +static inline bool order_node_equals(OrderNode *key1, OrderNode *key2) { + return key1->id == key2->id; +} + +static inline unsigned int order_edge_hash_function(OrderEdge *This) { + return (uint) (((uintptr_t)This->sink) ^ ((uintptr_t)This->source << 4)); +} + +static inline bool order_edge_equals(OrderEdge *key1, OrderEdge *key2) { + return key1->sink == key2->sink && key1->source == key2->source; +} + +static inline unsigned int order_element_hash_function(OrderElement* This) { + return (uint)This->item; +} + +static inline bool order_element_equals(OrderElement* key1, OrderElement* key2) { + return key1->item == key2->item; +} + + +HashSetImpl(Boolean, Boolean *, Ptr_hash_function, Ptr_equals); +HashSetImpl(TableEntry, TableEntry *, table_entry_hash_function, table_entry_equals); +HashSetImpl(OrderNode, OrderNode *, order_node_hash_function, order_node_equals); +HashSetImpl(OrderEdge, OrderEdge *, order_edge_hash_function, order_edge_equals); +HashSetImpl(OrderElement, OrderElement *, order_element_hash_function, order_element_equals); + +HashTableImpl(NodeToNodeSet, OrderNode *, HashSetOrderNode *, Ptr_hash_function, Ptr_equals, deleteHashSetOrderNode); +HashTableImpl(OrderPair, OrderPair *, OrderPair *, order_pair_hash_function, order_pair_equals, ourfree); diff --git a/src/Encoders/elementencoding.c b/src/Encoders/elementencoding.c deleted file mode 100644 index 1b0c6b8..0000000 --- a/src/Encoders/elementencoding.c +++ /dev/null @@ -1,40 +0,0 @@ -#include "elementencoding.h" -#include "common.h" -#include "naiveencoder.h" -#include "element.h" -#include "satencoder.h" - -void initElementEncoding(ElementEncoding *This, Element *element) { - This->element = element; - This->type = ELEM_UNASSIGNED; - This->variables = NULL; - This->encodingArray = NULL; - This->inUseArray = NULL; - This->numVars = 0; - This->encArraySize = 0; -} - -void deleteElementEncoding(ElementEncoding *This) { - if (This->variables != NULL) - ourfree(This->variables); - if (This->encodingArray != NULL) - ourfree(This->encodingArray); - if (This->inUseArray != NULL) - ourfree(This->inUseArray); -} - -void allocEncodingArrayElement(ElementEncoding *This, uint size) { - This->encodingArray = ourcalloc(1, sizeof(uint64_t) * size); - This->encArraySize = size; -} - -void allocInUseArrayElement(ElementEncoding *This, uint size) { - uint bytes = ((size + ((1 << 9) - 1)) >> 6) & ~7;//Depends on size of inUseArray - This->inUseArray = ourcalloc(1, bytes); -} - -void setElementEncodingType(ElementEncoding *This, ElementEncodingType type) { - This->type = type; -} - - diff --git a/src/Encoders/elementencoding.cc b/src/Encoders/elementencoding.cc new file mode 100644 index 0000000..dde2692 --- /dev/null +++ b/src/Encoders/elementencoding.cc @@ -0,0 +1,40 @@ +#include "elementencoding.h" +#include "common.h" +#include "naiveencoder.h" +#include "element.h" +#include "satencoder.h" + +void initElementEncoding(ElementEncoding *This, Element *element) { + This->element = element; + This->type = ELEM_UNASSIGNED; + This->variables = NULL; + This->encodingArray = NULL; + This->inUseArray = NULL; + This->numVars = 0; + This->encArraySize = 0; +} + +void deleteElementEncoding(ElementEncoding *This) { + if (This->variables != NULL) + ourfree(This->variables); + if (This->encodingArray != NULL) + ourfree(This->encodingArray); + if (This->inUseArray != NULL) + ourfree(This->inUseArray); +} + +void allocEncodingArrayElement(ElementEncoding *This, uint size) { + This->encodingArray = (uint64_t *) ourcalloc(1, sizeof(uint64_t) * size); + This->encArraySize = size; +} + +void allocInUseArrayElement(ElementEncoding *This, uint size) { + uint bytes = ((size + ((1 << 9) - 1)) >> 6) & ~7;//Depends on size of inUseArray + This->inUseArray = (uint64_t *) ourcalloc(1, bytes); +} + +void setElementEncodingType(ElementEncoding *This, ElementEncodingType type) { + This->type = type; +} + + diff --git a/src/Encoders/functionencoding.c b/src/Encoders/functionencoding.c deleted file mode 100644 index 75910cf..0000000 --- a/src/Encoders/functionencoding.c +++ /dev/null @@ -1,18 +0,0 @@ -#include "functionencoding.h" - -void initFunctionEncoding(FunctionEncoding *This, Element *function) { - This->op.function = function; - This->type = FUNC_UNASSIGNED; -} - -void initPredicateEncoding(FunctionEncoding *This, Boolean *predicate) { - This->op.predicate = predicate; - This->type = FUNC_UNASSIGNED; -} - -void deleteFunctionEncoding(FunctionEncoding *This) { -} - -void setFunctionEncodingType(FunctionEncoding *encoding, FunctionEncodingType type) { - encoding->type = type; -} diff --git a/src/Encoders/functionencoding.cc b/src/Encoders/functionencoding.cc new file mode 100644 index 0000000..75910cf --- /dev/null +++ b/src/Encoders/functionencoding.cc @@ -0,0 +1,18 @@ +#include "functionencoding.h" + +void initFunctionEncoding(FunctionEncoding *This, Element *function) { + This->op.function = function; + This->type = FUNC_UNASSIGNED; +} + +void initPredicateEncoding(FunctionEncoding *This, Boolean *predicate) { + This->op.predicate = predicate; + This->type = FUNC_UNASSIGNED; +} + +void deleteFunctionEncoding(FunctionEncoding *This) { +} + +void setFunctionEncodingType(FunctionEncoding *encoding, FunctionEncodingType type) { + encoding->type = type; +} diff --git a/src/Encoders/naiveencoder.c b/src/Encoders/naiveencoder.c deleted file mode 100644 index 71dc582..0000000 --- a/src/Encoders/naiveencoder.c +++ /dev/null @@ -1,108 +0,0 @@ -#include "naiveencoder.h" -#include "elementencoding.h" -#include "element.h" -#include "functionencoding.h" -#include "function.h" -#include "set.h" -#include "common.h" -#include "structs.h" -#include "csolver.h" -#include "boolean.h" -#include "table.h" -#include "tableentry.h" -#include "order.h" -#include - -void naiveEncodingDecision(CSolver *This) { - HSIteratorBoolean *iterator=iteratorBoolean(This->constraints); - while(hasNextBoolean(iterator)) { - Boolean *boolean = nextBoolean(iterator); - naiveEncodingConstraint(boolean); - } - deleteIterBoolean(iterator); -} - -void naiveEncodingConstraint(Boolean *This) { - switch (GETBOOLEANTYPE(This)) { - case BOOLEANVAR: { - return; - } - case ORDERCONST: { - setOrderEncodingType( ((BooleanOrder *)This)->order, PAIRWISE ); - return; - } - case LOGICOP: { - naiveEncodingLogicOp((BooleanLogic *) This); - return; - } - case PREDICATEOP: { - naiveEncodingPredicate((BooleanPredicate *) This); - return; - } - default: - ASSERT(0); - } -} - -void naiveEncodingLogicOp(BooleanLogic *This) { - for (uint i = 0; i < getSizeArrayBoolean(&This->inputs); i++) { - naiveEncodingConstraint(getArrayBoolean(&This->inputs, i)); - } -} - -void naiveEncodingPredicate(BooleanPredicate *This) { - FunctionEncoding *encoding = getPredicateFunctionEncoding(This); - if (getFunctionEncodingType(encoding) == FUNC_UNASSIGNED) - setFunctionEncodingType(getPredicateFunctionEncoding(This), ENUMERATEIMPLICATIONS); - - for (uint i = 0; i < getSizeArrayElement(&This->inputs); i++) { - Element *element = getArrayElement(&This->inputs, i); - naiveEncodingElement(element); - } -} - -void naiveEncodingElement(Element *This) { - ElementEncoding *encoding = getElementEncoding(This); - if (getElementEncodingType(encoding) == ELEM_UNASSIGNED) { - setElementEncodingType(encoding, BINARYINDEX); - encodingArrayInitialization(encoding); - } - - if (GETELEMENTTYPE(This) == ELEMFUNCRETURN) { - ElementFunction *function = (ElementFunction *) This; - for (uint i = 0; i < getSizeArrayElement(&function->inputs); i++) { - Element *element = getArrayElement(&function->inputs, i); - naiveEncodingElement(element); - } - FunctionEncoding *encoding = getElementFunctionEncoding(function); - if (getFunctionEncodingType(encoding) == FUNC_UNASSIGNED) - setFunctionEncodingType(getElementFunctionEncoding(function), ENUMERATEIMPLICATIONS); - } -} - -uint getSizeEncodingArray(ElementEncoding *This, uint setSize) { - switch (This->type) { - case BINARYINDEX: - return NEXTPOW2(setSize); - case ONEHOT: - case UNARY: - return setSize; - default: - ASSERT(0); - } - return -1; -} - -void encodingArrayInitialization(ElementEncoding *This) { - Element *element = This->element; - Set *set = getElementSet(element); - ASSERT(set->isRange == false); - uint size = getSizeVectorInt(set->members); - uint encSize = getSizeEncodingArray(This, size); - allocEncodingArrayElement(This, encSize); - allocInUseArrayElement(This, encSize); - for (uint i = 0; i < size; i++) { - This->encodingArray[i] = getVectorInt(set->members, i); - setInUseElement(This, i); - } -} diff --git a/src/Encoders/naiveencoder.cc b/src/Encoders/naiveencoder.cc new file mode 100644 index 0000000..71dc582 --- /dev/null +++ b/src/Encoders/naiveencoder.cc @@ -0,0 +1,108 @@ +#include "naiveencoder.h" +#include "elementencoding.h" +#include "element.h" +#include "functionencoding.h" +#include "function.h" +#include "set.h" +#include "common.h" +#include "structs.h" +#include "csolver.h" +#include "boolean.h" +#include "table.h" +#include "tableentry.h" +#include "order.h" +#include + +void naiveEncodingDecision(CSolver *This) { + HSIteratorBoolean *iterator=iteratorBoolean(This->constraints); + while(hasNextBoolean(iterator)) { + Boolean *boolean = nextBoolean(iterator); + naiveEncodingConstraint(boolean); + } + deleteIterBoolean(iterator); +} + +void naiveEncodingConstraint(Boolean *This) { + switch (GETBOOLEANTYPE(This)) { + case BOOLEANVAR: { + return; + } + case ORDERCONST: { + setOrderEncodingType( ((BooleanOrder *)This)->order, PAIRWISE ); + return; + } + case LOGICOP: { + naiveEncodingLogicOp((BooleanLogic *) This); + return; + } + case PREDICATEOP: { + naiveEncodingPredicate((BooleanPredicate *) This); + return; + } + default: + ASSERT(0); + } +} + +void naiveEncodingLogicOp(BooleanLogic *This) { + for (uint i = 0; i < getSizeArrayBoolean(&This->inputs); i++) { + naiveEncodingConstraint(getArrayBoolean(&This->inputs, i)); + } +} + +void naiveEncodingPredicate(BooleanPredicate *This) { + FunctionEncoding *encoding = getPredicateFunctionEncoding(This); + if (getFunctionEncodingType(encoding) == FUNC_UNASSIGNED) + setFunctionEncodingType(getPredicateFunctionEncoding(This), ENUMERATEIMPLICATIONS); + + for (uint i = 0; i < getSizeArrayElement(&This->inputs); i++) { + Element *element = getArrayElement(&This->inputs, i); + naiveEncodingElement(element); + } +} + +void naiveEncodingElement(Element *This) { + ElementEncoding *encoding = getElementEncoding(This); + if (getElementEncodingType(encoding) == ELEM_UNASSIGNED) { + setElementEncodingType(encoding, BINARYINDEX); + encodingArrayInitialization(encoding); + } + + if (GETELEMENTTYPE(This) == ELEMFUNCRETURN) { + ElementFunction *function = (ElementFunction *) This; + for (uint i = 0; i < getSizeArrayElement(&function->inputs); i++) { + Element *element = getArrayElement(&function->inputs, i); + naiveEncodingElement(element); + } + FunctionEncoding *encoding = getElementFunctionEncoding(function); + if (getFunctionEncodingType(encoding) == FUNC_UNASSIGNED) + setFunctionEncodingType(getElementFunctionEncoding(function), ENUMERATEIMPLICATIONS); + } +} + +uint getSizeEncodingArray(ElementEncoding *This, uint setSize) { + switch (This->type) { + case BINARYINDEX: + return NEXTPOW2(setSize); + case ONEHOT: + case UNARY: + return setSize; + default: + ASSERT(0); + } + return -1; +} + +void encodingArrayInitialization(ElementEncoding *This) { + Element *element = This->element; + Set *set = getElementSet(element); + ASSERT(set->isRange == false); + uint size = getSizeVectorInt(set->members); + uint encSize = getSizeEncodingArray(This, size); + allocEncodingArrayElement(This, encSize); + allocInUseArrayElement(This, encSize); + for (uint i = 0; i < size; i++) { + This->encodingArray[i] = getVectorInt(set->members, i); + setInUseElement(This, i); + } +} diff --git a/src/Encoders/orderedge.c b/src/Encoders/orderedge.c deleted file mode 100644 index c4632da..0000000 --- a/src/Encoders/orderedge.c +++ /dev/null @@ -1,19 +0,0 @@ -#include "orderedge.h" -#include "ordergraph.h" - -OrderEdge *allocOrderEdge(OrderNode *source, OrderNode *sink) { - OrderEdge *This = (OrderEdge *) ourmalloc(sizeof(OrderEdge)); - This->source = source; - This->sink = sink; - This->polPos = false; - This->polNeg = false; - This->mustPos = false; - This->mustNeg = false; - This->pseudoPos = false; - return This; -} - -void deleteOrderEdge(OrderEdge *This) { - ourfree(This); -} - diff --git a/src/Encoders/orderedge.cc b/src/Encoders/orderedge.cc new file mode 100644 index 0000000..c4632da --- /dev/null +++ b/src/Encoders/orderedge.cc @@ -0,0 +1,19 @@ +#include "orderedge.h" +#include "ordergraph.h" + +OrderEdge *allocOrderEdge(OrderNode *source, OrderNode *sink) { + OrderEdge *This = (OrderEdge *) ourmalloc(sizeof(OrderEdge)); + This->source = source; + This->sink = sink; + This->polPos = false; + This->polNeg = false; + This->mustPos = false; + This->mustNeg = false; + This->pseudoPos = false; + return This; +} + +void deleteOrderEdge(OrderEdge *This) { + ourfree(This); +} + diff --git a/src/Encoders/orderencoder.c b/src/Encoders/orderencoder.c deleted file mode 100644 index 99f826b..0000000 --- a/src/Encoders/orderencoder.c +++ /dev/null @@ -1,442 +0,0 @@ -#include "orderencoder.h" -#include "structs.h" -#include "csolver.h" -#include "boolean.h" -#include "ordergraph.h" -#include "order.h" -#include "ordernode.h" -#include "rewriter.h" -#include "mutableset.h" -#include "tunable.h" - -void DFS(OrderGraph *graph, VectorOrderNode *finishNodes) { - HSIteratorOrderNode *iterator = iteratorOrderNode(graph->nodes); - while (hasNextOrderNode(iterator)) { - OrderNode *node = nextOrderNode(iterator); - if (node->status == NOTVISITED) { - node->status = VISITED; - DFSNodeVisit(node, finishNodes, false, false, 0); - node->status = FINISHED; - pushVectorOrderNode(finishNodes, node); - } - } - deleteIterOrderNode(iterator); -} - -void DFSReverse(OrderGraph *graph, VectorOrderNode *finishNodes) { - uint size = getSizeVectorOrderNode(finishNodes); - uint sccNum = 1; - for (int i = size - 1; i >= 0; i--) { - OrderNode *node = getVectorOrderNode(finishNodes, i); - if (node->status == NOTVISITED) { - node->status = VISITED; - DFSNodeVisit(node, NULL, true, false, sccNum); - node->sccNum = sccNum; - node->status = FINISHED; - sccNum++; - } - } -} - -void DFSNodeVisit(OrderNode *node, VectorOrderNode *finishNodes, bool isReverse, bool mustvisit, uint sccNum) { - HSIteratorOrderEdge *iterator = isReverse ? iteratorOrderEdge(node->inEdges) : iteratorOrderEdge(node->outEdges); - while (hasNextOrderEdge(iterator)) { - OrderEdge *edge = nextOrderEdge(iterator); - if (mustvisit) { - if (!edge->mustPos) - continue; - } else - if (!edge->polPos && !edge->pseudoPos)//Ignore edges that do not have positive polarity - continue; - - OrderNode *child = isReverse ? edge->source : edge->sink; - - if (child->status == NOTVISITED) { - child->status = VISITED; - DFSNodeVisit(child, finishNodes, isReverse, mustvisit, sccNum); - child->status = FINISHED; - if (finishNodes != NULL) - pushVectorOrderNode(finishNodes, child); - if (isReverse) - child->sccNum = sccNum; - } - } - deleteIterOrderEdge(iterator); -} - -void resetNodeInfoStatusSCC(OrderGraph *graph) { - HSIteratorOrderNode *iterator = iteratorOrderNode(graph->nodes); - while (hasNextOrderNode(iterator)) { - nextOrderNode(iterator)->status = NOTVISITED; - } - deleteIterOrderNode(iterator); -} - -void computeStronglyConnectedComponentGraph(OrderGraph *graph) { - VectorOrderNode finishNodes; - initDefVectorOrderNode(&finishNodes); - DFS(graph, &finishNodes); - resetNodeInfoStatusSCC(graph); - DFSReverse(graph, &finishNodes); - resetNodeInfoStatusSCC(graph); - deleteVectorArrayOrderNode(&finishNodes); -} - -void removeMustBeTrueNodes(OrderGraph *graph) { - //TODO: Nodes that all the incoming/outgoing edges are MUST_BE_TRUE -} - -/** This function computes a source set for every nodes, the set of - nodes that can reach that node via pospolarity edges. It then - looks for negative polarity edges from nodes in the the source set - to determine whether we need to generate pseudoPos edges. */ - -void completePartialOrderGraph(OrderGraph *graph) { - VectorOrderNode finishNodes; - initDefVectorOrderNode(&finishNodes); - DFS(graph, &finishNodes); - resetNodeInfoStatusSCC(graph); - HashTableNodeToNodeSet *table = allocHashTableNodeToNodeSet(128, 0.25); - - VectorOrderNode sccNodes; - initDefVectorOrderNode(&sccNodes); - - uint size = getSizeVectorOrderNode(&finishNodes); - uint sccNum = 1; - for (int i = size - 1; i >= 0; i--) { - OrderNode *node = getVectorOrderNode(&finishNodes, i); - HashSetOrderNode *sources = allocHashSetOrderNode(4, 0.25); - putNodeToNodeSet(table, node, sources); - - if (node->status == NOTVISITED) { - //Need to do reverse traversal here... - node->status = VISITED; - DFSNodeVisit(node, &sccNodes, true, false, sccNum); - node->status = FINISHED; - node->sccNum = sccNum; - sccNum++; - pushVectorOrderNode(&sccNodes, node); - - //Compute in set for entire SCC - uint rSize = getSizeVectorOrderNode(&sccNodes); - for (int j = 0; j < rSize; j++) { - OrderNode *rnode = getVectorOrderNode(&sccNodes, j); - //Compute source sets - HSIteratorOrderEdge *iterator = iteratorOrderEdge(rnode->inEdges); - while (hasNextOrderEdge(iterator)) { - OrderEdge *edge = nextOrderEdge(iterator); - OrderNode *parent = edge->source; - if (edge->polPos) { - addHashSetOrderNode(sources, parent); - HashSetOrderNode *parent_srcs = (HashSetOrderNode *)getNodeToNodeSet(table, parent); - addAllHashSetOrderNode(sources, parent_srcs); - } - } - deleteIterOrderEdge(iterator); - } - for (int j=0; j < rSize; j++) { - //Copy in set of entire SCC - OrderNode *rnode = getVectorOrderNode(&sccNodes, j); - HashSetOrderNode * set = (j==0) ? sources : copyHashSetOrderNode(sources); - putNodeToNodeSet(table, rnode, set); - - //Use source sets to compute pseudoPos edges - HSIteratorOrderEdge *iterator = iteratorOrderEdge(rnode->inEdges); - while (hasNextOrderEdge(iterator)) { - OrderEdge *edge = nextOrderEdge(iterator); - OrderNode *parent = edge->source; - ASSERT(parent != rnode); - if (edge->polNeg && parent->sccNum != rnode->sccNum && - containsHashSetOrderNode(sources, parent)) { - OrderEdge *newedge = getOrderEdgeFromOrderGraph(graph, rnode, parent); - newedge->pseudoPos = true; - } - } - deleteIterOrderEdge(iterator); - } - - clearVectorOrderNode(&sccNodes); - } - } - - resetAndDeleteHashTableNodeToNodeSet(table); - deleteHashTableNodeToNodeSet(table); - resetNodeInfoStatusSCC(graph); - deleteVectorArrayOrderNode(&sccNodes); - deleteVectorArrayOrderNode(&finishNodes); -} - -void DFSMust(OrderGraph *graph, VectorOrderNode *finishNodes) { - HSIteratorOrderNode *iterator = iteratorOrderNode(graph->nodes); - while (hasNextOrderNode(iterator)) { - OrderNode *node = nextOrderNode(iterator); - if (node->status == NOTVISITED) { - node->status = VISITED; - DFSNodeVisit(node, finishNodes, false, true, 0); - node->status = FINISHED; - pushVectorOrderNode(finishNodes, node); - } - } - deleteIterOrderNode(iterator); -} - -void DFSClearContradictions(CSolver *solver, OrderGraph *graph, VectorOrderNode *finishNodes, bool computeTransitiveClosure) { - uint size = getSizeVectorOrderNode(finishNodes); - HashTableNodeToNodeSet *table = allocHashTableNodeToNodeSet(128, 0.25); - - for (int i = size - 1; i >= 0; i--) { - OrderNode *node = getVectorOrderNode(finishNodes, i); - HashSetOrderNode *sources = allocHashSetOrderNode(4, 0.25); - putNodeToNodeSet(table, node, sources); - - { - //Compute source sets - HSIteratorOrderEdge *iterator = iteratorOrderEdge(node->inEdges); - while (hasNextOrderEdge(iterator)) { - OrderEdge *edge = nextOrderEdge(iterator); - OrderNode *parent = edge->source; - if (edge->mustPos) { - addHashSetOrderNode(sources, parent); - HashSetOrderNode *parent_srcs = (HashSetOrderNode *)getNodeToNodeSet(table, parent); - addAllHashSetOrderNode(sources, parent_srcs); - } - } - deleteIterOrderEdge(iterator); - } - if (computeTransitiveClosure) { - //Compute full transitive closure for nodes - HSIteratorOrderNode *srciterator = iteratorOrderNode(sources); - while (hasNextOrderNode(srciterator)) { - OrderNode *srcnode = nextOrderNode(srciterator); - OrderEdge *newedge = getOrderEdgeFromOrderGraph(graph, srcnode, node); - newedge->mustPos = true; - newedge->polPos = true; - if (newedge->mustNeg) - solver->unsat = true; - addHashSetOrderEdge(srcnode->outEdges,newedge); - addHashSetOrderEdge(node->inEdges,newedge); - } - deleteIterOrderNode(srciterator); - } - { - //Use source sets to compute mustPos edges - HSIteratorOrderEdge *iterator = iteratorOrderEdge(node->inEdges); - while (hasNextOrderEdge(iterator)) { - OrderEdge *edge = nextOrderEdge(iterator); - OrderNode *parent = edge->source; - if (!edge->mustPos && containsHashSetOrderNode(sources, parent)) { - edge->mustPos = true; - edge->polPos = true; - if (edge->mustNeg) - solver->unsat = true; - } - } - deleteIterOrderEdge(iterator); - } - { - //Use source sets to compute mustNeg for edges that would introduce cycle if true - HSIteratorOrderEdge *iterator = iteratorOrderEdge(node->outEdges); - while (hasNextOrderEdge(iterator)) { - OrderEdge *edge = nextOrderEdge(iterator); - OrderNode *child = edge->sink; - if (!edge->mustNeg && containsHashSetOrderNode(sources, child)) { - edge->mustNeg = true; - edge->polNeg = true; - if (edge->mustPos) - solver->unsat = true; - } - } - deleteIterOrderEdge(iterator); - } - } - - resetAndDeleteHashTableNodeToNodeSet(table); - deleteHashTableNodeToNodeSet(table); -} - -/* This function finds edges that would form a cycle with must edges - and forces them to be mustNeg. It also decides whether an edge - must be true because of transitivity from other must be true - edges. */ - -void reachMustAnalysis(CSolver * solver, OrderGraph *graph, bool computeTransitiveClosure) { - VectorOrderNode finishNodes; - initDefVectorOrderNode(&finishNodes); - //Topologically sort the mustPos edge graph - DFSMust(graph, &finishNodes); - resetNodeInfoStatusSCC(graph); - - //Find any backwards edges that complete cycles and force them to be mustNeg - DFSClearContradictions(solver, graph, &finishNodes, computeTransitiveClosure); - deleteVectorArrayOrderNode(&finishNodes); -} - -/* This function finds edges that must be positive and forces the - inverse edge to be negative (and clears its positive polarity if it - had one). */ - -void localMustAnalysisTotal(CSolver *solver, OrderGraph *graph) { - HSIteratorOrderEdge *iterator = iteratorOrderEdge(graph->edges); - while (hasNextOrderEdge(iterator)) { - OrderEdge *edge = nextOrderEdge(iterator); - if (edge->mustPos) { - OrderEdge *invEdge = getInverseOrderEdge(graph, edge); - if (invEdge != NULL) { - if (!invEdge->mustPos) { - invEdge->polPos = false; - } else { - solver->unsat = true; - } - invEdge->mustNeg = true; - invEdge->polNeg = true; - } - } - } - deleteIterOrderEdge(iterator); -} - -/** This finds edges that must be positive and forces the inverse edge - to be negative. It also clears the negative flag of this edge. - It also finds edges that must be negative and clears the positive - polarity. */ - -void localMustAnalysisPartial(CSolver *solver, OrderGraph *graph) { - HSIteratorOrderEdge *iterator = iteratorOrderEdge(graph->edges); - while (hasNextOrderEdge(iterator)) { - OrderEdge *edge = nextOrderEdge(iterator); - if (edge->mustPos) { - if (!edge->mustNeg) { - edge->polNeg = false; - } else - solver->unsat = true; - - OrderEdge *invEdge = getInverseOrderEdge(graph, edge); - if (invEdge != NULL) { - if (!invEdge->mustPos) - invEdge->polPos = false; - else - solver->unsat = true; - invEdge->mustNeg = true; - invEdge->polNeg = true; - } - } - if (edge->mustNeg && !edge->mustPos) { - edge->polPos = false; - } - } - deleteIterOrderEdge(iterator); -} - -void decomposeOrder(CSolver *This, Order *order, OrderGraph *graph) { - VectorOrder ordervec; - VectorOrder partialcandidatevec; - initDefVectorOrder(&ordervec); - initDefVectorOrder(&partialcandidatevec); - uint size = getSizeVectorBooleanOrder(&order->constraints); - for (uint i = 0; i < size; i++) { - BooleanOrder *orderconstraint = getVectorBooleanOrder(&order->constraints, i); - OrderNode *from = getOrderNodeFromOrderGraph(graph, orderconstraint->first); - OrderNode *to = getOrderNodeFromOrderGraph(graph, orderconstraint->second); - model_print("from->sccNum:%u\tto->sccNum:%u\n", from->sccNum, to->sccNum); - if (from->sccNum != to->sccNum) { - OrderEdge *edge = getOrderEdgeFromOrderGraph(graph, from, to); - if (edge->polPos) { - replaceBooleanWithTrue(This, (Boolean *)orderconstraint); - } else if (edge->polNeg) { - replaceBooleanWithFalse(This, (Boolean *)orderconstraint); - } else { - //This case should only be possible if constraint isn't in AST - ASSERT(0); - } - } else { - //Build new order and change constraint's order - Order *neworder = NULL; - if (getSizeVectorOrder(&ordervec) > from->sccNum) - neworder = getVectorOrder(&ordervec, from->sccNum); - if (neworder == NULL) { - Set *set = (Set *) allocMutableSet(order->set->type); - neworder = allocOrder(order->type, set); - pushVectorOrder(This->allOrders, neworder); - setExpandVectorOrder(&ordervec, from->sccNum, neworder); - if (order->type == PARTIAL) - setExpandVectorOrder(&partialcandidatevec, from->sccNum, neworder); - else - setExpandVectorOrder(&partialcandidatevec, from->sccNum, NULL); - } - if (from->status != ADDEDTOSET) { - from->status = ADDEDTOSET; - addElementMSet((MutableSet *)neworder->set, from->id); - } - if (to->status != ADDEDTOSET) { - to->status = ADDEDTOSET; - addElementMSet((MutableSet *)neworder->set, to->id); - } - if (order->type == PARTIAL) { - OrderEdge *edge = getOrderEdgeFromOrderGraph(graph, from, to); - if (edge->polNeg) - setExpandVectorOrder(&partialcandidatevec, from->sccNum, NULL); - } - orderconstraint->order = neworder; - addOrderConstraint(neworder, orderconstraint); - } - } - - uint pcvsize=getSizeVectorOrder(&partialcandidatevec); - for(uint i=0;itype = TOTAL; - model_print("i=%u\t", i); - } - } - - deleteVectorArrayOrder(&ordervec); - deleteVectorArrayOrder(&partialcandidatevec); -} - -void orderAnalysis(CSolver *This) { - uint size = getSizeVectorOrder(This->allOrders); - for (uint i = 0; i < size; i++) { - Order *order = getVectorOrder(This->allOrders, i); - bool doDecompose=GETVARTUNABLE(This->tuner, order->type, DECOMPOSEORDER, &onoff); - if (!doDecompose) - continue; - - OrderGraph *graph = buildOrderGraph(order); - if (order->type == PARTIAL) { - //Required to do SCC analysis for partial order graphs. It - //makes sure we don't incorrectly optimize graphs with negative - //polarity edges - completePartialOrderGraph(graph); - } - - - bool mustReachGlobal=GETVARTUNABLE(This->tuner, order->type, MUSTREACHGLOBAL, &onoff); - - if (mustReachGlobal) - reachMustAnalysis(This, graph, false); - - bool mustReachLocal=GETVARTUNABLE(This->tuner, order->type, MUSTREACHLOCAL, &onoff); - - if (mustReachLocal) { - //This pair of analysis is also optional - if (order->type == PARTIAL) { - localMustAnalysisPartial(This, graph); - } else { - localMustAnalysisTotal(This, graph); - } - } - - bool mustReachPrune=GETVARTUNABLE(This->tuner, order->type, MUSTREACHPRUNE, &onoff); - - if (mustReachPrune) - removeMustBeTrueNodes(graph); - - //This is needed for splitorder - computeStronglyConnectedComponentGraph(graph); - - decomposeOrder(This, order, graph); - - deleteOrderGraph(graph); - } -} diff --git a/src/Encoders/orderencoder.cc b/src/Encoders/orderencoder.cc new file mode 100644 index 0000000..99f826b --- /dev/null +++ b/src/Encoders/orderencoder.cc @@ -0,0 +1,442 @@ +#include "orderencoder.h" +#include "structs.h" +#include "csolver.h" +#include "boolean.h" +#include "ordergraph.h" +#include "order.h" +#include "ordernode.h" +#include "rewriter.h" +#include "mutableset.h" +#include "tunable.h" + +void DFS(OrderGraph *graph, VectorOrderNode *finishNodes) { + HSIteratorOrderNode *iterator = iteratorOrderNode(graph->nodes); + while (hasNextOrderNode(iterator)) { + OrderNode *node = nextOrderNode(iterator); + if (node->status == NOTVISITED) { + node->status = VISITED; + DFSNodeVisit(node, finishNodes, false, false, 0); + node->status = FINISHED; + pushVectorOrderNode(finishNodes, node); + } + } + deleteIterOrderNode(iterator); +} + +void DFSReverse(OrderGraph *graph, VectorOrderNode *finishNodes) { + uint size = getSizeVectorOrderNode(finishNodes); + uint sccNum = 1; + for (int i = size - 1; i >= 0; i--) { + OrderNode *node = getVectorOrderNode(finishNodes, i); + if (node->status == NOTVISITED) { + node->status = VISITED; + DFSNodeVisit(node, NULL, true, false, sccNum); + node->sccNum = sccNum; + node->status = FINISHED; + sccNum++; + } + } +} + +void DFSNodeVisit(OrderNode *node, VectorOrderNode *finishNodes, bool isReverse, bool mustvisit, uint sccNum) { + HSIteratorOrderEdge *iterator = isReverse ? iteratorOrderEdge(node->inEdges) : iteratorOrderEdge(node->outEdges); + while (hasNextOrderEdge(iterator)) { + OrderEdge *edge = nextOrderEdge(iterator); + if (mustvisit) { + if (!edge->mustPos) + continue; + } else + if (!edge->polPos && !edge->pseudoPos)//Ignore edges that do not have positive polarity + continue; + + OrderNode *child = isReverse ? edge->source : edge->sink; + + if (child->status == NOTVISITED) { + child->status = VISITED; + DFSNodeVisit(child, finishNodes, isReverse, mustvisit, sccNum); + child->status = FINISHED; + if (finishNodes != NULL) + pushVectorOrderNode(finishNodes, child); + if (isReverse) + child->sccNum = sccNum; + } + } + deleteIterOrderEdge(iterator); +} + +void resetNodeInfoStatusSCC(OrderGraph *graph) { + HSIteratorOrderNode *iterator = iteratorOrderNode(graph->nodes); + while (hasNextOrderNode(iterator)) { + nextOrderNode(iterator)->status = NOTVISITED; + } + deleteIterOrderNode(iterator); +} + +void computeStronglyConnectedComponentGraph(OrderGraph *graph) { + VectorOrderNode finishNodes; + initDefVectorOrderNode(&finishNodes); + DFS(graph, &finishNodes); + resetNodeInfoStatusSCC(graph); + DFSReverse(graph, &finishNodes); + resetNodeInfoStatusSCC(graph); + deleteVectorArrayOrderNode(&finishNodes); +} + +void removeMustBeTrueNodes(OrderGraph *graph) { + //TODO: Nodes that all the incoming/outgoing edges are MUST_BE_TRUE +} + +/** This function computes a source set for every nodes, the set of + nodes that can reach that node via pospolarity edges. It then + looks for negative polarity edges from nodes in the the source set + to determine whether we need to generate pseudoPos edges. */ + +void completePartialOrderGraph(OrderGraph *graph) { + VectorOrderNode finishNodes; + initDefVectorOrderNode(&finishNodes); + DFS(graph, &finishNodes); + resetNodeInfoStatusSCC(graph); + HashTableNodeToNodeSet *table = allocHashTableNodeToNodeSet(128, 0.25); + + VectorOrderNode sccNodes; + initDefVectorOrderNode(&sccNodes); + + uint size = getSizeVectorOrderNode(&finishNodes); + uint sccNum = 1; + for (int i = size - 1; i >= 0; i--) { + OrderNode *node = getVectorOrderNode(&finishNodes, i); + HashSetOrderNode *sources = allocHashSetOrderNode(4, 0.25); + putNodeToNodeSet(table, node, sources); + + if (node->status == NOTVISITED) { + //Need to do reverse traversal here... + node->status = VISITED; + DFSNodeVisit(node, &sccNodes, true, false, sccNum); + node->status = FINISHED; + node->sccNum = sccNum; + sccNum++; + pushVectorOrderNode(&sccNodes, node); + + //Compute in set for entire SCC + uint rSize = getSizeVectorOrderNode(&sccNodes); + for (int j = 0; j < rSize; j++) { + OrderNode *rnode = getVectorOrderNode(&sccNodes, j); + //Compute source sets + HSIteratorOrderEdge *iterator = iteratorOrderEdge(rnode->inEdges); + while (hasNextOrderEdge(iterator)) { + OrderEdge *edge = nextOrderEdge(iterator); + OrderNode *parent = edge->source; + if (edge->polPos) { + addHashSetOrderNode(sources, parent); + HashSetOrderNode *parent_srcs = (HashSetOrderNode *)getNodeToNodeSet(table, parent); + addAllHashSetOrderNode(sources, parent_srcs); + } + } + deleteIterOrderEdge(iterator); + } + for (int j=0; j < rSize; j++) { + //Copy in set of entire SCC + OrderNode *rnode = getVectorOrderNode(&sccNodes, j); + HashSetOrderNode * set = (j==0) ? sources : copyHashSetOrderNode(sources); + putNodeToNodeSet(table, rnode, set); + + //Use source sets to compute pseudoPos edges + HSIteratorOrderEdge *iterator = iteratorOrderEdge(rnode->inEdges); + while (hasNextOrderEdge(iterator)) { + OrderEdge *edge = nextOrderEdge(iterator); + OrderNode *parent = edge->source; + ASSERT(parent != rnode); + if (edge->polNeg && parent->sccNum != rnode->sccNum && + containsHashSetOrderNode(sources, parent)) { + OrderEdge *newedge = getOrderEdgeFromOrderGraph(graph, rnode, parent); + newedge->pseudoPos = true; + } + } + deleteIterOrderEdge(iterator); + } + + clearVectorOrderNode(&sccNodes); + } + } + + resetAndDeleteHashTableNodeToNodeSet(table); + deleteHashTableNodeToNodeSet(table); + resetNodeInfoStatusSCC(graph); + deleteVectorArrayOrderNode(&sccNodes); + deleteVectorArrayOrderNode(&finishNodes); +} + +void DFSMust(OrderGraph *graph, VectorOrderNode *finishNodes) { + HSIteratorOrderNode *iterator = iteratorOrderNode(graph->nodes); + while (hasNextOrderNode(iterator)) { + OrderNode *node = nextOrderNode(iterator); + if (node->status == NOTVISITED) { + node->status = VISITED; + DFSNodeVisit(node, finishNodes, false, true, 0); + node->status = FINISHED; + pushVectorOrderNode(finishNodes, node); + } + } + deleteIterOrderNode(iterator); +} + +void DFSClearContradictions(CSolver *solver, OrderGraph *graph, VectorOrderNode *finishNodes, bool computeTransitiveClosure) { + uint size = getSizeVectorOrderNode(finishNodes); + HashTableNodeToNodeSet *table = allocHashTableNodeToNodeSet(128, 0.25); + + for (int i = size - 1; i >= 0; i--) { + OrderNode *node = getVectorOrderNode(finishNodes, i); + HashSetOrderNode *sources = allocHashSetOrderNode(4, 0.25); + putNodeToNodeSet(table, node, sources); + + { + //Compute source sets + HSIteratorOrderEdge *iterator = iteratorOrderEdge(node->inEdges); + while (hasNextOrderEdge(iterator)) { + OrderEdge *edge = nextOrderEdge(iterator); + OrderNode *parent = edge->source; + if (edge->mustPos) { + addHashSetOrderNode(sources, parent); + HashSetOrderNode *parent_srcs = (HashSetOrderNode *)getNodeToNodeSet(table, parent); + addAllHashSetOrderNode(sources, parent_srcs); + } + } + deleteIterOrderEdge(iterator); + } + if (computeTransitiveClosure) { + //Compute full transitive closure for nodes + HSIteratorOrderNode *srciterator = iteratorOrderNode(sources); + while (hasNextOrderNode(srciterator)) { + OrderNode *srcnode = nextOrderNode(srciterator); + OrderEdge *newedge = getOrderEdgeFromOrderGraph(graph, srcnode, node); + newedge->mustPos = true; + newedge->polPos = true; + if (newedge->mustNeg) + solver->unsat = true; + addHashSetOrderEdge(srcnode->outEdges,newedge); + addHashSetOrderEdge(node->inEdges,newedge); + } + deleteIterOrderNode(srciterator); + } + { + //Use source sets to compute mustPos edges + HSIteratorOrderEdge *iterator = iteratorOrderEdge(node->inEdges); + while (hasNextOrderEdge(iterator)) { + OrderEdge *edge = nextOrderEdge(iterator); + OrderNode *parent = edge->source; + if (!edge->mustPos && containsHashSetOrderNode(sources, parent)) { + edge->mustPos = true; + edge->polPos = true; + if (edge->mustNeg) + solver->unsat = true; + } + } + deleteIterOrderEdge(iterator); + } + { + //Use source sets to compute mustNeg for edges that would introduce cycle if true + HSIteratorOrderEdge *iterator = iteratorOrderEdge(node->outEdges); + while (hasNextOrderEdge(iterator)) { + OrderEdge *edge = nextOrderEdge(iterator); + OrderNode *child = edge->sink; + if (!edge->mustNeg && containsHashSetOrderNode(sources, child)) { + edge->mustNeg = true; + edge->polNeg = true; + if (edge->mustPos) + solver->unsat = true; + } + } + deleteIterOrderEdge(iterator); + } + } + + resetAndDeleteHashTableNodeToNodeSet(table); + deleteHashTableNodeToNodeSet(table); +} + +/* This function finds edges that would form a cycle with must edges + and forces them to be mustNeg. It also decides whether an edge + must be true because of transitivity from other must be true + edges. */ + +void reachMustAnalysis(CSolver * solver, OrderGraph *graph, bool computeTransitiveClosure) { + VectorOrderNode finishNodes; + initDefVectorOrderNode(&finishNodes); + //Topologically sort the mustPos edge graph + DFSMust(graph, &finishNodes); + resetNodeInfoStatusSCC(graph); + + //Find any backwards edges that complete cycles and force them to be mustNeg + DFSClearContradictions(solver, graph, &finishNodes, computeTransitiveClosure); + deleteVectorArrayOrderNode(&finishNodes); +} + +/* This function finds edges that must be positive and forces the + inverse edge to be negative (and clears its positive polarity if it + had one). */ + +void localMustAnalysisTotal(CSolver *solver, OrderGraph *graph) { + HSIteratorOrderEdge *iterator = iteratorOrderEdge(graph->edges); + while (hasNextOrderEdge(iterator)) { + OrderEdge *edge = nextOrderEdge(iterator); + if (edge->mustPos) { + OrderEdge *invEdge = getInverseOrderEdge(graph, edge); + if (invEdge != NULL) { + if (!invEdge->mustPos) { + invEdge->polPos = false; + } else { + solver->unsat = true; + } + invEdge->mustNeg = true; + invEdge->polNeg = true; + } + } + } + deleteIterOrderEdge(iterator); +} + +/** This finds edges that must be positive and forces the inverse edge + to be negative. It also clears the negative flag of this edge. + It also finds edges that must be negative and clears the positive + polarity. */ + +void localMustAnalysisPartial(CSolver *solver, OrderGraph *graph) { + HSIteratorOrderEdge *iterator = iteratorOrderEdge(graph->edges); + while (hasNextOrderEdge(iterator)) { + OrderEdge *edge = nextOrderEdge(iterator); + if (edge->mustPos) { + if (!edge->mustNeg) { + edge->polNeg = false; + } else + solver->unsat = true; + + OrderEdge *invEdge = getInverseOrderEdge(graph, edge); + if (invEdge != NULL) { + if (!invEdge->mustPos) + invEdge->polPos = false; + else + solver->unsat = true; + invEdge->mustNeg = true; + invEdge->polNeg = true; + } + } + if (edge->mustNeg && !edge->mustPos) { + edge->polPos = false; + } + } + deleteIterOrderEdge(iterator); +} + +void decomposeOrder(CSolver *This, Order *order, OrderGraph *graph) { + VectorOrder ordervec; + VectorOrder partialcandidatevec; + initDefVectorOrder(&ordervec); + initDefVectorOrder(&partialcandidatevec); + uint size = getSizeVectorBooleanOrder(&order->constraints); + for (uint i = 0; i < size; i++) { + BooleanOrder *orderconstraint = getVectorBooleanOrder(&order->constraints, i); + OrderNode *from = getOrderNodeFromOrderGraph(graph, orderconstraint->first); + OrderNode *to = getOrderNodeFromOrderGraph(graph, orderconstraint->second); + model_print("from->sccNum:%u\tto->sccNum:%u\n", from->sccNum, to->sccNum); + if (from->sccNum != to->sccNum) { + OrderEdge *edge = getOrderEdgeFromOrderGraph(graph, from, to); + if (edge->polPos) { + replaceBooleanWithTrue(This, (Boolean *)orderconstraint); + } else if (edge->polNeg) { + replaceBooleanWithFalse(This, (Boolean *)orderconstraint); + } else { + //This case should only be possible if constraint isn't in AST + ASSERT(0); + } + } else { + //Build new order and change constraint's order + Order *neworder = NULL; + if (getSizeVectorOrder(&ordervec) > from->sccNum) + neworder = getVectorOrder(&ordervec, from->sccNum); + if (neworder == NULL) { + Set *set = (Set *) allocMutableSet(order->set->type); + neworder = allocOrder(order->type, set); + pushVectorOrder(This->allOrders, neworder); + setExpandVectorOrder(&ordervec, from->sccNum, neworder); + if (order->type == PARTIAL) + setExpandVectorOrder(&partialcandidatevec, from->sccNum, neworder); + else + setExpandVectorOrder(&partialcandidatevec, from->sccNum, NULL); + } + if (from->status != ADDEDTOSET) { + from->status = ADDEDTOSET; + addElementMSet((MutableSet *)neworder->set, from->id); + } + if (to->status != ADDEDTOSET) { + to->status = ADDEDTOSET; + addElementMSet((MutableSet *)neworder->set, to->id); + } + if (order->type == PARTIAL) { + OrderEdge *edge = getOrderEdgeFromOrderGraph(graph, from, to); + if (edge->polNeg) + setExpandVectorOrder(&partialcandidatevec, from->sccNum, NULL); + } + orderconstraint->order = neworder; + addOrderConstraint(neworder, orderconstraint); + } + } + + uint pcvsize=getSizeVectorOrder(&partialcandidatevec); + for(uint i=0;itype = TOTAL; + model_print("i=%u\t", i); + } + } + + deleteVectorArrayOrder(&ordervec); + deleteVectorArrayOrder(&partialcandidatevec); +} + +void orderAnalysis(CSolver *This) { + uint size = getSizeVectorOrder(This->allOrders); + for (uint i = 0; i < size; i++) { + Order *order = getVectorOrder(This->allOrders, i); + bool doDecompose=GETVARTUNABLE(This->tuner, order->type, DECOMPOSEORDER, &onoff); + if (!doDecompose) + continue; + + OrderGraph *graph = buildOrderGraph(order); + if (order->type == PARTIAL) { + //Required to do SCC analysis for partial order graphs. It + //makes sure we don't incorrectly optimize graphs with negative + //polarity edges + completePartialOrderGraph(graph); + } + + + bool mustReachGlobal=GETVARTUNABLE(This->tuner, order->type, MUSTREACHGLOBAL, &onoff); + + if (mustReachGlobal) + reachMustAnalysis(This, graph, false); + + bool mustReachLocal=GETVARTUNABLE(This->tuner, order->type, MUSTREACHLOCAL, &onoff); + + if (mustReachLocal) { + //This pair of analysis is also optional + if (order->type == PARTIAL) { + localMustAnalysisPartial(This, graph); + } else { + localMustAnalysisTotal(This, graph); + } + } + + bool mustReachPrune=GETVARTUNABLE(This->tuner, order->type, MUSTREACHPRUNE, &onoff); + + if (mustReachPrune) + removeMustBeTrueNodes(graph); + + //This is needed for splitorder + computeStronglyConnectedComponentGraph(graph); + + decomposeOrder(This, order, graph); + + deleteOrderGraph(graph); + } +} diff --git a/src/Encoders/orderencoding.c b/src/Encoders/orderencoding.c deleted file mode 100644 index 51dddcc..0000000 --- a/src/Encoders/orderencoding.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "orderencoding.h" - -void initOrderEncoding(OrderEncoding *This, Order *order) { - This->type = ORDER_UNASSIGNED; - This->order = order; -} - -void deleteOrderEncoding(OrderEncoding *This) { -} diff --git a/src/Encoders/orderencoding.cc b/src/Encoders/orderencoding.cc new file mode 100644 index 0000000..51dddcc --- /dev/null +++ b/src/Encoders/orderencoding.cc @@ -0,0 +1,9 @@ +#include "orderencoding.h" + +void initOrderEncoding(OrderEncoding *This, Order *order) { + This->type = ORDER_UNASSIGNED; + This->order = order; +} + +void deleteOrderEncoding(OrderEncoding *This) { +} diff --git a/src/Encoders/ordergraph.c b/src/Encoders/ordergraph.c deleted file mode 100644 index 32e1350..0000000 --- a/src/Encoders/ordergraph.c +++ /dev/null @@ -1,182 +0,0 @@ -#include "ordergraph.h" -#include "ordernode.h" -#include "boolean.h" -#include "orderedge.h" -#include "ordergraph.h" -#include "order.h" - -OrderGraph *allocOrderGraph(Order *order) { - OrderGraph *This = (OrderGraph *) ourmalloc(sizeof(OrderGraph)); - This->nodes = allocHashSetOrderNode(HT_INITIAL_CAPACITY, HT_DEFAULT_FACTOR); - This->edges = allocHashSetOrderEdge(HT_INITIAL_CAPACITY, HT_DEFAULT_FACTOR); - This->order = order; - return This; -} - -OrderGraph *buildOrderGraph(Order *order) { - OrderGraph *orderGraph = allocOrderGraph(order); - uint constrSize = getSizeVectorBooleanOrder(&order->constraints); - for (uint j = 0; j < constrSize; j++) { - addOrderConstraintToOrderGraph(orderGraph, getVectorBooleanOrder(&order->constraints, j)); - } - return orderGraph; -} - -//Builds only the subgraph for the must order graph. -OrderGraph *buildMustOrderGraph(Order *order) { - OrderGraph *orderGraph = allocOrderGraph(order); - uint constrSize = getSizeVectorBooleanOrder(&order->constraints); - for (uint j = 0; j < constrSize; j++) { - addMustOrderConstraintToOrderGraph(orderGraph, getVectorBooleanOrder(&order->constraints, j)); - } - return orderGraph; -} - -void addOrderEdge(OrderGraph *graph, OrderNode *node1, OrderNode *node2, BooleanOrder *constr) { - Polarity polarity = constr->base.polarity; - BooleanValue mustval = constr->base.boolVal; - Order *order = graph->order; - switch (polarity) { - case P_BOTHTRUEFALSE: - case P_TRUE: { - OrderEdge *_1to2 = getOrderEdgeFromOrderGraph(graph, node1, node2); - if (mustval == BV_MUSTBETRUE || mustval == BV_UNSAT) - _1to2->mustPos = true; - _1to2->polPos = true; - addNewOutgoingEdge(node1, _1to2); - addNewIncomingEdge(node2, _1to2); - if (constr->base.polarity == P_TRUE) - break; - } - case P_FALSE: { - if (order->type == TOTAL) { - OrderEdge *_2to1 = getOrderEdgeFromOrderGraph(graph, node2, node1); - if (mustval == BV_MUSTBEFALSE || mustval == BV_UNSAT) - _2to1->mustPos = true; - _2to1->polPos = true; - addNewOutgoingEdge(node2, _2to1); - addNewIncomingEdge(node1, _2to1); - } else { - OrderEdge *_1to2 = getOrderEdgeFromOrderGraph(graph, node1, node2); - if (mustval == BV_MUSTBEFALSE || mustval == BV_UNSAT) - _1to2->mustNeg = true; - _1to2->polNeg = true; - addNewOutgoingEdge(node1, _1to2); - addNewIncomingEdge(node2, _1to2); - } - break; - } - case P_UNDEFINED: - //There is an unreachable order constraint if this assert fires - ASSERT(0); - } -} - -void addMustOrderEdge(OrderGraph *graph, OrderNode *node1, OrderNode *node2, BooleanOrder *constr) { - BooleanValue mustval = constr->base.boolVal; - Order *order = graph->order; - switch (mustval) { - case BV_UNSAT: - case BV_MUSTBETRUE: { - OrderEdge *_1to2 = getOrderEdgeFromOrderGraph(graph, node1, node2); - _1to2->mustPos = true; - _1to2->polPos = true; - addNewOutgoingEdge(node1, _1to2); - addNewIncomingEdge(node2, _1to2); - if (constr->base.boolVal == BV_MUSTBETRUE) - break; - } - case BV_MUSTBEFALSE: { - if (order->type == TOTAL) { - OrderEdge *_2to1 = getOrderEdgeFromOrderGraph(graph, node2, node1); - _2to1->mustPos = true; - _2to1->polPos = true; - addNewOutgoingEdge(node2, _2to1); - addNewIncomingEdge(node1, _2to1); - } else { - OrderEdge *_1to2 = getOrderEdgeFromOrderGraph(graph, node1, node2); - _1to2->mustNeg = true; - _1to2->polNeg = true; - addNewOutgoingEdge(node1, _1to2); - addNewIncomingEdge(node2, _1to2); - } - break; - } - case BV_UNDEFINED: - //Do Nothing - break; - } -} - -OrderNode *getOrderNodeFromOrderGraph(OrderGraph *graph, uint64_t id) { - OrderNode *node = allocOrderNode(id); - OrderNode *tmp = getHashSetOrderNode(graph->nodes, node); - if ( tmp != NULL) { - deleteOrderNode(node); - node = tmp; - } else { - addHashSetOrderNode(graph->nodes, node); - } - return node; -} - -OrderNode *lookupOrderNodeFromOrderGraph(OrderGraph *graph, uint64_t id) { - OrderNode node = {id, NULL, NULL, 0, 0}; - OrderNode *tmp = getHashSetOrderNode(graph->nodes, &node); - return tmp; -} - -OrderEdge *getOrderEdgeFromOrderGraph(OrderGraph *graph, OrderNode *begin, OrderNode *end) { - OrderEdge *edge = allocOrderEdge(begin, end); - OrderEdge *tmp = getHashSetOrderEdge(graph->edges, edge); - if ( tmp != NULL ) { - deleteOrderEdge(edge); - edge = tmp; - } else { - addHashSetOrderEdge(graph->edges, edge); - } - return edge; -} - -OrderEdge *lookupOrderEdgeFromOrderGraph(OrderGraph *graph, OrderNode *begin, OrderNode *end) { - OrderEdge edge = {begin, end, 0, 0, 0, 0, 0}; - OrderEdge *tmp = getHashSetOrderEdge(graph->edges, &edge); - return tmp; -} - -OrderEdge *getInverseOrderEdge(OrderGraph *graph, OrderEdge *edge) { - OrderEdge inverseedge = {edge->sink, edge->source, false, false, false, false, false}; - OrderEdge *tmp = getHashSetOrderEdge(graph->edges, &inverseedge); - return tmp; -} - -void addOrderConstraintToOrderGraph(OrderGraph *graph, BooleanOrder *bOrder) { - OrderNode *from = getOrderNodeFromOrderGraph(graph, bOrder->first); - OrderNode *to = getOrderNodeFromOrderGraph(graph, bOrder->second); - addOrderEdge(graph, from, to, bOrder); -} - -void addMustOrderConstraintToOrderGraph(OrderGraph *graph, BooleanOrder *bOrder) { - OrderNode *from = getOrderNodeFromOrderGraph(graph, bOrder->first); - OrderNode *to = getOrderNodeFromOrderGraph(graph, bOrder->second); - addMustOrderEdge(graph, from, to, bOrder); -} - -void deleteOrderGraph(OrderGraph *graph) { - HSIteratorOrderNode *iterator = iteratorOrderNode(graph->nodes); - while (hasNextOrderNode(iterator)) { - OrderNode *node = nextOrderNode(iterator); - deleteOrderNode(node); - } - deleteIterOrderNode(iterator); - - HSIteratorOrderEdge *eiterator = iteratorOrderEdge(graph->edges); - while (hasNextOrderEdge(eiterator)) { - OrderEdge *edge = nextOrderEdge(eiterator); - deleteOrderEdge(edge); - } - deleteIterOrderEdge(eiterator); - deleteHashSetOrderNode(graph->nodes); - deleteHashSetOrderEdge(graph->edges); - ourfree(graph); -} diff --git a/src/Encoders/ordergraph.cc b/src/Encoders/ordergraph.cc new file mode 100644 index 0000000..a6728d6 --- /dev/null +++ b/src/Encoders/ordergraph.cc @@ -0,0 +1,182 @@ +#include "ordergraph.h" +#include "ordernode.h" +#include "boolean.h" +#include "orderedge.h" +#include "ordergraph.h" +#include "order.h" + +OrderGraph *allocOrderGraph(Order *order) { + OrderGraph *This = (OrderGraph *) ourmalloc(sizeof(OrderGraph)); + This->nodes = allocHashSetOrderNode(HT_INITIAL_CAPACITY, HT_DEFAULT_FACTOR); + This->edges = allocHashSetOrderEdge(HT_INITIAL_CAPACITY, HT_DEFAULT_FACTOR); + This->order = order; + return This; +} + +OrderGraph *buildOrderGraph(Order *order) { + OrderGraph *orderGraph = allocOrderGraph(order); + uint constrSize = getSizeVectorBooleanOrder(&order->constraints); + for (uint j = 0; j < constrSize; j++) { + addOrderConstraintToOrderGraph(orderGraph, getVectorBooleanOrder(&order->constraints, j)); + } + return orderGraph; +} + +//Builds only the subgraph for the must order graph. +OrderGraph *buildMustOrderGraph(Order *order) { + OrderGraph *orderGraph = allocOrderGraph(order); + uint constrSize = getSizeVectorBooleanOrder(&order->constraints); + for (uint j = 0; j < constrSize; j++) { + addMustOrderConstraintToOrderGraph(orderGraph, getVectorBooleanOrder(&order->constraints, j)); + } + return orderGraph; +} + +void addOrderEdge(OrderGraph *graph, OrderNode *node1, OrderNode *node2, BooleanOrder *constr) { + Polarity polarity = constr->base.polarity; + BooleanValue mustval = constr->base.boolVal; + Order *order = graph->order; + switch (polarity) { + case P_BOTHTRUEFALSE: + case P_TRUE: { + OrderEdge *_1to2 = getOrderEdgeFromOrderGraph(graph, node1, node2); + if (mustval == BV_MUSTBETRUE || mustval == BV_UNSAT) + _1to2->mustPos = true; + _1to2->polPos = true; + addNewOutgoingEdge(node1, _1to2); + addNewIncomingEdge(node2, _1to2); + if (constr->base.polarity == P_TRUE) + break; + } + case P_FALSE: { + if (order->type == TOTAL) { + OrderEdge *_2to1 = getOrderEdgeFromOrderGraph(graph, node2, node1); + if (mustval == BV_MUSTBEFALSE || mustval == BV_UNSAT) + _2to1->mustPos = true; + _2to1->polPos = true; + addNewOutgoingEdge(node2, _2to1); + addNewIncomingEdge(node1, _2to1); + } else { + OrderEdge *_1to2 = getOrderEdgeFromOrderGraph(graph, node1, node2); + if (mustval == BV_MUSTBEFALSE || mustval == BV_UNSAT) + _1to2->mustNeg = true; + _1to2->polNeg = true; + addNewOutgoingEdge(node1, _1to2); + addNewIncomingEdge(node2, _1to2); + } + break; + } + case P_UNDEFINED: + //There is an unreachable order constraint if this assert fires + ASSERT(0); + } +} + +void addMustOrderEdge(OrderGraph *graph, OrderNode *node1, OrderNode *node2, BooleanOrder *constr) { + BooleanValue mustval = constr->base.boolVal; + Order *order = graph->order; + switch (mustval) { + case BV_UNSAT: + case BV_MUSTBETRUE: { + OrderEdge *_1to2 = getOrderEdgeFromOrderGraph(graph, node1, node2); + _1to2->mustPos = true; + _1to2->polPos = true; + addNewOutgoingEdge(node1, _1to2); + addNewIncomingEdge(node2, _1to2); + if (constr->base.boolVal == BV_MUSTBETRUE) + break; + } + case BV_MUSTBEFALSE: { + if (order->type == TOTAL) { + OrderEdge *_2to1 = getOrderEdgeFromOrderGraph(graph, node2, node1); + _2to1->mustPos = true; + _2to1->polPos = true; + addNewOutgoingEdge(node2, _2to1); + addNewIncomingEdge(node1, _2to1); + } else { + OrderEdge *_1to2 = getOrderEdgeFromOrderGraph(graph, node1, node2); + _1to2->mustNeg = true; + _1to2->polNeg = true; + addNewOutgoingEdge(node1, _1to2); + addNewIncomingEdge(node2, _1to2); + } + break; + } + case BV_UNDEFINED: + //Do Nothing + break; + } +} + +OrderNode *getOrderNodeFromOrderGraph(OrderGraph *graph, uint64_t id) { + OrderNode *node = allocOrderNode(id); + OrderNode *tmp = getHashSetOrderNode(graph->nodes, node); + if ( tmp != NULL) { + deleteOrderNode(node); + node = tmp; + } else { + addHashSetOrderNode(graph->nodes, node); + } + return node; +} + +OrderNode *lookupOrderNodeFromOrderGraph(OrderGraph *graph, uint64_t id) { + OrderNode node = {id, NULL, NULL, NOTVISITED, 0}; + OrderNode *tmp = getHashSetOrderNode(graph->nodes, &node); + return tmp; +} + +OrderEdge *getOrderEdgeFromOrderGraph(OrderGraph *graph, OrderNode *begin, OrderNode *end) { + OrderEdge *edge = allocOrderEdge(begin, end); + OrderEdge *tmp = getHashSetOrderEdge(graph->edges, edge); + if ( tmp != NULL ) { + deleteOrderEdge(edge); + edge = tmp; + } else { + addHashSetOrderEdge(graph->edges, edge); + } + return edge; +} + +OrderEdge *lookupOrderEdgeFromOrderGraph(OrderGraph *graph, OrderNode *begin, OrderNode *end) { + OrderEdge edge = {begin, end, 0, 0, 0, 0, 0}; + OrderEdge *tmp = getHashSetOrderEdge(graph->edges, &edge); + return tmp; +} + +OrderEdge *getInverseOrderEdge(OrderGraph *graph, OrderEdge *edge) { + OrderEdge inverseedge = {edge->sink, edge->source, false, false, false, false, false}; + OrderEdge *tmp = getHashSetOrderEdge(graph->edges, &inverseedge); + return tmp; +} + +void addOrderConstraintToOrderGraph(OrderGraph *graph, BooleanOrder *bOrder) { + OrderNode *from = getOrderNodeFromOrderGraph(graph, bOrder->first); + OrderNode *to = getOrderNodeFromOrderGraph(graph, bOrder->second); + addOrderEdge(graph, from, to, bOrder); +} + +void addMustOrderConstraintToOrderGraph(OrderGraph *graph, BooleanOrder *bOrder) { + OrderNode *from = getOrderNodeFromOrderGraph(graph, bOrder->first); + OrderNode *to = getOrderNodeFromOrderGraph(graph, bOrder->second); + addMustOrderEdge(graph, from, to, bOrder); +} + +void deleteOrderGraph(OrderGraph *graph) { + HSIteratorOrderNode *iterator = iteratorOrderNode(graph->nodes); + while (hasNextOrderNode(iterator)) { + OrderNode *node = nextOrderNode(iterator); + deleteOrderNode(node); + } + deleteIterOrderNode(iterator); + + HSIteratorOrderEdge *eiterator = iteratorOrderEdge(graph->edges); + while (hasNextOrderEdge(eiterator)) { + OrderEdge *edge = nextOrderEdge(eiterator); + deleteOrderEdge(edge); + } + deleteIterOrderEdge(eiterator); + deleteHashSetOrderNode(graph->nodes); + deleteHashSetOrderEdge(graph->edges); + ourfree(graph); +} diff --git a/src/Encoders/ordernode.c b/src/Encoders/ordernode.c deleted file mode 100644 index c0bd096..0000000 --- a/src/Encoders/ordernode.c +++ /dev/null @@ -1,28 +0,0 @@ -#include "ordernode.h" -#include "orderedge.h" - -OrderNode *allocOrderNode(uint64_t id) { - OrderNode *This = (OrderNode *) ourmalloc(sizeof(OrderNode)); - This->id = id; - This->inEdges = allocHashSetOrderEdge(HT_INITIAL_CAPACITY, HT_DEFAULT_FACTOR); - This->outEdges = allocHashSetOrderEdge(HT_INITIAL_CAPACITY, HT_DEFAULT_FACTOR); - This->status = NOTVISITED; - This->sccNum = 0; - return This; -} - -void addNewIncomingEdge(OrderNode *node, OrderEdge *edge) { - ASSERT(!containsHashSetOrderEdge(node->inEdges, edge)); // Only for testing ... Should be removed after testing - addHashSetOrderEdge(node->inEdges, edge); -} - -void addNewOutgoingEdge(OrderNode *node, OrderEdge *edge) { - ASSERT(!containsHashSetOrderEdge(node->outEdges, edge)); - addHashSetOrderEdge(node->outEdges, edge); -} - -void deleteOrderNode(OrderNode *node) { - deleteHashSetOrderEdge(node->inEdges); - deleteHashSetOrderEdge(node->outEdges); - ourfree(node); -} diff --git a/src/Encoders/ordernode.cc b/src/Encoders/ordernode.cc new file mode 100644 index 0000000..c0bd096 --- /dev/null +++ b/src/Encoders/ordernode.cc @@ -0,0 +1,28 @@ +#include "ordernode.h" +#include "orderedge.h" + +OrderNode *allocOrderNode(uint64_t id) { + OrderNode *This = (OrderNode *) ourmalloc(sizeof(OrderNode)); + This->id = id; + This->inEdges = allocHashSetOrderEdge(HT_INITIAL_CAPACITY, HT_DEFAULT_FACTOR); + This->outEdges = allocHashSetOrderEdge(HT_INITIAL_CAPACITY, HT_DEFAULT_FACTOR); + This->status = NOTVISITED; + This->sccNum = 0; + return This; +} + +void addNewIncomingEdge(OrderNode *node, OrderEdge *edge) { + ASSERT(!containsHashSetOrderEdge(node->inEdges, edge)); // Only for testing ... Should be removed after testing + addHashSetOrderEdge(node->inEdges, edge); +} + +void addNewOutgoingEdge(OrderNode *node, OrderEdge *edge) { + ASSERT(!containsHashSetOrderEdge(node->outEdges, edge)); + addHashSetOrderEdge(node->outEdges, edge); +} + +void deleteOrderNode(OrderNode *node) { + deleteHashSetOrderEdge(node->inEdges); + deleteHashSetOrderEdge(node->outEdges); + ourfree(node); +} diff --git a/src/Encoders/polarityassignment.c b/src/Encoders/polarityassignment.c deleted file mode 100644 index 3e41380..0000000 --- a/src/Encoders/polarityassignment.c +++ /dev/null @@ -1,150 +0,0 @@ -#include "polarityassignment.h" -#include "csolver.h" - -void computePolarities(CSolver *This) { - HSIteratorBoolean *iterator=iteratorBoolean(This->constraints); - while(hasNextBoolean(iterator)) { - Boolean *boolean = nextBoolean(iterator); - updatePolarity(boolean, P_TRUE); - updateMustValue(boolean, BV_MUSTBETRUE); - computePolarityAndBooleanValue(boolean); - } - deleteIterBoolean(iterator); -} - -void updatePolarity(Boolean *This, Polarity polarity) { - This->polarity |= polarity; -} - -void updateMustValue(Boolean *This, BooleanValue value) { - This->boolVal |= value; -} - -void computePolarityAndBooleanValue(Boolean *This) { - switch (GETBOOLEANTYPE(This)) { - case BOOLEANVAR: - case ORDERCONST: - return; - case PREDICATEOP: - return computePredicatePolarityAndBooleanValue((BooleanPredicate *)This); - case LOGICOP: - return computeLogicOpPolarityAndBooleanValue((BooleanLogic *)This); - default: - ASSERT(0); - } -} - -void computePredicatePolarityAndBooleanValue(BooleanPredicate *This) { - updatePolarity(This->undefStatus, P_BOTHTRUEFALSE); - computePolarityAndBooleanValue(This->undefStatus); -} - -void computeLogicOpPolarityAndBooleanValue(BooleanLogic *This) { - computeLogicOpBooleanValue(This); - computeLogicOpPolarity(This); - uint size = getSizeArrayBoolean(&This->inputs); - for (uint i = 0; i < size; i++) { - computePolarityAndBooleanValue(getArrayBoolean(&This->inputs, i)); - } -} - -Polarity negatePolarity(Polarity This) { - switch (This) { - case P_UNDEFINED: - case P_BOTHTRUEFALSE: - return This; - case P_TRUE: - return P_FALSE; - case P_FALSE: - return P_TRUE; - default: - ASSERT(0); - } -} - -BooleanValue negateBooleanValue(BooleanValue This) { - switch (This) { - case BV_UNDEFINED: - case BV_UNSAT: - return This; - case BV_MUSTBETRUE: - return BV_MUSTBEFALSE; - case BV_MUSTBEFALSE: - return BV_MUSTBETRUE; - default: - ASSERT(0); - } -} - -void computeLogicOpPolarity(BooleanLogic *This) { - Polarity parentpolarity = GETBOOLEANPOLARITY(This); - switch (This->op) { - case L_AND: - case L_OR: { - uint size = getSizeArrayBoolean(&This->inputs); - for (uint i = 0; i < size; i++) { - Boolean *tmp = getArrayBoolean(&This->inputs, i); - updatePolarity(tmp, parentpolarity); - } - break; - } - case L_NOT: { - Boolean *tmp = getArrayBoolean(&This->inputs, 0); - updatePolarity(tmp, negatePolarity(parentpolarity)); - break; - } - case L_XOR: { - updatePolarity(getArrayBoolean(&This->inputs, 0), P_BOTHTRUEFALSE); - updatePolarity(getArrayBoolean(&This->inputs, 1), P_BOTHTRUEFALSE); - break; - } - case L_IMPLIES: { - Boolean *left = getArrayBoolean(&This->inputs, 0); - updatePolarity(left, negatePolarity( parentpolarity)); - Boolean *right = getArrayBoolean(&This->inputs, 1); - updatePolarity(right, parentpolarity); - break; - } - default: - ASSERT(0); - } -} - -void computeLogicOpBooleanValue(BooleanLogic *This) { - BooleanValue parentbv = GETBOOLEANVALUE(This); - switch (This->op) { - case L_AND: { - if (parentbv == BV_MUSTBETRUE || parentbv == BV_UNSAT) { - uint size = getSizeArrayBoolean(&This->inputs); - for (uint i = 0; i < size; i++) { - updateMustValue(getArrayBoolean(&This->inputs, i), parentbv); - } - } - return; - } - case L_OR: { - if (parentbv == BV_MUSTBEFALSE || parentbv == BV_UNSAT) { - uint size = getSizeArrayBoolean(&This->inputs); - for (uint i = 0; i < size; i++) { - updateMustValue(getArrayBoolean(&This->inputs, i), parentbv); - } - } - return; - } - case L_NOT: - updateMustValue(getArrayBoolean(&This->inputs, 0), negateBooleanValue(parentbv)); - return; - case L_IMPLIES: - //implies is really an or with the first term negated - if (parentbv == BV_MUSTBEFALSE || parentbv == BV_UNSAT) { - uint size = getSizeArrayBoolean(&This->inputs); - updateMustValue(getArrayBoolean(&This->inputs, 0), negateBooleanValue(parentbv)); - updateMustValue(getArrayBoolean(&This->inputs, 1), parentbv); - } - return; - case L_XOR: - return; - default: - ASSERT(0); - } -} diff --git a/src/Encoders/polarityassignment.cc b/src/Encoders/polarityassignment.cc new file mode 100644 index 0000000..77d2a06 --- /dev/null +++ b/src/Encoders/polarityassignment.cc @@ -0,0 +1,150 @@ +#include "polarityassignment.h" +#include "csolver.h" + +void computePolarities(CSolver *This) { + HSIteratorBoolean *iterator=iteratorBoolean(This->constraints); + while(hasNextBoolean(iterator)) { + Boolean *boolean = nextBoolean(iterator); + updatePolarity(boolean, P_TRUE); + updateMustValue(boolean, BV_MUSTBETRUE); + computePolarityAndBooleanValue(boolean); + } + deleteIterBoolean(iterator); +} + +void updatePolarity(Boolean *This, Polarity polarity) { + This->polarity = (Polarity) (This->polarity | polarity); +} + +void updateMustValue(Boolean *This, BooleanValue value) { + This->boolVal = (BooleanValue) (This->boolVal | value); +} + +void computePolarityAndBooleanValue(Boolean *This) { + switch (GETBOOLEANTYPE(This)) { + case BOOLEANVAR: + case ORDERCONST: + return; + case PREDICATEOP: + return computePredicatePolarityAndBooleanValue((BooleanPredicate *)This); + case LOGICOP: + return computeLogicOpPolarityAndBooleanValue((BooleanLogic *)This); + default: + ASSERT(0); + } +} + +void computePredicatePolarityAndBooleanValue(BooleanPredicate *This) { + updatePolarity(This->undefStatus, P_BOTHTRUEFALSE); + computePolarityAndBooleanValue(This->undefStatus); +} + +void computeLogicOpPolarityAndBooleanValue(BooleanLogic *This) { + computeLogicOpBooleanValue(This); + computeLogicOpPolarity(This); + uint size = getSizeArrayBoolean(&This->inputs); + for (uint i = 0; i < size; i++) { + computePolarityAndBooleanValue(getArrayBoolean(&This->inputs, i)); + } +} + +Polarity negatePolarity(Polarity This) { + switch (This) { + case P_UNDEFINED: + case P_BOTHTRUEFALSE: + return This; + case P_TRUE: + return P_FALSE; + case P_FALSE: + return P_TRUE; + default: + ASSERT(0); + } +} + +BooleanValue negateBooleanValue(BooleanValue This) { + switch (This) { + case BV_UNDEFINED: + case BV_UNSAT: + return This; + case BV_MUSTBETRUE: + return BV_MUSTBEFALSE; + case BV_MUSTBEFALSE: + return BV_MUSTBETRUE; + default: + ASSERT(0); + } +} + +void computeLogicOpPolarity(BooleanLogic *This) { + Polarity parentpolarity = GETBOOLEANPOLARITY(This); + switch (This->op) { + case L_AND: + case L_OR: { + uint size = getSizeArrayBoolean(&This->inputs); + for (uint i = 0; i < size; i++) { + Boolean *tmp = getArrayBoolean(&This->inputs, i); + updatePolarity(tmp, parentpolarity); + } + break; + } + case L_NOT: { + Boolean *tmp = getArrayBoolean(&This->inputs, 0); + updatePolarity(tmp, negatePolarity(parentpolarity)); + break; + } + case L_XOR: { + updatePolarity(getArrayBoolean(&This->inputs, 0), P_BOTHTRUEFALSE); + updatePolarity(getArrayBoolean(&This->inputs, 1), P_BOTHTRUEFALSE); + break; + } + case L_IMPLIES: { + Boolean *left = getArrayBoolean(&This->inputs, 0); + updatePolarity(left, negatePolarity( parentpolarity)); + Boolean *right = getArrayBoolean(&This->inputs, 1); + updatePolarity(right, parentpolarity); + break; + } + default: + ASSERT(0); + } +} + +void computeLogicOpBooleanValue(BooleanLogic *This) { + BooleanValue parentbv = GETBOOLEANVALUE(This); + switch (This->op) { + case L_AND: { + if (parentbv == BV_MUSTBETRUE || parentbv == BV_UNSAT) { + uint size = getSizeArrayBoolean(&This->inputs); + for (uint i = 0; i < size; i++) { + updateMustValue(getArrayBoolean(&This->inputs, i), parentbv); + } + } + return; + } + case L_OR: { + if (parentbv == BV_MUSTBEFALSE || parentbv == BV_UNSAT) { + uint size = getSizeArrayBoolean(&This->inputs); + for (uint i = 0; i < size; i++) { + updateMustValue(getArrayBoolean(&This->inputs, i), parentbv); + } + } + return; + } + case L_NOT: + updateMustValue(getArrayBoolean(&This->inputs, 0), negateBooleanValue(parentbv)); + return; + case L_IMPLIES: + //implies is really an or with the first term negated + if (parentbv == BV_MUSTBEFALSE || parentbv == BV_UNSAT) { + uint size = getSizeArrayBoolean(&This->inputs); + updateMustValue(getArrayBoolean(&This->inputs, 0), negateBooleanValue(parentbv)); + updateMustValue(getArrayBoolean(&This->inputs, 1), parentbv); + } + return; + case L_XOR: + return; + default: + ASSERT(0); + } +} diff --git a/src/Makefile b/src/Makefile index 007705d..7a45513 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,11 +4,11 @@ PHONY += directories MKDIR_P = mkdir -p OBJ_DIR = bin -C_SOURCES := $(wildcard *.c) $(wildcard AST/*.c) $(wildcard Tuner/*.c) $(wildcard Collections/*.c) $(wildcard Backend/*.c) $(wildcard Encoders/*.c) +CPP_SOURCES := $(wildcard *.cc) $(wildcard AST/*.cc) $(wildcard Tuner/*.cc) $(wildcard Collections/*.cc) $(wildcard Backend/*.cc) $(wildcard Encoders/*.cc) HEADERS := $(wildcard *.h) $(wildcard AST/*.h) $(wildcard Tuner/*.h) $(wildcard Collections/*.h) $(wildcard Backend/*.h) $(wildcard Encoders/*.h) -OBJECTS := $(CPP_SOURCES:%.cc=$(OBJ_DIR)/%.o) $(C_SOURCES:%.c=$(OBJ_DIR)/%.o) +OBJECTS := $(CPP_SOURCES:%.cc=$(OBJ_DIR)/%.o) CFLAGS := -Wall -g -O0 CFLAGS += -IAST -ICollections -IBackend -I. -IEncoders -ITuner @@ -48,7 +48,7 @@ docs: $(C_SOURCES) $(HEADERS) ${OBJ_DIR}/$(LIB_SO): $(OBJECTS) $(CC) -g $(SHARED) -o ${OBJ_DIR}/$(LIB_SO) $+ $(LDFLAGS) -${OBJ_DIR}/%.o: %.c +${OBJ_DIR}/%.o: %.cc $(CC) -fPIC -c $< -o $@ $(CFLAGS) -Wno-unused-variable -include $(OBJECTS:%=$OBJ_DIR/.%.d) @@ -67,10 +67,10 @@ tags: ctags -R tabbing: - uncrustify -c C.cfg --no-backup *.c */*.c + uncrustify -c C.cfg --no-backup *.cc */*.cc uncrustify -c C.cfg --no-backup *.h */*.h wc: - wc */*.c */*.h *.c *.h + wc */*.cc */*.h *.cc *.h .PHONY: $(PHONY) diff --git a/src/Test/Makefile b/src/Test/Makefile index be27d60..2c24d58 100644 --- a/src/Test/Makefile +++ b/src/Test/Makefile @@ -1,6 +1,6 @@ BASE := .. -OBJECTS := $(patsubst %.c, ../bin/%, $(wildcard *.c)) +OBJECTS := $(patsubst %.cc, ../bin/%, $(wildcard *.cc)) include $(BASE)/common.mk @@ -12,7 +12,7 @@ all: $(OBJECTS) ../bin/run.sh -include $(DEPS) -../bin/%: %.c +../bin/%: %.cc $(CC) -MMD -MF $(@D)/.$(@F).d -o ../bin/$@ $< $(CPPFLAGS) -L$(BASE)/bin/ -l_cons_comp ../bin/run.sh: run.sh diff --git a/src/Test/buildconstraintstest.c b/src/Test/buildconstraintstest.c deleted file mode 100644 index 71dbafd..0000000 --- a/src/Test/buildconstraintstest.c +++ /dev/null @@ -1,59 +0,0 @@ -#include "csolver.h" - -/** - * e1={0, 1, 2} - * e2={0, 1, 2} - * e1 == e2 - * e3= e1+e2 {0, 1, 2, 3, 4} - * e4 = f(e1, e2) - * 0 1 => 0 - * 1 1 => 0 - * 2 1 => 2 - * 2 2 => 2 - * e3 == e4 - * Result: UNSAT! - */ -int main(int numargs, char **argv) { - CSolver *solver = allocCSolver(); - uint64_t set1[] = {0, 1, 2}; - uint64_t setbigarray[] = {0, 1, 2, 3, 4}; - - Set *s = createSet(solver, 0, set1, 3); - Set *setbig = createSet(solver, 0, setbigarray, 5); - Element *e1 = getElementVar(solver, s); - Element *e2 = getElementVar(solver, s); - Set *domain[] = {s, s}; - Predicate *equals = createPredicateOperator(solver, EQUALS, domain, 2); - Element *inputs[] = {e1, e2}; - Boolean *b = applyPredicate(solver, equals, inputs, 2); - addConstraint(solver, b); - - uint64_t set2[] = {2, 3}; - Set *rangef1 = createSet(solver, 1, set2, 2); - Function *f1 = createFunctionOperator(solver, ADD, domain, 2, setbig, IGNORE); - - Table *table = createTable(solver, domain, 2, s); - uint64_t row1[] = {0, 1}; - uint64_t row2[] = {1, 1}; - uint64_t row3[] = {2, 1}; - uint64_t row4[] = {2, 2}; - addTableEntry(solver, table, row1, 2, 0); - addTableEntry(solver, table, row2, 2, 0); - addTableEntry(solver, table, row3, 2, 2); - addTableEntry(solver, table, row4, 2, 2); - Function *f2 = completeTable(solver, table, IGNOREBEHAVIOR); //its range would be as same as s - Boolean *overflow = getBooleanVar(solver, 2); - Element *e3 = applyFunction(solver, f1, inputs, 2, overflow); - Element *e4 = applyFunction(solver, f2, inputs, 2, overflow); - Set *domain2[] = {s,rangef1}; - Predicate *equal2 = createPredicateOperator(solver, EQUALS, domain2, 2); - Element *inputs2 [] = {e4, e3}; - Boolean *pred = applyPredicate(solver, equal2, inputs2, 2); - addConstraint(solver, pred); - - if (startEncoding(solver) == 1) - printf("e1=%llu e2=%llu\n", getElementValue(solver,e1), getElementValue(solver, e2)); - else - printf("UNSAT\n"); - deleteSolver(solver); -} diff --git a/src/Test/buildconstraintstest.cc b/src/Test/buildconstraintstest.cc new file mode 100644 index 0000000..71dbafd --- /dev/null +++ b/src/Test/buildconstraintstest.cc @@ -0,0 +1,59 @@ +#include "csolver.h" + +/** + * e1={0, 1, 2} + * e2={0, 1, 2} + * e1 == e2 + * e3= e1+e2 {0, 1, 2, 3, 4} + * e4 = f(e1, e2) + * 0 1 => 0 + * 1 1 => 0 + * 2 1 => 2 + * 2 2 => 2 + * e3 == e4 + * Result: UNSAT! + */ +int main(int numargs, char **argv) { + CSolver *solver = allocCSolver(); + uint64_t set1[] = {0, 1, 2}; + uint64_t setbigarray[] = {0, 1, 2, 3, 4}; + + Set *s = createSet(solver, 0, set1, 3); + Set *setbig = createSet(solver, 0, setbigarray, 5); + Element *e1 = getElementVar(solver, s); + Element *e2 = getElementVar(solver, s); + Set *domain[] = {s, s}; + Predicate *equals = createPredicateOperator(solver, EQUALS, domain, 2); + Element *inputs[] = {e1, e2}; + Boolean *b = applyPredicate(solver, equals, inputs, 2); + addConstraint(solver, b); + + uint64_t set2[] = {2, 3}; + Set *rangef1 = createSet(solver, 1, set2, 2); + Function *f1 = createFunctionOperator(solver, ADD, domain, 2, setbig, IGNORE); + + Table *table = createTable(solver, domain, 2, s); + uint64_t row1[] = {0, 1}; + uint64_t row2[] = {1, 1}; + uint64_t row3[] = {2, 1}; + uint64_t row4[] = {2, 2}; + addTableEntry(solver, table, row1, 2, 0); + addTableEntry(solver, table, row2, 2, 0); + addTableEntry(solver, table, row3, 2, 2); + addTableEntry(solver, table, row4, 2, 2); + Function *f2 = completeTable(solver, table, IGNOREBEHAVIOR); //its range would be as same as s + Boolean *overflow = getBooleanVar(solver, 2); + Element *e3 = applyFunction(solver, f1, inputs, 2, overflow); + Element *e4 = applyFunction(solver, f2, inputs, 2, overflow); + Set *domain2[] = {s,rangef1}; + Predicate *equal2 = createPredicateOperator(solver, EQUALS, domain2, 2); + Element *inputs2 [] = {e4, e3}; + Boolean *pred = applyPredicate(solver, equal2, inputs2, 2); + addConstraint(solver, pred); + + if (startEncoding(solver) == 1) + printf("e1=%llu e2=%llu\n", getElementValue(solver,e1), getElementValue(solver, e2)); + else + printf("UNSAT\n"); + deleteSolver(solver); +} diff --git a/src/Test/cnftest.c b/src/Test/cnftest.c deleted file mode 100644 index b76af26..0000000 --- a/src/Test/cnftest.c +++ /dev/null @@ -1,34 +0,0 @@ -#include "constraint.h" -#include - -int main(int numargs, char **argv) { - CNF *cnf = createCNF(); - Edge v1 = constraintNewVar(cnf); - Edge v2 = constraintNewVar(cnf); - Edge v3 = constraintNewVar(cnf); - Edge v4 = constraintNewVar(cnf); - - Edge nv1 = constraintNegate(v1); - Edge nv2 = constraintNegate(v2); - Edge nv3 = constraintNegate(v3); - Edge nv4 = constraintNegate(v4); - - Edge c1 = constraintAND2(cnf, v1, nv2); - Edge c2 = constraintAND2(cnf, v3, nv4); - Edge c3 = constraintAND2(cnf, nv1, v2); - Edge c4 = constraintAND2(cnf, nv3, v4); - Edge cor = constraintOR2(cnf, constraintAND2(cnf, c1, c2), constraintAND2(cnf, c3, c4)); - printCNF(cor); - printf("\n"); - addConstraintCNF(cnf, cor); - int value = solveCNF(cnf); - if (value == 1) { - bool v1v = getValueCNF(cnf, v1); - bool v2v = getValueCNF(cnf, v2); - bool v3v = getValueCNF(cnf, v3); - bool v4v = getValueCNF(cnf, v4); - printf("%d %u %u %u %u\n", value, v1v, v2v, v3v, v4v); - } else - printf("%d\n",value); - deleteCNF(cnf); -} diff --git a/src/Test/cnftest.cc b/src/Test/cnftest.cc new file mode 100644 index 0000000..b76af26 --- /dev/null +++ b/src/Test/cnftest.cc @@ -0,0 +1,34 @@ +#include "constraint.h" +#include + +int main(int numargs, char **argv) { + CNF *cnf = createCNF(); + Edge v1 = constraintNewVar(cnf); + Edge v2 = constraintNewVar(cnf); + Edge v3 = constraintNewVar(cnf); + Edge v4 = constraintNewVar(cnf); + + Edge nv1 = constraintNegate(v1); + Edge nv2 = constraintNegate(v2); + Edge nv3 = constraintNegate(v3); + Edge nv4 = constraintNegate(v4); + + Edge c1 = constraintAND2(cnf, v1, nv2); + Edge c2 = constraintAND2(cnf, v3, nv4); + Edge c3 = constraintAND2(cnf, nv1, v2); + Edge c4 = constraintAND2(cnf, nv3, v4); + Edge cor = constraintOR2(cnf, constraintAND2(cnf, c1, c2), constraintAND2(cnf, c3, c4)); + printCNF(cor); + printf("\n"); + addConstraintCNF(cnf, cor); + int value = solveCNF(cnf); + if (value == 1) { + bool v1v = getValueCNF(cnf, v1); + bool v2v = getValueCNF(cnf, v2); + bool v3v = getValueCNF(cnf, v3); + bool v4v = getValueCNF(cnf, v4); + printf("%d %u %u %u %u\n", value, v1v, v2v, v3v, v4v); + } else + printf("%d\n",value); + deleteCNF(cnf); +} diff --git a/src/Test/elemequalsattest.c b/src/Test/elemequalsattest.c deleted file mode 100644 index 7841a70..0000000 --- a/src/Test/elemequalsattest.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "csolver.h" -/** - * e1 = {0, 1, 2} - * e2 = {3, 1, 7} - * e1 == e2 - * - * Result (Enumeration): - * e1=1 e2=1 - * Result (circuit): - * e1=0 e2=3 - * e1=1 e2=1 - * e1=2 e2=7 - */ -int main(int numargs, char **argv) { - CSolver *solver = allocCSolver(); - uint64_t set1[] = {0, 1, 2}; - uint64_t set2[] = {3, 1, 7}; - Set *s1 = createSet(solver, 0, set1, 3); - Set *s2 = createSet(solver, 0, set2, 3); - Element *e1 = getElementVar(solver, s1); - Element *e2 = getElementVar(solver, s2); - Set *domain[] = {s1, s2}; - Predicate *equals = createPredicateOperator(solver, EQUALS, domain, 2); - Element *inputs[] = {e1, e2}; - Boolean *b = applyPredicate(solver, equals, inputs, 2); - addConstraint(solver, b); - - if (startEncoding(solver) == 1) - printf("e1=%llu e2=%llu\n", getElementValue(solver,e1), getElementValue(solver, e2)); - else - printf("UNSAT\n"); - deleteSolver(solver); -} diff --git a/src/Test/elemequalsattest.cc b/src/Test/elemequalsattest.cc new file mode 100644 index 0000000..7841a70 --- /dev/null +++ b/src/Test/elemequalsattest.cc @@ -0,0 +1,33 @@ +#include "csolver.h" +/** + * e1 = {0, 1, 2} + * e2 = {3, 1, 7} + * e1 == e2 + * + * Result (Enumeration): + * e1=1 e2=1 + * Result (circuit): + * e1=0 e2=3 + * e1=1 e2=1 + * e1=2 e2=7 + */ +int main(int numargs, char **argv) { + CSolver *solver = allocCSolver(); + uint64_t set1[] = {0, 1, 2}; + uint64_t set2[] = {3, 1, 7}; + Set *s1 = createSet(solver, 0, set1, 3); + Set *s2 = createSet(solver, 0, set2, 3); + Element *e1 = getElementVar(solver, s1); + Element *e2 = getElementVar(solver, s2); + Set *domain[] = {s1, s2}; + Predicate *equals = createPredicateOperator(solver, EQUALS, domain, 2); + Element *inputs[] = {e1, e2}; + Boolean *b = applyPredicate(solver, equals, inputs, 2); + addConstraint(solver, b); + + if (startEncoding(solver) == 1) + printf("e1=%llu e2=%llu\n", getElementValue(solver,e1), getElementValue(solver, e2)); + else + printf("UNSAT\n"); + deleteSolver(solver); +} diff --git a/src/Test/elemequalunsattest.c b/src/Test/elemequalunsattest.c deleted file mode 100644 index 5cbdd04..0000000 --- a/src/Test/elemequalunsattest.c +++ /dev/null @@ -1,28 +0,0 @@ -#include "csolver.h" -/** - * e1 = {0, 1, 2} - * e2 = {3, 4} - * e1 == e2 - * - * Result: UNSAT - */ -int main(int numargs, char **argv) { - CSolver *solver = allocCSolver(); - uint64_t set1[] = {0, 1, 2}; - uint64_t set2[] = {3, 4}; - Set *s1 = createSet(solver, 0, set1, 3); - Set *s2 = createSet(solver, 0, set2, 2); - Element *e1 = getElementVar(solver, s1); - Element *e2 = getElementVar(solver, s2); - Set *domain[] = {s1, s2}; - Predicate *equals = createPredicateOperator(solver, EQUALS, domain, 2); - Element *inputs[] = {e1, e2}; - Boolean *b = applyPredicate(solver, equals, inputs, 2); - addConstraint(solver, b); - - if (startEncoding(solver) == 1) - printf("e1=%llu e2=%llu\n", getElementValue(solver,e1), getElementValue(solver, e2)); - else - printf("UNSAT\n"); - deleteSolver(solver); -} diff --git a/src/Test/elemequalunsattest.cc b/src/Test/elemequalunsattest.cc new file mode 100644 index 0000000..5cbdd04 --- /dev/null +++ b/src/Test/elemequalunsattest.cc @@ -0,0 +1,28 @@ +#include "csolver.h" +/** + * e1 = {0, 1, 2} + * e2 = {3, 4} + * e1 == e2 + * + * Result: UNSAT + */ +int main(int numargs, char **argv) { + CSolver *solver = allocCSolver(); + uint64_t set1[] = {0, 1, 2}; + uint64_t set2[] = {3, 4}; + Set *s1 = createSet(solver, 0, set1, 3); + Set *s2 = createSet(solver, 0, set2, 2); + Element *e1 = getElementVar(solver, s1); + Element *e2 = getElementVar(solver, s2); + Set *domain[] = {s1, s2}; + Predicate *equals = createPredicateOperator(solver, EQUALS, domain, 2); + Element *inputs[] = {e1, e2}; + Boolean *b = applyPredicate(solver, equals, inputs, 2); + addConstraint(solver, b); + + if (startEncoding(solver) == 1) + printf("e1=%llu e2=%llu\n", getElementValue(solver,e1), getElementValue(solver, e2)); + else + printf("UNSAT\n"); + deleteSolver(solver); +} diff --git a/src/Test/funcencodingtest.c b/src/Test/funcencodingtest.c deleted file mode 100644 index 24b652f..0000000 --- a/src/Test/funcencodingtest.c +++ /dev/null @@ -1,82 +0,0 @@ -#include "csolver.h" -/** - * e1 = {6} - * e2={4, 2} - * e3=Fsub(e1,e2) {4, 2} - * e4= f(e1, e2) - * 6 2 => 3 - * 6 4 => 1 - * e5 = f(e1)=>e1 {6} - * e6 = (e3, e4, e5) {2, 3, 1} - * 4 3 6 => 3 - * 2 1 6 => 1 - * 2 3 6 => 2 - * 4 1 6 => 1 - * e7 = {2, 1, 0} - * e7 > e6 - * Result: e1=6, e2=4, e7=2 - */ -int main(int numargs, char **argv) { - CSolver *solver = allocCSolver(); - uint64_t set1[] = {6}; - uint64_t set2[] = {4, 2}; - uint64_t set3[] = {3, 1}; - uint64_t set4[] = {2, 3, 1}; - uint64_t set5[] = {2, 1, 0}; - Set *s1 = createSet(solver, 0, set1, 1); - Set *s2 = createSet(solver, 0, set2, 2); - Set *s3 = createSet(solver, 0, set3, 2); - Set *s4 = createSet(solver, 0, set4, 3); - Set *s5 = createSet(solver, 0, set5, 3); - Element *e1 = getElementVar(solver, s1); - Element *e2 = getElementVar(solver, s2); - Element *e7 = getElementVar(solver, s5); - Boolean *overflow = getBooleanVar(solver, 2); - Set *d1[] = {s1, s2}; - //change the overflow flag - Function *f1 = createFunctionOperator(solver, SUB, d1, 2, s2, IGNORE); - Element *in1[] = {e1, e2}; - Element *e3 = applyFunction(solver, f1, in1, 2, overflow); - Table *t1 = createTable(solver, d1, 2, s3); - uint64_t row1[] = {6, 2}; - uint64_t row2[] = {6, 4}; - addTableEntry(solver, t1, row1, 2, 3); - addTableEntry(solver, t1, row2, 2, 1); - Function *f2 = completeTable(solver, t1, IGNOREBEHAVIOR); - Element *e4 = applyFunction(solver, f2, in1, 2, overflow); - - Set *d2[] = {s1}; - Element *in2[] = {e1}; - Table *t2 = createTable(solver, d2, 1, s1); - uint64_t row3[] = {6}; - addTableEntry(solver, t2, row3, 1, 6); - Function *f3 = completeTable(solver, t2, IGNOREBEHAVIOR); - Element *e5 = applyFunction(solver, f3, in2, 1, overflow); - - Set *d3[] = {s2, s3, s1}; - Element *in3[] = {e3, e4, e5}; - Table *t3 = createTable(solver, d3, 3, s4); - uint64_t row4[] = {4, 3, 6}; - uint64_t row5[] = {2, 1, 6}; - uint64_t row6[] = {2, 3, 6}; - uint64_t row7[] = {4, 1, 6}; - addTableEntry(solver, t3, row4, 3, 3); - addTableEntry(solver, t3, row5, 3, 1); - addTableEntry(solver, t3, row6, 3, 2); - addTableEntry(solver, t3, row7, 3, 1); - Function *f4 = completeTable(solver, t3, IGNOREBEHAVIOR); - Element *e6 = applyFunction(solver, f4, in3, 3, overflow); - - Set *deq[] = {s5,s4}; - Predicate *gt = createPredicateOperator(solver, GT, deq, 2); - Element *inputs2 [] = {e7, e6}; - Boolean *pred = applyPredicate(solver, gt, inputs2, 2); - addConstraint(solver, pred); - - if (startEncoding(solver) == 1) - printf("e1=%llu e2=%llu e7=%llu\n", - getElementValue(solver,e1), getElementValue(solver, e2), getElementValue(solver, e7)); - else - printf("UNSAT\n"); - deleteSolver(solver); -} diff --git a/src/Test/funcencodingtest.cc b/src/Test/funcencodingtest.cc new file mode 100644 index 0000000..24b652f --- /dev/null +++ b/src/Test/funcencodingtest.cc @@ -0,0 +1,82 @@ +#include "csolver.h" +/** + * e1 = {6} + * e2={4, 2} + * e3=Fsub(e1,e2) {4, 2} + * e4= f(e1, e2) + * 6 2 => 3 + * 6 4 => 1 + * e5 = f(e1)=>e1 {6} + * e6 = (e3, e4, e5) {2, 3, 1} + * 4 3 6 => 3 + * 2 1 6 => 1 + * 2 3 6 => 2 + * 4 1 6 => 1 + * e7 = {2, 1, 0} + * e7 > e6 + * Result: e1=6, e2=4, e7=2 + */ +int main(int numargs, char **argv) { + CSolver *solver = allocCSolver(); + uint64_t set1[] = {6}; + uint64_t set2[] = {4, 2}; + uint64_t set3[] = {3, 1}; + uint64_t set4[] = {2, 3, 1}; + uint64_t set5[] = {2, 1, 0}; + Set *s1 = createSet(solver, 0, set1, 1); + Set *s2 = createSet(solver, 0, set2, 2); + Set *s3 = createSet(solver, 0, set3, 2); + Set *s4 = createSet(solver, 0, set4, 3); + Set *s5 = createSet(solver, 0, set5, 3); + Element *e1 = getElementVar(solver, s1); + Element *e2 = getElementVar(solver, s2); + Element *e7 = getElementVar(solver, s5); + Boolean *overflow = getBooleanVar(solver, 2); + Set *d1[] = {s1, s2}; + //change the overflow flag + Function *f1 = createFunctionOperator(solver, SUB, d1, 2, s2, IGNORE); + Element *in1[] = {e1, e2}; + Element *e3 = applyFunction(solver, f1, in1, 2, overflow); + Table *t1 = createTable(solver, d1, 2, s3); + uint64_t row1[] = {6, 2}; + uint64_t row2[] = {6, 4}; + addTableEntry(solver, t1, row1, 2, 3); + addTableEntry(solver, t1, row2, 2, 1); + Function *f2 = completeTable(solver, t1, IGNOREBEHAVIOR); + Element *e4 = applyFunction(solver, f2, in1, 2, overflow); + + Set *d2[] = {s1}; + Element *in2[] = {e1}; + Table *t2 = createTable(solver, d2, 1, s1); + uint64_t row3[] = {6}; + addTableEntry(solver, t2, row3, 1, 6); + Function *f3 = completeTable(solver, t2, IGNOREBEHAVIOR); + Element *e5 = applyFunction(solver, f3, in2, 1, overflow); + + Set *d3[] = {s2, s3, s1}; + Element *in3[] = {e3, e4, e5}; + Table *t3 = createTable(solver, d3, 3, s4); + uint64_t row4[] = {4, 3, 6}; + uint64_t row5[] = {2, 1, 6}; + uint64_t row6[] = {2, 3, 6}; + uint64_t row7[] = {4, 1, 6}; + addTableEntry(solver, t3, row4, 3, 3); + addTableEntry(solver, t3, row5, 3, 1); + addTableEntry(solver, t3, row6, 3, 2); + addTableEntry(solver, t3, row7, 3, 1); + Function *f4 = completeTable(solver, t3, IGNOREBEHAVIOR); + Element *e6 = applyFunction(solver, f4, in3, 3, overflow); + + Set *deq[] = {s5,s4}; + Predicate *gt = createPredicateOperator(solver, GT, deq, 2); + Element *inputs2 [] = {e7, e6}; + Boolean *pred = applyPredicate(solver, gt, inputs2, 2); + addConstraint(solver, pred); + + if (startEncoding(solver) == 1) + printf("e1=%llu e2=%llu e7=%llu\n", + getElementValue(solver,e1), getElementValue(solver, e2), getElementValue(solver, e7)); + else + printf("UNSAT\n"); + deleteSolver(solver); +} diff --git a/src/Test/logicopstest.c b/src/Test/logicopstest.c deleted file mode 100644 index 9d12a05..0000000 --- a/src/Test/logicopstest.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "csolver.h" - -/** - * b1 AND b2=>b3 - * !b3 OR b4 - * b1 XOR b4 - * Result: b1=1 b2=0 b3=0 b4=0 - */ -int main(int numargs, char **argv) { - CSolver *solver = allocCSolver(); - Boolean *b1 = getBooleanVar(solver, 0); - Boolean *b2 = getBooleanVar(solver, 0); - Boolean *b3 = getBooleanVar(solver, 0); - Boolean *b4 = getBooleanVar(solver, 0); - //L_AND, L_OR, L_NOT, L_XOR, L_IMPLIES - Boolean *andb1b2 = applyLogicalOperation(solver, L_AND,(Boolean *[]) {b1, b2}, 2); - Boolean *imply = applyLogicalOperation(solver, L_IMPLIES, (Boolean *[]) {andb1b2, b3}, 2); - addConstraint(solver, imply); - Boolean *notb3 = applyLogicalOperation(solver, L_NOT, (Boolean *[]) {b3}, 1); - addConstraint(solver, applyLogicalOperation(solver, L_OR, (Boolean *[]) {notb3, b4}, 2)); - addConstraint(solver, applyLogicalOperation(solver, L_XOR, (Boolean * []) {b1, b4}, 2)); - if (startEncoding(solver) == 1) - printf("b1=%d b2=%d b3=%d b4=%d\n", - getBooleanValue(solver,b1), getBooleanValue(solver, b2), - getBooleanValue(solver, b3), getBooleanValue(solver, b4)); - else - printf("UNSAT\n"); - deleteSolver(solver); -} \ No newline at end of file diff --git a/src/Test/logicopstest.cc b/src/Test/logicopstest.cc new file mode 100644 index 0000000..9d12a05 --- /dev/null +++ b/src/Test/logicopstest.cc @@ -0,0 +1,29 @@ +#include "csolver.h" + +/** + * b1 AND b2=>b3 + * !b3 OR b4 + * b1 XOR b4 + * Result: b1=1 b2=0 b3=0 b4=0 + */ +int main(int numargs, char **argv) { + CSolver *solver = allocCSolver(); + Boolean *b1 = getBooleanVar(solver, 0); + Boolean *b2 = getBooleanVar(solver, 0); + Boolean *b3 = getBooleanVar(solver, 0); + Boolean *b4 = getBooleanVar(solver, 0); + //L_AND, L_OR, L_NOT, L_XOR, L_IMPLIES + Boolean *andb1b2 = applyLogicalOperation(solver, L_AND,(Boolean *[]) {b1, b2}, 2); + Boolean *imply = applyLogicalOperation(solver, L_IMPLIES, (Boolean *[]) {andb1b2, b3}, 2); + addConstraint(solver, imply); + Boolean *notb3 = applyLogicalOperation(solver, L_NOT, (Boolean *[]) {b3}, 1); + addConstraint(solver, applyLogicalOperation(solver, L_OR, (Boolean *[]) {notb3, b4}, 2)); + addConstraint(solver, applyLogicalOperation(solver, L_XOR, (Boolean * []) {b1, b4}, 2)); + if (startEncoding(solver) == 1) + printf("b1=%d b2=%d b3=%d b4=%d\n", + getBooleanValue(solver,b1), getBooleanValue(solver, b2), + getBooleanValue(solver, b3), getBooleanValue(solver, b4)); + else + printf("UNSAT\n"); + deleteSolver(solver); +} \ No newline at end of file diff --git a/src/Test/ltelemconsttest.c b/src/Test/ltelemconsttest.c deleted file mode 100644 index 4818f24..0000000 --- a/src/Test/ltelemconsttest.c +++ /dev/null @@ -1,26 +0,0 @@ -#include "csolver.h" -/** - * e1 = 5 - * e2 = {1, 3, 4, 6} - * e1 < e2 - * Result: e1=5 e2=6 - */ -int main(int numargs, char **argv) { - CSolver *solver = allocCSolver(); - uint64_t set1[] = {5}; - uint64_t set3[] = {1, 3, 4, 6}; - Set *s1 = createSet(solver, 0, set1, 3); - Set *s3 = createSet(solver, 0, set3, 4); - Element *e1 = getElementConst(solver, 4, 5); - Element *e2 = getElementVar(solver, s3); - Set *domain2[] = {s1, s3}; - Predicate *lt = createPredicateOperator(solver, LT, domain2, 2); - Element *inputs2[] = {e1, e2}; - Boolean *b = applyPredicate(solver, lt, inputs2, 2); - addConstraint(solver, b); - if (startEncoding(solver) == 1) - printf("e1=%llu e2=%llu\n", getElementValue(solver,e1), getElementValue(solver, e2)); - else - printf("UNSAT\n"); - deleteSolver(solver); -} \ No newline at end of file diff --git a/src/Test/ltelemconsttest.cc b/src/Test/ltelemconsttest.cc new file mode 100644 index 0000000..4818f24 --- /dev/null +++ b/src/Test/ltelemconsttest.cc @@ -0,0 +1,26 @@ +#include "csolver.h" +/** + * e1 = 5 + * e2 = {1, 3, 4, 6} + * e1 < e2 + * Result: e1=5 e2=6 + */ +int main(int numargs, char **argv) { + CSolver *solver = allocCSolver(); + uint64_t set1[] = {5}; + uint64_t set3[] = {1, 3, 4, 6}; + Set *s1 = createSet(solver, 0, set1, 3); + Set *s3 = createSet(solver, 0, set3, 4); + Element *e1 = getElementConst(solver, 4, 5); + Element *e2 = getElementVar(solver, s3); + Set *domain2[] = {s1, s3}; + Predicate *lt = createPredicateOperator(solver, LT, domain2, 2); + Element *inputs2[] = {e1, e2}; + Boolean *b = applyPredicate(solver, lt, inputs2, 2); + addConstraint(solver, b); + if (startEncoding(solver) == 1) + printf("e1=%llu e2=%llu\n", getElementValue(solver,e1), getElementValue(solver, e2)); + else + printf("UNSAT\n"); + deleteSolver(solver); +} \ No newline at end of file diff --git a/src/Test/ordergraphtest.c b/src/Test/ordergraphtest.c deleted file mode 100644 index 646b195..0000000 --- a/src/Test/ordergraphtest.c +++ /dev/null @@ -1,37 +0,0 @@ -#include "csolver.h" - -int main(int numargs, char **argv) { - CSolver *solver = allocCSolver(); - uint64_t set1[] = {1, 2, 3, 4, 5, 6, 7, 8}; - Set *s = createSet(solver, 0, set1, 8); - Order *order = createOrder(solver, TOTAL, s); - Boolean *o12 = orderConstraint(solver, order, 1, 2); - Boolean *o13 = orderConstraint(solver, order, 1, 3); - Boolean *o24 = orderConstraint(solver, order, 2, 4); - Boolean *o34 = orderConstraint(solver, order, 3, 4); - Boolean *o41 = orderConstraint(solver, order, 4, 1); - Boolean *o57 = orderConstraint(solver, order, 5, 7); - Boolean *o76 = orderConstraint(solver, order, 7, 6); - Boolean *o65 = orderConstraint(solver, order, 6, 5); - Boolean *o58 = orderConstraint(solver, order, 5, 8); - Boolean *o81 = orderConstraint(solver, order, 8, 1); - - addConstraint(solver, applyLogicalOperation(solver, L_OR,(Boolean *[]) {o12, o13, o24, o34}, 4) ); - Boolean *b1 = applyLogicalOperation(solver, L_XOR, (Boolean *[]) {o41, o57}, 2); - Boolean *o34n = applyLogicalOperation(solver, L_NOT, (Boolean *[]) {o34}, 1); - Boolean *o24n = applyLogicalOperation(solver, L_NOT, (Boolean *[]) {o24}, 1); - Boolean *b2 = applyLogicalOperation(solver, L_OR, (Boolean *[]) {o34n, o24n}, 2); - addConstraint(solver, applyLogicalOperation(solver, L_IMPLIES,(Boolean *[]) {b1, b2}, 2) ); - addConstraint(solver, applyLogicalOperation(solver, L_AND,(Boolean *[]) {o12, o13}, 2) ); - addConstraint(solver, applyLogicalOperation(solver, L_OR,(Boolean *[]) {o76, o65}, 2) ); - Boolean* b3= applyLogicalOperation(solver, L_AND,(Boolean *[]) {o76, o65}, 2) ; - Boolean* o57n= applyLogicalOperation(solver, L_NOT,(Boolean *[]) {o57}, 1); - addConstraint(solver, applyLogicalOperation(solver, L_IMPLIES,(Boolean *[]) {b3, o57n}, 2) ); - addConstraint(solver, applyLogicalOperation(solver, L_AND,(Boolean *[]) {o58, o81}, 2) ); - - if (startEncoding(solver) == 1) - printf("SAT\n"); - else - printf("UNSAT\n"); - deleteSolver(solver); -} \ No newline at end of file diff --git a/src/Test/ordergraphtest.cc b/src/Test/ordergraphtest.cc new file mode 100644 index 0000000..646b195 --- /dev/null +++ b/src/Test/ordergraphtest.cc @@ -0,0 +1,37 @@ +#include "csolver.h" + +int main(int numargs, char **argv) { + CSolver *solver = allocCSolver(); + uint64_t set1[] = {1, 2, 3, 4, 5, 6, 7, 8}; + Set *s = createSet(solver, 0, set1, 8); + Order *order = createOrder(solver, TOTAL, s); + Boolean *o12 = orderConstraint(solver, order, 1, 2); + Boolean *o13 = orderConstraint(solver, order, 1, 3); + Boolean *o24 = orderConstraint(solver, order, 2, 4); + Boolean *o34 = orderConstraint(solver, order, 3, 4); + Boolean *o41 = orderConstraint(solver, order, 4, 1); + Boolean *o57 = orderConstraint(solver, order, 5, 7); + Boolean *o76 = orderConstraint(solver, order, 7, 6); + Boolean *o65 = orderConstraint(solver, order, 6, 5); + Boolean *o58 = orderConstraint(solver, order, 5, 8); + Boolean *o81 = orderConstraint(solver, order, 8, 1); + + addConstraint(solver, applyLogicalOperation(solver, L_OR,(Boolean *[]) {o12, o13, o24, o34}, 4) ); + Boolean *b1 = applyLogicalOperation(solver, L_XOR, (Boolean *[]) {o41, o57}, 2); + Boolean *o34n = applyLogicalOperation(solver, L_NOT, (Boolean *[]) {o34}, 1); + Boolean *o24n = applyLogicalOperation(solver, L_NOT, (Boolean *[]) {o24}, 1); + Boolean *b2 = applyLogicalOperation(solver, L_OR, (Boolean *[]) {o34n, o24n}, 2); + addConstraint(solver, applyLogicalOperation(solver, L_IMPLIES,(Boolean *[]) {b1, b2}, 2) ); + addConstraint(solver, applyLogicalOperation(solver, L_AND,(Boolean *[]) {o12, o13}, 2) ); + addConstraint(solver, applyLogicalOperation(solver, L_OR,(Boolean *[]) {o76, o65}, 2) ); + Boolean* b3= applyLogicalOperation(solver, L_AND,(Boolean *[]) {o76, o65}, 2) ; + Boolean* o57n= applyLogicalOperation(solver, L_NOT,(Boolean *[]) {o57}, 1); + addConstraint(solver, applyLogicalOperation(solver, L_IMPLIES,(Boolean *[]) {b3, o57n}, 2) ); + addConstraint(solver, applyLogicalOperation(solver, L_AND,(Boolean *[]) {o58, o81}, 2) ); + + if (startEncoding(solver) == 1) + printf("SAT\n"); + else + printf("UNSAT\n"); + deleteSolver(solver); +} \ No newline at end of file diff --git a/src/Test/ordertest.c b/src/Test/ordertest.c deleted file mode 100644 index eef8c36..0000000 --- a/src/Test/ordertest.c +++ /dev/null @@ -1,23 +0,0 @@ - -#include "csolver.h" -/** - * TotalOrder(5, 1, 4) - * 5 => 1 - * 1 => 4 - * Result: O(5,1)=0 O(1,4)=0 O(5,4)=0 O(1,5)=1 O(1111,5)=2 - */ -int main(int numargs, char **argv) { - CSolver *solver = allocCSolver(); - uint64_t set1[] = {5, 1, 4}; - Set *s = createSet(solver, 0, set1, 3); - Order *order = createOrder(solver, TOTAL, s); - Boolean *b1 = orderConstraint(solver, order, 5, 1); - Boolean *b2 = orderConstraint(solver, order, 1, 4); - addConstraint(solver, b1); - addConstraint(solver, b2); - if (startEncoding(solver) == 1) - printf("SAT\n"); - else - printf("UNSAT\n"); - deleteSolver(solver); -} diff --git a/src/Test/ordertest.cc b/src/Test/ordertest.cc new file mode 100644 index 0000000..eef8c36 --- /dev/null +++ b/src/Test/ordertest.cc @@ -0,0 +1,23 @@ + +#include "csolver.h" +/** + * TotalOrder(5, 1, 4) + * 5 => 1 + * 1 => 4 + * Result: O(5,1)=0 O(1,4)=0 O(5,4)=0 O(1,5)=1 O(1111,5)=2 + */ +int main(int numargs, char **argv) { + CSolver *solver = allocCSolver(); + uint64_t set1[] = {5, 1, 4}; + Set *s = createSet(solver, 0, set1, 3); + Order *order = createOrder(solver, TOTAL, s); + Boolean *b1 = orderConstraint(solver, order, 5, 1); + Boolean *b2 = orderConstraint(solver, order, 1, 4); + addConstraint(solver, b1); + addConstraint(solver, b2); + if (startEncoding(solver) == 1) + printf("SAT\n"); + else + printf("UNSAT\n"); + deleteSolver(solver); +} diff --git a/src/Test/tablefuncencodetest.c b/src/Test/tablefuncencodetest.c deleted file mode 100644 index a7b9412..0000000 --- a/src/Test/tablefuncencodetest.c +++ /dev/null @@ -1,59 +0,0 @@ -#include "csolver.h" -/** - * e1 = {1, 2} - * e2={3, 5, 7} - * e3= f(e1, e2) - * 1 5 => 7 - * 2 3 => 5 - * 1 7 => 3 - * 2 7 => 5 - * 2 5 => 3 - * 1 3 => 5 - * e4 = {6, 10, 19} - * e4 <= e3 - * Result: e1=1, e2=5, e3=7, e4=6, overflow=0 - */ -int main(int numargs, char **argv) { - CSolver *solver = allocCSolver(); - uint64_t set1[] = {1, 2}; - uint64_t set2[] = {3, 5, 7}; - uint64_t set3[] = {6, 10, 19}; - Set *s1 = createSet(solver, 0, set1, 2); - Set *s2 = createSet(solver, 0, set2, 3); - Set *s3 = createSet(solver, 0, set3, 3); - Element *e1 = getElementVar(solver, s1); - Element *e2 = getElementVar(solver, s2); - Element *e4 = getElementVar(solver, s3); - Boolean *overflow = getBooleanVar(solver, 2); - Set *d1[] = {s1, s2}; - //change the overflow flag - Table *t1 = createTable(solver, d1, 2, s2); - uint64_t row1[] = {1, 5}; - uint64_t row2[] = {2, 3}; - uint64_t row3[] = {1, 7}; - uint64_t row4[] = {2, 7}; - uint64_t row5[] = {2, 5}; - uint64_t row6[] = {1, 3}; - addTableEntry(solver, t1, row1, 2, 7); - addTableEntry(solver, t1, row2, 2, 5); - addTableEntry(solver, t1, row3, 2, 3); - addTableEntry(solver, t1, row4, 2, 5); - addTableEntry(solver, t1, row5, 2, 3); - addTableEntry(solver, t1, row6, 2, 5); - Function *f1 = completeTable(solver, t1, FLAGIFFUNDEFINED); - Element *e3 = applyFunction(solver, f1, (Element * []) {e1,e2}, 2, overflow); - - Set *deq[] = {s3,s2}; - Predicate *lte = createPredicateOperator(solver, LTE, deq, 2); - Element *inputs2 [] = {e4, e3}; - Boolean *pred = applyPredicate(solver, lte, inputs2, 2); - addConstraint(solver, pred); - - if (startEncoding(solver) == 1) - printf("e1=%llu e2=%llu e3=%llu e4=%llu overFlow:%d\n", - getElementValue(solver,e1), getElementValue(solver, e2), getElementValue(solver, e3), - getElementValue(solver, e4), getBooleanValue(solver, overflow)); - else - printf("UNSAT\n"); - deleteSolver(solver); -} diff --git a/src/Test/tablefuncencodetest.cc b/src/Test/tablefuncencodetest.cc new file mode 100644 index 0000000..a7b9412 --- /dev/null +++ b/src/Test/tablefuncencodetest.cc @@ -0,0 +1,59 @@ +#include "csolver.h" +/** + * e1 = {1, 2} + * e2={3, 5, 7} + * e3= f(e1, e2) + * 1 5 => 7 + * 2 3 => 5 + * 1 7 => 3 + * 2 7 => 5 + * 2 5 => 3 + * 1 3 => 5 + * e4 = {6, 10, 19} + * e4 <= e3 + * Result: e1=1, e2=5, e3=7, e4=6, overflow=0 + */ +int main(int numargs, char **argv) { + CSolver *solver = allocCSolver(); + uint64_t set1[] = {1, 2}; + uint64_t set2[] = {3, 5, 7}; + uint64_t set3[] = {6, 10, 19}; + Set *s1 = createSet(solver, 0, set1, 2); + Set *s2 = createSet(solver, 0, set2, 3); + Set *s3 = createSet(solver, 0, set3, 3); + Element *e1 = getElementVar(solver, s1); + Element *e2 = getElementVar(solver, s2); + Element *e4 = getElementVar(solver, s3); + Boolean *overflow = getBooleanVar(solver, 2); + Set *d1[] = {s1, s2}; + //change the overflow flag + Table *t1 = createTable(solver, d1, 2, s2); + uint64_t row1[] = {1, 5}; + uint64_t row2[] = {2, 3}; + uint64_t row3[] = {1, 7}; + uint64_t row4[] = {2, 7}; + uint64_t row5[] = {2, 5}; + uint64_t row6[] = {1, 3}; + addTableEntry(solver, t1, row1, 2, 7); + addTableEntry(solver, t1, row2, 2, 5); + addTableEntry(solver, t1, row3, 2, 3); + addTableEntry(solver, t1, row4, 2, 5); + addTableEntry(solver, t1, row5, 2, 3); + addTableEntry(solver, t1, row6, 2, 5); + Function *f1 = completeTable(solver, t1, FLAGIFFUNDEFINED); + Element *e3 = applyFunction(solver, f1, (Element * []) {e1,e2}, 2, overflow); + + Set *deq[] = {s3,s2}; + Predicate *lte = createPredicateOperator(solver, LTE, deq, 2); + Element *inputs2 [] = {e4, e3}; + Boolean *pred = applyPredicate(solver, lte, inputs2, 2); + addConstraint(solver, pred); + + if (startEncoding(solver) == 1) + printf("e1=%llu e2=%llu e3=%llu e4=%llu overFlow:%d\n", + getElementValue(solver,e1), getElementValue(solver, e2), getElementValue(solver, e3), + getElementValue(solver, e4), getBooleanValue(solver, overflow)); + else + printf("UNSAT\n"); + deleteSolver(solver); +} diff --git a/src/Test/tablepredicencodetest.c b/src/Test/tablepredicencodetest.c deleted file mode 100644 index ee9094b..0000000 --- a/src/Test/tablepredicencodetest.c +++ /dev/null @@ -1,66 +0,0 @@ -#include "csolver.h" -/** - * e1 = {1, 2} - * e2={1, 3, 5, 7} - * e3 = {6, 10, 19} - * e4= p(e1, e2, e3) - * 1 5 6 => T - * 2 3 19 => T - * 1 3 19 => F - * 2 7 10 => F - * 1 7 6 => F - * 2 5 6 => T - * e1 == e2 - * e3 >= e2 - * Result: e1=1, e2=1, e3=6 OR 10 OR 19, overflow=1 - */ -int main(int numargs, char **argv) { - CSolver *solver = allocCSolver(); - uint64_t set1[] = {1, 2}; - uint64_t set2[] = {1, 3, 5, 7}; - uint64_t set3[] = {6, 10, 19}; - Set *s1 = createSet(solver, 0, set1, 2); - Set *s2 = createSet(solver, 0, set2, 4); - Set *s3 = createSet(solver, 0, set3, 3); - Element *e1 = getElementVar(solver, s1); - Element *e2 = getElementVar(solver, s2); - Element *e3 = getElementVar(solver, s3); - Set *d2[] = {s1, s2, s3}; - //change the overflow flag - Table *t1 = createTableForPredicate(solver, d2, 3); - uint64_t row1[] = {1, 5, 6}; - uint64_t row2[] = {2, 3, 19}; - uint64_t row3[] = {1, 3, 19}; - uint64_t row4[] = {2, 7, 10}; - uint64_t row5[] = {1, 7, 6}; - uint64_t row6[] = {2, 5, 6}; - addTableEntry(solver, t1, row1, 3, true); - addTableEntry(solver, t1, row2, 3, true); - addTableEntry(solver, t1, row3, 3, false); - addTableEntry(solver, t1, row4, 3, false); - addTableEntry(solver, t1, row5, 3, false); - addTableEntry(solver, t1, row6, 3, true); - Predicate *p1 = createPredicateTable(solver, t1, FLAGIFFUNDEFINED); - Boolean *undef = getBooleanVar(solver, 2); - Boolean *b1 = applyPredicateTable(solver, p1, (Element * []) {e1, e2, e3}, 3, undef); - addConstraint(solver, b1); - - Set *deq[] = {s3,s2}; - Predicate *gte = createPredicateOperator(solver, GTE, deq, 2); - Element *inputs2 [] = {e3, e2}; - Boolean *pred = applyPredicate(solver, gte, inputs2, 2); - addConstraint(solver, pred); - - Set *d1[] = {s1, s2}; - Predicate *eq = createPredicateOperator(solver, EQUALS, d1, 2); - Boolean *pred2 = applyPredicate(solver, eq,(Element *[]) {e1, e2}, 2); - addConstraint(solver, pred2); - - if (startEncoding(solver) == 1) - printf("e1=%llu e2=%llu e3=%llu undefFlag:%d\n", - getElementValue(solver,e1), getElementValue(solver, e2), - getElementValue(solver, e3), getBooleanValue(solver, undef)); - else - printf("UNSAT\n"); - deleteSolver(solver); -} diff --git a/src/Test/tablepredicencodetest.cc b/src/Test/tablepredicencodetest.cc new file mode 100644 index 0000000..ee9094b --- /dev/null +++ b/src/Test/tablepredicencodetest.cc @@ -0,0 +1,66 @@ +#include "csolver.h" +/** + * e1 = {1, 2} + * e2={1, 3, 5, 7} + * e3 = {6, 10, 19} + * e4= p(e1, e2, e3) + * 1 5 6 => T + * 2 3 19 => T + * 1 3 19 => F + * 2 7 10 => F + * 1 7 6 => F + * 2 5 6 => T + * e1 == e2 + * e3 >= e2 + * Result: e1=1, e2=1, e3=6 OR 10 OR 19, overflow=1 + */ +int main(int numargs, char **argv) { + CSolver *solver = allocCSolver(); + uint64_t set1[] = {1, 2}; + uint64_t set2[] = {1, 3, 5, 7}; + uint64_t set3[] = {6, 10, 19}; + Set *s1 = createSet(solver, 0, set1, 2); + Set *s2 = createSet(solver, 0, set2, 4); + Set *s3 = createSet(solver, 0, set3, 3); + Element *e1 = getElementVar(solver, s1); + Element *e2 = getElementVar(solver, s2); + Element *e3 = getElementVar(solver, s3); + Set *d2[] = {s1, s2, s3}; + //change the overflow flag + Table *t1 = createTableForPredicate(solver, d2, 3); + uint64_t row1[] = {1, 5, 6}; + uint64_t row2[] = {2, 3, 19}; + uint64_t row3[] = {1, 3, 19}; + uint64_t row4[] = {2, 7, 10}; + uint64_t row5[] = {1, 7, 6}; + uint64_t row6[] = {2, 5, 6}; + addTableEntry(solver, t1, row1, 3, true); + addTableEntry(solver, t1, row2, 3, true); + addTableEntry(solver, t1, row3, 3, false); + addTableEntry(solver, t1, row4, 3, false); + addTableEntry(solver, t1, row5, 3, false); + addTableEntry(solver, t1, row6, 3, true); + Predicate *p1 = createPredicateTable(solver, t1, FLAGIFFUNDEFINED); + Boolean *undef = getBooleanVar(solver, 2); + Boolean *b1 = applyPredicateTable(solver, p1, (Element * []) {e1, e2, e3}, 3, undef); + addConstraint(solver, b1); + + Set *deq[] = {s3,s2}; + Predicate *gte = createPredicateOperator(solver, GTE, deq, 2); + Element *inputs2 [] = {e3, e2}; + Boolean *pred = applyPredicate(solver, gte, inputs2, 2); + addConstraint(solver, pred); + + Set *d1[] = {s1, s2}; + Predicate *eq = createPredicateOperator(solver, EQUALS, d1, 2); + Boolean *pred2 = applyPredicate(solver, eq,(Element *[]) {e1, e2}, 2); + addConstraint(solver, pred2); + + if (startEncoding(solver) == 1) + printf("e1=%llu e2=%llu e3=%llu undefFlag:%d\n", + getElementValue(solver,e1), getElementValue(solver, e2), + getElementValue(solver, e3), getBooleanValue(solver, undef)); + else + printf("UNSAT\n"); + deleteSolver(solver); +} diff --git a/src/Tuner/tunable.c b/src/Tuner/tunable.c deleted file mode 100644 index 237b91c..0000000 --- a/src/Tuner/tunable.c +++ /dev/null @@ -1,16 +0,0 @@ -#include "tunable.h" - -Tuner * allocTuner() { - return ourmalloc(sizeof(Tuner)); -} - -void deleteTuner(Tuner *This) { - ourfree(This); -} - -int getTunable(Tuner *This, TunableParam param, TunableDesc * descriptor) { - return descriptor->defaultValue; -} -int getVarTunable(Tuner *This, VarType vartype, TunableParam param, TunableDesc * descriptor) { - return descriptor->defaultValue; -} diff --git a/src/Tuner/tunable.cc b/src/Tuner/tunable.cc new file mode 100644 index 0000000..e0a3201 --- /dev/null +++ b/src/Tuner/tunable.cc @@ -0,0 +1,16 @@ +#include "tunable.h" + +Tuner * allocTuner() { + return (Tuner *) ourmalloc(sizeof(Tuner)); +} + +void deleteTuner(Tuner *This) { + ourfree(This); +} + +int getTunable(Tuner *This, TunableParam param, TunableDesc * descriptor) { + return descriptor->defaultValue; +} +int getVarTunable(Tuner *This, VarType vartype, TunableParam param, TunableDesc * descriptor) { + return descriptor->defaultValue; +} diff --git a/src/common.c b/src/common.c deleted file mode 100644 index 660472f..0000000 --- a/src/common.c +++ /dev/null @@ -1,6 +0,0 @@ -#include "common.h" - -void assert_hook(void) -{ - model_print("Add breakpoint to line %u in file %s.\n", __LINE__, __FILE__); -} \ No newline at end of file diff --git a/src/common.cc b/src/common.cc new file mode 100644 index 0000000..660472f --- /dev/null +++ b/src/common.cc @@ -0,0 +1,6 @@ +#include "common.h" + +void assert_hook(void) +{ + model_print("Add breakpoint to line %u in file %s.\n", __LINE__, __FILE__); +} \ No newline at end of file diff --git a/src/csolver.c b/src/csolver.c deleted file mode 100644 index e9c9526..0000000 --- a/src/csolver.c +++ /dev/null @@ -1,242 +0,0 @@ -#include "csolver.h" -#include "set.h" -#include "mutableset.h" -#include "element.h" -#include "boolean.h" -#include "predicate.h" -#include "order.h" -#include "table.h" -#include "function.h" -#include "satencoder.h" -#include "sattranslator.h" -#include "tunable.h" -#include "orderencoder.h" -#include "polarityassignment.h" - -CSolver *allocCSolver() { - CSolver *This = (CSolver *) ourmalloc(sizeof(CSolver)); - This->unsat = false; - This->constraints = allocDefHashSetBoolean(); - This->allBooleans = allocDefVectorBoolean(); - This->allSets = allocDefVectorSet(); - This->allElements = allocDefVectorElement(); - This->allPredicates = allocDefVectorPredicate(); - This->allTables = allocDefVectorTable(); - This->allOrders = allocDefVectorOrder(); - This->allFunctions = allocDefVectorFunction(); - This->tuner = allocTuner(); - This->satEncoder = allocSATEncoder(This); - return This; -} - -/** This function tears down the solver and the entire AST */ - -void deleteSolver(CSolver *This) { - deleteHashSetBoolean(This->constraints); - - uint size = getSizeVectorBoolean(This->allBooleans); - for (uint i = 0; i < size; i++) { - deleteBoolean(getVectorBoolean(This->allBooleans, i)); - } - deleteVectorBoolean(This->allBooleans); - - size = getSizeVectorSet(This->allSets); - for (uint i = 0; i < size; i++) { - deleteSet(getVectorSet(This->allSets, i)); - } - deleteVectorSet(This->allSets); - - size = getSizeVectorElement(This->allElements); - for (uint i = 0; i < size; i++) { - deleteElement(getVectorElement(This->allElements, i)); - } - deleteVectorElement(This->allElements); - - size = getSizeVectorTable(This->allTables); - for (uint i = 0; i < size; i++) { - deleteTable(getVectorTable(This->allTables, i)); - } - deleteVectorTable(This->allTables); - - size = getSizeVectorPredicate(This->allPredicates); - for (uint i = 0; i < size; i++) { - deletePredicate(getVectorPredicate(This->allPredicates, i)); - } - deleteVectorPredicate(This->allPredicates); - - size = getSizeVectorOrder(This->allOrders); - for (uint i = 0; i < size; i++) { - deleteOrder(getVectorOrder(This->allOrders, i)); - } - deleteVectorOrder(This->allOrders); - - size = getSizeVectorFunction(This->allFunctions); - for (uint i = 0; i < size; i++) { - deleteFunction(getVectorFunction(This->allFunctions, i)); - } - deleteVectorFunction(This->allFunctions); - deleteSATEncoder(This->satEncoder); - deleteTuner(This->tuner); - ourfree(This); -} - -Set *createSet(CSolver *This, VarType type, uint64_t *elements, uint numelements) { - Set *set = allocSet(type, elements, numelements); - pushVectorSet(This->allSets, set); - return set; -} - -Set *createRangeSet(CSolver *This, VarType type, uint64_t lowrange, uint64_t highrange) { - Set *set = allocSetRange(type, lowrange, highrange); - pushVectorSet(This->allSets, set); - return set; -} - -MutableSet *createMutableSet(CSolver *This, VarType type) { - MutableSet *set = allocMutableSet(type); - pushVectorSet(This->allSets, set); - return set; -} - -void addItem(CSolver *This, MutableSet *set, uint64_t element) { - addElementMSet(set, element); -} - -uint64_t createUniqueItem(CSolver *This, MutableSet *set) { - uint64_t element = set->low++; - addElementMSet(set, element); - return element; -} - -Element *getElementVar(CSolver *This, Set *set) { - Element *element = allocElementSet(set); - pushVectorElement(This->allElements, element); - return element; -} - -Element *getElementConst(CSolver *This, VarType type, uint64_t value) { - Element *element = allocElementConst(value, type); - pushVectorElement(This->allElements, element); - return element; -} - -Boolean *getBooleanVar(CSolver *This, VarType type) { - Boolean *boolean = allocBooleanVar(type); - pushVectorBoolean(This->allBooleans, boolean); - return boolean; -} - -Function *createFunctionOperator(CSolver *This, ArithOp op, Set **domain, uint numDomain, Set *range,OverFlowBehavior overflowbehavior) { - Function *function = allocFunctionOperator(op, domain, numDomain, range, overflowbehavior); - pushVectorFunction(This->allFunctions, function); - return function; -} - -Predicate *createPredicateOperator(CSolver *This, CompOp op, Set **domain, uint numDomain) { - Predicate *predicate = allocPredicateOperator(op, domain,numDomain); - pushVectorPredicate(This->allPredicates, predicate); - return predicate; -} - -Predicate *createPredicateTable(CSolver *This, Table *table, UndefinedBehavior behavior) { - Predicate *predicate = allocPredicateTable(table, behavior); - pushVectorPredicate(This->allPredicates, predicate); - return predicate; -} - -Table *createTable(CSolver *This, Set **domains, uint numDomain, Set *range) { - Table *table = allocTable(domains,numDomain,range); - pushVectorTable(This->allTables, table); - return table; -} - -Table *createTableForPredicate(CSolver *solver, Set **domains, uint numDomain) { - return createTable(solver, domains, numDomain, NULL); -} - -void addTableEntry(CSolver *This, Table *table, uint64_t *inputs, uint inputSize, uint64_t result) { - addNewTableEntry(table,inputs, inputSize,result); -} - -Function *completeTable(CSolver *This, Table *table, UndefinedBehavior behavior) { - Function *function = allocFunctionTable(table, behavior); - pushVectorFunction(This->allFunctions,function); - return function; -} - -Element *applyFunction(CSolver *This, Function *function, Element **array, uint numArrays, Boolean *overflowstatus) { - Element *element = allocElementFunction(function,array,numArrays,overflowstatus); - pushVectorElement(This->allElements, element); - return element; -} - -Boolean *applyPredicate(CSolver *This, Predicate *predicate, Element **inputs, uint numInputs) { - return applyPredicateTable(This, predicate, inputs, numInputs, NULL); -} -Boolean *applyPredicateTable(CSolver *This, Predicate *predicate, Element **inputs, uint numInputs, Boolean *undefinedStatus) { - Boolean *boolean = allocBooleanPredicate(predicate, inputs, numInputs, undefinedStatus); - pushVectorBoolean(This->allBooleans, boolean); - return boolean; -} - -Boolean *applyLogicalOperation(CSolver *This, LogicOp op, Boolean **array, uint asize) { - return allocBooleanLogicArray(This, op, array, asize); -} - -void addConstraint(CSolver *This, Boolean *constraint) { - addHashSetBoolean(This->constraints, constraint); -} - -Order *createOrder(CSolver *This, OrderType type, Set *set) { - Order *order = allocOrder(type, set); - pushVectorOrder(This->allOrders, order); - return order; -} - -Boolean *orderConstraint(CSolver *This, Order *order, uint64_t first, uint64_t second) { - Boolean *constraint = allocBooleanOrder(order, first, second); - pushVectorBoolean(This->allBooleans,constraint); - return constraint; -} - -int startEncoding(CSolver *This) { - naiveEncodingDecision(This); - SATEncoder *satEncoder = This->satEncoder; - computePolarities(This); - orderAnalysis(This); - encodeAllSATEncoder(This, satEncoder); - int result = solveCNF(satEncoder->cnf); - model_print("sat_solver's result:%d\tsolutionSize=%d\n", result, satEncoder->cnf->solver->solutionsize); - for (uint i = 1; i <= satEncoder->cnf->solver->solutionsize; i++) { - model_print("%d, ", satEncoder->cnf->solver->solution[i]); - } - model_print("\n"); - return result; -} - -uint64_t getElementValue(CSolver *This, Element *element) { - switch (GETELEMENTTYPE(element)) { - case ELEMSET: - case ELEMCONST: - case ELEMFUNCRETURN: - return getElementValueSATTranslator(This, element); - default: - ASSERT(0); - } - exit(-1); -} - -bool getBooleanValue( CSolver *This, Boolean *boolean) { - switch (GETBOOLEANTYPE(boolean)) { - case BOOLEANVAR: - return getBooleanVariableValueSATTranslator(This, boolean); - default: - ASSERT(0); - } - exit(-1); -} - -HappenedBefore getOrderConstraintValue(CSolver *This, Order *order, uint64_t first, uint64_t second) { - return getOrderConstraintValueSATTranslator(This, order, first, second); -} - diff --git a/src/csolver.cc b/src/csolver.cc new file mode 100644 index 0000000..e9c9526 --- /dev/null +++ b/src/csolver.cc @@ -0,0 +1,242 @@ +#include "csolver.h" +#include "set.h" +#include "mutableset.h" +#include "element.h" +#include "boolean.h" +#include "predicate.h" +#include "order.h" +#include "table.h" +#include "function.h" +#include "satencoder.h" +#include "sattranslator.h" +#include "tunable.h" +#include "orderencoder.h" +#include "polarityassignment.h" + +CSolver *allocCSolver() { + CSolver *This = (CSolver *) ourmalloc(sizeof(CSolver)); + This->unsat = false; + This->constraints = allocDefHashSetBoolean(); + This->allBooleans = allocDefVectorBoolean(); + This->allSets = allocDefVectorSet(); + This->allElements = allocDefVectorElement(); + This->allPredicates = allocDefVectorPredicate(); + This->allTables = allocDefVectorTable(); + This->allOrders = allocDefVectorOrder(); + This->allFunctions = allocDefVectorFunction(); + This->tuner = allocTuner(); + This->satEncoder = allocSATEncoder(This); + return This; +} + +/** This function tears down the solver and the entire AST */ + +void deleteSolver(CSolver *This) { + deleteHashSetBoolean(This->constraints); + + uint size = getSizeVectorBoolean(This->allBooleans); + for (uint i = 0; i < size; i++) { + deleteBoolean(getVectorBoolean(This->allBooleans, i)); + } + deleteVectorBoolean(This->allBooleans); + + size = getSizeVectorSet(This->allSets); + for (uint i = 0; i < size; i++) { + deleteSet(getVectorSet(This->allSets, i)); + } + deleteVectorSet(This->allSets); + + size = getSizeVectorElement(This->allElements); + for (uint i = 0; i < size; i++) { + deleteElement(getVectorElement(This->allElements, i)); + } + deleteVectorElement(This->allElements); + + size = getSizeVectorTable(This->allTables); + for (uint i = 0; i < size; i++) { + deleteTable(getVectorTable(This->allTables, i)); + } + deleteVectorTable(This->allTables); + + size = getSizeVectorPredicate(This->allPredicates); + for (uint i = 0; i < size; i++) { + deletePredicate(getVectorPredicate(This->allPredicates, i)); + } + deleteVectorPredicate(This->allPredicates); + + size = getSizeVectorOrder(This->allOrders); + for (uint i = 0; i < size; i++) { + deleteOrder(getVectorOrder(This->allOrders, i)); + } + deleteVectorOrder(This->allOrders); + + size = getSizeVectorFunction(This->allFunctions); + for (uint i = 0; i < size; i++) { + deleteFunction(getVectorFunction(This->allFunctions, i)); + } + deleteVectorFunction(This->allFunctions); + deleteSATEncoder(This->satEncoder); + deleteTuner(This->tuner); + ourfree(This); +} + +Set *createSet(CSolver *This, VarType type, uint64_t *elements, uint numelements) { + Set *set = allocSet(type, elements, numelements); + pushVectorSet(This->allSets, set); + return set; +} + +Set *createRangeSet(CSolver *This, VarType type, uint64_t lowrange, uint64_t highrange) { + Set *set = allocSetRange(type, lowrange, highrange); + pushVectorSet(This->allSets, set); + return set; +} + +MutableSet *createMutableSet(CSolver *This, VarType type) { + MutableSet *set = allocMutableSet(type); + pushVectorSet(This->allSets, set); + return set; +} + +void addItem(CSolver *This, MutableSet *set, uint64_t element) { + addElementMSet(set, element); +} + +uint64_t createUniqueItem(CSolver *This, MutableSet *set) { + uint64_t element = set->low++; + addElementMSet(set, element); + return element; +} + +Element *getElementVar(CSolver *This, Set *set) { + Element *element = allocElementSet(set); + pushVectorElement(This->allElements, element); + return element; +} + +Element *getElementConst(CSolver *This, VarType type, uint64_t value) { + Element *element = allocElementConst(value, type); + pushVectorElement(This->allElements, element); + return element; +} + +Boolean *getBooleanVar(CSolver *This, VarType type) { + Boolean *boolean = allocBooleanVar(type); + pushVectorBoolean(This->allBooleans, boolean); + return boolean; +} + +Function *createFunctionOperator(CSolver *This, ArithOp op, Set **domain, uint numDomain, Set *range,OverFlowBehavior overflowbehavior) { + Function *function = allocFunctionOperator(op, domain, numDomain, range, overflowbehavior); + pushVectorFunction(This->allFunctions, function); + return function; +} + +Predicate *createPredicateOperator(CSolver *This, CompOp op, Set **domain, uint numDomain) { + Predicate *predicate = allocPredicateOperator(op, domain,numDomain); + pushVectorPredicate(This->allPredicates, predicate); + return predicate; +} + +Predicate *createPredicateTable(CSolver *This, Table *table, UndefinedBehavior behavior) { + Predicate *predicate = allocPredicateTable(table, behavior); + pushVectorPredicate(This->allPredicates, predicate); + return predicate; +} + +Table *createTable(CSolver *This, Set **domains, uint numDomain, Set *range) { + Table *table = allocTable(domains,numDomain,range); + pushVectorTable(This->allTables, table); + return table; +} + +Table *createTableForPredicate(CSolver *solver, Set **domains, uint numDomain) { + return createTable(solver, domains, numDomain, NULL); +} + +void addTableEntry(CSolver *This, Table *table, uint64_t *inputs, uint inputSize, uint64_t result) { + addNewTableEntry(table,inputs, inputSize,result); +} + +Function *completeTable(CSolver *This, Table *table, UndefinedBehavior behavior) { + Function *function = allocFunctionTable(table, behavior); + pushVectorFunction(This->allFunctions,function); + return function; +} + +Element *applyFunction(CSolver *This, Function *function, Element **array, uint numArrays, Boolean *overflowstatus) { + Element *element = allocElementFunction(function,array,numArrays,overflowstatus); + pushVectorElement(This->allElements, element); + return element; +} + +Boolean *applyPredicate(CSolver *This, Predicate *predicate, Element **inputs, uint numInputs) { + return applyPredicateTable(This, predicate, inputs, numInputs, NULL); +} +Boolean *applyPredicateTable(CSolver *This, Predicate *predicate, Element **inputs, uint numInputs, Boolean *undefinedStatus) { + Boolean *boolean = allocBooleanPredicate(predicate, inputs, numInputs, undefinedStatus); + pushVectorBoolean(This->allBooleans, boolean); + return boolean; +} + +Boolean *applyLogicalOperation(CSolver *This, LogicOp op, Boolean **array, uint asize) { + return allocBooleanLogicArray(This, op, array, asize); +} + +void addConstraint(CSolver *This, Boolean *constraint) { + addHashSetBoolean(This->constraints, constraint); +} + +Order *createOrder(CSolver *This, OrderType type, Set *set) { + Order *order = allocOrder(type, set); + pushVectorOrder(This->allOrders, order); + return order; +} + +Boolean *orderConstraint(CSolver *This, Order *order, uint64_t first, uint64_t second) { + Boolean *constraint = allocBooleanOrder(order, first, second); + pushVectorBoolean(This->allBooleans,constraint); + return constraint; +} + +int startEncoding(CSolver *This) { + naiveEncodingDecision(This); + SATEncoder *satEncoder = This->satEncoder; + computePolarities(This); + orderAnalysis(This); + encodeAllSATEncoder(This, satEncoder); + int result = solveCNF(satEncoder->cnf); + model_print("sat_solver's result:%d\tsolutionSize=%d\n", result, satEncoder->cnf->solver->solutionsize); + for (uint i = 1; i <= satEncoder->cnf->solver->solutionsize; i++) { + model_print("%d, ", satEncoder->cnf->solver->solution[i]); + } + model_print("\n"); + return result; +} + +uint64_t getElementValue(CSolver *This, Element *element) { + switch (GETELEMENTTYPE(element)) { + case ELEMSET: + case ELEMCONST: + case ELEMFUNCRETURN: + return getElementValueSATTranslator(This, element); + default: + ASSERT(0); + } + exit(-1); +} + +bool getBooleanValue( CSolver *This, Boolean *boolean) { + switch (GETBOOLEANTYPE(boolean)) { + case BOOLEANVAR: + return getBooleanVariableValueSATTranslator(This, boolean); + default: + ASSERT(0); + } + exit(-1); +} + +HappenedBefore getOrderConstraintValue(CSolver *This, Order *order, uint64_t first, uint64_t second) { + return getOrderConstraintValueSATTranslator(This, order, first, second); +} +