### Running the Cloud Balancing Hello World Source: https://docs.timefold.ai/timefold-solver/0.8.x/use-cases-and-examples/cloud-balancing/cloud-balancing?docs=1 Provides instructions on how to run the cloud balancing Hello World example, including IDE setup and configuring the main class. ```APIDOC ## Run the Cloud Balancing Hello World ### Description This section guides you through setting up and running the cloud balancing Hello World example. ### Steps 1. Download and configure the examples in your preferred IDE. 2. Create a run configuration with the following main class: `ai.timefold.solver.examples.cloudbalancing.app.CloudBalancingHelloWorld`. By default, the example runs for 120 seconds. ``` -------------------------------- ### Clone Timefold Quickstarts Repository Source: https://docs.timefold.ai/timefold-solver/0.8.x/quickstart/quarkus/quarkus-quickstart Command to download the official Timefold quickstart examples, which include various use cases for constraint solving. ```shell git clone https://github.com/TimefoldAI/timefold-quickstarts ``` -------------------------------- ### Run Cloud Balancing Hello World Example (Java) Source: https://docs.timefold.ai/timefold-solver/0.8.x/use-cases-and-examples/use-cases-and-examples?platform=1 This snippet shows the main method for the Cloud Balancing Hello World example. It demonstrates building a solver from an XML configuration, loading a generated problem, solving it, and printing the solution. Dependencies include Timefold Solver libraries. ```java public class CloudBalancingHelloWorld { public static void main(String[] args) { // Build the Solver SolverFactory solverFactory = SolverFactory.createFromXmlResource( "ai/timefold/solver/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)); } ... } ``` -------------------------------- ### Run Timefold Examples via Command Line Source: https://docs.timefold.ai/timefold-solver/0.8.x/introduction/introduction Instructions for launching the Timefold Examples GUI application on different operating systems using provided shell scripts. ```bash cd examples ./runExamples.sh ``` ```batch cd examples runExamples.bat ``` -------------------------------- ### Run Timefold Examples with Maven Source: https://docs.timefold.ai/timefold-solver/0.8.x/introduction/introduction After building, this command navigates to the examples directory and executes the Java examples using Maven's exec plugin. This allows you to test the built solver with sample use cases. ```sh cd timefold-solver-examples mvn exec:java ``` -------------------------------- ### Configure Allocate From Pool Construction Heuristic Source: https://docs.timefold.ai/timefold-solver/0.8.x/construction-heuristics/construction-heuristics?platform=1 Provides XML configuration examples for the ALLOCATE_FROM_POOL construction heuristic, ranging from simple setups to advanced pooled entity placer configurations. ```xml ALLOCATE_FROM_POOL ``` ```xml ALLOCATE_FROM_POOL DECREASING_DIFFICULTY_IF_AVAILABLE INCREASING_STRENGTH_IF_AVAILABLE ``` ```xml PHASE SORTED DECREASING_DIFFICULTY PHASE SORTED INCREASING_STRENGTH ``` -------------------------------- ### Java Example: CloudBalancePartitioner Implementation Source: https://docs.timefold.ai/timefold-solver/0.8.x/partitioned-search/partitioned-search?platform=1 This Java class provides a concrete implementation of the SolutionPartitioner interface for the Cloud Balancing example. It demonstrates how to dynamically determine the number of partitions and distribute computers and processes among them. ```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; } } ``` -------------------------------- ### Run Timefold Examples Script (Windows) Source: https://docs.timefold.ai/timefold-solver/0.8.x This script is used to execute Timefold examples on Windows systems after downloading and unzipping the release. It navigates to the examples directory and runs the main example script. ```bat cd examples runExamples.bat ``` -------------------------------- ### Run Timefold Examples Script (Linux/Mac) Source: https://docs.timefold.ai/timefold-solver/0.8.x This script is used to execute Timefold examples on Linux or macOS systems after downloading and unzipping the release. It navigates to the examples directory and runs the main example script. ```sh cd examples ./runExamples.sh ``` -------------------------------- ### Example Implementation of ConstraintMatchAwareIncrementalScoreCalculator Source: https://docs.timefold.ai/timefold-solver/0.8.x/score-calculation/score-calculation?docs=1 Provides a concrete implementation example for a machine reassignment problem. It shows how to aggregate constraint matches and return them as part of the score calculation process. ```java public class MachineReassignmentIncrementalScoreCalculator implements ConstraintMatchAwareIncrementalScoreCalculator { @Override public void resetWorkingSolution(MachineReassignment workingSolution, boolean constraintMatchEnabled) { resetWorkingSolution(workingSolution); } @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; } } ``` -------------------------------- ### Cloud Balancing ProblemChange Example Source: https://docs.timefold.ai/timefold-solver/0.8.x/repeated-planning/repeated-planning?docs=1 An example demonstrating how to implement a ProblemChange to delete a computer from a cloud balancing problem. ```APIDOC ## POST /api/problem-changes ### Description This endpoint allows for the dynamic modification of a planning problem by applying a `ProblemChange`. This specific example demonstrates the deletion of a `CloudComputer`. ### Method POST ### Endpoint /api/problem-changes ### Parameters #### Request Body - **problemChange** (object) - Required - An object representing the change to be applied to the problem. - **type** (string) - Required - Specifies the type of change, e.g., 'deleteComputer'. - **computer** (object) - Required - The `CloudComputer` object to be deleted. ### Request Example ```json { "problemChange": { "type": "deleteComputer", "computer": { "id": 1, "name": "Computer A", "cpu": 4, "memory": 16, "cost": 100 } } } ``` ### Response #### Success Response (200) - **status** (string) - Indicates the success of the operation, e.g., 'success'. #### Response Example ```json { "status": "success" } ``` ### Error Handling - **400 Bad Request**: If the specified computer does not exist or has already been deleted. - **500 Internal Server Error**: For unexpected server-side issues during the problem change application. ``` -------------------------------- ### Configure Jackson JSON Solution File IO in Benchmark Source: https://docs.timefold.ai/timefold-solver/0.8.x/benchmarking-and-tweaking/benchmarking-and-tweaking Example of how to configure the JacksonSolutionFileIO within the problemBenchmarks section of a benchmark configuration file. ```xml ai.timefold.solver.examples.nqueens.persistence.NQueensJsonSolutionFileIO data/nqueens/unsolved/32queens.json ... ``` -------------------------------- ### Execute Cloud Balancing Solver Source: https://docs.timefold.ai/timefold-solver/0.8.x/use-cases-and-examples/cloud-balancing/cloud-balancing Demonstrates the main entry point for running the Cloud Balancing Hello World example, including solver initialization, problem generation, and execution. ```java public class CloudBalancingHelloWorld { public static void main(String[] args) { SolverFactory solverFactory = SolverFactory.createFromXmlResource("ai/timefold/solver/examples/cloudbalancing/solver/cloudBalancingSolverConfig.xml"); Solver solver = solverFactory.buildSolver(); CloudBalance unsolvedCloudBalance = new CloudBalancingGenerator().createCloudBalance(400, 1200); CloudBalance solvedCloudBalance = solver.solve(unsolvedCloudBalance); System.out.println("\nSolved cloudBalance with 400 computers and 1200 processes:\n" + toDisplayString(solvedCloudBalance)); } } ``` -------------------------------- ### Define Simple Constraint Stream Source: https://docs.timefold.ai/timefold-solver/0.8.x/constraint-streams/constraint-streams A basic example of a constraint stream starting with forEach and ending with a penalty. ```java private Constraint penalizeInitializedShifts(ConstraintFactory factory) { return factory.forEach(Shift.class) .penalize(HardSoftScore.ONE_SOFT) .asConstraint("Initialized shift"); } ``` -------------------------------- ### Run Cloud Balancing Hello World Source: https://docs.timefold.ai/timefold-solver/0.8.x/use-cases-and-examples/cloud-balancing/cloud-balancing?docs=1 Demonstrates the main execution flow for the Cloud Balancing example, including building the solver, generating an unsolved problem instance, solving it, and displaying the results. ```java public class CloudBalancingHelloWorld { public static void main(String[] args) { SolverFactory solverFactory = SolverFactory.createFromXmlResource( "ai/timefold/solver/examples/cloudbalancing/solver/cloudBalancingSolverConfig.xml"); Solver solver = solverFactory.buildSolver(); CloudBalance unsolvedCloudBalance = new CloudBalancingGenerator().createCloudBalance(400, 1200); CloudBalance solvedCloudBalance = solver.solve(unsolvedCloudBalance); System.out.println("\nSolved cloudBalance with 400 computers and 1200 processes:\n" + toDisplayString(solvedCloudBalance)); } } ``` -------------------------------- ### Example Timefold Solver Log Output Source: https://docs.timefold.ai/timefold-solver/0.8.x/configuration/configuration This is an example of the detailed log output when the Timefold Solver is configured with 'debug' logging. It shows the start and end of phases, steps taken, scores, and performance metrics like score calculation speed. ```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). ``` -------------------------------- ### Configure and Run PlannerBenchmark Source: https://docs.timefold.ai/timefold-solver/0.8.x/benchmarking-and-tweaking/benchmarking-and-tweaking Demonstrates how to initialize a PlannerBenchmark from an XML resource and execute the benchmark process, which generates a report. ```java PlannerBenchmarkFactory benchmarkFactory = PlannerBenchmarkFactory.createFromXmlResource("ai/timefold/solver/examples/cloudbalancing/benchmark/cloudBalancingBenchmarkConfig.xml"); PlannerBenchmark benchmark = benchmarkFactory.buildPlannerBenchmark(); benchmark.benchmarkAndShowReportInBrowser(); ``` -------------------------------- ### Execute Simple Planner Benchmark Source: https://docs.timefold.ai/timefold-solver/0.8.x/benchmarking-and-tweaking/benchmarking-and-tweaking Demonstrates how to initialize a PlannerBenchmarkFactory from a solver configuration file and execute a benchmark against multiple datasets. The process generates a report in the local directory and opens it in the default browser. ```java PlannerBenchmarkFactory benchmarkFactory = PlannerBenchmarkFactory.createFromSolverConfigXmlResource( "ai/timefold/solver/examples/cloudbalancing/solver/cloudBalancingSolverConfig.xml"); CloudBalance dataset1 = ...; CloudBalance dataset2 = ...; CloudBalance dataset3 = ...; PlannerBenchmark benchmark = benchmarkFactory.buildPlannerBenchmark( dataset1, dataset2, dataset3); benchmark.benchmarkAndShowReportInBrowser(); ``` -------------------------------- ### Build and Run Cloud Balancing Solver Source: https://docs.timefold.ai/timefold-solver/0.8.x/use-cases-and-examples/use-cases-and-examples?platform=1 Demonstrates how to initialize the solver using either XML configuration or the programmatic API, load problem data, and execute the solver. ```APIDOC ## Java Programmatic Solver API ### Description This section describes how to configure and execute the Timefold solver for cloud balancing problems. It supports both XML-based configuration and a fluent programmatic API. ### Method Java API Execution ### Parameters #### Request Body - **SolverConfig** (Object) - Required - Configuration object defining solution class, entity classes, score calculator, and termination limits. - **CloudBalance** (Object) - Required - The unsolved problem instance containing computers and processes. ### Request Example ```java SolverFactory solverFactory = SolverFactory.create(new SolverConfig() .withSolutionClass(CloudBalance.class) .withEntityClasses(CloudProcess.class) .withEasyScoreCalculatorClass(CloudBalancingEasyScoreCalculator.class) .withTerminationSpentLimit(Duration.ofMinutes(2))); Solver solver = solverFactory.buildSolver(); ``` ### Response #### Success Response (200) - **solvedCloudBalance** (CloudBalance) - The optimized solution object containing the assigned processes to computers. #### Response Example ```java CloudBalance solvedCloudBalance = solver.solve(unsolvedCloudBalance); System.out.println(toDisplayString(solvedCloudBalance)); ``` ``` -------------------------------- ### Start Quarkus Application Source: https://docs.timefold.ai/timefold-solver/0.8.x/quickstart/quarkus/quarkus-quickstart Command to compile and start the Quarkus development environment. ```shell mvn compile quarkus:dev ``` -------------------------------- ### Penalize Configurable Example Source: https://docs.timefold.ai/timefold-solver/0.8.x/score-calculation/score-calculation?platform=1 An example of a constraint implementation using `penalizeConfigurable` with a match weight calculation. ```APIDOC ## Penalize Configurable Example ### Description This example shows a constraint implementation for 'Content conflict' that uses `penalizeConfigurable`. The penalty is calculated based on the number of overlapping content tags and the duration of the overlap, and this calculated penalty is then multiplied by the constraint weight. ### Method N/A (Configuration) ### Endpoint N/A (Configuration) ### Parameters N/A ### Request Example ```java @ConstraintWeight("Content conflict") private HardMediumSoftScore contentConflict = HardMediumSoftScore.ofSoft(100); // ... in ConstraintProvider class Constraint contentConflict(ConstraintFactory factory) { return factory.forEachUniquePair(Talk.class, overlapping(t -> t.getTimeslot().getStartDateTime(), t -> t.getTimeslot().getEndDateTime()), filtering((talk1, talk2) -> talk1.overlappingContentCount(talk2) > 0)) .penalizeConfigurable("Content conflict", (talk1, talk2) -> talk1.overlappingContentCount(talk2) * talk1.overlappingDurationInMinutes(talk2)); } ``` ### Response N/A ### Notes - The constraint weight `contentConflict` is set to `100soft`. - The `penalizeConfigurable` method calculates a penalty for each match, which is then scaled by the constraint weight. ``` -------------------------------- ### Configure and Run PlannerBenchmark in Java Source: https://docs.timefold.ai/timefold-solver/0.8.x/benchmarking-and-tweaking/benchmarking-and-tweaking?platform=1 This Java code demonstrates how to create a PlannerBenchmark instance using a factory, configure it with an XML resource, build the benchmark, and run it to show a report in the browser. It requires the timefold-solver-benchmark dependency. ```java PlannerBenchmarkFactory benchmarkFactory = PlannerBenchmarkFactory.createFromXmlResource( "ai/timefold/solver/examples/cloudbalancing/benchmark/cloudBalancingBenchmarkConfig.xml"); PlannerBenchmark benchmark = benchmarkFactory.buildPlannerBenchmark(); benchmark.benchmarkAndShowReportInBrowser(); ``` -------------------------------- ### N-Queens Incremental Score Calculator Example Source: https://docs.timefold.ai/timefold-solver/0.8.x/score-calculation/score-calculation An example implementation of `IncrementalScoreCalculator` for the N-Queens problem, demonstrating how to manage state and update the score incrementally. ```APIDOC ## N-Queens Incremental Score Calculator Example ### Description This class provides an incremental score calculation for the N-Queens problem. It uses HashMaps to efficiently track queen placements in rows and diagonals, updating the score dynamically as changes occur. ### Class `NQueensAdvancedIncrementalScoreCalculator` ### Implements `IncrementalScoreCalculator` ### Key Features - Uses `rowIndexMap`, `ascendingDiagonalIndexMap`, and `descendingDiagonalIndexMap` for efficient lookups. - The `score` variable is updated incrementally in `insert` and `retract` methods. - `resetWorkingSolution` initializes the maps and the score based on the initial solution. - `afterEntityAdded`, `beforeVariableChanged`, `afterVariableChanged`, and `beforeEntityRemoved` methods call `insert` or `retract` to update the score. ### Code Example ```java public class NQueensAdvancedIncrementalScoreCalculator implements IncrementalScoreCalculator { private Map> rowIndexMap; private Map> ascendingDiagonalIndexMap; private Map> descendingDiagonalIndexMap; private int score; public void resetWorkingSolution(NQueens nQueens) { int n = nQueens.getN(); rowIndexMap = new HashMap>(n); ascendingDiagonalIndexMap = new HashMap>(n * 2); descendingDiagonalIndexMap = new HashMap>(n * 2); for (int i = 0; i < n; i++) { rowIndexMap.put(i, new ArrayList(n)); ascendingDiagonalIndexMap.put(i, new ArrayList(n)); descendingDiagonalIndexMap.put(i, new ArrayList(n)); if (i != 0) { ascendingDiagonalIndexMap.put(n - 1 + i, new ArrayList(n)); descendingDiagonalIndexMap.put((-i), new ArrayList(n)); } } score = 0; for (Queen queen : nQueens.getQueenList()) { insert(queen); } } public void beforeEntityAdded(Object entity) { // Do nothing } public void afterEntityAdded(Object entity) { insert((Queen) entity); } public void beforeVariableChanged(Object entity, String variableName) { retract((Queen) entity); } public void afterVariableChanged(Object entity, String variableName) { insert((Queen) entity); } public void beforeEntityRemoved(Object entity) { retract((Queen) entity); } public void afterEntityRemoved(Object entity) { // Do nothing } private void insert(Queen queen) { Row row = queen.getRow(); if (row != null) { int rowIndex = queen.getRowIndex(); List rowIndexList = rowIndexMap.get(rowIndex); score -= rowIndexList.size(); rowIndexList.add(queen); List ascendingDiagonalIndexList = ascendingDiagonalIndexMap.get(queen.getAscendingDiagonalIndex()); score -= ascendingDiagonalIndexList.size(); ascendingDiagonalIndexList.add(queen); List descendingDiagonalIndexList = descendingDiagonalIndexMap.get(queen.getDescendingDiagonalIndex()); score -= descendingDiagonalIndexList.size(); descendingDiagonalIndexList.add(queen); } } private void retract(Queen queen) { Row row = queen.getRow(); if (row != null) { List rowIndexList = rowIndexMap.get(queen.getRowIndex()); rowIndexList.remove(queen); score += rowIndexList.size(); List ascendingDiagonalIndexList = ascendingDiagonalIndexMap.get(queen.getAscendingDiagonalIndex()); ascendingDiagonalIndexList.remove(queen); score += ascendingDiagonalIndexList.size(); List descendingDiagonalIndexList = descendingDiagonalIndexMap.get(queen.getDescendingDiagonalIndex()); descendingDiagonalIndexList.remove(queen); score += descendingDiagonalIndexList.size(); } } public SimpleScore calculateScore() { return SimpleScore.valueOf(score); } } ``` ``` -------------------------------- ### Initialize PlannerBenchmarkFactory from Freemarker Template Source: https://docs.timefold.ai/timefold-solver/0.8.x/benchmarking-and-tweaking/benchmarking-and-tweaking Demonstrates how to instantiate a PlannerBenchmarkFactory using a Freemarker XML template file in Java. ```java PlannerBenchmarkFactory benchmarkFactory = PlannerBenchmarkFactory.createFromFreemarkerXmlResource("ai/timefold/solver/examples/cloudbalancing/optional/benchmark/cloudBalancingBenchmarkConfigTemplate.xml.ftl"); PlannerBenchmark benchmark = benchmarkFactory.buildPlannerBenchmark(); ``` -------------------------------- ### CloudBalancingIncrementalScoreCalculator.java Example Source: https://docs.timefold.ai/timefold-solver/0.8.x/use-cases-and-examples/use-cases-and-examples?platform=1 An example implementation of the `IncrementalScoreCalculator` interface for the Cloud Balancing problem. This class incrementally updates the score based on changes to the working solution. ```APIDOC ## CloudBalancingIncrementalScoreCalculator.java ### Description This Java class implements the `IncrementalScoreCalculator` interface to calculate the hard and soft scores for the Cloud Balancing problem incrementally. It maintains maps to track resource usage (CPU, memory, network bandwidth) and process counts for each computer, updating the scores as processes are added, removed, or their assignments change. ### Method Java Implementation ### Endpoint N/A (Class implementation) ### Parameters N/A ### Request Example ```java public class CloudBalancingIncrementalScoreCalculator implements IncrementalScoreCalculator { private Map cpuPowerUsageMap; private Map memoryUsageMap; private Map networkBandwidthUsageMap; private Map processCountMap; private int hardScore; private int softScore; @Override public void resetWorkingSolution(CloudBalance cloudBalance) { // ... initialization logic ... hardScore = 0; softScore = 0; for (CloudProcess process : cloudBalance.getProcessList()) { insert(process); } } @Override public void beforeVariableChanged(Object entity, String variableName) { retract((CloudProcess) entity); } @Override public void afterVariableChanged(Object entity, String variableName) { insert((CloudProcess) entity); } @Override public void beforeEntityRemoved(Object entity) { retract((CloudProcess) entity); } // ... other methods like insert and retract ... private void insert(CloudProcess process) { CloudComputer computer = process.getComputer(); if (computer != null) { // ... CPU power update ... cpuPowerUsageMap.put(computer, newCpuPowerUsage); // ... Memory update ... memoryUsageMap.put(computer, newMemoryUsage); // ... Network bandwidth update ... networkBandwidthUsageMap.put(computer, newNetworkBandwidthUsage); // ... Process count update ... int oldProcessCount = processCountMap.get(computer); if (oldProcessCount == 0) { softScore -= computer.getCost(); } int newProcessCount = oldProcessCount + 1; processCountMap.put(computer, newProcessCount); } } private void retract(CloudProcess process) { CloudComputer computer = process.getComputer(); if (computer != null) { // ... CPU power update ... cpuPowerUsageMap.put(computer, newCpuPowerUsage); // ... Memory update ... memoryUsageMap.put(computer, newMemoryUsage); // ... Network bandwidth update ... networkBandwidthUsageMap.put(computer, newNetworkBandwidthUsage); } } } ``` ### Response N/A ``` -------------------------------- ### Build Planner Benchmark with Multiple Datasets Source: https://docs.timefold.ai/timefold-solver/0.8.x/benchmarking-and-tweaking/benchmarking-and-tweaking Shows how to build a PlannerBenchmark instance when datasets are loaded in advance and passed directly to the buildPlannerBenchmark method, bypassing file input. ```java PlannerBenchmark plannerBenchmark = benchmarkFactory.buildPlannerBenchmark(dataset1, dataset2, dataset3); ``` -------------------------------- ### NQueens Advanced Incremental Score Calculator Example Source: https://docs.timefold.ai/timefold-solver/0.8.x/score-calculation/score-calculation?docs=1 A practical example of implementing the IncrementalScoreCalculator for the N-Queens problem, demonstrating how to manage state and update the score incrementally. ```APIDOC ## NQueens Advanced Incremental Score Calculator Example ### Description This example shows a concrete implementation of `IncrementalScoreCalculator` for the N-Queens problem. It uses HashMaps to track queen placements and incrementally updates the score based on added, removed, or changed entities and variables. ### Class Definition ```java public class NQueensAdvancedIncrementalScoreCalculator implements IncrementalScoreCalculator { private Map> rowIndexMap; private Map> ascendingDiagonalIndexMap; private Map> descendingDiagonalIndexMap; private int score; @Override public void resetWorkingSolution(NQueens nQueens) { // ... initialization logic ... score = 0; for (Queen queen : nQueens.getQueenList()) { insert(queen); } } @Override public void beforeEntityAdded(Object entity) { // No-op } @Override public void afterEntityAdded(Object entity) { insert((Queen) entity); } @Override public void beforeVariableChanged(Object entity, String variableName) { retract((Queen) entity); } @Override public void afterVariableChanged(Object entity, String variableName) { insert((Queen) entity); } @Override public void beforeEntityRemoved(Object entity) { retract((Queen) entity); } @Override public void afterEntityRemoved(Object entity) { // No-op } private void insert(Queen queen) { // ... logic to update score and maps when inserting a queen ... } private void retract(Queen queen) { // ... logic to update score and maps when retracting a queen ... } @Override public SimpleScore calculateScore() { return SimpleScore.valueOf(score); } } ``` ### Configuration To use this incremental score calculator, configure it in your solver configuration XML: ```xml ai.timefold.solver.examples.nqueens.optional.score.NQueensAdvancedIncrementalScoreCalculator ``` ``` -------------------------------- ### Create Uninitialized Planning Solution Source: https://docs.timefold.ai/timefold-solver/0.8.x/configuration/configuration?platform=1 Demonstrates how to instantiate a @PlanningSolution and populate it with planning entities where planning variables are left as null. This is the standard approach for preparing a dataset for the solver. ```java private NQueens createNQueens(int n) { NQueens nQueens = new NQueens(); nQueens.setId(0L); nQueens.setN(n); nQueens.setColumnList(createColumnList(nQueens)); nQueens.setRowList(createRowList(nQueens)); nQueens.setQueenList(createQueenList(nQueens)); return nQueens; } private List createQueenList(NQueens nQueens) { int n = nQueens.getN(); List queenList = new ArrayList(n); long id = 0L; for (Column column : nQueens.getColumnList()) { Queen queen = new Queen(); queen.setId(id); id++; queen.setColumn(column); queenList.add(queen); } return queenList; } ``` -------------------------------- ### Run Cloud Balancing Hello World (Java) Source: https://docs.timefold.ai/timefold-solver/0.8.x/use-cases-and-examples/cloud-balancing/cloud-balancing This code demonstrates how to initialize and run the Timefold Solver for the cloud balancing problem. It involves building a Solver instance, loading an unsolved problem, solving it, and displaying the results. Dependencies include Timefold Solver API and a problem generator. ```java import ai.timefold.solver.core.api.solver.SolverFactory; import ai.timefold.solver.core.api.solver.Solver; import ai.timefold.solver.core.config.solver.SolverConfig; import java.time.Duration; public class CloudBalancingHelloWorld { public static void main(String[] args) { // Build the Solver using XML configuration SolverFactory solverFactoryXml = SolverFactory.createFromXmlResource( "ai/timefold/solver/examples/cloudbalancing/solver/cloudBalancingSolverConfig.xml"); Solver solverXml = solverFactoryXml.buildSolver(); // Build the Solver using programmatic configuration SolverFactory solverFactoryProgrammatic = SolverFactory.create(new SolverConfig() .withSolutionClass(CloudBalance.class) .withEntityClasses(CloudProcess.class) .withEasyScoreCalculatorClass(CloudBalancingEasyScoreCalculator.class) .withTerminationSpentLimit(Duration.ofMinutes(2))); Solver solverProgrammatic = solverFactoryProgrammatic.buildSolver(); // Load a problem CloudBalance unsolvedCloudBalance = new CloudBalancingGenerator().createCloudBalance(400, 1200); // Solve the problem CloudBalance solvedCloudBalance = solverXml.solve(unsolvedCloudBalance); // Using solver built from XML // Display the result System.out.println("Solved cloudBalance with 400 computers and 1200 processes:\n" + toDisplayString(solvedCloudBalance)); } // Placeholder for toDisplayString method private static String toDisplayString(CloudBalance balance) { return "Display string representation of solved balance."; } } ``` -------------------------------- ### Implement Custom SolutionFileIO Source: https://docs.timefold.ai/timefold-solver/0.8.x/benchmarking-and-tweaking/benchmarking-and-tweaking?platform=1 Demonstrates how to configure a custom SolutionFileIO implementation for non-standard formats like text or binary files. ```xml ai.timefold.solver.examples.machinereassignment.persistence.MachineReassignmentFileIO data/machinereassignment/import/model_a1_1.txt ``` -------------------------------- ### Configure Custom Solution File IO in Benchmark Source: https://docs.timefold.ai/timefold-solver/0.8.x/benchmarking-and-tweaking/benchmarking-and-tweaking Demonstrates how to configure a custom SolutionFileIO implementation for reading and writing solutions in formats other than JSON or XML, such as TXT or binary. ```xml ai.timefold.solver.examples.machinereassignment.persistence.MachineReassignmentFileIO data/machinereassignment/import/model_a1_1.txt ... ``` -------------------------------- ### Java N-Queens Easy Score Calculation Example Source: https://docs.timefold.ai/timefold-solver/0.8.x/score-calculation/score-calculation An example implementation of the EasyScoreCalculator interface for the N-Queens problem. It calculates the score by iterating through queen pairs and checking for conflicts in rows and diagonals. The score is decremented for each conflict. ```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); } } ``` -------------------------------- ### Configure Simple Construction Heuristic Source: https://docs.timefold.ai/timefold-solver/0.8.x/construction-heuristics/construction-heuristics?platform=1 Demonstrates the basic XML configuration for a construction heuristic using the ALLOCATE_ENTITY_FROM_QUEUE type. ```xml ALLOCATE_ENTITY_FROM_QUEUE ``` -------------------------------- ### N-Queens Incremental Score Calculator Example in Java Source: https://docs.timefold.ai/timefold-solver/0.8.x/score-calculation/score-calculation?docs=1 An example implementation of `IncrementalScoreCalculator` for the N-Queens problem. This class demonstrates how to incrementally update the score by maintaining maps for rows and diagonals, efficiently calculating score changes when entities are added, removed, or modified. ```java public class NQueensAdvancedIncrementalScoreCalculator implements IncrementalScoreCalculator { private Map> rowIndexMap; private Map> ascendingDiagonalIndexMap; private Map> descendingDiagonalIndexMap; private int score; public void resetWorkingSolution(NQueens nQueens) { int n = nQueens.getN(); rowIndexMap = new HashMap>(n); ascendingDiagonalIndexMap = new HashMap>(n * 2); descendingDiagonalIndexMap = new HashMap>(n * 2); for (int i = 0; i < n; i++) { rowIndexMap.put(i, new ArrayList(n)); ascendingDiagonalIndexMap.put(i, new ArrayList(n)); descendingDiagonalIndexMap.put(i, new ArrayList(n)); if (i != 0) { ascendingDiagonalIndexMap.put(n - 1 + i, new ArrayList(n)); descendingDiagonalIndexMap.put((-i), new ArrayList(n)); } } score = 0; for (Queen queen : nQueens.getQueenList()) { insert(queen); } } public void beforeEntityAdded(Object entity) { // Do nothing } public void afterEntityAdded(Object entity) { insert((Queen) entity); } public void beforeVariableChanged(Object entity, String variableName) { retract((Queen) entity); } public void afterVariableChanged(Object entity, String variableName) { insert((Queen) entity); } public void beforeEntityRemoved(Object entity) { retract((Queen) entity); } public void afterEntityRemoved(Object entity) { // Do nothing } private void insert(Queen queen) { Row row = queen.getRow(); if (row != null) { int rowIndex = queen.getRowIndex(); List rowIndexList = rowIndexMap.get(rowIndex); score -= rowIndexList.size(); rowIndexList.add(queen); List ascendingDiagonalIndexList = ascendingDiagonalIndexMap.get(queen.getAscendingDiagonalIndex()); score -= ascendingDiagonalIndexList.size(); ascendingDiagonalIndexList.add(queen); List descendingDiagonalIndexList = descendingDiagonalIndexMap.get(queen.getDescendingDiagonalIndex()); score -= descendingDiagonalIndexList.size(); descendingDiagonalIndexList.add(queen); } } private void retract(Queen queen) { Row row = queen.getRow(); if (row != null) { List rowIndexList = rowIndexMap.get(queen.getRowIndex()); rowIndexList.remove(queen); score += rowIndexList.size(); List ascendingDiagonalIndexList = ascendingDiagonalIndexMap.get(queen.getAscendingDiagonalIndex()); ascendingDiagonalIndexList.remove(queen); score += ascendingDiagonalIndexList.size(); List descendingDiagonalIndexList = descendingDiagonalIndexMap.get(queen.getDescendingDiagonalIndex()); descendingDiagonalIndexList.remove(queen); score += descendingDiagonalIndexList.size(); } } public SimpleScore calculateScore() { return SimpleScore.valueOf(score); } } ``` -------------------------------- ### SelectionOrder Configuration Example Source: https://docs.timefold.ai/timefold-solver/0.8.x/move-and-neighborhood-selection/move-and-neighborhood-selection?platform=1 Demonstrates how to set the selectionOrder within a moveSelector configuration. ```APIDOC ## POST /api/configure/selectionOrder ### Description This endpoint allows configuring the `selectionOrder` for various selectors within the Timefold Solver configuration. The `selectionOrder` determines the sequence in which selections (like Moves, entities, or values) are iterated over by the optimization algorithm. ### Method POST ### Endpoint /api/configure/selectionOrder ### Parameters #### Request Body - **selectorConfig** (object) - Required - Configuration object for the selector. - **selectionOrder** (string) - Required - The desired order for selection. Accepted values: ORIGINAL, SORTED, RANDOM, SHUFFLED, PROBABILISTIC. - **cacheType** (string) - Optional - The cache type to be used with the selector. ### Request Example ```json { "selectorConfig": { "selectionOrder": "RANDOM", "cacheType": "JUST_IN_TIME" } } ``` ### Response #### Success Response (200) - **message** (string) - Confirmation message indicating successful configuration. #### Response Example ```json { "message": "SelectionOrder configured successfully." } ``` ``` -------------------------------- ### GET /api/shadow-variables Source: https://docs.timefold.ai/timefold-solver/0.8.x/shadow-variable/shadow-variable?docs=1 Retrieves information about shadow variable configurations and their relationship to planning entities. ```APIDOC ## GET /api/shadow-variables ### Description Returns a list of configured shadow variables and their associated planning entity classes. This endpoint helps developers understand which variables are automatically updated by the solver. ### Method GET ### Endpoint /api/shadow-variables ### Parameters #### Query Parameters - **entityClass** (string) - Optional - Filter results by a specific planning entity class name. ### Request Example GET /api/shadow-variables?entityClass=Vehicle ### Response #### Success Response (200) - **variables** (array) - List of shadow variable objects containing name, source, and entity type. #### Response Example { "variables": [ { "name": "arrivalTime", "source": "previousStandstill", "entity": "Customer" } ] } ``` -------------------------------- ### Initialize Planning Entities from Data Layer Source: https://docs.timefold.ai/timefold-solver/0.8.x/configuration/configuration?platform=1 Shows how to aggregate data from a domain model and create uninitialized planning entities for a schedule. ```java private void createLectureList(CourseSchedule schedule) { List courseList = schedule.getCourseList(); List lectureList = new ArrayList(courseList.size()); long id = 0L; for (Course course : courseList) { for (int i = 0; i < course.getLectureSize(); i++) { Lecture lecture = new Lecture(); lecture.setId(id); id++; lecture.setCourse(course); lecture.setLectureIndexInCourse(i); lectureList.add(lecture); } } schedule.setLectureList(lectureList); } ``` -------------------------------- ### GET /api/score/interface Source: https://docs.timefold.ai/timefold-solver/0.8.x/score-calculation/score-calculation?platform=1 Retrieves the definition and implementation guidelines for the Score interface used in Timefold solvers. ```APIDOC ## GET /api/score/interface ### Description Provides the structure of the Score interface which extends Comparable. Users must implement a consistent Score type throughout the Solver runtime. ### Method GET ### Endpoint /api/score/interface ### Request Example {} ### Response #### Success Response (200) - **interface** (string) - The Java interface definition for Score. - **implementation_guidelines** (string) - Instructions on using built-in types like HardSoftScore or custom implementations. #### Response Example { "interface": "public interface Score<...> extends Comparable<...>", "implementation_guidelines": "Use HardSoftScore for most use cases or implement custom Score for specific requirements." } ```