### Clone Quickstarts Repository Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Clone the repository containing the completed quick start examples. ```bash $ git clone https://github.com/kiegroup/optaplanner-quickstarts ``` -------------------------------- ### Run OptaPlanner Examples on Linux/Mac Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Navigate to the examples directory and execute the shell script to launch the OptaPlanner examples GUI. Ensure you have downloaded and unzipped a release of OptaPlanner. ```bash $ cd examples $ ./runExamples.sh ``` -------------------------------- ### Run OptaPlanner Examples on Windows Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Navigate to the examples directory and execute the batch script to launch the OptaPlanner examples GUI. Ensure you have downloaded and unzipped a release of OptaPlanner. ```batch $ cd examples $ runExamples.bat ``` -------------------------------- ### Run OptaPlanner Examples Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Execute the examples module after building the project. ```bash $ cd optaplanner-examples $ mvn exec:java ... ``` -------------------------------- ### Example CustomPhaseCommand Implementation Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html This example demonstrates initializing a solution by setting processes to their original machines. Remember to notify the `ScoreDirector` before and after variable changes and trigger variable listeners. ```java public class ToOriginalMachineSolutionInitializer extends AbstractCustomPhaseCommand { public void changeWorkingSolution(ScoreDirector scoreDirector) { MachineReassignment machineReassignment = scoreDirector.getWorkingSolution(); for (MrProcessAssignment processAssignment : machineReassignment.getProcessAssignmentList()) { scoreDirector.beforeVariableChanged(processAssignment, "machine"); processAssignment.setMachine(processAssignment.getOriginalMachine()); scoreDirector.afterVariableChanged(processAssignment, "machine"); scoreDirector.triggerVariableListeners(); } } } ``` -------------------------------- ### View Hello World Output Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Example console output showing the optimized school timetable solution. ```text ... INFO Solving ended: time spent (5000), best score (0hard/9soft), ... INFO INFO | | Room A | Room B | Room C | INFO |------------|------------|------------|------------| INFO | MON 08:30 | English | Math | | INFO | | I. Jones | A. Turing | | INFO | | 9th grade | 10th grade | | INFO |------------|------------|------------|------------| INFO | MON 09:30 | History | Physics | | INFO | | I. Jones | M. Curie | | INFO | | 9th grade | 10th grade | | INFO |------------|------------|------------|------------| INFO | MON 10:30 | History | Physics | | INFO | | I. Jones | M. Curie | | INFO | | 10th grade | 9th grade | | INFO |------------|------------|------------|------------| ... INFO |------------|------------|------------|------------| ``` -------------------------------- ### NQueens Solution Class Example Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Example of a planning solution class for the N-Queens problem. It includes problem facts, planning entities, and the score, annotated with @PlanningSolution. ```java @PlanningSolution public class NQueens { // Problem facts private int n; private List columnList; private List rowList; // Planning entities private List queenList; private SimpleScore score; ... } ``` -------------------------------- ### Example CloudBalancePartitioner Implementation Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html A concrete implementation of the SolutionPartitioner interface for the CloudBalance problem. ```java public class CloudBalancePartitioner implements SolutionPartitioner { private int partCount = 4; private int minimumProcessListSize = 75; @Override public List splitWorkingSolution(ScoreDirector scoreDirector, Integer runnablePartThreadLimit) { CloudBalance originalSolution = scoreDirector.getWorkingSolution(); List originalComputerList = originalSolution.getComputerList(); List originalProcessList = originalSolution.getProcessList(); int partCount = this.partCount; if (originalProcessList.size() / partCount < minimumProcessListSize) { partCount = originalProcessList.size() / minimumProcessListSize; } List partList = new ArrayList<>(partCount); for (int i = 0; i < partCount; i++) { CloudBalance partSolution = new CloudBalance(originalSolution.getId(), new ArrayList<>(originalComputerList.size() / partCount + 1), new ArrayList<>(originalProcessList.size() / partCount + 1)); partList.add(partSolution); } int partIndex = 0; Map> idToPartIndexAndComputerMap = new HashMap<>(originalComputerList.size()); for (CloudComputer originalComputer : originalComputerList) { CloudBalance part = partList.get(partIndex); CloudComputer computer = new CloudComputer( originalComputer.getId(), originalComputer.getCpuPower(), originalComputer.getMemory(), originalComputer.getNetworkBandwidth(), originalComputer.getCost()); part.getComputerList().add(computer); idToPartIndexAndComputerMap.put(computer.getId(), Pair.of(partIndex, computer)); partIndex = (partIndex + 1) % partList.size(); } partIndex = 0; for (CloudProcess originalProcess : originalProcessList) { CloudBalance part = partList.get(partIndex); CloudProcess process = new CloudProcess( originalProcess.getId(), originalProcess.getRequiredCpuPower(), originalProcess.getRequiredMemory(), originalProcess.getRequiredNetworkBandwidth()); part.getProcessList().add(process); if (originalProcess.getComputer() != null) { Pair partIndexAndComputer = idToPartIndexAndComputerMap.get( originalProcess.getComputer().getId()); if (partIndexAndComputer == null) { throw new IllegalStateException("The initialized process (" + originalProcess + ") has a computer (" + originalProcess.getComputer() + ") which doesn't exist in the originalSolution (" + originalSolution + ")."); } if (partIndex != partIndexAndComputer.getLeft().intValue()) { throw new IllegalStateException("The initialized process (" + originalProcess + ") with partIndex (" + partIndex + ") has a computer (" + originalProcess.getComputer() + ") which belongs to another partIndex (" + partIndexAndComputer.getLeft() + ")."); } process.setComputer(partIndexAndComputer.getRight()); } partIndex = (partIndex + 1) % partList.size(); } return partList; } } ``` -------------------------------- ### Example JSON Response from Solve Endpoint Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html This is an example of a successful JSON response after the OptaPlanner service has solved the problem. It includes the assigned timeslots, rooms, and lessons, along with the final score. ```json HTTP/1.1 200 Content-Type: application/json ... {"timeslotList":...,"roomList":...,"lessonList":[{"id":1,"subject":"Math","teacher":"A. Turing","studentGroup":"9th grade","timeslot":{"dayOfWeek":"MONDAY","startTime":"08:30:00","endTime":"09:30:00"},"room":{"name":"Room A"}},{"id":2,"subject":"Chemistry","teacher":"M. Curie","studentGroup":"9th grade","timeslot":{"dayOfWeek":"MONDAY","startTime":"09:30:00","endTime":"10:30:00"},"room":{"name":"Room A"}},{"id":3,"subject":"French","teacher":"M. Curie","studentGroup":"10th grade","timeslot":{"dayOfWeek":"MONDAY","startTime":"08:30:00","endTime":"09:30:00"},"room":{"name":"Room B"}},{"id":4,"subject":"History","teacher":"I. Jones","studentGroup":"10th grade","timeslot":{"dayOfWeek":"MONDAY","startTime":"09:30:00","endTime":"10:30:00"},"room":{"name":"Room B"}}],"score":"0hard/0soft"} ``` -------------------------------- ### CloudBalancingHelloWorld Main Class Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html The complete main class for the Cloud Balancing Hello World example. ```java public class CloudBalancingHelloWorld { public static void main(String[] args) { // Build the Solver SolverFactory solverFactory = SolverFactory.createFromXmlResource( "org/optaplanner/examples/cloudbalancing/solver/cloudBalancingSolverConfig.xml"); Solver solver = solverFactory.buildSolver(); // Load a problem with 400 computers and 1200 processes CloudBalance unsolvedCloudBalance = new CloudBalancingGenerator().createCloudBalance(400, 1200); // Solve the problem CloudBalance solvedCloudBalance = solver.solve(unsolvedCloudBalance); // Display the result System.out.println("\nSolved cloudBalance with 400 computers and 1200 processes:\n" + toDisplayString(solvedCloudBalance)); } ... } ``` -------------------------------- ### Example MoveListFactory Implementation Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html A concrete implementation of MoveListFactory for generating cloud computer change moves. ```java public class CloudComputerChangeMoveFactory implements MoveListFactory { @Override public List createMoveList(CloudBalance cloudBalance) { List moveList = new ArrayList<>(); List cloudComputerList = cloudBalance.getComputerList(); for (CloudProcess cloudProcess : cloudBalance.getProcessList()) { for (CloudComputer cloudComputer : cloudComputerList) { moveList.add(new CloudComputerChangeMove(cloudProcess, cloudComputer)); } } return moveList; } } ``` -------------------------------- ### Integrate Prometheus registry Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Example of setting up a Prometheus registry and exposing it via an HTTP server. ```java PrometheusMeterRegistry prometheusRegistry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT); try { HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0); server.createContext("/prometheus", httpExchange -> { String response = prometheusRegistry.scrape(); (1) httpExchange.sendResponseHeaders(200, response.getBytes().length); try (OutputStream os = httpExchange.getResponseBody()) { os.write(response.getBytes()); } }); new Thread(server::start).start(); } catch (IOException e) { throw new RuntimeException(e); } Metrics.addRegistry(prometheusRegistry); ``` -------------------------------- ### Simple Construction Heuristic Configuration Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Use this for basic construction heuristic setup with a default entity placer. ```xml ALLOCATE_ENTITY_FROM_QUEUE ``` -------------------------------- ### Simplest Constraint Stream Example Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html This example shows the most basic constraint stream, starting with `forEach` and ending with a `penalize` operation to penalize each initialized `Shift` instance. ```java private Constraint penalizeInitializedShifts(ConstraintFactory factory) { return factory.forEach(Shift.class) .penalize(HardSoftScore.ONE_SOFT) .asConstraint("Initialized shift"); } ``` -------------------------------- ### Example Solver Logging Output Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Observe solver progress, phase completion, and step execution with debug and info logging levels. ```log INFO Solving started: time spent (3), best score (-4init/0), random (JDK with seed 0). DEBUG CH step (0), time spent (5), score (-3init/0), selected move count (1), picked move (Queen-2 {null -> Row-0}). DEBUG CH step (1), time spent (7), score (-2init/0), selected move count (3), picked move (Queen-1 {null -> Row-2}). DEBUG CH step (2), time spent (10), score (-1init/0), selected move count (4), picked move (Queen-3 {null -> Row-3}). DEBUG CH step (3), time spent (12), score (-1), selected move count (4), picked move (Queen-0 {null -> Row-1}). INFO Construction Heuristic phase (0) ended: time spent (12), best score (-1), score calculation speed (9000/sec), step total (4). DEBUG LS step (0), time spent (19), score (-1), best score (-1), accepted/selected move count (12/12), picked move (Queen-1 {Row-2 -> Row-3}). DEBUG LS step (1), time spent (24), score (0), new best score (0), accepted/selected move count (9/12), picked move (Queen-3 {Row-3 -> Row-2}). INFO Local Search phase (1) ended: time spent (24), best score (0), score calculation speed (4000/sec), step total (2). INFO Solving ended: time spent (24), best score (0), score calculation speed (7000/sec), phase total (2), environment mode (REPRODUCIBLE). ``` -------------------------------- ### Implement NQueensEasyScoreCalculator Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Example implementation of the EasyScoreCalculator for the N Queens problem. ```java public class NQueensEasyScoreCalculator implements EasyScoreCalculator { @Override public SimpleScore calculateScore(NQueens nQueens) { int n = nQueens.getN(); List queenList = nQueens.getQueenList(); int score = 0; for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { Queen leftQueen = queenList.get(i); Queen rightQueen = queenList.get(j); if (leftQueen.getRow() != null && rightQueen.getRow() != null) { if (leftQueen.getRowIndex() == rightQueen.getRowIndex()) { score--; } if (leftQueen.getAscendingDiagonalIndex() == rightQueen.getAscendingDiagonalIndex()) { score--; } if (leftQueen.getDescendingDiagonalIndex() == rightQueen.getDescendingDiagonalIndex()) { score--; } } } } return SimpleScore.valueOf(score); } } ``` -------------------------------- ### Combine Partitioned and Non-Partitioned Search Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Configuration example showing a Partitioned Search phase followed by a non-partitioned Local Search phase. ```xml ...CloudBalancePartitioner 60 ``` -------------------------------- ### Configure a ChangeMoveSelector Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Examples of simple and advanced configurations for the ChangeMoveSelector. ```xml ``` ```xml ... ...Lecture ... ... ... ``` -------------------------------- ### Simple Allocate From Pool Configuration Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Use this configuration to enable the ALLOCATE_FROM_POOL construction heuristic. It provides a basic setup for initializing a solution. ```xml ALLOCATE_FROM_POOL ``` -------------------------------- ### Construction Heuristic for Multiple Entity Classes (CatEntity) Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Example of configuring a construction heuristic for a specific entity class, 'CatEntity'. ```xml ...CatEntity PHASE ... ``` -------------------------------- ### Configure Variable Neighborhood Descent Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Provides both simple and advanced configuration examples for the Variable Neighborhood Descent algorithm. ```xml VARIABLE_NEIGHBORHOOD_DESCENT ``` ```xml ORIGINAL ... HILL_CLIMBING FIRST_LAST_STEP_SCORE_IMPROVING ``` -------------------------------- ### Advanced Partitioned Search Configuration Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Advanced setup including thread limits and custom phase definitions for construction heuristics and local search. ```xml ... org.optaplanner.examples.cloudbalancing.optional.partitioner.CloudBalancePartitioner 4 ... ... ``` -------------------------------- ### Construction Heuristic for Multiple Entity Classes (DogEntity) Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Example of configuring a construction heuristic for a specific entity class, 'DogEntity'. ```xml ...DogEntity PHASE ... ``` -------------------------------- ### Interpret Solving Log Output Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Example of the info log output showing the progress and results of the OptaPlanner solving process. ```text ... Solving started: time spent (33), best score (-8init/0hard/0soft), environment mode (REPRODUCIBLE), random (JDK with seed 0). ... Construction Heuristic phase (0) ended: time spent (73), best score (0hard/0soft), score calculation speed (459/sec), step total (4). ... Local Search phase (1) ended: time spent (5000), best score (0hard/0soft), score calculation speed (28949/sec), step total (28398). ... Solving ended: time spent (5000), best score (0hard/0soft), score calculation speed (28524/sec), phase total (2), environment mode (REPRODUCIBLE). ``` -------------------------------- ### Implement ConstraintMatchAwareIncrementalScoreCalculator in Machine Reassignment Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html A concrete implementation example showing how to calculate constraint matches and indictments within the machine reassignment problem. ```java public class MachineReassignmentIncrementalScoreCalculator implements ConstraintMatchAwareIncrementalScoreCalculator { ... @Override public void resetWorkingSolution(MachineReassignment workingSolution, boolean constraintMatchEnabled) { resetWorkingSolution(workingSolution); // ignore constraintMatchEnabled, it is always presumed enabled } @Override public Collection> getConstraintMatchTotals() { ConstraintMatchTotal maximumCapacityMatchTotal = new DefaultConstraintMatchTotal<>(CONSTRAINT_PACKAGE, "maximumCapacity", HardSoftLongScore.ZERO); ... for (MrMachineScorePart machineScorePart : machineScorePartMap.values()) { for (MrMachineCapacityScorePart machineCapacityScorePart : machineScorePart.machineCapacityScorePartList) { if (machineCapacityScorePart.maximumAvailable < 0L) { maximumCapacityMatchTotal.addConstraintMatch( Arrays.asList(machineCapacityScorePart.machineCapacity), HardSoftLongScore.valueOf(machineCapacityScorePart.maximumAvailable, 0)); } } } ... List> constraintMatchTotalList = new ArrayList<>(4); constraintMatchTotalList.add(maximumCapacityMatchTotal); ... return constraintMatchTotalList; } @Override public Map> getIndictmentMap() { return null; // Calculate it non-incrementally from getConstraintMatchTotals() } } ``` -------------------------------- ### Configure cloudBalancingSolverConfig.xml Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html The complete XML configuration file for the Cloud Balancing example, defining domain classes, score calculation, and termination limits. ```xml org.optaplanner.examples.cloudbalancing.domain.CloudBalance org.optaplanner.examples.cloudbalancing.domain.CloudProcess org.optaplanner.examples.cloudbalancing.optional.score.CloudBalancingEasyScoreCalculator 30 ``` -------------------------------- ### Implement Cloud Balancing ProblemChange Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Example of a ProblemChange implementation for the cloud balancing use case. It demonstrates deleting a computer and updating associated processes. ```java public void deleteComputer(final CloudComputer computer) { solver.addProblemChange((cloudBalance, problemChangeDirector) -> { CloudComputer workingComputer = problemChangeDirector.lookUpWorkingObject(computer); if (workingComputer == null) { throw new IllegalStateException("A computer " + computer + " does not exist. Maybe it has been already deleted."); } // First remove the problem fact from all planning entities that use it for (CloudProcess process : cloudBalance.getProcessList()) { if (process.getComputer() == workingComputer) { problemChangeDirector.changeVariable(process, "computer", workingProcess -> workingProcess.setComputer(null)); } } // A SolutionCloner does not clone problem fact lists (such as computerList) // Shallow clone the computerList so only workingSolution is affected, not bestSolution or guiSolution ArrayList computerList = new ArrayList<>(cloudBalance.getComputerList()); cloudBalance.setComputerList(computerList); // Remove the problem fact itself problemChangeDirector.removeProblemFact(workingComputer, computerList::remove); }); } ``` -------------------------------- ### Standstill Interface Example - TSP Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Interface used by both anchors and planning entities in TSP, defining a common method to get the City. This is the return type for chained planning variables. ```java public interface Standstill { City getCity(); } ``` -------------------------------- ### Run Simple Benchmark with PlannerBenchmarkFactory Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Create a PlannerBenchmarkFactory from a solver configuration XML, load datasets, build a PlannerBenchmark, and run it to generate a report. Ensure the solver configuration includes a termination setting. ```java PlannerBenchmarkFactory benchmarkFactory = PlannerBenchmarkFactory.createFromSolverConfigXmlResource( "org/optaplanner/examples/cloudbalancing/solver/cloudBalancingSolverConfig.xml"); CloudBalance dataset1 = ...; CloudBalance dataset2 = ...; CloudBalance dataset3 = ...; PlannerBenchmark benchmark = benchmarkFactory.buildPlannerBenchmark( dataset1, dataset2, dataset3); benchmark.benchmarkAndShowReportInBrowser(); ``` -------------------------------- ### Domicile Class Example - TSP Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Example of a Domicile class, which serves as an anchor in TSP problems. It implements the Standstill interface. ```java public class Domicile ... implements Standstill { ... public City getCity() {...} } ``` -------------------------------- ### Configure Logback for OptaPlanner Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Create this file in src/main/resource/logback.xml to enable console logging for OptaPlanner. ```xml %d{HH:mm:ss.SSS} [%-12.12t] %-5p %m%n ``` -------------------------------- ### Build PlannerBenchmark from XML Resource Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Instantiate a PlannerBenchmarkFactory from an XML resource and build a PlannerBenchmark instance. Then, run the benchmark and display the report in a browser. ```java PlannerBenchmarkFactory benchmarkFactory = PlannerBenchmarkFactory.createFromXmlResource( "org/optaplanner/examples/cloudbalancing/benchmark/cloudBalancingBenchmarkConfig.xml"); PlannerBenchmark benchmark = benchmarkFactory.buildPlannerBenchmark(); benchmark.benchmarkAndShowReportInBrowser(); ``` -------------------------------- ### Create Java Application with OptaPlanner Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html This is the main application class that sets up the SolverFactory, loads demo data, solves the timetable problem, and prints the solution. It configures the solver with solution and entity classes, a constraint provider, and a termination limit. ```java package org.acme.schooltimetabling; import java.time.DayOfWeek; import java.time.Duration; import java.time.LocalTime; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import org.acme.schooltimetabling.domain.Lesson; import org.acme.schooltimetabling.domain.Room; import org.acme.schooltimetabling.domain.TimeTable; import org.acme.schooltimetabling.domain.Timeslot; import org.acme.schooltimetabling.solver.TimeTableConstraintProvider; import org.optaplanner.core.api.solver.Solver; import org.optaplanner.core.api.solver.SolverFactory; import org.optaplanner.core.config.solver.SolverConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TimeTableApp { private static final Logger LOGGER = LoggerFactory.getLogger(TimeTableApp.class); public static void main(String[] args) { SolverFactory solverFactory = SolverFactory.create(new SolverConfig() .withSolutionClass(TimeTable.class) .withEntityClasses(Lesson.class) .withConstraintProviderClass(TimeTableConstraintProvider.class) // The solver runs only for 5 seconds on this small dataset. // It's recommended to run for at least 5 minutes ("5m") otherwise. .withTerminationSpentLimit(Duration.ofSeconds(5))); // Load the problem TimeTable problem = generateDemoData(); // Solve the problem Solver solver = solverFactory.buildSolver(); TimeTable solution = solver.solve(problem); // Visualize the solution printTimetable(solution); } public static TimeTable generateDemoData() { List timeslotList = new ArrayList<>(10); timeslotList.add(new Timeslot(DayOfWeek.MONDAY, LocalTime.of(8, 30), LocalTime.of(9, 30))); timeslotList.add(new Timeslot(DayOfWeek.MONDAY, LocalTime.of(9, 30), LocalTime.of(10, 30))); timeslotList.add(new Timeslot(DayOfWeek.MONDAY, LocalTime.of(10, 30), LocalTime.of(11, 30))); timeslotList.add(new Timeslot(DayOfWeek.MONDAY, LocalTime.of(13, 30), LocalTime.of(14, 30))); timeslotList.add(new Timeslot(DayOfWeek.MONDAY, LocalTime.of(14, 30), LocalTime.of(15, 30))); timeslotList.add(new Timeslot(DayOfWeek.TUESDAY, LocalTime.of(8, 30), LocalTime.of(9, 30))); timeslotList.add(new Timeslot(DayOfWeek.TUESDAY, LocalTime.of(9, 30), LocalTime.of(10, 30))); timeslotList.add(new Timeslot(DayOfWeek.TUESDAY, LocalTime.of(10, 30), LocalTime.of(11, 30))); timeslotList.add(new Timeslot(DayOfWeek.TUESDAY, LocalTime.of(13, 30), LocalTime.of(14, 30))); timeslotList.add(new Timeslot(DayOfWeek.TUESDAY, LocalTime.of(14, 30), LocalTime.of(15, 30))); List roomList = new ArrayList<>(3); roomList.add(new Room("Room A")); roomList.add(new Room("Room B")); roomList.add(new Room("Room C")); List lessonList = new ArrayList<>(); long id = 0; lessonList.add(new Lesson(id++, "Math", "A. Turing", "9th grade")); lessonList.add(new Lesson(id++, "Math", "A. Turing", "9th grade")); lessonList.add(new Lesson(id++, "Physics", "M. Curie", "9th grade")); lessonList.add(new Lesson(id++, "Chemistry", "M. Curie", "9th grade")); lessonList.add(new Lesson(id++, "Biology", "C. Darwin", "9th grade")); lessonList.add(new Lesson(id++, "History", "I. Jones", "9th grade")); lessonList.add(new Lesson(id++, "English", "I. Jones", "9th grade")); lessonList.add(new Lesson(id++, "English", "I. Jones", "9th grade")); lessonList.add(new Lesson(id++, "Spanish", "P. Cruz", "9th grade")); lessonList.add(new Lesson(id++, "Spanish", "P. Cruz", "9th grade")); lessonList.add(new Lesson(id++, "Math", "A. Turing", "10th grade")); lessonList.add(new Lesson(id++, "Math", "A. Turing", "10th grade")); lessonList.add(new Lesson(id++, "Math", "A. Turing", "10th grade")); lessonList.add(new Lesson(id++, "Physics", "M. Curie", "10th grade")); lessonList.add(new Lesson(id++, "Chemistry", "M. Curie", "10th grade")); return new TimeTable(timeslotList, roomList, lessonList); } private static void printTimetable(TimeTable timeTable) { // This is a simplified print method. For a real application, you might want to use a UI framework. LOGGER.info("Solution not visualized, console output is too limited."); // Example of how to access the solution: // Map> lessonsByRoom = timeTable.getLessonList().stream() // .collect(Collectors.groupingBy(lesson -> lesson.getRoom().getName())); // lessonsByRoom.forEach((roomName, lessons) -> { // LOGGER.info("Lessons in {}:\n", roomName); // lessons.forEach(lesson -> LOGGER.info(" - {}\n", lesson)); // }); } } ``` -------------------------------- ### Implement CustomerNearbyDistanceMeter Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Example implementation of the NearbyDistanceMeter interface for VRP scenarios. ```java public class CustomerNearbyDistanceMeter implements NearbyDistanceMeter { public double getNearbyDistance(Customer origin, LocationAware destination) { return origin.getDistanceTo(destination); } } ``` -------------------------------- ### Build OptaPlanner with Maven Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Compile the project using Maven. Note that the first build may take time to download dependencies. ```bash $ cd optaplanner $ mvn clean install -DskipTests ... ``` -------------------------------- ### Configure SelectionOrder in a Selector Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Example of setting the selection order to RANDOM within a changeMoveSelector. ```xml ... RANDOM ... ``` -------------------------------- ### Configure module-info.java for OptaPlanner Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Required to open domain, constraint, and configuration packages to OptaPlanner when using the Java Platform Module System. ```java module org.optaplanner.cloudbalancing { requires org.optaplanner.core; ... opens org.optaplanner.examples.cloudbalancing; // Solver configuration opens org.optaplanner.examples.cloudbalancing.domain; // Domain classes opens org.optaplanner.examples.cloudbalancing.score; // Constraints ... } ``` -------------------------------- ### View Timetable Console Output Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Example of the pretty-printed timetable output generated by the printTimetable method. ```text ... INFO | | Room A | Room B | Room C | INFO |------------|------------|------------|------------| INFO | MON 08:30 | English | Math | | INFO | | I. Jones | A. Turing | | INFO | | 9th grade | 10th grade | | INFO |------------|------------|------------|------------| INFO | MON 09:30 | History | Physics | | INFO | | I. Jones | M. Curie | | INFO | | 9th grade | 10th grade | | ... ``` -------------------------------- ### Preparing Test Data for ConstraintVerifier Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Setup of planning entities and dependencies required for the unit test. ```java Row row1 = new Row(0); Column column1 = new Column(0); Column column2 = new Column(1); Queen queen1 = new Queen(0, row1, column1); Queen queen2 = new Queen(1, row1, column2); ``` -------------------------------- ### Logback Configuration for OptaPlanner Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Configure the logging level for the 'org.optaplanner' package in your logback.xml file. ```xml ... ``` -------------------------------- ### Custom Move Implementation Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Example of extending AbstractMove to implement a custom change move for cloud balancing. ```java public class CloudComputerChangeMove extends AbstractMove { private CloudProcess cloudProcess; private CloudComputer toCloudComputer; public CloudComputerChangeMove(CloudProcess cloudProcess, CloudComputer toCloudComputer) { this.cloudProcess = cloudProcess; this.toCloudComputer = toCloudComputer; } @Override protected void doMoveOnGenuineVariables(ScoreDirector scoreDirector) { scoreDirector.beforeVariableChanged(cloudProcess, "computer"); cloudProcess.setComputer(toCloudComputer); scoreDirector.afterVariableChanged(cloudProcess, "computer"); } // ... } ``` -------------------------------- ### Implement SolverEventListener Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Example of adding a listener to handle best solution changes, with a check for solution feasibility. ```java solver.addEventListener(new SolverEventListener() { public void bestSolutionChanged(BestSolutionChangedEvent event) { // Ignore infeasible (including uninitialized) solutions if (event.getNewBestSolution().getScore().isFeasible()) { ... } } }); ``` -------------------------------- ### Benchmark Configuration for Custom Solution File IO Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Configure the benchmark to use a custom solution file IO for formats like TXT or binary. Specify the custom solutionFileIOClass and the inputSolutionFile. ```xml org.optaplanner.examples.machinereassignment.persistence.MachineReassignmentFileIO data/machinereassignment/import/model_a1_1.txt ... ``` -------------------------------- ### Define Drools Score Rules Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Example DRL rules for hard and soft constraints using a ScoreHolder. ```DRL global HardSoftScoreHolder scoreHolder; rule "requiredCpuPowerTotal" when ... then scoreHolder.addHardConstraintMatch(...); end ... rule "computerCost" when ... then scoreHolder.addSoftConstraintMatch(...); end ``` -------------------------------- ### Initialize TimeTable SolverFactory Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Configures the solver with solution, entity, and constraint provider classes, and sets a 5-second termination limit. ```java SolverFactory solverFactory = SolverFactory.create(new SolverConfig() .withSolutionClass(TimeTable.class) .withEntityClasses(Lesson.class) .withConstraintProviderClass(TimeTableConstraintProvider.class) // The solver runs only for 5 seconds on this small dataset. // It's recommended to run for at least 5 minutes ("5m") otherwise. .withTerminationSpentLimit(Duration.ofSeconds(5))); ``` -------------------------------- ### Build Planner Benchmark with Datasets Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Load datasets in advance and pass them to the buildPlannerBenchmark method. This is an alternative to serializing datasets to local files. ```java PlannerBenchmark plannerBenchmark = benchmarkFactory.buildPlannerBenchmark(dataset1, dataset2, dataset3); ``` -------------------------------- ### Default Constraint Justification Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Example of a standard constraint definition where the indicted objects include both the Vehicle and the demand Integer. ```java protected Constraint vehicleCapacity(ConstraintFactory factory) { return factory.forEach(Customer.class) .filter(customer -> customer.getVehicle() != null) .groupBy(Customer::getVehicle, sum(Customer::getDemand)) .filter((vehicle, demand) -> demand > vehicle.getCapacity()) .penalizeLong(HardSoftLongScore.ONE_HARD, (vehicle, demand) -> demand - vehicle.getCapacity()) .asConstraint("vehicleCapacity"); } ``` -------------------------------- ### Implement ConstraintProvider in Java Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Implement the `ConstraintProvider` interface to define custom constraints for your OptaPlanner solution. This example shows how to define a single constraint that penalizes every shift. ```java public class MyConstraintProvider implements ConstraintProvider { @Override public Constraint[] defineConstraints(ConstraintFactory factory) { return new Constraint[] { penalizeEveryShift(factory) }; } private Constraint penalizeEveryShift(ConstraintFactory factory) { return factory.forEach(Shift.class) .penalize(HardSoftScore.ONE_SOFT) .asConstraint("Penalize a shift"); } } ``` -------------------------------- ### Configure Allocate To Value From Queue Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Configures the Allocate To Value From Queue algorithm, ranging from simple to advanced setups. ```xml ALLOCATE_TO_VALUE_FROM_QUEUE ``` ```xml ALLOCATE_TO_VALUE_FROM_QUEUE DECREASING_DIFFICULTY_IF_AVAILABLE INCREASING_STRENGTH_IF_AVAILABLE ``` ```xml PHASE SORTED INCREASING_STRENGTH PHASE SORTED DECREASING_DIFFICULTY ``` -------------------------------- ### Generate Quarkus Project via Maven CLI Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Use this command to bootstrap a new Quarkus project with the necessary OptaPlanner extensions. ```bash $ mvn io.quarkus:quarkus-maven-plugin:3.0.0.Final:create \ -DprojectGroupId=org.acme \ -DprojectArtifactId=optaplanner-quickstart \ -Dextensions="resteasy,resteasy-jackson,optaplanner-quarkus,optaplanner-quarkus-jackson" \ -DnoExamples $ cd optaplanner-quickstart ``` -------------------------------- ### Marshal Score with JAXB Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Use ScoreJaxbAdapter to correctly marshal scores to XML or JSON. This example shows the adapter for HardSoftScore. ```java @PlanningSolution @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class CloudBalance { @PlanningScore @XmlJavaTypeAdapter(HardSoftScoreJaxbAdapter.class) private HardSoftScore score; ... } ``` -------------------------------- ### Benchmark Configuration XML Structure Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html An example of a benchmark configuration XML file. It defines benchmark directories, inherited solver configurations, and individual solver benchmarks with specific configurations and input solution files. ```xml local/data/nqueens ... ... data/cloudbalancing/unsolved/100computers-300processes.json data/cloudbalancing/unsolved/200computers-600processes.json Tabu Search ... Simulated Annealing ... Late Acceptance ... ``` -------------------------------- ### Execute Solver and Visualize Solution Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Loads the problem data, executes the solver, and prints the resulting timetable. ```java // Load the problem TimeTable problem = generateDemoData(); // Solve the problem Solver solver = solverFactory.buildSolver(); TimeTable solution = solver.solve(problem); // Visualize the solution printTimetable(solution); ``` -------------------------------- ### Gradle build.gradle for OptaPlanner Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Configure your Gradle build.gradle to include OptaPlanner core, test, and logging dependencies. Utilize the optaplanner-bom for version management. ```gradle plugins { id "java" id "application" } def optaplannerVersion = "9.44.0.Final" def logbackVersion = "1.2.9" group = "org.acme" version = "1.0-SNAPSHOT" repositories { mavenCentral() } dependencies { implementation platform("org.optaplanner:optaplanner-bom:${optaplannerVersion}") implementation "org.optaplanner:optaplanner-core" testImplementation "org.optaplanner:optaplanner-test" runtimeOnly "ch.qos.logback:logback-classic:${logbackVersion}" } java { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } compileJava { options.encoding = "UTF-8" options.compilerArgs << "-parameters" } compileTestJava { options.encoding = "UTF-8" } application { mainClass = "org.acme.schooltimetabling.TimeTableApp" } test { // Log the test execution results. testLogging { events "passed", "skipped", "failed" } } ``` -------------------------------- ### Configure Best Score Termination Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Examples of terminating the solver when a specific score limit is reached for different score types. ```xml 0 ``` ```xml 0hard/-5000soft ``` ```xml [0/0/0]hard/[-5000]soft ``` -------------------------------- ### Implement a score rule in DRL Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Example of a score constraint rule that uses the scoreHolder global to update the solution score. ```drl rule "Horizontal conflict" when Queen($id : id, row != null, $i : rowIndex) Queen(id > $id, rowIndex == $i) then scoreHolder.addConstraintMatch(kcontext, -1); end ``` -------------------------------- ### Clone OptaPlanner Repository Source: https://docs.optaplanner.org/9.44.0.Final/optaplanner-docs/html_single/index.html Use this command to clone the OptaPlanner source code from GitHub. ```bash $ git clone https://github.com/kiegroup/optaplanner.git ... ```