JBoss.orgCommunity Documentation
Hard constraints which must be fulfilled:
Soft constraints which should be optimized:
Let's start by taking a look at the domain model. It's pretty simple:
In the UML class diagram above, the Planner concepts are already annotated:
Try it yourself. Download and configure the examples in your
favorite IDE. Run org.optaplanner.examples.cloudbalancing.app.CloudBalancingHelloWorld
.
By default, it is configured to run for 120 seconds. It will execute this code:
The code above does this:
Build the Solver
based on a solver configuration (in this case an XML file).
SolverFactory solverFactory = new XmlSolverFactory(
"/org/optaplanner/examples/cloudbalancing/solver/cloudBalancingSolverConfig.xml");
Solver solver = solverFactory.buildSolver();
Load the problem. CloudBalancingGenerator
generates a random problem: you'll replace
this with a class that loads a real problem, for example from a database.
CloudBalance unsolvedCloudBalance = new CloudBalancingGenerator().createCloudBalance(400, 1200);
Solve the problem.
solver.setPlanningProblem(unsolvedCloudBalance);
solver.solve();
CloudBalance solvedCloudBalance = (CloudBalance) solver.getBestSolution();
Display the result.
System.out.println("\nSolved cloudBalance with 400 computers and 1200 processes:\n"
+ toDisplayString(solvedCloudBalance));
The only non-obvious part is building the Solver
. Let's examine that.
Take a look at the solver configuration:
This solver configuration consists out of 3 parts:
Domain model configuration: What can Planner change? We need to make Planner aware of our domain classes:
<solutionClass>org.optaplanner.examples.cloudbalancing.domain.CloudBalance</solutionClass>
<planningEntityClass>org.optaplanner.examples.cloudbalancing.domain.CloudProcess</planningEntityClass>
Score configuration: How should Planner optimize the planning
variables? Since we have hard and soft constraints, we use a HardSoftScore
. But we also
need to tell Planner how to calculate such the score, depending on our business requirements. Further down, we
'll look into 2 alternatives to calculate the score: using a simple Java implementation or using Drools
DRL.
<scoreDirectorFactory>
<scoreDefinitionType>HARD_SOFT</scoreDefinitionType>
<simpleScoreCalculatorClass>org.optaplanner.examples.cloudbalancing.solver.score.CloudBalancingSimpleScoreCalculator</simpleScoreCalculatorClass>
<!--<scoreDrl>/org/optaplanner/examples/cloudbalancing/solver/cloudBalancingScoreRules.drl</scoreDrl>-->
</scoreDirectorFactory>
Optimization algorithms configuration: How should Planner optimize it? Don't worry about this for now: this is a good default configuration that works on most planning problems. It will already surpass human planners and most in-house implementations. Using the Planner benchmark toolkit, you can tweak it to get even better results.
<termination>
<maximumSecondsSpend>120</maximumSecondsSpend>
</termination>
<constructionHeuristic>
<constructionHeuristicType>FIRST_FIT_DECREASING</constructionHeuristicType>
<constructionHeuristicPickEarlyType>FIRST_LAST_STEP_SCORE_EQUAL_OR_IMPROVING</constructionHeuristicPickEarlyType>
</constructionHeuristic>
<localSearch>
<acceptor>
<planningEntityTabuSize>7</planningEntityTabuSize>
</acceptor>
<forager>
<minimalAcceptedSelection>1000</minimalAcceptedSelection>
</forager>
</localSearch>
Let's examine the domain model classes and the score configuration.
Let's take a look look at 2 different implementations:
<scoreDirectorFactory>
<scoreDefinitionType>HARD_SOFT</scoreDefinitionType>
<simpleScoreCalculatorClass>org.optaplanner.examples.cloudbalancing.solver.score.CloudBalancingSimpleScoreCalculator</simpleScoreCalculatorClass>
</scoreDirectorFactory>
Just implement the method calculateScore(Solution)
to return a
HardSoftScore
instance.
Even if we optimize the code above to use Map
s to iterate through the
processList
only once, it is still slow because it doesn't
do incremental score calculation. To fix that, either use an incremental Java score function or a Drools score
function. Let's take a look at the latter.
To use the Drools rule engine as a score function, simply add a scoreDrl
resource in
the classpath:
<scoreDirectorFactory>
<scoreDefinitionType>HARD_SOFT</scoreDefinitionType>
<scoreDrl>/org/optaplanner/examples/cloudbalancing/solver/cloudBalancingScoreRules.drl</scoreDrl>
</scoreDirectorFactory>
Next, if those constraints are met, we want to minimize the maintenance cost, so we add that as a soft constraint:
Example 2.8. cloudBalancingScoreRules.drl - soft constraints
// ############################################################################ // Soft constraints // ############################################################################ rule "computerCost" when $computer : CloudComputer($cost : cost) exists CloudProcess(computer == $computer) then scoreHolder.addSoftConstraintMatch(kcontext, - $cost); end
If you use the Drools rule engine for score calculation, you can integrate with other Drools technologies, such as decision tables (XLS or web based), the Guvnor rule repository, ...