### Application Response Example Source: https://docs.timefold.ai/timefold-solver/latest/quickstart/quarkus/quarkus-quickstart Example output from the REST service after assigning lessons to time slots and rooms. ```json HTTP/1.1 200 Content-Type: application/json ... {"timeslots":...,"rooms":...,"lessons":[{"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"} ``` -------------------------------- ### Debug Logging: Solver Steps Source: https://docs.timefold.ai/timefold-solver/latest/quickstart/quarkus/quarkus-quickstart Example output when using debug logging, showing solver start information and details about CH steps, including time spent, score, and selected moves. ```log ... Solving started: time spent (67), best score (0hard/0soft), environment mode (PHASE_ASSERT), random (JDK with seed 0). ... CH step (0), time spent (128), score (0hard/0soft), selected move count (15), picked move ([Math(101) {null -> Room A}, Math(101) {null -> MONDAY 08:30}]). ... CH step (1), time spent (145), score (0hard/0soft), selected move count (15), picked move ([Physics(102) {null -> Room A}, Physics(102) {null -> MONDAY 09:30}]). ... ``` -------------------------------- ### Clone Timefold Quickstarts Repository Source: https://docs.timefold.ai/timefold-solver/latest/quickstart/quarkus/quarkus-quickstart Clone the Timefold quickstarts repository to access the completed example application. ```shell git clone https://github.com/TimefoldAI/timefold-quickstarts ``` -------------------------------- ### UniConstraintStream Example Source: https://docs.timefold.ai/timefold-solver/latest/constraints-and-score/score-calculation Demonstrates a simple UniConstraintStream starting with a forEach operation. ```java private Constraint doNotAssignAnn(ConstraintFactory factory) { return factory.forEach(Shift.class) // Returns UniStream. ... } ``` -------------------------------- ### Basic MoveTester Setup Source: https://docs.timefold.ai/timefold-solver/latest/optimization-algorithms/neighborhoods Illustrates the initial setup for the MoveTester API using a fluent builder pattern. This requires defining the solution and entity classes, and obtaining a working solution instance. ```java // Timetable is the solution class, Lesson is a planning entity class. var solutionMetaModel = PlanningSolutionMetaModel.of(Timetable.class, Lesson.class); var tester = MoveTester.build(solutionMetaModel); var context = tester.using(solution); var move = ...; // Move you wish to test. context.execute(move); ``` -------------------------------- ### Start Application with Maven Source: https://docs.timefold.ai/timefold-solver/latest/quickstart/quarkus/quarkus-quickstart Starts the Quarkus application in development mode using Maven. ```shell $ mvn compile quarkus:dev ``` -------------------------------- ### Start Application with Gradle Source: https://docs.timefold.ai/timefold-solver/latest/quickstart/quarkus/quarkus-quickstart Starts the Quarkus application in development mode using Gradle. ```shell $ gradle --console=plain quarkusDev ``` -------------------------------- ### Example Console Output of Timetable Application Source: https://docs.timefold.ai/timefold-solver/latest/quickstart/hello-world/hello-world-quickstart This is an example of the console output when running the Timetable application. It displays the schedule and indicates the solving process. ```log ... 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 | ... ``` -------------------------------- ### Install Java using Sdkman Source: https://docs.timefold.ai/timefold-solver/latest/quickstart/quarkus/quarkus-quickstart Install Java 21+ using Sdkman, a tool for managing parallel versions of multiple Software Development Kits. ```shell curl -s "https://get.sdkman.io" | bash sdk install java ``` -------------------------------- ### Install Java using Sdkman Source: https://docs.timefold.ai/timefold-solver/latest/quickstart/spring-boot/spring-boot-quickstart Install Java 21+ using Sdkman, a tool for managing parallel versions of multiple SDKs. ```shell $ curl -s "https://get.sdkman.io" | bash $ sdk install java ``` -------------------------------- ### Solver Configuration XML Example Source: https://docs.timefold.ai/timefold-solver/latest/using-timefold-solver/configuration An example of a Timefold Solver configuration XML file, defining the solution class, entity class, score director factory, and optimization algorithms. ```xml org.acme.schooltimetabling.domain.Timetable org.acme.schooltimetabling.domain.Lesson org.acme.schooltimetabling.solver.TimetableConstraintProvider ... ... ... ``` -------------------------------- ### Example Move Evaluation Speed Log Source: https://docs.timefold.ai/timefold-solver/latest/quickstart/quarkus/quarkus-quickstart An example of the 'move evaluation speed' log output, which helps assess the performance impact of adding constraints. ```log ... Solving ended: ..., move evaluation speed (29455/sec), ... ``` -------------------------------- ### Simple Strongest Fit Configuration Source: https://docs.timefold.ai/timefold-solver/latest/optimization-algorithms/construction-heuristics Configures the STRONGEST_FIT construction heuristic. Use this for a basic setup. ```xml STRONGEST_FIT ``` -------------------------------- ### Allocate From Pool Simple Configuration Source: https://docs.timefold.ai/timefold-solver/latest/optimization-algorithms/construction-heuristics Configures the ALLOCATE_FROM_POOL construction heuristic. Use this for a basic setup. ```xml ALLOCATE_FROM_POOL ``` -------------------------------- ### Configure Solver Spent Limit Source: https://docs.timefold.ai/timefold-solver/latest/integration/integration Example of configuring different spent limits for two solvers in the application.properties file. ```properties timefold.solver.solverA.termination.spent-limit=10s timefold.solver.solverB.termination.spent-limit=5m ``` -------------------------------- ### Server-Side Solver Logs Source: https://docs.timefold.ai/timefold-solver/latest/quickstart/quarkus/quarkus-quickstart Example log output from the server showing the Timefold Solver's activity during the solving process. ```log ... Solving started: time spent (33), best score (0hard/0soft), environment mode (PHASE_ASSERT), random (JDK with seed 0). ... Construction Heuristic phase (0) ended: time spent (73), best score (0hard/0soft), move evaluation speed (459/sec), step total (4). ... Local Search phase (1) ended: time spent (5000), best score (0hard/0soft), move evaluation speed (28949/sec), step total (28398). ... Solving ended: time spent (5000), best score (0hard/0soft), move evaluation speed (28524/sec), phase total (2), environment mode (PHASE_ASSERT). ``` -------------------------------- ### Example ChangeMove Implementation Source: https://docs.timefold.ai/timefold-solver/latest/optimization-algorithms/neighborhoods A concrete implementation of a Move interface that changes the value of a basic planning variable, assigning a timeslot to a lesson. ```java public final class ChangeMove implements Move { private final PlanningVariableMetaModel timeslotVariable; private final Lesson lesson; private final Timeslot timeslot; public ChangeMove(PlanningVariableMetaModel timeslotVariable, Lesson lesson, Timeslot timeslot) { this.timeslotVariable = Objects.requireNonNull(timeslotVariable); this.lesson = Objects.requireNonNull(lesson); this.timeslot = timeslot; } @Override public void execute(MutableSolutionView solutionView) { solutionView.changeVariable(timeslotVariable, lesson, timeslot); } @Override public ChangeMove rebase(Lookup lookup) { return new ChangeMove(timeslotVariable, lookup.lookUpWorkingObject(lesson), lookup.lookUpWorkingObject(timeslot)); } @Override public Collection getPlanningEntities() { return Collections.singletonList(lesson); } @Override public Collection getPlanningValues() { return Collections.singletonList(timeslot); } @Override public boolean equals(Object o) { return o instanceof ChangeMove other && Objects.equals(timeslotVariable, other.timeslotVariable) && Objects.equals(lesson, other.lesson) && Objects.equals(timeslot, other.timeslot); } @Override public int hashCode() { return Objects.hash(timeslotVariable, lesson, timeslot); } @Override public String toString() { return lesson + " -> " + timeslot; } } ``` -------------------------------- ### Configure Additional Solver Metrics Source: https://docs.timefold.ai/timefold-solver/latest/using-timefold-solver/running-the-solver Add a monitoring section to your solver configuration XML to enable specific metrics. This example shows how to enable BEST_SCORE and SCORE_CALCULATION_COUNT. ```xml BEST_SCORE SCORE_CALCULATION_COUNT ... ... ``` -------------------------------- ### Set up Prometheus Registry and HTTP Server Source: https://docs.timefold.ai/timefold-solver/latest/using-timefold-solver/running-the-solver This example demonstrates setting up a Prometheus Meter Registry and an HTTP server to expose Timefold Solver metrics. The metrics are scraped from the Prometheus registry and made available at the /prometheus endpoint. ```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); ``` -------------------------------- ### ValueRangeFactory with Integer Range and Increment Unit Source: https://docs.timefold.ai/timefold-solver/latest/using-timefold-solver/modeling-planning-problems Shows how to use ValueRangeFactory to create an integer ValueRange with a specified increment unit. This example creates a range of integers starting from 0, up to 10,000,000, with increments of 200. ```java @ValueRangeProvider public ValueRange getStockAmountRange() { // Range: 0, 200, 400, 600, ..., 9999600, 9999800, 10000000 return ValueRangeFactory.createIntValueRange(0, 10000000, 200); } ``` -------------------------------- ### Run a Simple Benchmark with Multiple Datasets Source: https://docs.timefold.ai/timefold-solver/latest/using-timefold-solver/benchmarking-and-tweaking Create a PlannerBenchmarkFactory from your solver configuration XML, load datasets, and build a benchmark to run. The benchmark report will be generated in 'local/benchmarkReport'. ```java PlannerBenchmarkFactory benchmarkFactory = PlannerBenchmarkFactory.createFromSolverConfigXmlResource( "org/acme/vehiclerouting/solverConfig.xml"); VehicleRoutePlan dataset1 = ...; VehicleRoutePlan dataset2 = ...; VehicleRoutePlan dataset3 = ...; PlannerBenchmark benchmark = benchmarkFactory.buildPlannerBenchmark(dataset1, dataset2, dataset3); benchmark.benchmark(); ``` -------------------------------- ### Configure and Run Planner Benchmark Source: https://docs.timefold.ai/timefold-solver/latest/using-timefold-solver/benchmarking-and-tweaking Instantiate a PlannerBenchmark using a factory created from an XML resource. This is the primary method for setting up and executing a benchmark run. ```java PlannerBenchmarkFactory benchmarkFactory = PlannerBenchmarkFactory.createFromXmlResource( "org/acme/vehiclerouting/benchmarkConfig.xml"); PlannerBenchmark benchmark = benchmarkFactory.buildPlannerBenchmark(); benchmark.benchmark(); ``` -------------------------------- ### Example Solver Logging Output Source: https://docs.timefold.ai/timefold-solver/latest/using-timefold-solver/running-the-solver Observe the solver's progress, phase transitions, and step-by-step move evaluations with debug logging enabled. This output is invaluable for identifying bottlenecks during development. ```log INFO Solving started: time spent (31), best score (0hard/0soft), environment mode (PHASE_ASSERT), move thread count (NONE), random (JDK with seed 0). INFO Problem scale: entity count (4), variable count (8), approximate value count (4), approximate problem scale (256). DEBUG CH step (0), time spent (47), score (0hard/0soft), selected move count (4), picked move ([Math(0) {null -> Room A}, Math(0) {null -> MONDAY 08:30}]). DEBUG CH step (1), time spent (50), score (0hard/0soft), selected move count (4), picked move ([Physics(1) {null -> Room A}, Physics(1) {null -> MONDAY 09:30}]). DEBUG CH step (2), time spent (51), score (-1hard/-1soft), selected move count (4), picked move ([Chemistry(2) {null -> Room B}, Chemistry(2) {null -> MONDAY 08:30}]). DEBUG CH step (3), time spent (52), score (-2hard/-1soft), selected move count (4), picked move ([Biology(3) {null -> Room A}, Biology(3) {null -> MONDAY 08:30}]). INFO Construction Heuristic phase (0) ended: time spent (53), best score (-2hard/-1soft), move evaluation speed (1066/sec), step total (4). DEBUG LS step (0), time spent (56), score (-2hard/0soft), new best score (-2hard/0soft), accepted/selected move count (1/1), picked move (Chemistry(2) {Room B, MONDAY 08:30} <-> Physics(1) {Room A, MONDAY 09:30}). DEBUG LS step (1), time spent (60), score (-2hard/1soft), new best score (-2hard/1soft), accepted/selected move count (1/2), picked move (Math(0) {Room A, MONDAY 08:30} <-> Physics(1) {Room B, MONDAY 08:30}). DEBUG LS step (2), time spent (60), score (-2hard/0soft), best score (-2hard/1soft), accepted/selected move count (1/1), picked move (Math(0) {Room B, MONDAY 08:30} <-> Physics(1) {Room A, MONDAY 08:30}). ... INFO Local Search phase (1) ended: time spent (100), best score (0hard/1soft), move evaluation speed (2021/sec), step total (59). INFO Solving ended: time spent (100), best score (0hard/1soft), move evaluation speed (1100/sec), phase total (2), environment mode (PHASE_ASSERT), move thread count (NONE). ``` -------------------------------- ### Build Planner Benchmark with Multiple Datasets Source: https://docs.timefold.ai/timefold-solver/latest/using-timefold-solver/benchmarking-and-tweaking Load multiple datasets in advance and pass them to the `buildPlannerBenchmark()` method. This is an alternative to using `` elements for each dataset. ```java PlannerBenchmark plannerBenchmark = benchmarkFactory.buildPlannerBenchmark(dataset1, dataset2, dataset3); ``` -------------------------------- ### Running the Maven Built Application Source: https://docs.timefold.ai/timefold-solver/latest/quickstart/hello-world/hello-world-quickstart Commands to build the project using Maven and then run the generated executable JAR. This demonstrates how to deploy and execute the standalone application. ```bash $ mvn clean install ... $ java -jar target/hello-world-run.jar ``` -------------------------------- ### Build Planner Benchmark from Freemarker XML Source: https://docs.timefold.ai/timefold-solver/latest/using-timefold-solver/benchmarking-and-tweaking Instantiate and build a PlannerBenchmark using the PlannerBenchmarkFactory, loading the configuration from a Freemarker XML resource. ```java PlannerBenchmarkFactory benchmarkFactory = PlannerBenchmarkFactory.createFromFreemarkerXmlResource( "org/acme/vehiclerouting/solverConfig.xml"); PlannerBenchmark benchmark = benchmarkFactory.buildPlannerBenchmark(); ``` -------------------------------- ### Custom Move Iterator Factory Example Source: https://docs.timefold.ai/timefold-solver/latest/optimization-algorithms/move-selector-reference An example implementation of MoveIteratorFactory that generates only possible assignment moves. It demonstrates how to calculate the size and create iterators for both original and random move selection. ```java public class PossibleAssignmentsOnlyMoveIteratorFactory implements MoveIteratorFactory { @Override public long getSize(ScoreDirector scoreDirector) { // In this case, we return the exact size, but an estimate can be used // if it too expensive to calculate or unknown long totalSize = 0L; var solution = scoreDirector.getWorkingSolution(); for (MyEntity entity : solution.getEntities()) { for (MyPlanningValue value : solution.getValues()) { if (entity.canBeAssigned(value)) { totalSize++; } } } return totalSize; } @Override public Iterator createOriginalMoveIterator(ScoreDirector scoreDirector) { // Only needed if selectionOrder is ORIGINAL or if it is cached var solution = scoreDirector.getWorkingSolution(); var entities = solution.getEntities(); var values = solution.getValues(); // Assumes each entity has at least one assignable value var firstEntityIndex = 0; var firstValueIndex = 0; while (!entities.get(firstEntityIndex).canBeAssigned(values.get(firstValueIndex))) { firstValueIndex++; } return new Iterator<>() { int nextEntityIndex = firstEntityIndex; int nextValueIndex = firstValueIndex; @Override public boolean hasNext() { return nextEntityIndex < entities.size(); } @Override public MyChangeMove next() { var selectedEntity = entities.get(nextEntityIndex); var selectedValue = values.get(nextValueIndex); nextValueIndex++; while (nextValueIndex < values.size() && !selectedEntity.canBeAssigned(values.get(nextValueIndex))) { nextValueIndex++; } if (nextValueIndex >= values.size()) { // value list exhausted, go to next entity nextEntityIndex++; if (nextEntityIndex < entities.size()) { nextValueIndex = 0; while (nextValueIndex < values.size() && !entities.get(nextEntityIndex).canBeAssigned(values.get(nextValueIndex))) { // Assumes each entity has at least one assignable value nextValueIndex++; } } } return new MyChangeMove(selectedEntity, selectedValue); } }; } @Override public Iterator createRandomMoveIterator(ScoreDirector scoreDirector, Random workingRandom) { // Not needed if selectionOrder is ORIGINAL or if it is cached var solution = scoreDirector.getWorkingSolution(); var entities = solution.getEntities(); var values = solution.getValues(); return new Iterator<>() { @Override public boolean hasNext() { return !entities.isEmpty(); } @Override public MyChangeMove next() { var selectedEntity = entities.get(workingRandom.nextInt(entities.size())); var selectedValue = values.get(workingRandom.nextInt(values.size())); while (!selectedEntity.canBeAssigned(selectedValue)) { // This assumes there at least one value that can be assigned to the selected entity selectedValue = values.get(workingRandom.nextInt(values.size())); } return new MyChangeMove(selectedEntity, selectedValue); } }; } } ``` -------------------------------- ### Create SolverFactory from XML Resource Source: https://docs.timefold.ai/timefold-solver/latest/using-timefold-solver/configuration Instantiate a SolverFactory by loading a solver configuration XML file from the classpath. This is the recommended approach for portability. ```java SolverFactory solverFactory = SolverFactory.createFromXmlResource( "org/acme/schooltimetabling/solverConfig.xml"); Solver solver = solverFactory.buildSolver(); ``` -------------------------------- ### Configure Logging with Logback Source: https://docs.timefold.ai/timefold-solver/latest/quickstart/hello-world/hello-world-quickstart Create this logback.xml file to see console output from Timefold Solver. It sets up a console appender and configures the solver's logger to 'info' level. ```xml %d{HH:mm:ss.SSS} [%-12.12t] %-5p %m%n ``` -------------------------------- ### Job Entity with Shadow Variable for End Date Source: https://docs.timefold.ai/timefold-solver/latest/using-timefold-solver/modeling-planning-problems Defines a Job entity with a start date, duration, and a shadow variable for the end date. The endDateSupplier method calculates the end date based on the start date and duration. ```java public class Job { public Job(LocalDate startDate, int durationInDays) { ... } @PlanningVariable private LocalDate startDate; private int durationInDays; @ShadowVariable(supplierName="endDateSupplier") private LocalDate endDate; @ShadowSources("startDate") public LocalDate endDateSupplier() { if (startDate == null) { return null; } else { return startDate.plusDays(durationInDays); } } } ``` -------------------------------- ### Example Routing Service Response Source: https://docs.timefold.ai/timefold-solver/latest/quickstart/quarkus-vehicle-routing/quarkus-vehicle-routing-quickstart This is an example of the JSON response received from the routing service after processing the POST request. It details the assigned visits for each vehicle, arrival times, total demands, and driving times, along with the overall score. ```json HTTP/1.1 200 Content-Type: application/json ... {"name":"demo","vehicles":[{"id":"1","capacity":15,"homeLocation":[40.605994321126936,-75.68106859680056],"departureTime":"2024-02-10T07:30:00","visits":[],"arrivalTime":"2024-02-10T15:34:11","totalDemand":3,"totalDrivingTimeSeconds":10826},{"id":"2","capacity":25,"homeLocation":[40.32196770776356,-75.69785667307953],"departureTime":"2024-02-10T07:30:00","visits":[],"arrivalTime":"2024-02-10T13:52:18","totalDemand":3,"totalDrivingTimeSeconds":7890}],"visits":[{"id":"1","name":"Dan Green","location":[40.76104493121754,-75.16056341466826],"demand":1,"minStartTime":"2024-02-10T13:00:00","maxEndTime":"2024-02-10T18:00:00","serviceDuration":1200.000000000,"vehicle":"1","previousVisit":"5","nextVisit":"4","arrivalTime":"2024-02-10T09:40:50","startServiceTime":"2024-02-10T13:00:00","departureTime":"2024-02-10T13:20:00","drivingTimeSecondsFromPreviousStandstill":4250},{"id":"2","name":"Ivy King","location":[40.13754381024318,-75.492526629236],"demand":1,"minStartTime":"2024-02-10T13:00:00","maxEndTime":"2024-02-10T18:00:00","serviceDuration":1200.000000000,"vehicle":"2","previousVisit":"3","nextVisit":null,"arrivalTime":"2024-02-10T09:19:12","startServiceTime":"2024-02-10T13:00:00","departureTime":"2024-02-10T13:20:00","drivingTimeSecondsFromPreviousStandstill":2329},{"id":"3","name":"Flo Li","location":[39.87122455090297,-75.64520072015769],"demand":2,"minStartTime":"2024-02-10T08:00:00","maxEndTime":"2024-02-10T12:00:00","serviceDuration":600.000000000,"vehicle":"2","previousVisit":null,"nextVisit":"2","arrivalTime":"2024-02-10T08:30:23","startServiceTime":"2024-02-10T08:30:23","departureTime":"2024-02-10T08:40:23","drivingTimeSecondsFromPreviousStandstill":3623},{"id":"4","name":"Flo Cole","location":[40.46124744193433,-75.18250987609025],"demand":1,"minStartTime":"2024-02-10T13:00:00","maxEndTime":"2024-02-10T18:00:00","serviceDuration":2400.000000000,"vehicle":"1","previousVisit":"1","nextVisit":null,"arrivalTime":"2024-02-10T14:00:04","startServiceTime":"2024-02-10T14:00:04","departureTime":"2024-02-10T14:40:04","drivingTimeSecondsFromPreviousStandstill":2404},{"id":"5","name":"Carl Green","location":[40.61352381171549,-75.83301278355529],"demand":1,"minStartTime":"2024-02-10T08:00:00","maxEndTime":"2024-02-10T12:00:00","serviceDuration":1800.000000000,"vehicle":"1","previousVisit":null,"nextVisit":"1","arrivalTime":"2024-02-10T07:45:25","startServiceTime":"2024-02-10T08:00:00","departureTime":"2024-02-10T08:30:00","drivingTimeSecondsFromPreviousStandstill":925}],"score":"0hard/-18716soft","totalDrivingTimeSeconds":18716} ``` -------------------------------- ### Solving a Planning Problem Source: https://docs.timefold.ai/timefold-solver/latest/using-timefold-solver/running-the-solver Demonstrates how to use a configured `Solver` to find the best solution for a given planning problem instance. ```java Timetable problem = ...; Timetable bestSolution = solver.solve(problem); ``` -------------------------------- ### Deprecated Shadow Variable Annotation Source: https://docs.timefold.ai/timefold-solver/latest/upgrading-timefold-solver/migration-guides/variable-listeners-to-custom-shadow-variables Example of a deprecated shadow variable annotation using variableListenerClass. ```java @ShadowVariable( variableListenerClass = MyVariableListener.class, sourceVariableName = "someGenuineVariable" ) private SomeType myShadow; ``` -------------------------------- ### Simplest Partitioned Search Configuration Source: https://docs.timefold.ai/timefold-solver/latest/using-timefold-solver/running-the-solver Configure partitioned search with a custom solution partitioner class. ```xml ...MyPartitioner ``` -------------------------------- ### Filtered Entity Selection Example Source: https://docs.timefold.ai/timefold-solver/latest/optimization-algorithms/move-selector-reference Implements a SelectionFilter to accept only long lectures. Configure the 'filterClass' on the entitySelector. ```java public class LongLectureSelectionFilter implements SelectionFilter { @Override public boolean accept(ScoreDirector scoreDirector, Lecture lecture) { return lecture.isLong(); } } ``` ```xml ...LongLectureSelectionFilter ``` -------------------------------- ### Benchmark Configuration for Custom Solution File IO Source: https://docs.timefold.ai/timefold-solver/latest/using-timefold-solver/benchmarking-and-tweaking Configure the benchmark to use a custom `SolutionFileIO` implementation for reading and writing solutions in a custom format. Specify the custom IO class and input file. ```xml ...MyXlsxSolutionFileIO dataset01.xslx ... ``` -------------------------------- ### Build and Solve Timetable Source: https://docs.timefold.ai/timefold-solver/latest/quickstart/hello-world/hello-world-quickstart Configures the solver with a constraint provider and termination limit, loads demo data, builds the solver, and solves the problem. ```kotlin val solverFactory = SolverFactory.createFromXml("solver-config.xml") // 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 val problem = generateDemoData(DemoData.SMALL) // Solve the problem val solver = solverFactory.buildSolver() val solution = solver.solve(problem) // Visualize the solution printTimetable(solution) ``` -------------------------------- ### Get MoveTestContext from NeighborhoodTester Source: https://docs.timefold.ai/timefold-solver/latest/optimization-algorithms/neighborhoods Obtain a MoveTestContext directly from a NeighborhoodTester context to facilitate move execution testing. ```java var tester = NeighborhoodTester.build(new SwapMoveProvider(), solutionMetaModel); var testerContext = tester.using(solution); var moveTestContext = testerContext.getMoveTestContext(); ``` -------------------------------- ### Composite Selector CacheType Configuration Source: https://docs.timefold.ai/timefold-solver/latest/optimization-algorithms/move-selector-reference A cacheType can be set on composite selectors as well. This example shows setting it on a unionMoveSelector. ```xml PHASE ... ``` -------------------------------- ### Benchmark Configuration with Solver Benchmark Blueprint Source: https://docs.timefold.ai/timefold-solver/latest/using-timefold-solver/benchmarking-and-tweaking Use a solverBenchmarkBluePrint for quick configuration and execution of benchmarks for typical solver configurations. This example uses the 'EVERY_CONSTRUCTION_HEURISTIC_TYPE_WITH_EVERY_LOCAL_SEARCH_TYPE' blueprint. ```xml local/ org.acme.vehiclerouting.domain.VehicleRoutePlan org.acme.vehiclerouting.domain.Vehicle org.acme.vehiclerouting.domain.Visit org.acme.vehiclerouting.solver.VehicleRoutingConstraintProvider 1 org.acme.vehiclerouting.persistence.VehicleRoutePlanSolutionFileIO data/dataset01.json data/dataset02.json EVERY_CONSTRUCTION_HEURISTIC_TYPE_WITH_EVERY_LOCAL_SEARCH_TYPE ``` -------------------------------- ### Generate Demo Timetable Data Source: https://docs.timefold.ai/timefold-solver/latest/quickstart/hello-world/hello-world-quickstart Creates a sample Timetable object with timeslots, rooms, and lessons for demonstration purposes. ```kotlin fun generateDemoData(): Timetable { val timeslots: MutableList = ArrayList(10) timeslots.add(Timeslot(DayOfWeek.MONDAY, LocalTime.of(8, 30), LocalTime.of(9, 30))) timeslots.add(Timeslot(DayOfWeek.MONDAY, LocalTime.of(9, 30), LocalTime.of(10, 30))) timeslots.add(Timeslot(DayOfWeek.MONDAY, LocalTime.of(10, 30), LocalTime.of(11, 30))) timeslots.add(Timeslot(DayOfWeek.MONDAY, LocalTime.of(13, 30), LocalTime.of(14, 30))) timeslots.add(Timeslot(DayOfWeek.MONDAY, LocalTime.of(14, 30), LocalTime.of(15, 30))) timeslots.add(Timeslot(DayOfWeek.TUESDAY, LocalTime.of(8, 30), LocalTime.of(9, 30))) timeslots.add(Timeslot(DayOfWeek.TUESDAY, LocalTime.of(9, 30), LocalTime.of(10, 30))) timeslots.add(Timeslot(DayOfWeek.TUESDAY, LocalTime.of(10, 30), LocalTime.of(11, 30))) timeslots.add(Timeslot(DayOfWeek.TUESDAY, LocalTime.of(13, 30), LocalTime.of(14, 30))) timeslots.add(Timeslot(DayOfWeek.TUESDAY, LocalTime.of(14, 30), LocalTime.of(15, 30))) val rooms: MutableList = ArrayList(3) rooms.add(Room("Room A")) rooms.add(Room("Room B")) rooms.add(Room("Room C")) val lessons: MutableList = ArrayList() var nextLessonId = 0L lessons.add(Lesson(nextLessonId++.toString(), "Math", "A. Turing", "9th grade")) lessons.add(Lesson(nextLessonId++.toString(), "Math", "A. Turing", "9th grade")) lessons.add(Lesson(nextLessonId++.toString(), "Physics", "M. Curie", "9th grade")) lessons.add(Lesson(nextLessonId++.toString(), "Chemistry", "M. Curie", "9th grade")) lessons.add(Lesson(nextLessonId++.toString(), "Biology", "C. Darwin", "9th grade")) lessons.add(Lesson(nextLessonId++.toString(), "History", "I. Jones", "9th grade")) lessons.add(Lesson(nextLessonId++.toString(), "English", "I. Jones", "9th grade")) lessons.add(Lesson(nextLessonId++.toString(), "English", "I. Jones", "9th grade")) lessons.add(Lesson(nextLessonId++.toString(), "Spanish", "P. Cruz", "9th grade")) lessons.add(Lesson(nextLessonId++.toString(), "Spanish", "P. Cruz", "9th grade")) lessons.add(Lesson(nextLessonId++.toString(), "Math", "A. Turing", "10th grade")) lessons.add(Lesson(nextLessonId++.toString(), "Math", "A. Turing", "10th grade")) lessons.add(Lesson(nextLessonId++.toString(), "Math", "A. Turing", "10th grade")) lessons.add(Lesson(nextLessonId++.toString(), "Physics", "M. Curie", "10th grade")) lessons.add(Lesson(nextLessonId++.toString(), "Chemistry", "M. Curie", "10th grade")) lessons.add(Lesson(nextLessonId++.toString(), "French", "M. Curie", "10th grade")) lessons.add(Lesson(nextLessonId++.toString(), "Geography", "C. Darwin", "10th grade")) lessons.add(Lesson(nextLessonId++.toString(), "History", "I. Jones", "10th grade")) lessons.add(Lesson(nextLessonId++.toString(), "English", "P. Cruz", "10th grade")) lessons.add(Lesson(nextLessonId.toString(), "Spanish", "P. Cruz", "10th grade")) return Timetable(timeslots, rooms, lessons) } ``` -------------------------------- ### SimpleScore Declaration Source: https://docs.timefold.ai/timefold-solver/latest/constraints-and-score/overview Example of declaring a SimpleScore in the domain class, suitable for use cases with a single score level. ```java @PlanningScore private SimpleScore score; ``` -------------------------------- ### Simple Construction Heuristic Configuration Source: https://docs.timefold.ai/timefold-solver/latest/optimization-algorithms/construction-heuristics Use this for a basic construction heuristic that allocates entities from a queue. ```xml ALLOCATE_ENTITY_FROM_QUEUE ``` -------------------------------- ### Configure EntitySelector with ComparatorFactory Source: https://docs.timefold.ai/timefold-solver/latest/optimization-algorithms/move-selector-reference Configure an EntitySelector to use a ComparatorFactory for sorting. This example uses DESCENDING sorterOrder and requires the comparatorFactoryClass. ```xml PHASE SORTED ...MyComparatorFactory DESCENDING ``` -------------------------------- ### Copy SolverConfig for concurrent requests Source: https://docs.timefold.ai/timefold-solver/latest/using-timefold-solver/configuration Demonstrates how to create a template SolverConfig and copy it for each user request to ensure thread-safe dynamic configuration. ```java private SolverConfig template; public void init() { template = SolverConfig.createFromXmlResource("org/acme/schooltimetabling/solverConfig.xml"); template.setTerminationConfig(new TerminationConfig()); } // Called concurrently from different threads public void userRequest(..., long userInput) { SolverConfig solverConfig = new SolverConfig(template); // Copy it solverConfig.getTerminationConfig().setMinutesSpentLimit(userInput); SolverFactory solverFactory = SolverFactory.create(solverConfig); Solver solver = solverFactory.buildSolver(); ... ``` -------------------------------- ### Filtered Entity Selection Example Source: https://docs.timefold.ai/timefold-solver/latest/optimization-algorithms/move-selector-reference A custom filter to select only long lectures. This is useful when certain entities should not be considered for moves. ```java public class LongLectureSelectionFilter implements SelectionFilter { @Override public boolean accept(ScoreDirector scoreDirector, Lecture lecture) { return lecture.isLong(); } } ``` -------------------------------- ### Running the Gradle Built Application Source: https://docs.timefold.ai/timefold-solver/latest/quickstart/hello-world/hello-world-quickstart Commands to build the project using Gradle and then run the generated executable JAR. This shows the execution of the application built with Gradle. ```bash $ gradle build ... $ java -jar build/libs/hello-world-1.0-SNAPSHOT.jar ``` -------------------------------- ### Replace @ConstraintConfiguration with ConstraintWeightOverrides in Solution Source: https://docs.timefold.ai/timefold-solver/latest/upgrading-timefold-solver/upgrade-from-v1 This example demonstrates how to replace the @ConstraintConfiguration annotation in a Solution class with the new constraintWeightOverrides mechanism. ```java @ConstraintConfiguration private MyConstraintConfiguration myConstraintConfiguration; ``` ```java ConstraintWeightOverrides constraintWeightOverrides; constraintWeightOverrides = ConstraintWeightOverrides.of( Map.of( "maxHoursWorked", HardSoftScore.ofSoft(10) ) ); ``` -------------------------------- ### Mixed Modeling Construction Heuristic Simple Configuration (Basic Variable) Source: https://docs.timefold.ai/timefold-solver/latest/optimization-algorithms/construction-heuristics Simple configuration for mixed modeling construction heuristics using queuedEntityPlacer for basic variables. ```xml ``` -------------------------------- ### Overriding SolverManager Bean in Java Source: https://docs.timefold.ai/timefold-solver/latest/integration/integration Provides an example of creating a custom `SolverManager` bean in Java by using `SolverFactory` and `SolverManagerConfig`. ```java package org.acme.schooltimetabling.rest; import ai.timefold.solver.core.api.solver.SolverFactory; import ai.timefold.solver.core.api.solver.SolverManager; import ai.timefold.solver.core.config.solver.SolverManagerConfig; import ai.timefold.solver.spring.boot.autoconfigure.TimefoldAutoConfiguration; import org.acme.schooltimetabling.domain.Timetable; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Primary; @Configuration @Import(TimefoldAutoConfiguration.class) public class BeanProducer { @Bean @Primary public SolverManager overrideSolverManager(SolverFactory solverFactory) { SolverManagerConfig solverManagerConfig = new SolverManagerConfig(); return SolverManager.create(solverFactory, solverManagerConfig); } } ``` -------------------------------- ### Cheapest Insertion Construction Heuristic (Simple) Source: https://docs.timefold.ai/timefold-solver/latest/optimization-algorithms/construction-heuristics Simple configuration for the Cheapest Insertion construction heuristic. It initializes entities by assigning the best available planning entity to the best planning value. ```xml CHEAPEST_INSERTION ``` -------------------------------- ### BendableScore Declaration with Levels Source: https://docs.timefold.ai/timefold-solver/latest/constraints-and-score/overview Example of declaring a BendableScore with a configurable number of hard and soft levels, specified at compilation time. ```java @PlanningScore(bendableHardLevelsSize = 2, bendableSoftLevelsSize = 3) private BendableScore score; ``` -------------------------------- ### Move Generation using asMove Source: https://docs.timefold.ai/timefold-solver/latest/optimization-algorithms/neighborhoods Shows how to generate a move from picked items using the asMove method. This example creates a built-in change move for a planning variable. ```java public class TimeslotChangeMoveProvider implements MoveProvider { ... @Override public MoveStream build(MoveStreamFactory factory) { ... return factory.pick(...) .pick(...) .asMove((solutionView, lesson, newTimeslot) -> Moves.change(timeslotVariable, lesson, newTimeslot)); } } ```