Merging with Tuner branch
[satune.git] / src / Interpreter / alloyinterpreter.cc
1 #include "alloyinterpreter.h"
2 #include <string>
3 #include "signatureenc.h"
4 #include "structs.h"
5 #include "csolver.h"
6 #include "boolean.h"
7 #include "predicate.h"
8 #include "element.h"
9 #include "alloysig.h"
10 #include "set.h"
11 #include "function.h"
12 #include "inc_solver.h"
13 #include <fstream>
14 #include "cppvector.h"
15 #include "math.h"
16
17 using namespace std;
18
19 #define ALLOYFILENAME "satune.als"
20 #define ALLOYSOLUTIONFILE "solution.sol"
21
22 AlloyInterpreter::AlloyInterpreter(CSolver *_solver): 
23         Interpreter(_solver) 
24 {
25         output.open(ALLOYFILENAME);
26         if(!output.is_open()){
27                 model_print("AlloyEnc:Error in opening the dump file satune.als\n");
28                 exit(-1);
29         }
30 }
31
32 AlloyInterpreter::~AlloyInterpreter(){
33         if(output.is_open()){
34                 output.close();
35         }
36 }
37
38 ValuedSignature *AlloyInterpreter::getBooleanSignature(uint id){
39         return new AlloyBoolSig(id);
40 }
41
42 ValuedSignature *AlloyInterpreter::getElementSignature(uint id, Signature *ssig){
43         return new AlloyElementSig(id, ssig);
44 }
45
46 Signature *AlloyInterpreter::getSetSignature(uint id, Set *set){
47         return new AlloySetSig(id, set);
48 }
49
50 void AlloyInterpreter::dumpAllConstraints(Vector<char *> &facts){
51         output << "fact {" << endl;
52         for(uint i=0; i< facts.getSize(); i++){
53                 char *cstr = facts.get(i);
54                 writeToFile(cstr);
55         }
56         output << "}" << endl;
57 }
58
59
60 int AlloyInterpreter::getResult(){
61         ifstream input(ALLOYSOLUTIONFILE, ios::in);
62         string line;
63         while(getline(input, line)){
64                 if(line.find("Unsatisfiable.")== 0){
65                         return IS_UNSAT;
66                 }
67                 if(line.find("univ") == 0){
68                         continue;
69                 }
70                 if(line.find("this/AbsBool<:value") == 0 || line.find("this/AbsElement<:value=") == 0){
71                         const char delim [2] = ",";
72                         char cline [line.size()+1];
73                         strcpy ( cline, line.c_str() );
74                         char *token = strtok(cline, delim);
75                         while( token != NULL ) {
76                                 uint i1, i2, i3;
77                                 if (3 == sscanf(token,"%*[^0123456789]%u%*[^0123456789]%d%*[^0123456789]%u", &i1, &i2, &i3)){
78                                         model_print("Signature%u = %u\n", i1, i3);
79                                         sigEnc.setValue(i1, i3);
80                                 }
81                                 token = strtok(NULL, delim);
82                         }
83                 }
84         }
85         return IS_SAT;
86 }
87
88
89 int AlloyInterpreter::getAlloyIntScope(){
90         double mylog = log2(sigEnc.getMaxValue() + 1);
91         return floor(mylog) == mylog ? (int)mylog + 1: (int)mylog + 2;
92 }
93
94 void AlloyInterpreter::dumpFooter(){
95         output << "pred show {}" << endl;
96         output << "run show for " << getAlloyIntScope() << " int" << endl;
97 }
98
99 void AlloyInterpreter::dumpHeader(){
100         output << "open util/integer" << endl;
101 }
102
103 void AlloyInterpreter::compileRunCommand(char * command, size_t size){
104         snprintf(command, size, "./run.sh timeout %u java -Xmx10000m edu.mit.csail.sdg.alloy4whole.ExampleAlloyCompilerNoViz %s > %s", getTimeout(), ALLOYFILENAME, ALLOYSOLUTIONFILE);
105 }
106
107 string AlloyInterpreter::negateConstraint(string constr){
108         return "not ( " + constr + " )";
109 }
110
111 string AlloyInterpreter::encodeBooleanLogic( BooleanLogic *bl){
112         uint size = bl->inputs.getSize();
113         string array[size];
114         for (uint i = 0; i < size; i++)
115                 array[i] = encodeConstraint(bl->inputs.get(i));
116         string op;
117         switch (bl->op){
118                 case SATC_OR:
119                         op = " or ";
120                         break;
121                 case SATC_AND:
122                         op = " and ";
123                         break;
124                 case SATC_NOT:
125                         op = " not ";
126                         break;
127                 case SATC_IFF:
128                         op = " iff ";
129                         break;
130                 case SATC_IMPLIES:
131                         op = " implies ";
132                         break;
133                 case SATC_XOR:
134                 default:
135                         ASSERT(0);
136         }
137         switch (bl->op) {
138                 case SATC_OR:
139                 case SATC_AND:{
140                         ASSERT(size >= 2);
141                         string res = "( ";
142                         res += array[0];
143                         for( uint i=1; i< size; i++){
144                                 res += op + array[i];
145                         }
146                         res += " )";
147                         return res;
148                 }
149                 case SATC_NOT:{
150                         return "not ( " + array[0] + " )";
151                 }
152                 case SATC_IMPLIES:
153                 case SATC_IFF:
154                         return "( " + array[0] + op + array[1] + " )";
155                 case SATC_XOR:
156                 default:
157                         ASSERT(0);
158
159         }
160 }
161
162 string AlloyInterpreter::encodeBooleanVar( BooleanVar *bv){
163         ValuedSignature * boolSig = sigEnc.getBooleanSignature(bv);
164         return *boolSig + " = 1";
165 }
166
167 string AlloyInterpreter::processElementFunction(ElementFunction* elemFunc, ValuedSignature *signature){
168         FunctionOperator *function = (FunctionOperator *) elemFunc->getFunction();
169         uint numDomains = elemFunc->inputs.getSize();
170         ASSERT(numDomains > 1);
171         ValuedSignature *inputs[numDomains];
172         string result;
173         for (uint i = 0; i < numDomains; i++) {
174                 Element *elem = elemFunc->inputs.get(i);
175                 inputs[i] = sigEnc.getElementSignature(elem);
176                 if(elem->type == ELEMFUNCRETURN){
177                         result += processElementFunction((ElementFunction *) elem, inputs[i]);
178                 }
179         }
180         string op;
181         switch(function->op){
182                 case SATC_ADD:
183                         op = ".add";
184                         break;
185                 case SATC_SUB:
186                         op = ".sub";
187                         break;
188                 default:
189                         ASSERT(0);
190         }
191         result += *signature + " = " + *inputs[0];
192         for (uint i = 1; i < numDomains; i++) {
193                 result += op + "["+ *inputs[i] +"]";
194         }
195         result += "\n";
196         return result;
197 }
198
199 string AlloyInterpreter::operatorPredicateConstraint(CompOp op, ValuedSignature *elemSig1, ValuedSignature *elemSig2){
200         switch (op) {
201                 case SATC_EQUALS:
202                         return *elemSig1 + " = " + *elemSig2;
203                 case SATC_LT:
204                         return *elemSig1 + " < " + *elemSig2;
205                 case SATC_GT:
206                         return *elemSig1 + " > " + *elemSig2;
207                 default:
208                         ASSERT(0);
209         }
210 }
211
212