Skip to content

Commit 9355222

Browse files
committed
tests and exercise for random search
1 parent 8b0dd18 commit 9355222

File tree

5 files changed

+151
-2
lines changed

5 files changed

+151
-2
lines changed

Diff for: docs/exercises/ex10.md

+14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# Exercise 10
22

3+
## Part A
4+
5+
The code of `RandomForKnapsack` is not particularly good, as it creates
6+
new arrays on the heap at each step.
7+
Write a new `RandomForKnapsackOptimized` class, in which __ONLY 2__ arrays
8+
are instantiated: one to keep the best solution seen so far, and one as
9+
a buffer to randomize at each step to evaluate a new configuration.
10+
When a new, better configuration is found, just swap the two array pointers.
11+
12+
Create a new `RandomForKnapsackOptimizedTest`, based on `RandomForKnapsackTest`,
13+
to test this new implementation.
14+
15+
## Part B
16+
317
Consider the class `HillClimbingForQueens`.
418
Modify the Hill Climbing algorithm to use *Steepest Ascent*:
519
instead of climbing to the first better element in the neighbourhood,

Diff for: lessons/src/main/java/org/pg4200/les10/knapsack/RandomForKnapsack.java

+10-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
public class RandomForKnapsack {
1010

1111

12-
public boolean[] solve(int maxIterations, KnapsackProblem problem){
12+
public static boolean[] solve(int maxIterations, KnapsackProblem problem){
1313

1414
if(maxIterations < 1){
1515
throw new IllegalArgumentException("Invalid number of iterations");
@@ -37,8 +37,16 @@ public boolean[] solve(int maxIterations, KnapsackProblem problem){
3737
return solution;
3838
}
3939

40-
private boolean[] sample(int n, Random random){
40+
private static boolean[] sample(int n, Random random){
4141

42+
/*
43+
Note: the code here is not particularly good... as we are
44+
instantiating a new array on the heap at each step.
45+
Even if we store only the best array, we are still polluting
46+
the heap, increasing the number of invocations of the
47+
JVM Garbage Collector.
48+
How to fix is given as exercise.
49+
*/
4250
boolean[] solution = new boolean[n];
4351
for(int i=0; i<solution.length; i++){
4452
solution[i] = random.nextBoolean();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package org.pg4200.les10.knapsack;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import static org.junit.jupiter.api.Assertions.*;
6+
7+
class RandomForKnapsackTest {
8+
9+
private void test(int iterations, KnapsackInstanceWithSolution p, double optimum){
10+
11+
boolean[] res = RandomForKnapsack.solve(iterations, p.getProblem());
12+
13+
double fitness = p.getProblem().evaluate(res);
14+
15+
assertEquals(optimum, fitness, 0.001);
16+
17+
double best = p.getBestFitness();
18+
19+
assertEquals(best, fitness, 0.001);
20+
}
21+
22+
/*
23+
Note: here we put high enough number of iterations (compared to the size
24+
of search space) that it is more likely to be hit on the head by a meteor
25+
while reading this text than these tests will fail.
26+
*/
27+
28+
@Test
29+
public void testP05(){
30+
31+
test(1000, KnapsackInstanceWithSolution.problemP05(), 51d);
32+
}
33+
34+
@Test
35+
public void testP15(){
36+
37+
test(1_000_000, KnapsackInstanceWithSolution.problemP15(), 1458d);
38+
}
39+
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package org.pg4200.sol10;
2+
3+
import org.pg4200.les10.knapsack.KnapsackProblem;
4+
5+
import java.util.Objects;
6+
import java.util.Random;
7+
8+
public class RandomForKnapsackOptimized {
9+
10+
11+
public static boolean[] solve(int maxIterations, KnapsackProblem problem){
12+
13+
if(maxIterations < 1){
14+
throw new IllegalArgumentException("Invalid number of iterations");
15+
}
16+
Objects.requireNonNull(problem);
17+
18+
Random random = new Random();
19+
20+
final int n = problem.getSize();
21+
22+
boolean[] solution = new boolean[n];
23+
boolean[] buffer = new boolean[n];
24+
25+
sample(solution, random);
26+
27+
for(int i=1; i<maxIterations; i++){
28+
sample(buffer, random);
29+
30+
if(problem.evaluate(buffer) > problem.evaluate(solution)){
31+
boolean[] tmp = solution;
32+
solution = buffer;
33+
buffer = tmp;
34+
}
35+
}
36+
37+
return solution;
38+
}
39+
40+
private static void sample(boolean[] buffer, Random random){
41+
for(int i=0; i<buffer.length; i++){
42+
buffer[i] = random.nextBoolean();
43+
}
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package org.pg4200.sol10;
2+
3+
import org.junit.jupiter.api.Test;
4+
import org.pg4200.les10.knapsack.KnapsackInstanceWithSolution;
5+
import org.pg4200.les10.knapsack.RandomForKnapsack;
6+
7+
import static org.junit.jupiter.api.Assertions.assertEquals;
8+
9+
class RandomForKnapsackOptimizedTest {
10+
11+
private void test(int iterations, KnapsackInstanceWithSolution p, double optimum){
12+
13+
boolean[] res = RandomForKnapsackOptimized.solve(iterations, p.getProblem());
14+
15+
double fitness = p.getProblem().evaluate(res);
16+
17+
assertEquals(optimum, fitness, 0.001);
18+
19+
double best = p.getBestFitness();
20+
21+
assertEquals(best, fitness, 0.001);
22+
}
23+
24+
/*
25+
Note: here we put high enough number of iterations (compared to the size
26+
of search space) that it is more likely to be hit on the head by a meteor
27+
while reading this text than these tests will fail.
28+
*/
29+
30+
@Test
31+
public void testP05(){
32+
33+
test(1000, KnapsackInstanceWithSolution.problemP05(), 51d);
34+
}
35+
36+
@Test
37+
public void testP15(){
38+
39+
test(1_000_000, KnapsackInstanceWithSolution.problemP15(), 1458d);
40+
}
41+
42+
}

0 commit comments

Comments
 (0)