write solution to array instead of returning

test concurrent and sequential at the same time
This commit is contained in:
Luca Conte 2025-06-11 04:45:03 +02:00
parent e2acf6899e
commit 3cd69b92c8
1 changed files with 71 additions and 21 deletions

View File

@ -27,10 +27,10 @@ final public class Solver extends JPanel {
private static final long serialVersionUID = 1L;
// The default size of the labyrinth (i.e. unless program is invoked with size arguments):
private static final int DEFAULT_WIDTH_IN_CELLS = 1000;
private static final int DEFAULT_HEIGHT_IN_CELLS = 1000;
private static final int DEFAULT_WIDTH_IN_CELLS = 5000;
private static final int DEFAULT_HEIGHT_IN_CELLS = 5000;
private static final int N_RUNS_HALF = 10; // #runs will be 2*N_RUNS_HALF + 1
private static final int N_RUNS_HALF = 5; // #runs will be 2*N_RUNS_HALF + 1
// The grid defining the structure of the labyrinth
private final Labyrinth labyrinth;
@ -38,7 +38,6 @@ final public class Solver extends JPanel {
// For each cell in the labyrinth: Has solve() visited it yet?
private boolean[][] visited; // initialized in solve()
private AtomicBoolean[][] visitedAtomic;
private AtomicInteger numTasks = new AtomicInteger(0);
private Semaphore[] sectors;
private static final int SECTOR_SIZE = (int) Math.sqrt(DEFAULT_WIDTH_IN_CELLS * DEFAULT_HEIGHT_IN_CELLS) / 50;
@ -48,6 +47,8 @@ final public class Solver extends JPanel {
private Point[] solution = null; // set to solution path once that has been computed
private ArrayList<Point> solutionArrayList;
public Solver(Labyrinth labyrinth) {
this.labyrinth = labyrinth;
}
@ -156,14 +157,27 @@ final public class Solver extends JPanel {
sectors[i] = new Semaphore(1);
}
solutionArrayList = new ArrayList<>();
ForkJoinPool pool = ForkJoinPool.commonPool();
ArrayDeque<Point> pathSoFar = new ArrayDeque<>();
ConcurrentSolverTask t = new ConcurrentSolverTask(start, pathSoFar, pool);
Point[] result = pool.invoke(t);
ConcurrentSolverTask t = new ConcurrentSolverTask(start, pathSoFar, pool, solutionArrayList);
pool.submit(t);
synchronized (solutionArrayList) {
while (solutionArrayList.isEmpty()) {
try {
solutionArrayList.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Point[] result = solutionArrayList.toArray(new Point[0]);
System.out.println("Used tasks: " + numTasks.get());
System.out.println("Task to Solution Length Ratio: " + (double)result.length / numTasks.get());
return result;
}
@ -174,11 +188,13 @@ final public class Solver extends JPanel {
private ArrayDeque<Point> pathSoFar;
private ForkJoinPool pool;
private ArrayList<ConcurrentSolverTask> subtasks;
private ArrayList<Point> solutionArrayList;
private int currentSector;
public ConcurrentSolverTask(PointAndDirection start, ArrayDeque<Point> pathSoFar, ForkJoinPool pool) {
public ConcurrentSolverTask(PointAndDirection start, ArrayDeque<Point> pathSoFar, ForkJoinPool pool, ArrayList<Point> solutionArrayList) {
this.start = start;
this.pathSoFar = pathSoFar;
this.pool = pool;
this.solutionArrayList = solutionArrayList;
this.backtrackStack = new ArrayDeque<>();
this.subtasks = new ArrayList<>();
@ -208,7 +224,6 @@ final public class Solver extends JPanel {
}
public Point[] compute() {
numTasks.incrementAndGet();
int currentLength = 0;
Point current = this.start.getPoint();
@ -266,7 +281,8 @@ final public class Solver extends JPanel {
ConcurrentSolverTask subtask = new ConcurrentSolverTask(
new PointAndDirection(neighbour, dir.opposite),
subPath,
this.pool
this.pool,
this.solutionArrayList
);
subtasks.add(subtask);
@ -298,13 +314,13 @@ final public class Solver extends JPanel {
// check for solutions in subtasks
// System.out.println("End of task reached - waiting for " + subtasks.size() + " subtasks");
for (ConcurrentSolverTask subtask : subtasks) {
Point[] subtaskResult = subtask.join();
if (subtaskResult != null) {
// found a solution in a subtask
return subtaskResult;
}
}
// for (ConcurrentSolverTask subtask : subtasks) {
// Point[] subtaskResult = subtask.join();
// if (subtaskResult != null) {
// // found a solution in a subtask
// return subtaskResult;
// }
// }
// no solution found
return null;
}
@ -332,6 +348,11 @@ final public class Solver extends JPanel {
subtask.cancel(true);
}
synchronized (this.solutionArrayList) {
this.solutionArrayList.addAll(pathSoFar);
this.solutionArrayList.notify();
}
return pathSoFar.toArray(new Point[0]);
}
}
@ -455,6 +476,7 @@ private static void displayLabyrinth(Solver solver) {
*/
public static void main(String[] args) {
long[] runTimes = new long[2*N_RUNS_HALF + 1];
long[] concurrentRunTimes = new long[2*N_RUNS_HALF + 1];
for (int run = 0; run < 2*N_RUNS_HALF + 1; ++run) {
@ -464,7 +486,7 @@ private static void displayLabyrinth(Solver solver) {
}
long startTime = System.currentTimeMillis();
solver.solution = solver.solveConcurrently();
solver.solution = solver.solve();
long endTime = System.currentTimeMillis();
if (solver.solution == null)
@ -485,8 +507,36 @@ private static void displayLabyrinth(Solver solver) {
else
System.out.println("Solution incorrect :-(");
}
solver.solution = null;
long concurrentStartTime = System.currentTimeMillis();
solver.solution = solver.solveConcurrently();
long concurrentEndTime = System.currentTimeMillis();
if (solver.solution == null)
System.out.println("No solution exists.");
else {
System.out.println("Computed concurrent solution of length " + solver.solution.length + " to labyrinth of size " +
solver.labyrinth.getWidth() + "x" + solver.labyrinth.getHeight() + " in " + (concurrentEndTime - concurrentStartTime) + "ms.");
concurrentRunTimes[run] = concurrentEndTime - concurrentStartTime;
if (solver.labyrinth.smallEnoughToDisplay()) {
solver.displaySolution();
solver.printSolution();
}
if (solver.labyrinth.checkSolution(solver.solution))
System.out.println("Solution correct :-)");
else
System.out.println("Solution incorrect :-(");
}
System.out.println();
}
Arrays.sort(runTimes);
System.out.println("Median run time was " + runTimes[N_RUNS_HALF] + " ms.");
System.out.println("Median sequential run time was " + runTimes[N_RUNS_HALF] + " ms.");
Arrays.sort(concurrentRunTimes);
System.out.println("Median concurrent run time was " + concurrentRunTimes[N_RUNS_HALF] + " ms.");
}
}