Commiting my local changes ...
[satune.git] / src / Tuner / autotuner.cc
index 78d16c82f78911c7b42e4790b193dde72d2ab818..29c3289ec2d371f71f9e47f0ea2745e8ee71e023 100644 (file)
 #include <math.h>
 #include <stdlib.h>
 #include <float.h>
+#include <iostream>
+#include <chrono>
+#include <thread>
+#include <mutex>
+#include <condition_variable>
+
+#define TIMEOUT 1000s
+#define UNSETVALUE -1
+#define POSINFINITY 9999999999L
+
+using namespace std::chrono_literals;
+
+int solve(CSolver *solver)
+{
+       try{
+               return solver->solve();
+       }
+       catch(std::runtime_error& e) {
+               return UNSETVALUE;
+       }
+}
+
+int solveWrapper(CSolver *solver)
+{
+       std::mutex m;
+       std::condition_variable cv;
+       int retValue;
+
+       std::thread t([&cv, &retValue, solver]()
+       {
+               retValue = solve(solver);
+               cv.notify_one();
+       });
+
+       t.detach();
+
+       {
+               std::unique_lock<std::mutex> l(m);
+               if(cv.wait_for(l, TIMEOUT) == std::cv_status::timeout)
+                       throw std::runtime_error("Timeout");
+       }
+
+       return retValue;
+}
+
 
 AutoTuner::AutoTuner(uint _budget) :
-       budget(_budget) {
+       budget(_budget), result(UNSETVALUE) {
 }
 
 void AutoTuner::addProblem(CSolver *solver) {
        solvers.push(solver);
 }
 
-long long AutoTuner::evaluate(CSolver * problem, SearchTuner *tuner) {
-       CSolver * copy=problem->clone();
+long long AutoTuner::evaluate(CSolver *problem, SearchTuner *tuner) {
+       CSolver *copy = problem->clone();
        copy->setTuner(tuner);
-       int result = copy->startEncoding();
-       long long elapsedTime=copy->getElapsedTime();
-       long long encodeTime=copy->getEncodeTime();
-       long long solveTime=copy->getSolveTime();
-       long long metric=elapsedTime;
+       model_print("**********************\n");
+       long long metric = 0L;
+       try {
+               int sat = solveWrapper(copy);
+               if (result == UNSETVALUE)
+                       result = sat;
+               else if (result != sat) {
+                       model_print("&&&&&&&&&&&&&&&&&& Result has changed &&&&&&&&&&&&&\n");
+                       copy->printConstraints();
+               }
+               metric = copy->getElapsedTime();
+       }
+       catch(std::runtime_error& e) {
+               metric = POSINFINITY;
+               model_print("TimeOut has hit\n");
+       }
+       
        delete copy;
        return metric;
 }
 
 double AutoTuner::evaluateAll(SearchTuner *tuner) {
-       double product=1;
-       for(uint i=0;i<solvers.getSize();i++) {
-               CSolver * problem=solvers.get(i);
-               double score=evaluate(problem, tuner);
-               product*=score;
+       double product = 1;
+       for (uint i = 0; i < solvers.getSize(); i++) {
+               CSolver *problem = solvers.get(i);
+               double score = evaluate(problem, tuner);
+               product *= score;
        }
-       return pow(product, 1/((double)solvers.getSize()));
+       return pow(product, 1 / ((double)solvers.getSize()));
 }
 
-SearchTuner * AutoTuner::mutateTuner(SearchTuner * oldTuner, uint k) {
-       SearchTuner *newTuner=oldTuner->copyUsed();
-       uint numSettings=oldTuner->getSize();
-       double factor=0.3;//Adjust this factor...
-       uint settingsToMutate=(uint)(factor*(((double)numSettings) * k)/(budget));
+SearchTuner *AutoTuner::mutateTuner(SearchTuner *oldTuner, uint k) {
+       SearchTuner *newTuner = oldTuner->copyUsed();
+       uint numSettings = oldTuner->getSize();
+       uint settingsToMutate = (uint)(AUTOTUNERFACTOR * (((double)numSettings) * (budget - k)) / (budget));
        if (settingsToMutate < 1)
-               settingsToMutate=1;
+               settingsToMutate = 1;
        model_print("Mutating %u settings\n", settingsToMutate);
-       while(settingsToMutate-- != 0) {
+       while (settingsToMutate-- != 0) {
                newTuner->randomMutate();
        }
        return newTuner;
@@ -51,18 +107,22 @@ SearchTuner * AutoTuner::mutateTuner(SearchTuner * oldTuner, uint k) {
 
 
 void AutoTuner::tune() {
-       SearchTuner * bestTuner = NULL;
-       double bestScore=DBL_MAX;
+       SearchTuner *bestTuner = NULL;
+       double bestScore = DBL_MAX;
 
-       SearchTuner * oldTuner=new SearchTuner();
-       double base_temperature=evaluateAll(oldTuner);
-       double oldScore=base_temperature;
+       SearchTuner *oldTuner = new SearchTuner();
+       double base_temperature = evaluateAll(oldTuner);
+       double oldScore = base_temperature;
 
-       for (uint i=0;i<budget;i++) {
-               SearchTuner *newTuner=mutateTuner(oldTuner, i);
-               double newScore=evaluateAll(newTuner);
-               double scoreDiff=newScore - oldScore; //smaller is better
+       for (uint i = 0; i < budget; i++) {
+               SearchTuner *newTuner = mutateTuner(oldTuner, i);
+               double newScore = evaluateAll(newTuner);
+               newTuner->printUsed();
+               model_print("Received score %f\n", newScore);
+               double scoreDiff = newScore - oldScore; //smaller is better
                if (newScore < bestScore) {
+                       if (bestTuner != NULL)
+                               delete bestTuner;
                        bestScore = newScore;
                        bestTuner = newTuner->copyUsed();
                }
@@ -71,15 +131,23 @@ void AutoTuner::tune() {
                if (scoreDiff < 0) {
                        acceptanceP = 1;
                } else {
-                       double currTemp=base_temperature * (((double)budget - i) / budget);
+                       double currTemp = base_temperature * (((double)budget - i) / budget);
                        acceptanceP = exp(-scoreDiff / currTemp);
                }
                double ran = ((double)random()) / RAND_MAX;
                if (ran <= acceptanceP) {
+                       delete oldTuner;
                        oldScore = newScore;
                        oldTuner = newTuner;
                } else {
                        delete newTuner;
                }
        }
+       model_print("Best tuner:\n");
+       bestTuner->print();
+       bestTuner->serialize();
+       model_print("Received score %f\n", bestScore);
+       if (bestTuner != NULL)
+               delete bestTuner;
+       delete oldTuner;
 }