Skip to content

Commit 3ef4b5d

Browse files
committed
v1.2.1: fixes and full int API
1 parent 50d098c commit 3ef4b5d

32 files changed

+1226
-919
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ EasyCSP supports CSPs to be formalized using objects or int expressions.
1313

1414
### Release Notes
1515

16+
!Release 1.2.1
17+
- fix: ConflictMinimizing search algorithm bug.
18+
- feature: added full support (algorithms and API) for int specific CSPs and CSOPs.
19+
1620
!Release 1.2.0
1721
- fix: IntDomain size() bug when containing both positive and negative ints.
1822
- feature: added int specific model classes, constraint expressions API and

easycsp/src-samples/net/sourceforge/easycsp/sample/jobscheduling/FlowtimeMain.java

Lines changed: 45 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -22,60 +22,66 @@
2222
import net.sourceforge.easycsp.Algorithm.Fitness;
2323
import net.sourceforge.easycsp.alg.BranchAndBound;
2424

25+
import static net.sourceforge.easycsp.Constraints.notEqual;
26+
2527
public class FlowtimeMain {
2628

2729
/**
28-
* FlowtimeMain.main method solves the formal JobScheduling CSOP( Z, D , C):
30+
* Flowtime main method solves the formal JobScheduling CSOP(Z,D,C):
2931
* 5 Machines and 5 Jobs (for assigning more than one Job per Machine, the
30-
* domain must contain arrays of Jobs)
32+
* domain must contain arrays of Jobs).
3133
*/
3234
public static void main(String[] args) {
3335
// create CSP(Z,D,C):
34-
Machine[] machines = new Machine[]{
35-
new Machine(0, 3),
36-
new Machine(1, 12),
37-
new Machine(2, 8),
38-
new Machine(3, 6),
39-
new Machine(4, 7)
40-
};
41-
Domain<Job> domain = new ObjectDomain<>(new Job(0, 3), new Job(1, 6), new Job(2, 5), new Job(3, 10), new Job(4, 9));
42-
43-
EasyCSP flowtime = EasyCSPBuilder.of("Flowtime", domain, machines)
44-
.constrainEachTwo(Constraints.notEqual())
36+
EasyCSP flowtime = EasyCSPBuilder.of("Flowtime",
37+
new ObjectDomain<>(
38+
new Job(0, 3),
39+
new Job(1, 6),
40+
new Job(2, 5),
41+
new Job(3, 10),
42+
new Job(4, 9)),
43+
new Machine[]{
44+
new Machine(0, 3),
45+
new Machine(1, 12),
46+
new Machine(2, 8),
47+
new Machine(3, 6),
48+
new Machine(4, 7)
49+
})
50+
.constrainEachTwo(notEqual())
4551
.build();
4652

47-
Fitness<Machine, Job> estimation = (s, idx, score) -> {
48-
if (idx == 0) {
49-
double totalEstim = s.value(0).getOperationCount() / s.variable(0).get().getExecutionSpeed();
50-
for (int i = 1; i < s.size(); i++) {
51-
// estimate the best case: the job with smallest OperationCount / Machine ExecutionSpeed:
52-
Variable<Machine, Job> v = s.variable(i);
53-
totalEstim += v.getDomain().get(0).getOperationCount() / v.get().getExecutionSpeed();
54-
}
55-
return totalEstim;
56-
} else {
57-
Variable<Machine, Job> v = s.variable(idx);
58-
// undo last estimation:
59-
double time = score - (v.getDomain().get(0).getOperationCount() / v.get().getExecutionSpeed());
60-
// add the last element:
61-
return time + (s.value(idx).getOperationCount() / v.get().getExecutionSpeed());
53+
// solve:
54+
BranchAndBound alg = BranchAndBound.minimizationOf(flowtime, FlowtimeMain::estimate, FlowtimeMain::evaluate);
55+
Solver solver = new EasyCSPSolver(alg);
56+
while (solver.solve()) {
57+
System.out.println(solver.getSolutionCount() + " " + solver.currentSolution() + ", Flowtime= " + alg.evaluation());
58+
}
59+
System.out.println(solver.getSolutionCount() + " optimal solution(s) in " + solver.getElapsedTime() / 1000.00 + " seconds");
60+
}
61+
62+
private static double estimate(Solution<Machine, Job> s, int idx, double score) {
63+
if (idx == 0) {
64+
double totalEstim = s.value(0).getOperationCount() / s.variable(0).get().getExecutionSpeed();
65+
for (int i = 1; i < s.size(); i++) {
66+
// estimate the best case: the job with smallest OperationCount / Machine ExecutionSpeed:
67+
Variable<Machine, Job> v = s.variable(i);
68+
totalEstim += v.getDomain().get(0).getOperationCount() / v.get().getExecutionSpeed();
6269
}
63-
};
64-
Fitness<Machine, Job> evaluation = (s, idx, score) ->
65-
{
70+
return totalEstim;
71+
} else {
6672
Variable<Machine, Job> v = s.variable(idx);
6773
// undo last estimation:
6874
double time = score - (v.getDomain().get(0).getOperationCount() / v.get().getExecutionSpeed());
6975
// add the last element:
7076
return time + (s.value(idx).getOperationCount() / v.get().getExecutionSpeed());
71-
};
72-
73-
// solve:
74-
BranchAndBound alg = BranchAndBound.minimizationOf(flowtime, estimation, evaluation);
75-
Solver solver = new Solver(alg);
76-
while (solver.solve()) {
77-
System.out.println(solver.getSolutionCount() + " " + solver.currentSolution() + ", Flowtime= " + alg.evaluation());
7877
}
79-
System.out.println(solver.getSolutionCount() + " optimal solution(s) in " + solver.getElapsedTime() / 1000.00 + " seconds");
78+
}
79+
80+
private static double evaluate(Solution<Machine, Job> s, int idx, double score) {
81+
Variable<Machine, Job> v = s.variable(idx);
82+
// undo last estimation:
83+
double time = score - (v.getDomain().get(0).getOperationCount() / v.get().getExecutionSpeed());
84+
// add the last element:
85+
return time + (s.value(idx).getOperationCount() / v.get().getExecutionSpeed());
8086
}
8187
}

easycsp/src-samples/net/sourceforge/easycsp/sample/jobscheduling/MakespanMain.java

Lines changed: 52 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -19,63 +19,73 @@
1919
package net.sourceforge.easycsp.sample.jobscheduling;
2020

2121
import net.sourceforge.easycsp.*;
22-
import net.sourceforge.easycsp.Algorithm.Fitness;
2322
import net.sourceforge.easycsp.alg.BranchAndBound;
2423

24+
import static net.sourceforge.easycsp.Constraints.notEqual;
25+
2526
public class MakespanMain {
2627

2728
/**
28-
* MakespanMain.main method solves the formal JobScheduling CSOP( Z, D , C):
29+
* Makespan main method solves the formal JobScheduling CSOP(Z,D,C):
2930
* 5 Machines and 5 Jobs (for assigning more than one Job per Machine, the
30-
* domain must contain arrays of Jobs)
31+
* domain must contain arrays of Jobs).
3132
*/
3233
public static void main(String[] args) {
3334
// create CSP(Z,D,C):
34-
Machine[] machines = new Machine[]{new Machine(0, 3), new Machine(1, 12), new Machine(2, 8), new Machine(3, 6), new Machine(4, 7)};
35-
Domain<Job> domain = new ObjectDomain<>(new Job(0, 3), new Job(1, 6), new Job(2, 5), new Job(3, 10), new Job(4, 9));
36-
37-
EasyCSP makespan = EasyCSPBuilder.of("Makespan", domain, machines)
38-
.constrainEachTwo(Constraints.notEqual())
35+
EasyCSP makespan = EasyCSPBuilder.of("Makespan",
36+
new ObjectDomain<>(
37+
new Job(0, 3),
38+
new Job(1, 6),
39+
new Job(2, 5),
40+
new Job(3, 10),
41+
new Job(4, 9)),
42+
new Machine[]{
43+
new Machine(0, 3),
44+
new Machine(1, 12),
45+
new Machine(2, 8),
46+
new Machine(3, 6),
47+
new Machine(4, 7)})
48+
.constrainEachTwo(notEqual())
3949
.build();
4050

41-
Fitness<Machine, Job> estimation = (s, idx, score) -> {
42-
double ret;
43-
if (idx == 0) {
44-
ret = s.value(0).getOperationCount() / s.variable(0).get().getExecutionSpeed();
45-
} else {
46-
double prvV = s.value(idx - 1).getOperationCount() / s.variable(idx - 1).get().getExecutionSpeed();
47-
double crtV = s.value(idx).getOperationCount() / s.variable(idx).get().getExecutionSpeed();
48-
ret = prvV > crtV ? prvV : crtV;
49-
}
50-
double max = Double.NEGATIVE_INFINITY;
51-
for (int i = idx + 1; i < s.size(); i++) {
52-
// estimate the best case: the job with smallest OperationCount / Machine ExecutionSpeed
53-
Variable<Machine, Job> v = s.variable(i);
54-
double crtValue = v.getDomain().get(0).getOperationCount() / v.get().getExecutionSpeed();
55-
if (crtValue > max) {
56-
max = crtValue;
57-
}
58-
}
59-
return ret > max ? ret : max;
60-
};
61-
Fitness<Machine, Job> evaluation = (s, idx, score) ->
62-
{
63-
double max = Double.NEGATIVE_INFINITY;
64-
for (int i = 0; i < s.size(); i++) {
65-
double crtValue = s.value(i).getOperationCount() / s.variable(i).get().getExecutionSpeed();
66-
if (crtValue > max) {
67-
max = crtValue;
68-
}
69-
}
70-
return max;
71-
};
72-
7351
// solve:
74-
BranchAndBound alg = BranchAndBound.minimizationOf(makespan, estimation, evaluation);
75-
Solver solver = new Solver(alg);
52+
BranchAndBound alg = BranchAndBound.minimizationOf(makespan, MakespanMain::estimate, MakespanMain::evaluate);
53+
Solver solver = new EasyCSPSolver(alg);
7654
while (solver.solve()) {
7755
System.out.println(solver.getSolutionCount() + " " + solver.currentSolution() + ", Makespan= " + alg.evaluation());
7856
}
7957
System.out.println(solver.getSolutionCount() + " optimal solution(s) in " + solver.getElapsedTime() / 1000.00 + " seconds");
8058
}
59+
60+
private static double estimate(Solution<Machine, Job> s, int idx, double score) {
61+
double ret;
62+
if (idx == 0) {
63+
ret = s.value(0).getOperationCount() / s.variable(0).get().getExecutionSpeed();
64+
} else {
65+
double prvV = s.value(idx - 1).getOperationCount() / s.variable(idx - 1).get().getExecutionSpeed();
66+
double crtV = s.value(idx).getOperationCount() / s.variable(idx).get().getExecutionSpeed();
67+
ret = prvV > crtV ? prvV : crtV;
68+
}
69+
double max = Double.NEGATIVE_INFINITY;
70+
for (int i = idx + 1; i < s.size(); i++) {
71+
// estimate the best case: the job with smallest OperationCount / Machine ExecutionSpeed
72+
Variable<Machine, Job> v = s.variable(i);
73+
double crtValue = v.getDomain().get(0).getOperationCount() / v.get().getExecutionSpeed();
74+
if (crtValue > max) {
75+
max = crtValue;
76+
}
77+
}
78+
return ret > max ? ret : max;
79+
}
80+
81+
private static double evaluate(Solution<Machine, Job> s, int idx, double score) {
82+
double max = Double.NEGATIVE_INFINITY;
83+
for (int i = 0; i < s.size(); i++) {
84+
double crtValue = s.value(i).getOperationCount() / s.variable(i).get().getExecutionSpeed();
85+
if (crtValue > max) {
86+
max = crtValue;
87+
}
88+
}
89+
return max;
90+
}
8191
}

easycsp/src-samples/net/sourceforge/easycsp/sample/knighttour/Main.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
import net.sourceforge.easycsp.Algorithm.Fitness;
2323
import net.sourceforge.easycsp.alg.Greedy;
2424

25+
import static net.sourceforge.easycsp.Constraints.is;
26+
import static net.sourceforge.easycsp.Constraints.notEqual;
27+
2528
public class Main {
2629

2730
private static final int BOARD_SIZE = 8;
@@ -36,17 +39,18 @@ public static void main(String[] args) {
3639
cells[cell] = new Cell(i, j);
3740
}
3841
}
39-
EasyCSP<?, Cell> knighttour = EasyCSPBuilder.of("Knight's Tour", CELL_COUNT, new ObjectDomain<>((Cell[]) cells))
40-
.constrain(Constraints.equal(START), 0)
42+
EasyCSP<?, Cell> knighttour = EasyCSPBuilder.of("Knight's Tour", CELL_COUNT, new ObjectDomain<>(cells))
43+
.constrain(is(START), 0)
4144
.constrainSequentially(assignments -> {
4245
int dX = Math.abs(assignments.value(0).x - assignments.value(1).x);
4346
int dY = Math.abs(assignments.value(0).y - assignments.value(1).y);
4447
return dX == 1 && dY == 2 || dX == 2 && dY == 1;
4548
})
46-
.constrainEachTwo(Constraints.notEqual())
49+
.constrainEachTwo(notEqual())
4750
.build();
51+
4852
// solve:
49-
Solver s = new Solver(new Greedy(knighttour, minDegree()));
53+
Solver s = new EasyCSPSolver(new Greedy(knighttour, minDegree()));
5054
s.stream()
5155
.findAny()
5256
.ifPresent(System.out::println);

easycsp/src-samples/net/sourceforge/easycsp/sample/nqueens/IntMain.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,13 @@
1818
*/
1919
package net.sourceforge.easycsp.sample.nqueens;
2020

21-
import net.sourceforge.easycsp.IntDomain;
22-
import net.sourceforge.easycsp.numeric.IntEasyCSP;
23-
import net.sourceforge.easycsp.numeric.IntEasyCSPBuilder;
24-
import net.sourceforge.easycsp.numeric.IntSolver;
21+
import net.sourceforge.easycsp.*;
2522

2623
import static net.sourceforge.easycsp.Constraints.notEqual;
2724

2825
public class IntMain {
2926

30-
private static final int BOARD_SIZE = 124;
27+
private static final int BOARD_SIZE = 131;
3128

3229
public static void main(String[] args) {
3330
// create CSP(Z,D,C):
@@ -41,10 +38,10 @@ public static void main(String[] args) {
4138
nqueensBuilder.constrainEachTwoInRange(notEqual(), 0, BOARD_SIZE);
4239
nqueensBuilder.constrainEachTwoInRange(notEqual(), BOARD_SIZE, 2 * BOARD_SIZE);
4340
nqueensBuilder.constrainEachTwoInRange(notEqual(), 2 * BOARD_SIZE, 3 * BOARD_SIZE);
44-
IntEasyCSP nqueens = nqueensBuilder.build();
41+
IntEasyCSP<?> nqueens = nqueensBuilder.build();
4542

4643
// solve:
47-
IntSolver<?> solver = new IntSolver<>(nqueens);
44+
IntEasyCSPSolver<?> solver = new IntEasyCSPSolver(nqueens);
4845
solver.stream()
4946
.limit(100)
5047
.map(sol -> sol.toStringFirst(BOARD_SIZE))

easycsp/src-samples/net/sourceforge/easycsp/sample/nqueens/Main.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,28 +18,27 @@
1818
*/
1919
package net.sourceforge.easycsp.sample.nqueens;
2020

21-
import net.sourceforge.easycsp.EasyCSP;
22-
import net.sourceforge.easycsp.EasyCSPBuilder;
23-
import net.sourceforge.easycsp.IntDomain;
24-
import net.sourceforge.easycsp.Solver;
21+
import net.sourceforge.easycsp.*;
2522

2623
import java.util.stream.IntStream;
2724

2825
public class Main {
2926

30-
private static final int BOARD_SIZE = 124;
27+
private static final int BOARD_SIZE = 131;
3128

3229
public static void main(String[] args) {
3330
// create CSP(Z,D,C):
34-
Integer[] rows = IntStream.rangeClosed(1, BOARD_SIZE).mapToObj(Integer::valueOf).toArray(Integer[]::new);
35-
EasyCSP<Integer, Integer> nqueens = EasyCSPBuilder.of("NQueens", new IntDomain(1, BOARD_SIZE), rows)
31+
EasyCSP<Integer, Integer> nqueens = EasyCSPBuilder.of("NQueens",
32+
new IntDomain(1, BOARD_SIZE),
33+
IntStream.rangeClosed(1, BOARD_SIZE).mapToObj(Integer::valueOf).toArray(Integer[]::new))
3634
.constrainEachTwo(assignments ->
3735
!assignments.value(0).equals(assignments.value(1))
3836
&& Math.abs(assignments.variable(0).get() - assignments.variable(1).get())
3937
!= Math.abs(assignments.value(0) - assignments.value(1)))
4038
.build();
39+
4140
// solve:
42-
Solver solver = new Solver(nqueens);
41+
Solver solver = new EasyCSPSolver(nqueens);
4342
solver.stream()
4443
.limit(100)
4544
.forEach(System.out::println);

easycsp/src-samples/net/sourceforge/easycsp/sample/semaphoresync/Main.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,25 +42,25 @@ public static void main(String[] args) {
4242
.constrain(notEqual(), 4, 5)
4343
.build();
4444

45+
// solve:
4546
// since estimation and evaluation functions are alike for this csp,
4647
// the same instance will be used for both estimation and evaluation.
47-
Fitness<Object, Integer> estimation = (s, idx, score) -> {
48-
int varIdxVal = s.value(idx);
49-
for (int i = 0; i < idx; i++) {
50-
if (s.value(i) == varIdxVal) {
51-
return score;
52-
}
53-
}
54-
return score + 1;
55-
};
56-
57-
// solve:
58-
BranchAndBound alg = BranchAndBound.minimizationOf(semsync, estimation, estimation);
59-
Solver<?, Integer> solver = new Solver(alg);
48+
BranchAndBound alg = BranchAndBound.minimizationOf(semsync, Main::estimate, Main::estimate);
49+
Solver solver = new EasyCSPSolver<>(alg);
6050
solver.stream()
6151
.forEach(solution -> {
6252
System.out.println(solution + ", with " + alg.evaluation() + " states");
6353
});
6454
System.out.println(solver.getSolutionCount() + " optimal solution(s) in " + solver.getElapsedTime() / 1000.00 + " seconds");
6555
}
56+
57+
private static double estimate(Solution<?, Integer> s, int idx, double score) {
58+
int varIdxVal = s.value(idx);
59+
for (int i = 0; i < idx; i++) {
60+
if (s.value(i) == varIdxVal) {
61+
return score;
62+
}
63+
}
64+
return score + 1;
65+
}
6666
}

0 commit comments

Comments
 (0)