-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSeesawSearchIncremental.java
263 lines (210 loc) · 7.87 KB
/
SeesawSearchIncremental.java
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
//******************************************************************************
//
// File: SeesawSearchIncremental.java
//
//******************************************************************************
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Random;
/**
* Class SeesawSearchIncremental is used to perform the Incremental Seesaw
* Search for solving the MAX-SAT problem.
*
* @author Harshad Paradkar
*
*/
public class SeesawSearchIncremental {
/**
* This method performs the Incremental Seesaw Search to solve the
* MAX-SAT problem for the given parameters.
*
* @param parameters The parameters for the MAX-SAT problem that needs
* to be solved.
* @param maxTries Number of times to perform the search, after which
* the Seesaw Search gives up.
* @param seed The seed value, to initialize the PRNG.
* @return An object of type Solution.
* @throws Exception Any exception that might occur during execution.
*/
public static Solution solveMAXSAT(MAXSATParameters parameters,
int maxTries, long seed) throws Exception {
Random random;
if(seed == 0) {
// If the calling method does not want to provide a seed value.
random = new Random();
}else {
// Use the seed value provided by the calling method.
random = new Random(seed);
}
// To store the clauses which need to be added to the solution
LinkedList<Clause> unexploredClauses = new LinkedList<Clause>();
for(int i = 0; i < parameters.clauses.length; i++) {
unexploredClauses.add(parameters.clauses[i]);
}
// To hold the clauses that are satisfied
LinkedList<Clause> trueClauses = new LinkedList<Clause>();
Clause falseClause = null;
int noOfIterations = 0, maxSatisfiedClausesCount = 0;
Clause[] maxSatisfiedClauses = null;
long startTime = System.currentTimeMillis();
for(int i = 0; i < maxTries; i++) {
noOfIterations++;
int index;
Clause unExploredClause = null;
/******************************************************************
* Optimization phase
*
* Keep on adding clauses to the solution. If the last clause
* added was FALSE, break out of Optimization phase, since the
* solution is now in an inconsistent state.
*****************************************************************/
while(true) {
if(unexploredClauses.size() == 0) {
break;
}
// Randomly generate index of the next clause to pick
index = random.nextInt(unexploredClauses.size());
// Get the randomly picked clause
unExploredClause = unexploredClauses.remove(index);
if(unExploredClause.isClauseSatisfied()) {
// Add the clause to solution if it is TRUE
trueClauses.add(unExploredClause);
}else {
// Mark the FALSE clause, and break
falseClause = unExploredClause;
break;
}
}// Optimization phase.
if(trueClauses.size() == parameters.noOfClauses) {
/* if all the clauses evaluated to true, then no need to go
* to the constraining phase.
*/
break;
}
/******************************************************************
* Constraining phase
*
* Make all the clauses in the solution evaluate to TRUE.
*
* Method 1: Remove the FALSE clause from solution, and place it
* back in the list of unexplored clauses, to be picked up by the
* Optimization phase.
*
* Method 2: Flip a randomly chosen variable from the FALSE clause,
* and remove the clauses which might have turned FALSE now from the
* solution, and place them back in the list of unexplored clauses,
* to be picked up by the Optimization phase.
*****************************************************************/
Literal[] falseClauseLiterals = falseClause.getLiterals();
boolean falseClauseSatisfied = false;
// Generate random value between 0.0 and 1.0(exclusive)
double sigma = random.nextDouble();
//sigma = 0.6;
if(sigma <= 0.3) {
/**
* Prefer the FALSE clauses.
* But only do it less often, as it makes the solution
* deviate from the Optimum, but it's required to provide the
* necessary randomization.
**/
Variable variable
= falseClauseLiterals[random
.nextInt(falseClauseLiterals.length)]
.variable;
// Flip the randomly chosen variable value from FALSE clause
variable.value = !variable.value;
// Add the FALSE clause turned TRUE to the solution
trueClauses.add(falseClause);
Iterator<Clause> iterator = trueClauses.iterator();
while(iterator.hasNext()) {
Clause clause = iterator.next();
if(clause.isClauseSatisfied()) {
// if this clause still evaluates to true, check others
continue;
}else {
// Add the TRUE clause turned FALSE back to the list
// of unexplored clauses
unexploredClauses.add(clause);
iterator.remove();
}
}
}else {
/**
* Prefer the TRUE clauses.
* Try flipping all variables in the FALSE clauses, so that this
* clause is compatible with the rest of the TRUE clauses, even
* after flipping the values.
*
* If it isn't, put the FALSE clause back into the list of
* unexplored clauses.
* (Also remove a TRUE clause, because there was some TRUE
* clause that wasn't compatible with the FALSE clause.
* Helps the program stay out of local optima.)
**/
LinkedList<Clause> unCompatibleClauses = new LinkedList<Clause>();
for(int j = 0; j < falseClauseLiterals.length; j++) {
unCompatibleClauses.clear();
// get each variable in the false clause, and flip it.
Variable variable = falseClauseLiterals[j].variable;
variable.value = !variable.value;
boolean trueClausesStillSatisfied = true;
/* After flipping a variable in the false clause, in order
* to make it evaluate to true, check if the other true
* clauses in the intermediate solution are still
* evaluating to true.*/
Iterator<Clause> iterator = trueClauses.iterator();
while(iterator.hasNext()) {
Clause clause = iterator.next();
if(clause.isClauseSatisfied()) {
// if this clause still evaluates to true,
// check others
continue;
}else {
/* if this clause is no more true, flip back the
* variable in the false clause to it's original
* value. Also, set a flag, to continue flipping
* other variables in the false clause.
*/
variable.value = !variable.value;
trueClausesStillSatisfied = false;
unCompatibleClauses.add(clause);
break;
}
}
if(trueClausesStillSatisfied) {
falseClauseSatisfied = true;
break;
}
}
if(falseClauseSatisfied) {
trueClauses.add(falseClause);
}else {
/*unexploredClauses.add(falseClause);
Clause unCompatibleClause = unCompatibleClauses
.remove(random.nextInt(unCompatibleClauses.size()));
trueClauses.remove(unCompatibleClause);
unexploredClauses.add(unCompatibleClause);
unCompatibleClauses.clear();*/
unexploredClauses.add(falseClause);
unexploredClauses.add(trueClauses.remove(random.nextInt(trueClauses.size())));
}
}// Constraining phase
// Save this state if a better solution was found
if(trueClauses.size() > maxSatisfiedClausesCount) {
maxSatisfiedClausesCount = trueClauses.size();
maxSatisfiedClauses = Utilities
.getDeepCopiedClauses(parameters.clauses,
parameters.noOfVariables);
}
}// max-tries
long endTime = System.currentTimeMillis();
// Save time elapsed in seconds
float difference = (endTime - startTime) / 1000.0f;
Solution solution = new Solution(parameters.noOfVariables);
solution.setNoOfIterations(noOfIterations);
solution.setNoOfSatisfiedClauses(maxSatisfiedClausesCount);
solution.setTime(difference);
solution.setClauses(maxSatisfiedClauses);
return solution;
}
}