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; private static final long serialVersionUID = 1L;
// The default size of the labyrinth (i.e. unless program is invoked with size arguments): // 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_WIDTH_IN_CELLS = 5000;
private static final int DEFAULT_HEIGHT_IN_CELLS = 1000; 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 // The grid defining the structure of the labyrinth
private final Labyrinth 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? // For each cell in the labyrinth: Has solve() visited it yet?
private boolean[][] visited; // initialized in solve() private boolean[][] visited; // initialized in solve()
private AtomicBoolean[][] visitedAtomic; private AtomicBoolean[][] visitedAtomic;
private AtomicInteger numTasks = new AtomicInteger(0);
private Semaphore[] sectors; private Semaphore[] sectors;
private static final int SECTOR_SIZE = (int) Math.sqrt(DEFAULT_WIDTH_IN_CELLS * DEFAULT_HEIGHT_IN_CELLS) / 50; 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 Point[] solution = null; // set to solution path once that has been computed
private ArrayList<Point> solutionArrayList;
public Solver(Labyrinth labyrinth) { public Solver(Labyrinth labyrinth) {
this.labyrinth = labyrinth; this.labyrinth = labyrinth;
} }
@ -156,14 +157,27 @@ final public class Solver extends JPanel {
sectors[i] = new Semaphore(1); sectors[i] = new Semaphore(1);
} }
solutionArrayList = new ArrayList<>();
ForkJoinPool pool = ForkJoinPool.commonPool(); ForkJoinPool pool = ForkJoinPool.commonPool();
ArrayDeque<Point> pathSoFar = new ArrayDeque<>(); ArrayDeque<Point> pathSoFar = new ArrayDeque<>();
ConcurrentSolverTask t = new ConcurrentSolverTask(start, pathSoFar, pool); ConcurrentSolverTask t = new ConcurrentSolverTask(start, pathSoFar, pool, solutionArrayList);
Point[] result = pool.invoke(t); 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; return result;
} }
@ -174,11 +188,13 @@ final public class Solver extends JPanel {
private ArrayDeque<Point> pathSoFar; private ArrayDeque<Point> pathSoFar;
private ForkJoinPool pool; private ForkJoinPool pool;
private ArrayList<ConcurrentSolverTask> subtasks; private ArrayList<ConcurrentSolverTask> subtasks;
private ArrayList<Point> solutionArrayList;
private int currentSector; 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.start = start;
this.pathSoFar = pathSoFar; this.pathSoFar = pathSoFar;
this.pool = pool; this.pool = pool;
this.solutionArrayList = solutionArrayList;
this.backtrackStack = new ArrayDeque<>(); this.backtrackStack = new ArrayDeque<>();
this.subtasks = new ArrayList<>(); this.subtasks = new ArrayList<>();
@ -208,7 +224,6 @@ final public class Solver extends JPanel {
} }
public Point[] compute() { public Point[] compute() {
numTasks.incrementAndGet();
int currentLength = 0; int currentLength = 0;
Point current = this.start.getPoint(); Point current = this.start.getPoint();
@ -266,7 +281,8 @@ final public class Solver extends JPanel {
ConcurrentSolverTask subtask = new ConcurrentSolverTask( ConcurrentSolverTask subtask = new ConcurrentSolverTask(
new PointAndDirection(neighbour, dir.opposite), new PointAndDirection(neighbour, dir.opposite),
subPath, subPath,
this.pool this.pool,
this.solutionArrayList
); );
subtasks.add(subtask); subtasks.add(subtask);
@ -298,13 +314,13 @@ final public class Solver extends JPanel {
// check for solutions in subtasks // check for solutions in subtasks
// System.out.println("End of task reached - waiting for " + subtasks.size() + " subtasks"); // System.out.println("End of task reached - waiting for " + subtasks.size() + " subtasks");
for (ConcurrentSolverTask subtask : subtasks) { // for (ConcurrentSolverTask subtask : subtasks) {
Point[] subtaskResult = subtask.join(); // Point[] subtaskResult = subtask.join();
if (subtaskResult != null) { // if (subtaskResult != null) {
// found a solution in a subtask // // found a solution in a subtask
return subtaskResult; // return subtaskResult;
} // }
} // }
// no solution found // no solution found
return null; return null;
} }
@ -332,6 +348,11 @@ final public class Solver extends JPanel {
subtask.cancel(true); subtask.cancel(true);
} }
synchronized (this.solutionArrayList) {
this.solutionArrayList.addAll(pathSoFar);
this.solutionArrayList.notify();
}
return pathSoFar.toArray(new Point[0]); return pathSoFar.toArray(new Point[0]);
} }
} }
@ -455,6 +476,7 @@ private static void displayLabyrinth(Solver solver) {
*/ */
public static void main(String[] args) { public static void main(String[] args) {
long[] runTimes = new long[2*N_RUNS_HALF + 1]; 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) { 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(); long startTime = System.currentTimeMillis();
solver.solution = solver.solveConcurrently(); solver.solution = solver.solve();
long endTime = System.currentTimeMillis(); long endTime = System.currentTimeMillis();
if (solver.solution == null) if (solver.solution == null)
@ -484,9 +506,37 @@ private static void displayLabyrinth(Solver solver) {
System.out.println("Solution correct :-)"); System.out.println("Solution correct :-)");
else else
System.out.println("Solution incorrect :-("); 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); 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.");
} }
} }