-
Notifications
You must be signed in to change notification settings - Fork 1
/
solver.cpp
116 lines (93 loc) · 2.87 KB
/
solver.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
class Solver {
public:
static Model *solve(Formula *formula);
private:
static Model *solveR(Formula *formula, Model *model, int backtrackDepth);
static Model *solveRClone(Formula *formula, Model *model, int index, int setVar, int backtrackDepth);
static int maxDepth;
static int nodesFailed;
static int CUTOFF;
};
int Solver::maxDepth = 0;
int Solver::CUTOFF = GLOBAL_CUTOFF;
int Solver::nodesFailed = Solver::CUTOFF;
Model *Solver::solve(Formula *formula) {
Model *model = new Model(formula->getNVars());
// // This is just testing code.
// model->setVar(0);
// model->setVar(1);
// model->clearVar(2);
// cout << model->toString() << endl;
// Setup.
srand(time(NULL));
Model *solvedModel;
// If nodes failed was surpassed, we restart.
while (nodesFailed >= CUTOFF) {
nodesFailed = 0;
CUTOFF += GLOBAL_CUTOFF;
solvedModel = solveR(formula, model, 0);
}
return solvedModel;
}
Model *Solver::solveR(Formula *formula, Model *model, int backtrackDepth) {
invariant(formula != NULL, 2331);
// Restart solver if nodes failed is above cutoff.
if (nodesFailed >= CUTOFF) {
return NULL;
}
int state = formula->simplify(model);
switch (state) {
case -1: // If unsat, return null.
if (DEBUG >= 5)
cout << "Unsatisfied model: " << model->toString() << endl;
return NULL;
case 1: // If sat, return the model.
model->complete();
return model->clone();
}
int nextIndex = formula->nextVar();
invariant(!model->isAssigned(nextIndex), 1940);
// Should we try setting the literal or clearing the literal first?
int firstSet = rand() % 2;
//int firstSet = 0;
if (DEBUG >= 5)
cout << "firstSet = " << firstSet << endl;
Model *retModel;
if (DEBUG >= 5) {
cout << "Trying a value for " << nextIndex + 1 << " at depth " <<
backtrackDepth << "..." << endl;
}
if (DEBUG >= 2) {
if (backtrackDepth > maxDepth) {
maxDepth = backtrackDepth;
}
cout << "progress: " << backtrackDepth << "/" << formula->getNVars() <<
"\tnodes failed: " << nodesFailed << endl;
}
if ((retModel = solveRClone(formula, model, nextIndex, firstSet, backtrackDepth))) {
nodesFailed = 0;
return retModel;
}
if (DEBUG >= 5) {
cout << "Backtracking... depth=" << backtrackDepth << endl;
}
if ((retModel = solveRClone(formula, model, nextIndex, !firstSet, backtrackDepth))) {
nodesFailed = 0;
return retModel;
}
nodesFailed ++;
return NULL;
}
Model *Solver::solveRClone(Formula *formula, Model *model, int index, int setVar, int backtrackDepth) {
Model *modelClone = model->clone();
Formula *formulaClone = formula->clone();
if (setVar) {
modelClone->setVar(index);
} else {
modelClone->clearVar(index);
}
Model *retModel = solveR(formulaClone, modelClone, backtrackDepth + 1);
delete formulaClone;
delete modelClone;
return retModel;
}