Adding a directed search based config for the tuner
[satune.git] / src / Tuner / autotuner.cc
1 #include "autotuner.h"
2 #include "csolver.h"
3 #include "searchtuner.h"
4 #include <math.h>
5 #include <stdlib.h>
6 #include <float.h>
7
8 #define UNSETVALUE -1
9 #define TIMEOUTSEC 5000
10 AutoTuner::AutoTuner(uint _budget) :
11         budget(_budget), result(UNSETVALUE) {
12 }
13
14 void AutoTuner::addProblem(CSolver *solver) {
15         solvers.push(solver);
16 }
17
18 long long AutoTuner::evaluate(CSolver *problem, SearchTuner *tuner) {
19         CSolver *copy = problem->clone();
20         copy->setTuner(tuner);
21         copy->setSatSolverTimeout(TIMEOUTSEC);
22         model_print("**********************\n");
23         int sat = copy->solve();
24         if (result == UNSETVALUE && sat != IS_INDETER)
25                 result = sat;
26         else if (result != sat && sat != IS_INDETER) {
27                 model_print("&&&&&&&&&&&&&&&&&& Result has changed &&&&&&&&&&&&&\n");
28                 copy->printConstraints();
29         }
30         long long metric = copy->getElapsedTime();
31         delete copy;
32         return metric;
33 }
34
35 double AutoTuner::evaluateAll(SearchTuner *tuner) {
36         double product = 1;
37         for (uint i = 0; i < solvers.getSize(); i++) {
38                 CSolver *problem = solvers.get(i);
39                 double score = evaluate(problem, tuner);
40                 product *= score;
41         }
42         return pow(product, 1 / ((double)solvers.getSize()));
43 }
44
45 SearchTuner *AutoTuner::mutateTuner(SearchTuner *oldTuner, uint k) {
46         SearchTuner *newTuner = oldTuner->copyUsed();
47         uint numSettings = oldTuner->getSize();
48         uint settingsToMutate = (uint)(AUTOTUNERFACTOR * (((double)numSettings) * (budget - k)) / (budget));
49         if (settingsToMutate < 1)
50                 settingsToMutate = 1;
51         model_print("Mutating %u settings\n", settingsToMutate);
52         while (settingsToMutate-- != 0) {
53                 newTuner->randomMutate();
54         }
55         return newTuner;
56 }
57
58 #ifdef STATICENCGEN
59 SearchTuner *AutoTuner::mutateTuner(SearchTuner *oldTuner) {
60         SearchTuner *newTuner = oldTuner->copyUsed();
61         result = newTuner->nextStaticTuner();
62         return result==EXIT_FAILURE? newTuner: NULL;
63 }
64 #endif
65
66 void AutoTuner::tune() {
67         SearchTuner *bestTuner = NULL;
68         double bestScore = DBL_MAX;
69
70         SearchTuner *oldTuner = new SearchTuner();
71         double base_temperature = evaluateAll(oldTuner);
72         double oldScore = base_temperature;
73
74 #ifdef STATICENCGEN
75         while(true){
76                 SearchTuner *newTuner = mutateTuner(oldTuner);
77                 if(newTuner == NULL)
78                         return;
79                 double newScore = evaluateAll(newTuner);
80                 newTuner->printUsed();
81                 model_print("Received score %f\n", newScore);
82                 delete oldTuner;
83                 oldScore = newScore;
84                 oldTuner = newTuner;
85         }
86 #endif
87         
88         for (uint i = 0; i < budget; i++) {
89                 SearchTuner *newTuner = mutateTuner(oldTuner, i);
90                 double newScore = evaluateAll(newTuner);
91                 newTuner->printUsed();
92                 model_print("Received score %f\n", newScore);
93                 double scoreDiff = newScore - oldScore; //smaller is better
94                 if (newScore < bestScore) {
95                         if (bestTuner != NULL)
96                                 delete bestTuner;
97                         bestScore = newScore;
98                         bestTuner = newTuner->copyUsed();
99                 }
100
101                 double acceptanceP;
102                 if (scoreDiff < 0) {
103                         acceptanceP = 1;
104                 } else {
105                         double currTemp = base_temperature * (((double)budget - i) / budget);
106                         acceptanceP = exp(-scoreDiff / currTemp);
107                 }
108                 double ran = ((double)random()) / RAND_MAX;
109                 if (ran <= acceptanceP) {
110                         delete oldTuner;
111                         oldScore = newScore;
112                         oldTuner = newTuner;
113                 } else {
114                         delete newTuner;
115                 }
116         }
117         model_print("Best tuner:\n");
118         bestTuner->print();
119         bestTuner->serialize();
120         model_print("Received score %f\n", bestScore);
121         if (bestTuner != NULL)
122                 delete bestTuner;
123         delete oldTuner;
124 }