1)core dump in regex for big strings 2) Boolean Var bugs 3) adding support for other...
[satune.git] / src / AlloyEnc / alloyenc.cc
index c7acf23e140c691b1da8e8a067f2d04da497bb9a..6a8dcdfe1a122af005f6abd8e99f87521299ddf6 100644 (file)
@@ -7,8 +7,10 @@
 #include "predicate.h"
 #include "element.h"
 #include "signature.h"
+#include "set.h"
+#include "function.h"
 #include <fstream>
-#include <regex>
+#include <vector>
 
 using namespace std;
 
@@ -33,12 +35,12 @@ AlloyEnc::~AlloyEnc(){
 }
 
 void AlloyEnc::encode(){
+       dumpAlloyHeader();
        SetIteratorBooleanEdge *iterator = csolver->getConstraints();
        Vector<char *> facts;
        while(iterator->hasNext()){
                BooleanEdge constraint = iterator->next();
                string constr = encodeConstraint(constraint);
-               //model_print("constr=%s\n", constr.c_str());
                char *cstr = new char [constr.length()+1];
                strcpy (cstr, constr.c_str());
                facts.push(cstr);
@@ -53,34 +55,61 @@ void AlloyEnc::encode(){
        delete iterator;
 }
 
+void tokenize(string const &str, const char delim, vector<std::string> &out)
+{
+       size_t start;
+       size_t end = 0;
+
+       while ((start = str.find_first_not_of(delim, end)) != string::npos)
+       {
+               end = str.find(delim, start);
+               out.push_back(str.substr(start, end - start));
+       }
+}
+
 int AlloyEnc::getResult(){
        ifstream input(solutionFile, ios::in);
        string line;
        while(getline(input, line)){
-               if(regex_match(line, regex("Unsatisfiable."))){
+               if(line.find("Unsatisfiable.")== 0){
                        return IS_UNSAT;
                }
-               if(regex_match(line, regex(".*Element\\d+.*value=.*Element\\d+.*->\\d+.*"))){
-                       int tmp=0, index=0, value=0;
-                       const char* s = line.c_str();
-                       uint i1, i2, i3;
-                       uint64_t i4;
-                       if (4 == sscanf(s,"%*[^0123456789]%u%*[^0123456789]%d%*[^0123456789]%d%*[^0123456789]%" PRId64 "", &i1, &i2, &i3, &i4)){
-                               model_print("Element%d = %" PRId64 "\n", i1, i4);
-                               sigEnc.setValue(i1, i4);
+               if(line.find("univ") == 0){
+                       continue;
+               }
+               if(line.find("this/AbsBool<:value") == 0 || line.find("this/AbsElement<:value=") == 0){
+                       vector<string> values;
+                       const char delim = ',';
+                       tokenize(line, delim, values);
+                       for (uint i=0; i<values.size(); i++){
+                               uint i1, i2, i3;
+                               if (3 == sscanf(values[i].c_str(),"%*[^0123456789]%u%*[^0123456789]%d%*[^0123456789]%u", &i1, &i2, &i3)){
+                                       model_print("Signature%u = %u\n", i1, i3);
+                                       sigEnc.setValue(i1, i3);
+                               }
                        }
                }
        }
        return IS_SAT;
 }
 
+void AlloyEnc::dumpAlloyFooter(){
+       output << "pred show {}" << endl;
+       output << "run show for " << sigEnc.getAlloyIntScope() << " int" << endl;
+}
+
+void AlloyEnc::dumpAlloyHeader(){
+       output << "open util/integer" << endl;
+}
+
 int AlloyEnc::solve(){
+       dumpAlloyFooter();
        int result = IS_INDETER;
        char buffer [512];
        if( output.is_open()){
                output.close();
        }
-       snprintf(buffer, sizeof(buffer), "./run.sh java edu.mit.csail.sdg.alloy4whole.ExampleAlloyCompilerNoViz %s > %s", alloyFileName, solutionFile);
+       snprintf(buffer, sizeof(buffer), "./run.sh java -Xmx10000m edu.mit.csail.sdg.alloy4whole.ExampleAlloyCompilerNoViz %s > %s", alloyFileName, solutionFile);
        int status = system(buffer);
        if (status == 0) {
                //Read data in from results file
@@ -101,6 +130,10 @@ string AlloyEnc::encodeConstraint(BooleanEdge c){
                        res = encodePredicate((BooleanPredicate *) constraint);
                        break;
                }
+               case BOOLEANVAR:{
+                       res = encodeBooleanVar( (BooleanVar *) constraint);
+                       break;
+               }
                default:
                        ASSERT(0);
        }
@@ -115,24 +148,46 @@ string AlloyEnc::encodeBooleanLogic( BooleanLogic *bl){
        string array[size];
        for (uint i = 0; i < size; i++)
                array[i] = encodeConstraint(bl->inputs.get(i));
+       string op;
+       switch (bl->op){
+               case SATC_OR:
+                       op = " or ";
+                       break;
+               case SATC_AND:
+                       op = " and ";
+                       break;
+               case SATC_NOT:
+                       op = " not ";
+                       break;
+               case SATC_IFF:
+                       op = " iff ";
+                       break;
+               case SATC_IMPLIES:
+                       op = " implies ";
+                       break;
+               case SATC_XOR:
+               default:
+                       ASSERT(0);
+       }
        switch (bl->op) {
+               case SATC_OR:
                case SATC_AND:{
                        ASSERT(size >= 2);
-                       string res = "";
+                       string res = "";
                        res += array[0];
                        for( uint i=1; i< size; i++){
-                               res += " and " + array[i];
+                               res += op + array[i];
                        }
+                       res += " )";
                        return res;
                }
                case SATC_NOT:{
-                       return "not " + array[0];
+                       return "not ( " + array[0] + " )";
                }
+               case SATC_IMPLIES:
                case SATC_IFF:
-                       return array[0] + " iff " + array[1];
-               case SATC_OR:
+                       return "( " + array[0] + op + array[1] + " )";
                case SATC_XOR:
-               case SATC_IMPLIES:
                default:
                        ASSERT(0);
 
@@ -150,33 +205,84 @@ string AlloyEnc::encodePredicate( BooleanPredicate *bp){
        }
 }
 
+string AlloyEnc::encodeBooleanVar( BooleanVar *bv){
+       BooleanSig * boolSig = sigEnc.getBooleanSignature(bv);
+       return *boolSig + " = 1";
+}
+
+string AlloyEnc::processElementFunction(ElementFunction* elemFunc, ElementSig *signature){
+       FunctionOperator *function = (FunctionOperator *) elemFunc->getFunction();
+       uint numDomains = elemFunc->inputs.getSize();
+       ASSERT(numDomains > 1);
+       ElementSig *inputs[numDomains];
+       string result;
+       for (uint i = 0; i < numDomains; i++) {
+               Element *elem = elemFunc->inputs.get(i);
+               inputs[i] = sigEnc.getElementSignature(elem);
+               if(elem->type == ELEMFUNCRETURN){
+                       result += processElementFunction((ElementFunction *) elem, inputs[i]);
+               }
+       }
+       string op;
+       switch(function->op){
+               case SATC_ADD:
+                       op = ".add";
+                       break;
+               case SATC_SUB:
+                       op = ".sub";
+                       break;
+               default:
+                       ASSERT(0);
+       }
+       result += *signature + " = " + *inputs[0];
+       for (uint i = 1; i < numDomains; i++) {
+               result += op + "["+ *inputs[i] +"]";
+       }
+       result += "\n";
+       return result;
+}
+
 string AlloyEnc::encodeOperatorPredicate(BooleanPredicate *constraint){
        PredicateOperator *predicate = (PredicateOperator *) constraint->predicate;
        ASSERT(constraint->inputs.getSize() == 2);
+       string str;
        Element *elem0 = constraint->inputs.get(0);
-       ASSERT(elem0->type = ELEMSET);
+       ASSERT(elem0->type == ELEMSET || elem0->type == ELEMFUNCRETURN || elem0->type == ELEMCONST);
        ElementSig *elemSig1 = sigEnc.getElementSignature(elem0);
+       if(elem0->type == ELEMFUNCRETURN){
+               str += processElementFunction((ElementFunction *) elem0, elemSig1);
+       }
        Element *elem1 = constraint->inputs.get(1);
-       ASSERT(elem1->type = ELEMSET);
+       ASSERT(elem1->type == ELEMSET || elem1->type == ELEMFUNCRETURN || elem1->type == ELEMCONST);
        ElementSig *elemSig2 = sigEnc.getElementSignature(elem1);
+       if(elem1->type == ELEMFUNCRETURN){
+               str += processElementFunction((ElementFunction *) elem1, elemSig2);
+       }
        switch (predicate->getOp()) {
                case SATC_EQUALS:
-                       return *elemSig1 + " = " + *elemSig2;
+                       str += *elemSig1 + " = " + *elemSig2;
+                       break;
                case SATC_LT:
-                       return *elemSig1 + " < " + *elemSig2;
+                       str += *elemSig1 + " < " + *elemSig2;
+                       break;
                case SATC_GT:
-                       return *elemSig1 + " > " + *elemSig2; 
+                       str += *elemSig1 + " > " + *elemSig2;
+                       break; 
                default:
                        ASSERT(0);
        }
-       exit(-1);
+       return str;
 }
 
 void AlloyEnc::writeToFile(string str){
        output << str << endl;
 }
 
+bool AlloyEnc::getBooleanValue(Boolean *b){
+       return (bool)sigEnc.getValue(b);
+}
+
 uint64_t AlloyEnc::getValue(Element * element){
-       return sigEnc.getValue(element);
+       return (uint64_t)sigEnc.getValue(element);
 }