Adding support for VAR constraints in Dirk
[satune.git] / src / Test / dirkreader.cc
1 #include <iostream>
2 #include <fstream>
3 #include "csolver.h"
4 #include "hashset.h"
5 #include "cppvector.h"
6 #include <dirent.h>
7 #include <string>
8 #include <sstream>
9 #include <sstream>
10 #include <string.h>
11 #include "common.h"
12
13 using namespace std;
14 const char * assertstart = "ASSERTSTART";
15 const char * assertend = "ASSERTEND";
16 const char * satstart = "SATSTART";
17 const char * satend = "SATEND";
18 const char * varstart = "VARSTART";
19 const char * varend = "VAREND";
20
21 int skipahead(const char * token1, const char * token2, const char * token3);
22 char * readuntilend(const char * token);
23 BooleanEdge parseConstraint(CSolver * solver, char * constraint, int & offset);
24 void processEquality(char * constraint, int &offset);
25 void dumpSMTproblem(string &smtProblem, long long id);
26 void renameDumpFile(const char *path, long long id);
27 void addASSERTConstraintToSMTProblem(string & smtProblem, char * assert);
28 void addVarConstraintToSMTProblem(string & smtProblem, Vector<char *> & varconstraint);
29 void addSATConstraintToSMTProblem(string &smtProblem, char * sat);
30 void createSATtuneDumps (char *assert, char *sat, Vector<char *> & varconstraints, long long &smtID);
31
32 std::ifstream * file;
33 Order * order;
34 MutableSet * set;
35 bool incremental = true;
36 class intwrapper {
37 public:
38   intwrapper(int _val) : value(_val) {
39   }
40   int32_t value;
41 };
42
43 unsigned int iw_hash_function(intwrapper *i) {
44   return i->value;
45 }
46
47 bool iw_equals(intwrapper *key1, intwrapper *key2) {
48   return (key1->value == key2->value);
49 }
50
51 typedef Hashset<intwrapper *, uintptr_t, PTRSHIFT, iw_hash_function, iw_equals> HashsetIW;
52 typedef SetIterator<intwrapper *, uintptr_t, PTRSHIFT, iw_hash_function, iw_equals> HashsetIWIterator;
53 class OrderRec {
54 public:
55   OrderRec() : set (NULL), value(-1), alloced(false) {
56   }
57   ~OrderRec() {
58     if (set != NULL) {
59       set->resetAndDelete();
60       delete set;
61     }
62   }
63   HashsetIW * set;
64   int32_t value;
65   bool alloced;
66 };
67
68 typedef Hashtable<intwrapper *, OrderRec *, uintptr_t, PTRSHIFT, iw_hash_function, iw_equals> HashtableIW;
69 typedef Hashtable<intwrapper *, Boolean *, uintptr_t, PTRSHIFT, iw_hash_function, iw_equals> HashtableBV;
70 Vector<OrderRec*> * orderRecVector = NULL;
71 HashtableIW * ordertable = NULL;
72 HashtableBV * vartable = new HashtableBV();
73 HashsetIW * intSet = new HashsetIW();
74 HashsetIW * boolSet = new HashsetIW();
75
76 void cleanAndFreeOrderRecVector(){
77         for(uint i=0; i< orderRecVector->getSize(); i++){
78                 delete orderRecVector->get(i);
79         }
80         orderRecVector->clear();
81 }
82
83 int main(int numargs, char ** argv) {
84   file = new std::ifstream(argv[1]);
85   if(numargs > 2){
86         incremental = false;
87   }
88   char * assert = NULL;
89   char * sat = NULL;
90   char * var = NULL;
91   Vector<char *> varconstraints;
92   string smtProblem = "";
93   long long smtID=0L;
94   Vector<OrderRec*> orderRecs;
95   orderRecVector = &orderRecs;
96   while(true) {
97     int retval = skipahead(assertstart, satstart, varstart);
98     //printf("%d\n", retval);
99     if (retval == 0){
100       break;
101     }
102     if (retval == 1) {
103       if (assert != NULL){
104         free(assert);
105         assert = NULL;
106         dumpSMTproblem(smtProblem, smtID);
107         smtProblem = "";
108         for(uint i=0; i< varconstraints.getSize(); i++){
109                 free(varconstraints.get(i));
110         }
111         varconstraints.clear();
112         intSet->reset();
113         boolSet->reset();
114       }
115       assert = readuntilend(assertend);
116       addASSERTConstraintToSMTProblem(smtProblem, assert);
117       //cout << "INFO: SMTProblem After adding ASSERT Constraints\n" << smtProblem << "\n&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&\n";
118       //printf("[%s]\n", assert);
119     } else if (retval == 2) {
120       if (sat != NULL) {
121         free(sat);
122         sat = NULL;
123         vartable->resetAndDeleteKeys();
124         ordertable->reset();
125         cleanAndFreeOrderRecVector();
126       } else {
127         ordertable = new HashtableIW();
128         addVarConstraintToSMTProblem(smtProblem, varconstraints);
129       }
130       sat = readuntilend(satend);
131       createSATtuneDumps(assert, sat, varconstraints, smtID);
132       addSATConstraintToSMTProblem(smtProblem, sat);
133       if(!incremental){
134         dumpSMTproblem(smtProblem, smtID);
135       }
136       //cout << "INFO: SMTProblem After adding SAT Constraints\n" << smtProblem << "\n&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&\n";
137     } else if (retval == 3) {
138       var = readuntilend(varend);
139       varconstraints.push(var);
140     }
141   }
142   
143   if(smtID == 0L){
144         char trueString [] = "true";
145         ordertable = new HashtableIW();
146         createSATtuneDumps(assert, trueString, varconstraints, smtID);
147         addSATConstraintToSMTProblem(smtProblem, trueString);
148   }
149   if(incremental){
150         dumpSMTproblem(smtProblem, smtID);
151   }
152   cleanAndFreeOrderRecVector();
153   if(ordertable != NULL){
154         delete ordertable;
155   }
156   if(assert != NULL){
157         free(assert);
158   }
159   if(sat != NULL){
160         free(sat);
161   }
162   vartable->resetAndDeleteKeys();
163   delete vartable;
164   file->close();
165   delete file;
166 }
167
168 void createSATtuneDumps (char *assert, char *sat, Vector<char *> & varconstraints, long long &smtID){
169         CSolver *solver = new CSolver();
170 //      solver->turnoffOptimizations();
171         set = solver->createMutableSet(1);
172         order = solver->createOrder(SATC_TOTAL, (Set *) set);
173         int offset = 0;
174         processEquality(sat, offset);
175         offset = 0;
176         processEquality(assert, offset);
177         offset = 0;
178         solver->addConstraint(parseConstraint(solver, sat, offset));
179         offset = 0;
180         solver->addConstraint(parseConstraint(solver, assert, offset));
181         for(uint i=0; i<varconstraints.getSize(); i++){
182                 offset = 0;
183                 processEquality(varconstraints.get(i),offset);
184                 offset = 0;
185                 solver->addConstraint(parseConstraint(solver, varconstraints.get(i), offset));
186         }
187         //printf("[%s]\n", sat);
188         solver->finalizeMutableSet(set);
189         solver->serialize();
190         //solver->printConstraints();
191         smtID= getTimeNano();
192         renameDumpFile("./", smtID);
193         //solver->solve();
194         delete solver;
195 }
196
197 void doExit(const char * message){
198         printf("%s", message);
199         exit(-1);
200 }
201
202 void doExit() {
203         doExit("Parse Error\n");
204 }
205
206 void renameDumpFile(const char *path, long long id) {
207         struct dirent *entry;
208         DIR *dir = opendir(path);
209         if (dir == NULL) {
210                 return;
211         }
212         char newname[128] ={0};
213         sprintf(newname, "%lld.dump", id);
214         bool duplicate = false;
215         while ((entry = readdir(dir)) != NULL) {
216                  if(strstr(entry->d_name, "DUMP") != NULL){
217                         if(duplicate){
218                                 doExit("Multiplle DUMP file exists. Make sure to clean them all before running the program");
219                         }
220                         int result= rename( entry->d_name , newname );
221                         if ( result == 0 )
222                                 printf ( "File successfully renamed to %s\n" , newname);
223                         else
224                                 doExit( "Error renaming file" );
225                         duplicate = true;
226                  }
227         }
228         closedir(dir);
229 }
230 template <class MyType>
231 string to_string(MyType value){
232         string number;
233         std::stringstream strstream;
234         strstream << value;
235         strstream >> number;
236         return number;
237 }
238
239 void dumpDeclarations(std::ofstream& smtfile){
240         HashsetIWIterator* iterator = intSet->iterator();
241         smtfile << "(set-logic QF_LRA)" << endl;
242         while(iterator->hasNext()){
243                 intwrapper * iw = iterator->next();
244                 string declare = "(declare-const O!"+ to_string<uint32_t>(iw->value) + " Real)\n";
245                 smtfile << declare;
246         }
247         delete iterator;
248
249         iterator = boolSet->iterator();
250         while(iterator->hasNext()){
251                 intwrapper * iw = iterator->next();
252                 string declare = "(declare-const S!" + to_string<uint32_t>(iw->value) + " Bool)\n";
253                 smtfile << declare;
254         }
255         delete iterator;
256 }
257
258
259 void addVarConstraintToSMTProblem(string & smtProblem, Vector<char *> & varconstraints){
260         for(uint i=0; i<varconstraints.getSize(); i++){
261                 //cout << "[ " << varconstraints.get(i) << " ]" << endl;
262                 smtProblem += "(assert "+ string(varconstraints.get(i)) +")\n";
263         }
264 }
265
266 void addASSERTConstraintToSMTProblem(string & smtProblem, char * assert){
267         string ssat(assert);
268         string assertStatement = "(assert "+ ssat + "\n)\n";
269         smtProblem += assertStatement;
270 }
271
272 void addSATConstraintToSMTProblem(string &smtProblem, char * sat){
273         string ssat(sat);
274         string satStatement;
275         if(incremental){
276                 satStatement = "(push)\n(assert "+ ssat + "\n)\n(check-sat)\n(pop)\n";
277         } else {
278                 satStatement = "(assert "+ ssat + "\n)\n(check-sat)\n";
279         }
280         smtProblem += satStatement;
281 }
282
283
284 void dumpSMTproblem(string &smtProblem, long long id){
285         std::ofstream smtfile;
286         string smtfilename = to_string<long long>(id) + ".smt";
287         smtfile.open (smtfilename.c_str());
288         if(!smtfile.is_open())
289         {
290                 doExit("Unable to create file.\n");
291         }
292         dumpDeclarations(smtfile);
293         smtfile << smtProblem;
294         smtfile.close();
295         cout <<"************here is the SMT file*********" << endl << smtProblem  <<endl << "****************************" << endl;;
296 }
297
298
299 void skipwhitespace(char * constraint, int & offset) {
300   //skip whitespace
301   while (constraint[offset] == ' ' || constraint[offset] == '\n')
302     offset++;
303 }
304
305 int32_t getOrderVar(char *constraint, int & offset) {
306   if (constraint[offset++] != 'O' || constraint[offset++] != '!' ) {
307     doExit();
308   }
309   int32_t num = 0;
310   while(true) {
311     char next = constraint[offset];
312     if (next >= '0' && next <= '9') {
313       num = (num * 10) + (next - '0');
314       offset++;
315     } else
316       return num;
317   }
318 }
319
320 int32_t getBooleanVar(char *constraint, int & offset) {
321         if (constraint[offset++] != 'S' || constraint[offset++] != '!' ) {
322                 cout << "Constraint= " << constraint << "\tconstraint[offset=" << offset - 1 << "]" << &constraint[offset -1] <<"\n";
323                 doExit();
324         }
325   int32_t num = 0;
326   while(true) {
327     char next = constraint[offset];
328     if (next >= '0' && next <= '9') {
329       num = (num * 10) + (next - '0');
330       offset++;
331     } else
332       return num;
333   }
334 }
335
336 BooleanEdge checkBooleanVar(CSolver *solver, int32_t value) {
337   intwrapper v(value);
338   if (vartable->contains(&v)) {
339     return BooleanEdge(vartable->get(&v));
340   } else {
341     Boolean* ve = solver->getBooleanVar(2).getBoolean();
342     vartable->put(new intwrapper(value), ve);
343     return BooleanEdge(ve);
344   }
345 }
346
347 void mergeVars(int32_t value1, int32_t value2) {
348   intwrapper v1(value1);
349   intwrapper v2(value2);
350   OrderRec *r1 = ordertable->get(&v1);
351   OrderRec *r2 = ordertable->get(&v2);
352   if (r1 == r2) {
353     if (r1 == NULL) {
354       OrderRec * r = new OrderRec();
355       orderRecVector->push(r);
356       r->value = value1;
357       r->set = new HashsetIW();
358       intwrapper * k1 = new intwrapper(v1);
359       intwrapper * k2 = new intwrapper(v2);
360       r->set->add(k1);
361       r->set->add(k2);
362       ordertable->put(k1, r);
363       ordertable->put(k2, r);
364     }
365   } else if (r1 == NULL) {
366     intwrapper * k = new intwrapper(v1);
367     ordertable->put(k, r2);
368     r2->set->add(k);
369   } else if (r2 == NULL) {
370     intwrapper * k = new intwrapper(v2);
371     ordertable->put(k, r1);
372     r1->set->add(k);
373   } else {
374     SetIterator<intwrapper *, uintptr_t, PTRSHIFT, iw_hash_function, iw_equals> * it1 = r1->set->iterator();
375     while (it1->hasNext()) {
376       intwrapper * k = it1->next();
377       ordertable->put(k, r2);
378       r2->set->add(k);
379     }
380     delete r2->set;
381     r2->set = NULL;
382     delete r2;
383     delete it1;
384   }
385 }
386
387 int32_t checkordervar(CSolver * solver, int32_t value) {
388   intwrapper v(value);
389   OrderRec * rec = ordertable->get(&v);
390   if (rec == NULL) {
391     intwrapper * k = new intwrapper(value);
392     rec = new OrderRec();
393     orderRecVector->push(rec);
394     rec->value = value;
395     rec->set = new HashsetIW();
396     rec->set->add(k);
397     ordertable->put(k, rec);
398   }
399   if (!rec->alloced) {
400     solver->addItem(set, rec->value);
401     rec->alloced = true;
402   }
403   return rec->value;
404 }
405
406 void processLetExpression (char * constraint){
407         int constrSize = strlen(constraint);
408         char * replace = (char *) malloc(constrSize);
409         for (int i=0; i< constrSize; i++){
410                 replace[i] = 0;
411         }
412         int offset = 1;
413         offset +=4;
414         skipwhitespace(constraint, offset);
415         ASSERT(strncmp(&constraint[offset], "((a!1",5) == 0);
416         offset +=5;
417         skipwhitespace(constraint, offset);
418         int startOffset = offset;
419         processEquality(constraint, offset);
420         strncpy(replace, &constraint[startOffset], offset-startOffset);
421         while(constraint[offset] == ')')
422                 offset++;
423         skipwhitespace(constraint, offset);
424         string modified = "";
425         while(offset < constrSize){
426                 bool done = false;
427                 while(strncmp(&constraint[offset], "a!1",3) != 0){
428                         modified += constraint[offset++];
429                         if(offset >= constrSize -2){ //Not considering ) and \n ...
430                                 ASSERT(constraint[constrSize-1] == '\n');
431                                 ASSERT(constraint[constrSize-2] == ')');
432                                 done = true;
433                                 break;
434                         }
435                 }
436                 if(done){
437                         break;
438                 }
439                 offset += 3;
440                 modified += replace;
441         }
442         strcpy(constraint, modified.c_str());
443         cout << "modified:*****" << modified << "****\n";
444         free(replace);
445 }
446
447 void processEquality(char * constraint, int &offset) {
448   skipwhitespace(constraint, offset);
449   if (strncmp(&constraint[offset], "(and",4) == 0) {
450     offset +=4;
451     Vector<BooleanEdge> vec;
452     while(true) {
453       skipwhitespace(constraint, offset);
454       if (constraint[offset] == ')') {
455         offset++;
456         return;
457       }
458       processEquality(constraint, offset);
459     }
460   } else if (strncmp(&constraint[offset], "(or",3) == 0) {
461     offset +=3;
462     Vector<BooleanEdge> vec;
463     while(true) {
464       skipwhitespace(constraint, offset);
465       if (constraint[offset] == ')') {
466         offset++;
467         return;
468       }
469       processEquality(constraint, offset);
470     }
471   } else if (strncmp(&constraint[offset], "(let",4) == 0){
472     ASSERT(offset == 1);
473     cout << "Before: " << constraint << endl;
474     processLetExpression(constraint);
475     cout << "After: " << constraint << endl;
476     offset=0;
477     processEquality(constraint, offset);
478   } else if (strncmp(&constraint[offset], "(=>",3) == 0){
479     offset +=3;
480     skipwhitespace(constraint, offset);
481     processEquality(constraint, offset);
482     skipwhitespace(constraint, offset);
483     processEquality(constraint, offset);
484     skipwhitespace(constraint, offset);
485     if (constraint[offset++] != ')'){
486             doExit();
487     }
488     return;
489   } else if (strncmp(&constraint[offset], "(<", 2) == 0) {
490     offset+=2;
491     skipwhitespace(constraint, offset);
492     getOrderVar(constraint, offset);
493     skipwhitespace(constraint, offset);
494     getOrderVar(constraint, offset);
495     skipwhitespace(constraint, offset);
496     if (constraint[offset++] != ')'){
497             doExit();
498     }
499     return;
500   } else if (strncmp(&constraint[offset], "(=", 2) == 0) {
501     offset+=2;
502     skipwhitespace(constraint, offset);
503     int v1=getOrderVar(constraint, offset);
504     intwrapper iwv1(v1);
505     if(intSet->get(&iwv1) == NULL){
506         intSet->add(new intwrapper(v1));
507     }
508     skipwhitespace(constraint, offset);
509     int v2=getOrderVar(constraint, offset);
510     intwrapper iwv2(v2);
511     if(intSet->get(&iwv2) == NULL){
512         intSet->add(new intwrapper(v2));
513     }
514     skipwhitespace(constraint, offset);
515     if (constraint[offset++] != ')')
516       doExit();
517     mergeVars(v1, v2);
518     return;
519   } else if (strncmp(&constraint[offset], "tr", 2) == 0){
520         offset+=4;
521         skipwhitespace(constraint, offset);
522         return;
523   }
524   else{
525         int32_t b1 = getBooleanVar(constraint, offset);
526         intwrapper iwb1(b1);
527         if(boolSet->get(&iwb1) == NULL){
528             boolSet->add(new intwrapper(b1));
529         }
530         skipwhitespace(constraint, offset);
531 return;
532   }
533 }
534
535 BooleanEdge parseConstraint(CSolver * solver, char * constraint, int & offset) {
536   skipwhitespace(constraint, offset);
537   if (strncmp(&constraint[offset], "(and", 4) == 0) {
538     offset +=4;
539     Vector<BooleanEdge> vec;
540     while(true) {
541       skipwhitespace(constraint, offset);
542       if (constraint[offset] == ')') {
543         offset++;
544         return solver->applyLogicalOperation(SATC_AND, vec.expose(), vec.getSize());
545       }
546       vec.push(parseConstraint(solver, constraint, offset));
547     }
548   } else if (strncmp(&constraint[offset], "(or", 3) == 0) {
549     offset +=3;
550     Vector<BooleanEdge> vec;
551     while(true) {
552       skipwhitespace(constraint, offset);
553       if (constraint[offset] == ')') {
554         offset++;
555         return solver->applyLogicalOperation(SATC_OR, vec.expose(), vec.getSize());
556       }
557       vec.push(parseConstraint(solver, constraint, offset));
558     }
559   } else if (strncmp(&constraint[offset], "(=>", 3) == 0){
560     offset += 3;
561     skipwhitespace(constraint, offset);
562     BooleanEdge b1 = parseConstraint(solver, constraint, offset);
563     skipwhitespace(constraint, offset);
564     BooleanEdge b2 = parseConstraint(solver, constraint, offset);
565     skipwhitespace(constraint, offset);
566     if (constraint[offset++] != ')')
567       doExit();
568     return solver->applyLogicalOperation(SATC_IMPLIES, b1, b2);
569   } else if (strncmp(&constraint[offset], "(<", 2) == 0) {
570     offset+=2;
571     skipwhitespace(constraint, offset);
572     int32_t v1 = getOrderVar(constraint, offset);
573     intwrapper iwv1(v1);
574     if(intSet->get(&iwv1) == NULL){
575         intSet->add(new intwrapper(v1));
576     }
577     skipwhitespace(constraint, offset);
578     int32_t v2 = getOrderVar(constraint, offset);
579     intwrapper iwv2(v2);
580     if(intSet->get(&iwv2) == NULL){
581         intSet->add(new intwrapper(v2));
582     }
583     skipwhitespace(constraint, offset);
584     if (constraint[offset++] != ')')
585       doExit();
586 //    int32_t o1 = checkordervar(solver, v1);
587 //    int32_t o2 = checkordervar(solver, v2);
588 //    cout << "V1=" << v1 << ",V2=" << v2 << ",O1=" << o1 << ",O2=" << o2<< endl;
589 //    ASSERT( o1 != o2); 
590     return solver->orderConstraint(order, checkordervar(solver, v1), checkordervar(solver, v2));
591   } else if (strncmp(&constraint[offset], "(=", 2) == 0) {
592     offset+=2;
593     skipwhitespace(constraint, offset);
594     getOrderVar(constraint, offset);
595     skipwhitespace(constraint, offset);
596     getOrderVar(constraint, offset);
597     skipwhitespace(constraint, offset);
598     if (constraint[offset++] != ')')
599       doExit();
600     return solver->getBooleanTrue();
601   }else if (strncmp(&constraint[offset], "tr", 2) == 0){
602         offset+=4;
603         skipwhitespace(constraint, offset);
604         return solver->getBooleanTrue();
605   }
606   else {
607     int32_t v = getBooleanVar(constraint, offset);
608     intwrapper iwb1(v);
609     if(boolSet->get(&iwb1) == NULL){
610         boolSet->add(new intwrapper(v));
611     }
612     skipwhitespace(constraint, offset);
613     return checkBooleanVar(solver, v);
614   }
615 }
616
617 int skipahead(const char * token1, const char * token2, const char * token3) {
618   int index1 = 0, index2 = 0, index3 = 0;
619   char buffer[256];
620   while(true) {
621     if (token1[index1] == 0)
622       return 1;
623     if (token2[index2] == 0)
624       return 2;
625     if (token3[index3] == 0)
626       return 3;
627     if (file->eof())
628       return 0;
629     file->read(buffer, 1);
630     if (buffer[0] == token1[index1])
631       index1++;
632     else
633       index1 = 0;
634     if (buffer[0] == token2[index2])
635       index2++;
636     else
637       index2 = 0;
638     if (buffer[0] == token3[index3])
639       index3++;
640     else
641       index3 = 0;
642   }
643 }
644
645 char * readuntilend(const char * token) {
646   int index = 0;
647   char buffer[256];
648   int length = 256;
649   int offset = 0;
650   char * outbuffer = (char *) malloc(length);
651   while(true) {
652     if (token[index] == 0) {
653       outbuffer[offset - index] = 0;
654       return outbuffer;
655     }
656     if (file->eof()) {
657       free(outbuffer);
658       return NULL;
659     }
660       
661     file->read(buffer, 1);
662     outbuffer[offset++] = buffer[0];
663     if (offset == length) {
664       length = length * 2;
665       outbuffer = (char *) realloc(outbuffer, length);
666     }
667     if (buffer[0] == token[index])
668       index++;
669     else
670       index=0;
671   }
672 }