return false;
}
+ /** @brief Return random key from set. */
+
+ _Key getRandomElement() {
+ if (getSize() == 0)
+ return NULL;
+ else if (getSize() < 6) {
+ uint count = random() % getSize();
+ LinkNode<_Key> *ptr=list;
+ while(count > 0) {
+ ptr = ptr->next;
+ count--;
+ }
+ return ptr->key;
+ } else
+ return table->getRandomValue()->key;
+ }
+
/** @brief Gets the original key corresponding to this one from the
* hashset. Returns NULL if not present. */
size = 0;
}
+ /** Doesn't work with zero value */
+ _Val getRandomValue() {
+ while(true) {
+ unsigned int index=random() & capacitymask;
+ struct hashlistnode<_Key, _Val> *bin = &table[index];
+ if (bin->key != NULL && bin->val != NULL) {
+ return bin->val;
+ }
+ }
+ }
+
void resetanddelete() {
for (unsigned int i = 0; i < capacity; i++) {
struct hashlistnode<_Key, _Val> *bin = &table[i];
#include "autotuner.h"
#include "csolver.h"
+#include "searchtuner.h"
+#include <math.h>
+#include <stdlib.h>
+#include <float.h>
+
+AutoTuner::AutoTuner(uint _budget) :
+ budget(_budget) {
+}
void AutoTuner::addProblem(CSolver *solver) {
solvers.push(solver);
}
+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;
+ 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;
+ }
+ 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));
+ if (settingsToMutate < 1)
+ settingsToMutate=1;
+ model_print("Mutating %u settings\n", settingsToMutate);
+ while(settingsToMutate-- != 0) {
+ newTuner->randomMutate();
+ }
+ return newTuner;
+}
+
+
void AutoTuner::tune() {
-
-
+ SearchTuner * bestTuner = NULL;
+ double bestScore=DBL_MAX;
+
+ 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
+ if (newScore < bestScore) {
+ bestScore = newScore;
+ bestTuner = newTuner->copyUsed();
+ }
+
+ double acceptanceP;
+ if (scoreDiff < 0) {
+ acceptanceP = 1;
+ } else {
+ double currTemp=base_temperature * (((double)budget - i) / budget);
+ acceptanceP = exp(-scoreDiff / currTemp);
+ }
+ double ran = ((double)random()) / RAND_MAX;
+ if (ran <= acceptanceP) {
+ oldScore = newScore;
+ oldTuner = newTuner;
+ } else {
+ delete newTuner;
+ }
+ }
}
class AutoTuner {
public:
- AutoTuner();
+ AutoTuner(uint budget);
void addProblem(CSolver *solver);
void tune();
MEMALLOC;
private:
- Vector<CSolver *> solvers;
+ long long evaluate(CSolver *problem, SearchTuner *tuner);
+ double evaluateAll(SearchTuner *tuner);
+ SearchTuner * mutateTuner(SearchTuner * oldTuner, uint k);
+
+ Vector<CSolver *> solvers;
+ uint budget;
};
#endif
param(_param) {
}
+TunableSetting::TunableSetting(TunableSetting * ts) :
+ hasVar(ts->hasVar),
+ type(ts->type),
+ param(ts->param),
+ lowValue(ts->lowValue),
+ highValue(ts->highValue),
+ defaultValue(ts->defaultValue),
+ selectedValue(ts->selectedValue)
+{
+}
+
void TunableSetting::setDecision(int _low, int _high, int _default, int _selection) {
lowValue = _low;
highValue = _high;
SearchTuner::SearchTuner() {
}
+SearchTuner * SearchTuner::copyUsed() {
+ SearchTuner * tuner = new SearchTuner();
+ HSIteratorTunableSetting *iterator=usedSettings.iterator();
+ while(iterator->hasNext()) {
+ TunableSetting *setting=iterator->next();
+ TunableSetting *copy=new TunableSetting(setting);
+ tuner->settings.add(copy);
+ }
+ delete iterator;
+ return tuner;
+}
+
SearchTuner::~SearchTuner() {
HSIteratorTunableSetting *iterator=settings.iterator();
while(iterator->hasNext()) {
result = settings.get(&setting);
if ( result == NULL) {
result=new TunableSetting(param);
- result->setDecision(descriptor->lowValue, descriptor->highValue, descriptor->defaultValue, descriptor->defaultValue);
+ uint value = descriptor->lowValue + (random() % (1+ descriptor->highValue - descriptor->lowValue));
+ result->setDecision(descriptor->lowValue, descriptor->highValue, descriptor->defaultValue, value);
settings.add(result);
}
usedSettings.add(result);
result = settings.get(&setting);
if ( result == NULL) {
result=new TunableSetting(vartype, param);
- result->setDecision(descriptor->lowValue, descriptor->highValue, descriptor->defaultValue, descriptor->defaultValue);
+ uint value = descriptor->lowValue + (random() % (1+ descriptor->highValue - descriptor->lowValue));
+ result->setDecision(descriptor->lowValue, descriptor->highValue, descriptor->defaultValue, value);
settings.add(result);
}
usedSettings.add(result);
}
return result->selectedValue;
}
+
+void SearchTuner::randomMutate() {
+ TunableSetting * randomSetting = settings.getRandomElement();
+ uint range=randomSetting->highValue-randomSetting->lowValue;
+ uint randomchoice=(random() % range) + randomSetting->lowValue;
+ if (randomchoice < randomSetting->selectedValue)
+ randomSetting->selectedValue = randomchoice;
+ else
+ randomSetting->selectedValue = randomchoice + 1;
+}
public:
TunableSetting(VarType type, TunableParam param);
TunableSetting(TunableParam param);
+ TunableSetting(TunableSetting * ts);
void setDecision(int _low, int _high, int _default, int _selection);
MEMALLOC;
private:
~SearchTuner();
int getTunable(TunableParam param, TunableDesc *descriptor);
int getVarTunable(VarType vartype, TunableParam param, TunableDesc *descriptor);
+ SearchTuner * copyUsed();
+ void randomMutate();
+ uint getSize() { return usedSettings.getSize();}
+
MEMALLOC;
private:
+ /** Used Settings keeps track of settings that were actually used by
+ the example. Mutating settings may cause the Constraint Compiler
+ not to query other settings.*/
HashSetTunableSetting usedSettings;
+ /** Settings contains all settings. */
HashSetTunableSetting settings;
};
-
#endif