Fix tuner issues
[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 AutoTuner::~AutoTuner() {}
15
16 void AutoTuner::addProblem(CSolver *solver) {
17         solvers.push(solver);
18 }
19
20 long long AutoTuner::evaluate(CSolver *problem, SearchTuner *tuner) {
21         CSolver *copy = problem->clone();
22         copy->setTuner(tuner);
23         copy->setSatSolverTimeout(TIMEOUTSEC);
24         model_print("**********************\n");
25         int sat = copy->solve();
26         if (result == UNSETVALUE && sat != IS_INDETER)
27                 result = sat;
28         else if (result != sat && sat != IS_INDETER) {
29                 model_print("&&&&&&&&&&&&&&&&&& Result has changed &&&&&&&&&&&&&\n");
30                 copy->printConstraints();
31         }
32         long long metric = copy->getElapsedTime();
33         delete copy;
34         return metric;
35 }
36
37 double AutoTuner::evaluateAll(SearchTuner *tuner) {
38         double product = 1;
39         for (uint i = 0; i < solvers.getSize(); i++) {
40                 CSolver *problem = solvers.get(i);
41                 double score = evaluate(problem, tuner);
42                 product *= score;
43         }
44         return pow(product, 1 / ((double)solvers.getSize()));
45 }
46
47 SearchTuner *AutoTuner::mutateTuner(SearchTuner *oldTuner, uint k) {
48         SearchTuner *newTuner = oldTuner->copyUsed();
49         uint numSettings = oldTuner->getSize();
50         uint settingsToMutate = (uint)(AUTOTUNERFACTOR * (((double)numSettings) * (budget - k)) / (budget));
51         if (settingsToMutate < 1)
52                 settingsToMutate = 1;
53         model_print("Mutating %u settings\n", settingsToMutate);
54         while (settingsToMutate-- != 0) {
55                 newTuner->randomMutate();
56         }
57         return newTuner;
58 }
59
60 void AutoTuner::tune() {
61         SearchTuner *bestTuner = NULL;
62         double bestScore = DBL_MAX;
63
64         SearchTuner *oldTuner = new SearchTuner();
65         double base_temperature = evaluateAll(oldTuner);
66         double oldScore = base_temperature;
67
68         for (uint i = 0; i < budget; i++) {
69                 SearchTuner *newTuner = mutateTuner(oldTuner, i);
70                 double newScore = evaluateAll(newTuner);
71                 newTuner->printUsed();
72                 model_print("Received score %f\n", newScore);
73                 double scoreDiff = newScore - oldScore; //smaller is better
74                 if (newScore < bestScore) {
75                         if (bestTuner != NULL)
76                                 delete bestTuner;
77                         bestScore = newScore;
78                         bestTuner = newTuner->copyUsed();
79                 }
80
81                 double acceptanceP;
82                 if (scoreDiff < 0) {
83                         acceptanceP = 1;
84                 } else {
85                         double currTemp = base_temperature * (((double)budget - i) / budget);
86                         acceptanceP = exp(-scoreDiff / currTemp);
87                 }
88                 double ran = ((double)random()) / RAND_MAX;
89                 if (ran <= acceptanceP) {
90                         delete oldTuner;
91                         oldScore = newScore;
92                         oldTuner = newTuner;
93                 } else {
94                         delete newTuner;
95                 }
96         }
97         model_print("Best tuner:\n");
98         bestTuner->print();
99         bestTuner->serialize("TUNER.conf");
100         model_print("Received score %f\n", bestScore);
101         if (bestTuner != NULL)
102                 delete bestTuner;
103         delete oldTuner;
104 }