Toggle navigation OptaPlanner logo
  • Home
  • Download
  • Learn
    • Documentation
    • Videos
    • Slides
    • Training
    • Use cases
    • Compatibility
    • Testimonials and case studies
  • Get help
  • Source
  • Team
  • Services
  • Star
  • @OptaPlanner
  • Fb
Fork me on GitHub

Upgrade recipe 6.1

OptaPlanner’s public API classes are backwards compatible (per series), but users often also use impl classes (which are documented in the reference manual too). This upgrade recipe minimizes the pain to upgrade your code and to take advantage of the newest features in OptaPlanner 6.1.

Legend

Every upgrade note has an indication how likely your code will be affected by that change:

  • Major Likely to affect your code.
  • Minor Unlikely to affect your code (especially if you followed the examples), unless you have hacks.
  • Impl detail Will not affect your code, unless you have very deep hacks.
  • Recommended Not a backward incompatible change, but you probably want to do this.
  • Readme Read this to better understand why the subsequent major changes were made.

Upgrade from an older version

To upgrade from an older version, first apply the previous upgrade recipes.

Note for Red Hat Decision Manager customers

The RHDM version differs from the OptaPlanner version:

RHDM version OptaPlanner version
7.7 7.33
7.8 7.39
7.9 7.44

From 6.0.0.Final to 6.1.0.Beta1

Backwards Compatible Public API

As promised, starting from OptaPlanner 6.1.0.Final, there will be a public API, which will be backwards compatible in later versions (such as 6.2, 6.3, etc). The public API are all classes in the package org.optaplanner.core.api (or subpackages thereof). For more information, see the documentation, chapter "Status of OptaPlanner". Bear with us: this should be the last time we require you to do a large number of migrations during upgrading.

Simulated Annealing behaviour change

Simulated Annealing now uses the time gradient of the current step instead of the time gradient of the last step. The impact of this change is negligible.

AbstractScore: methods changes

On AbstractScore, the methods parseLevelStrings(…​) and buildScorePattern(…​) have been changed from public to protected. It’s highly unlikely that this affects your code.

@ValueRangeProvider that returns numbers: use ValueRange

If you have @ValueRangeProvider that returns a collection of numbers (for example List<Integer> or List<BigDecimal>), then you probably want to switch to a ValueRange, which uses less memory and offers additional opportunities.

Before in *.java:

@ValueRangeProvider(id = "delayRange")
public List<Integer> getDelayRange() {
    List<Integer> = new ArrayList<Integer>(5000);
    for (int i = 0; i < 5000; i++) {
        delayRange.add(i);
    }
    return delayRange;
}

After in *.java:

@ValueRangeProvider(id = "delayRange")
public CountableValueRange<Integer> getDelayRange() {
    return ValueRangeFactory.createIntValueRange(0, 5000);
}

@ValueRangeProvider: moved

The annotation @ValueRangeProvider has been moved into another package

Before in *.java:

import org.optaplanner.core.api.domain.value.ValueRangeProvider;

After in *.java:

import org.optaplanner.core.api.domain.valuerange.ValueRangeProvider;

Descriptor classes: moved

The *Descriptor classes have been moved into a descriptor package.

Selector: isContinuous() renamed

Selector.isContinuous() has been renamed to isCountable and its boolean return value has been inverted. It’s highly unlikely that your code uses isContinuous() because uncountable value ranges weren’t supported yet.

SolutionDescriptor: isInitialized(…​) changed

SolutionDescriptor.isInitialized(Solution) now requires a ScoreDirector parameter too

IMPROVING_STEP_PERCENTAGE removed

The deprecated statisticType IMPROVING_STEP_PERCENTAGE has been removed.

Before in *BenchmarkConfig.xml:

<problemBenchmarks>
  ...
  <problemStatisticType>IMPROVING_STEP_PERCENTAGE</problemStatisticType>
</problemBenchmarks>

Custom Benchmarker ranking: Benchmark classes renamed

If you have custom Benchmarker ranking: SolverBenchmark has been renamed to SolverBenchmarkResult. ProblemBenchmark has been renamed to ProblemBenchmarkResult. SingleBenchmark has been renamed to SingleBenchmarkResult. They also moved into the package result.

Before in *.java:

public int compare(SolverBenchmark a, SolverBenchmark b) {...}

After in *.java:

public int compare(SolverBenchmarkResult a, SolverBenchmarkResult b) {...}

Before in *.java:

public Comparable createRankingWeight(List<SolverBenchmark> solverBenchmarkList, SolverBenchmark solverBenchmark) {...}

After in *.java:

public Comparable createRankingWeight(List<SolverBenchmarkResult> solverBenchmarkResultList, SolverBenchmarkResult solverBenchmarkResult) {...}

Non-default Benchmarker rank: config change

If you explicitly specify Benchmarker rankings: All solverBenchmarkRanking* properties have been renamed to solverRanking*.

Before in *BenchmarkConfig.xml:

   <solverBenchmarkRankingType>TOTAL_SCORE</solverBenchmarkRankingType>

After in *BenchmarkConfig.xml:

   <solverRankingType>TOTAL_SCORE</solverRankingType>

Before in *BenchmarkConfig.xml:

   <solverBenchmarkRankingComparatorClass>...</solverBenchmarkRankingComparatorClass>

After in *BenchmarkConfig.xml:

   <solverRankingComparatorClass>...</solverRankingComparatorClass>

Before in *BenchmarkConfig.xml:

   <solverBenchmarkRankingWeightFactoryClass>...</solverBenchmarkRankingWeightFactoryClass>

After in *BenchmarkConfig.xml:

   <solverRankingWeightFactoryClass>...</solverRankingWeightFactoryClass>

Before in *.java:

   ... implements SolverRankingWeightFactory

After in *.java:

   ... implements SolverBenchmarkRankingWeightFactory

optaplanner-benchmark refactoring

The internals of optaplanner-benchmark have been deeply refactored to support the new aggregator functionality.

Benchmarker: output report directory structure changed

The benchmark output report directory structure is slightly different: the CSV files have been renamed.

Non-default Benchmarker ranking or report locale: config change

If you explicitly specify Benchmarker rankings or report locale: The elements <benchmarkReportLocale>, <solverRankingType>, <solverRankingComparatorClass> and <solverRankingWeightFactoryClass> have been moved inside the new element <benchmarkReport>.

Before in *BenchmarkConfig.xml:

<benchmarkReportLocale>...</benchmarkReportLocale>

After in *BenchmarkConfig.xml:

<benchmarkReport>
  <locale>...</locale>
</benchmarkReport>

Before in *BenchmarkConfig.xml:

<solverRankingType>...</solverRankingType>

After in *BenchmarkConfig.xml:

<benchmarkReport>
  <solverRankingType>...</solverRankingType>
</benchmarkReport>

<entitySelector>: <cacheType>PHASE</cacheType> obsolete

If you explicitly configured all your <entitySelector> elements with <cacheType>PHASE</cacheType> for performance, you now no longer have to do that, as OptaPlanner does the fast thing out of the box, if and only if no other properties (such as filtering) were specified on that <entitySelector>.

Before in *SolverConfig.xml and *BenchmarkConfig.xml:

<unionMoveSelector>
  <changeMoveSelector>
    <entitySelector>
      <cacheType>PHASE</cacheType>
    </entitySelector>
  </changeMoveSelector>
  <swapMoveSelector>
    <entitySelector>
      <cacheType>PHASE</cacheType>
    </entitySelector>
  </swapMoveSelector>
</unionMoveSelector>

After in *SolverConfig.xml and *BenchmarkConfig.xml:

<unionMoveSelector>
  <changeMoveSelector/>
  <swapMoveSelector/>
</unionMoveSelector>

time spend typo fixed

The phrase time spend has been renamed to time spent. This includes the log output and the benchmark report.

<termination>: config changed

All child elements of <termination> have been renamed: The element <maximumTimeMillisSpend> has been renamed to <millisecondsSpentLimit> The element <maximumSecondsSpend> has been renamed to <secondsSpentLimit> The element <maximumMinutesSpend> has been renamed to <minutesSpentLimit> The element <maximumHoursSpend> has been renamed to <hoursSpentLimit> The element <scoreAttained> has been renamed to <bestScoreLimit> The element <maximumStepCount> has been renamed to <stepCountLimit> The element <maximumUnimprovedStepCount> has been renamed to <unimprovedStepCountLimit>

Before in *SolverConfig.xml and *BenchmarkConfig.xml:

<termination>
  <maximumTimeMillisSpend>...</maximumTimeMillisSpend>
  <maximumSecondsSpend>...</maximumSecondsSpend>
  <maximumMinutesSpend>...</maximumMinutesSpend>
  <maximumHoursSpend>...</maximumHoursSpend>
  <scoreAttained>...</scoreAttained>
  <maximumStepCount>...</maximumStepCount>
  <maximumUnimprovedStepCount>...</maximumUnimprovedStepCount>
</termination>

After in *SolverConfig.xml and *BenchmarkConfig.xml:

<termination>
  <millisecondsSpentLimit>...</millisecondsSpentLimit>
  <secondsSpentLimit>...</secondsSpentLimit>
  <minutesSpentLimit>...</minutesSpentLimit>
  <hoursSpentLimit>...</hoursSpentLimit>
  <bestScoreLimit>...</bestScoreLimit>
  <stepCountLimit>...</stepCountLimit>
  <unimprovedStepCountLimit>...</unimprovedStepCountLimit>
</termination>

Solver and BestSolutionChangedEvent: getTimeMillisSpend() renamed

In Solver and BestSolutionChangedEvent, the method getTimeMillisSpend() has been renamed to getTimeMillisSpent().

Before in *.java:

... = solver.getTimeMillisSpend();

After in *.java:

... = solver.getTimeMillisSpent();

Before in *.java:

    public void bestSolutionChanged(BestSolutionChangedEvent event) {
        ... = event.getTimeMillisSpend();
    }

After in *.java:

    public void bestSolutionChanged(BestSolutionChangedEvent event) {
        ... = event.getTimeMillisSpent();
    }

Benchmarker: <warmUp*> config renamed

Benchmarker: the <warmUp*> elements have been renamed: The element <warmUpTimeMillisSpend> has been renamed to <warmUpMillisecondsSpentLimit> The element <warmUpSecondsSpend> has been renamed to <warmUpSecondsSpentLimit> The element <warmUpMinutesSpend> has been renamed to <warmUpMinutesSpentLimit> The element <warmUpHoursSpend> has been renamed to <warmUpHoursSpentLimit>

Before in *BenchmarkConfig.xml:

<plannerBenchmark>
  <warmUpTimeMillisSpend>...</warmUpTimeMillisSpend>
  <warmUpSecondsSpend>...</warmUpSecondsSpend>
  <warmUpMinutesSpend>...</warmUpMinutesSpend>
  <warmUpHoursSpend>...</warmUpHoursSpend>
  ...
</plannerBenchmark>

After in *BenchmarkConfig.xml:

<plannerBenchmark>
  <warmUpMillisecondsSpentLimit>...</warmUpMillisecondsSpentLimit>
  <warmUpSecondsSpentLimit>...</warmUpSecondsSpentLimit>
  <warmUpMinutesSpentLimit>...</warmUpMinutesSpentLimit>
  <warmUpHoursSpentLimit>...</warmUpHoursSpentLimit>
  ...
</plannerBenchmark>

Real time planning: addProblemFactChange(…​) behaviour changed

Real time planning: addProblemFactChange(…​) no longer causes solver `Termination`s to reset (but it still causes phase terminations to reset).

BestSolutionChangedEvent and SolverEventListener: moved

Classes BestSolutionChangedEvent and SolverEventListener moved from package impl.event to api.solver.event. They are now part of the public api.

Before in *.java:

import org.optaplanner.core.impl.event.BestSolutionChangedEvent;
import org.optaplanner.core.impl.event.SolverEventListener;

After in *.java:

import org.optaplanner.core.api.solver.event.BestSolutionChangedEvent;
import org.optaplanner.core.api.solver.event.SolverEventListener;

Package config.termination: moved

The package config.termination has been moved to config.solver.termination. Similarly, the package impl.termination has been moved to impl.solver.termination.

Before in *.java:

import org.optaplanner.core.config.termination....;
import org.optaplanner.core.impl.termination....;

After in *.java:

import org.optaplanner.core.config.solver.termination....;
import org.optaplanner.core.impl.solver.termination....;

RandomUtils: moved

RandomUtils moved from package impl.util to impl.solver.random.

AbstractSolverPhaseScope and AbstractStepScope: moved

AbstractSolverPhaseScope and AbstractStepScope moved to package impl.phase.scope.

Package impl.move: moved

All classes in the package impl.move have been moved to impl.heuristic.move. None of them are future-proof enough at this time to be added the public API. Prefer generic moves whenever possible.

Before in *.java:

import org.optaplanner.core.impl.move.Move;
import org.optaplanner.core.impl.move.CompositeMove;
import org.optaplanner.core.impl.move.NoChangeMove;

After in *.java:

import org.optaplanner.core.impl.heuristic.move.Move;
import org.optaplanner.core.impl.heuristic.move.CompositeMove;
import org.optaplanner.core.impl.heuristic.move.NoChangeMove;

PLANNING_ENTITY_TABU and PLANNING_VALUE_TABU: renamed

The <acceptorType> values PLANNING_ENTITY_TABU and PLANNING_VALUE_TABU are renamed to ENTITY_TABU and VALUE_TABU. It’s very unlikely that you’re using either, because neither specifies the tabu size.

Before in *SolverConfig.xml and *BenchmarkConfig.xml:

<acceptorType>PLANNING_ENTITY_TABU</acceptorType>

After in *SolverConfig.xml and *BenchmarkConfig.xml:

<acceptorType>ENTITY_TABU</acceptorType>

Before in *SolverConfig.xml and *BenchmarkConfig.xml:

<acceptorType>PLANNING_VALUE_TABU</acceptorType>

After in *SolverConfig.xml and *BenchmarkConfig.xml:

<acceptorType>VALUE_TABU</acceptorType>

BestSolutionRecaller: moved

BestSolutionRecaller moved from package impl.bestsolution to impl.solver.recaller.

Before in *.java:

import org.optaplanner.core.impl.bestsolution.BestSolutionRecaller;

After in *.java:

import org.optaplanner.core.impl.solver.recaller.BestSolutionRecaller;

From 6.1.0.Beta1 to 6.1.0.Beta2

PlanningEntityDescriptor: renamed

PlanningEntityDescriptor has been renamed to EntityDescriptor.

PlanningVariableDescriptor: renamed

PlanningVariableDescriptor has been renamed to GenuineVariableDescriptor.

PlanningVariableListener: renamed

The interface PlanningVariableListener has been renamed to VariableListener.

Before in *.java:

public class VehicleUpdatingVariableListener implements PlanningVariableListener<Customer> {

After in *.java:

public class VehicleUpdatingVariableListener implements VariableListener<Customer> {

AbstractPlanningVariableListener: renamed

The class AbstractPlanningVariableListener has been removed.

Before in *.java:

public class VehicleUpdatingVariableListener extends AbstractPlanningVariableListener<Customer> {

After in *.java:

public class VehicleUpdatingVariableListener implements VariableListener<Customer> {

solutionEquals() and solutionHashCode(): removed

If you’ve copied the solutionEquals() and solutionHashCode() from the examples, it’s safe to remove it if you’re not using solutionTabu (which is often pointless to use). Also remove the equals() and hashCode() method on your Solution implementation.

DEBUG logging: changed

In DEBUG logging, each step now mentions it’s phase type first: CH is Construction Heuristic, LS is Local Search, ES is Exhaustive Search.

GreatDelugeAcceptor: removed

GreatDelugeAcceptor, an experimental implementation, has been removed. Use Late Acceptance instead.

Before in *SolverConfig.xml and *BenchmarkConfig.xml:

  <greatDelugeWaterLevelUpperBoundRate>...</greatDelugeWaterLevelUpperBoundRate>
  <greatDelugeWaterRisingRate>...</greatDelugeWaterRisingRate>

Specify an <initializingScoreTrend>

Specify an <initializingScoreTrend> in the <scoreDirectorFactory>, to increase performance of some algorithms (Construction Heuristics and Exhaustive Search). See the documentation section on InitializingScoreTrend when to use ANY, ONLY_UP or ONLY_DOWN.

Before in *SolverConfig.xml and *BenchmarkConfig.xml:

  <scoreDirectorFactory>
<scoreDefinitionType>HARD_SOFT</scoreDefinitionType>
<scoreDrl>.../cloudBalancingScoreRules.drl</scoreDrl>
  </scoreDirectorFactory>

After in *SolverConfig.xml and *BenchmarkConfig.xml:

  <scoreDirectorFactory>
<scoreDefinitionType>HARD_SOFT</scoreDefinitionType>
<scoreDrl>.../cloudBalancingScoreRules.drl</scoreDrl>
<initializingScoreTrend>ONLY_DOWN</initializingScoreTrend>
  </scoreDirectorFactory>

<pickEarlyType>: replaced

Replace <pickEarlyType> FIRST_NON_DETERIORATING_SCORE with <initializingScoreTrend> ONLY_DOWN. If the <initializingScoreTrend> is specified, the <constructionHeuristic> will automatically use the most appropriate <pickEarlyType>.

Before in *SolverConfig.xml and *BenchmarkConfig.xml:

  <scoreDirectorFactory>
...
  </scoreDirectorFactory>
  ...
  <constructionHeuristic>
<constructionHeuristicType>FIRST_FIT_DECREASING</constructionHeuristicType>
<forager>
  <pickEarlyType>FIRST_NON_DETERIORATING_SCORE</pickEarlyType>
</forager>
  </constructionHeuristic>

After in *SolverConfig.xml and *BenchmarkConfig.xml:

  <scoreDirectorFactory>
...
<initializingScoreTrend>ONLY_DOWN</initializingScoreTrend>
  </scoreDirectorFactory>
  ...
  <constructionHeuristic>
<constructionHeuristicType>FIRST_FIT_DECREASING</constructionHeuristicType>
  </constructionHeuristic>

<bruteForce>: renamed

The solver phase <bruteForce> has been replaced by <exhaustiveSearch>'s BRUTE_FORCE type.

Before in *SolverConfig.xml and *BenchmarkConfig.xml:

  <bruteForce/>

After in *SolverConfig.xml and *BenchmarkConfig.xml:

  <exhaustiveSearch>
    <exhaustiveSearchType>BRUTE_FORCE</exhaustiveSearchType>
  </exhaustiveSearch>

There is now a better alternative to Brute Force: Branch And Bound, see docs for more information.

ConstraintOccurrence classes: removed

The ConstraintOccurrence classes (which were deprecated) have been removed. If you hadn’t switch them to the ConstraintMatch system yet, scroll up to the section From 6.0.0.Alpha9 to 6.0.0.Beta1 for instructions.

Solver: setPlanningProblem(Solution) and solve() merged

Solver interface: the methods setPlanningProblem(Solution) and solve() have been merged as the method solve(Solution).

Before in *.java:

solver.setPlanningProblem(planningProblem);
solver.solve();

After in *.java:

solver.solve(planningProblem);

Note: you still need to use solver.getBestSolution() to retrieve the best solution. That is intentional due to real-time planning and to support pareto optimization in the future.

From 6.1.0.Beta2 to 6.1.0.Beta3

@ValueRangeProvider on an entity class: use <swapMoveSelector> as is

If you have a @ValueRangeProvider on an entity class (instead of the Solution class), then it’s now safe to use the <swapMoveSelector> as is. It’s no longer needed to filter out swaps which could put a value in an entity’s variable that’s not in its value range.

Before in *SolverConfig.xml and *BenchmarkConfig.xml:

  <swapMoveSelector>
    <filterClass>...ValidSwapsOnlySwapMoveFilter</filterClass>
  </swapMoveSelector>

After in *SolverConfig.xml and *BenchmarkConfig.xml:

  <swapMoveSelector/>

ScoreDirector: split up

The interface ScoreDirector has been split up in ScoreDirector and InnerScoreDirector. ScoreDirector now only has methods which might make the public API in a future version. InnerScoreDirector extends ScoreDirector and it holds all methods which will never be made part of the public API. Similarly, ScoreDirectorFactory has been split up in ScoreDirectorFactory and InnerScoreDirectorFactory.

Programmatic configuration: usage changed

If you’re doing programmatic configuration (instead of by XML), Config methods that accepted a property wrapped in a singleton list (due to XStream limitations), now no longer need the property wrapped in a list.

Before in *.java:

  localSearchSolverPhaseConfig.setMoveSelectorConfigList(Collections.singletonList(moveSelectorConfig));

After in *.java:

  localSearchSolverPhaseConfig.setMoveSelectorConfig(moveSelectorConfig);

XmlSolverFactory: removed

The class XmlSolverFactory (which was not part of the public API) has been removed and replaced by static methods on SolverFactory (which are part of the public API).

Before in *.java:

SolverFactory solverFactory = new XmlSolverFactory("...solverConfig.xml");

After in *.java:

SolverFactory solverFactory = SolverFactory.createFromXmlResource("...solverConfig.xml");

Before in *.java:

SolverFactory solverFactory = new XmlSolverFactory().configure(inputStream);

After in *.java:

SolverFactory solverFactory = SolverFactory.createFromXmlInputStream(inputStream);

Before in *.java:

SolverFactory solverFactory = new XmlSolverFactory().configure(reader);

After in *.java:

SolverFactory solverFactory = SolverFactory.createFromXmlReader(reader);

Note: If you used the method addXstreamAnnotations(), take a look at the non-public API class XStreamXmlSolverFactory.

XmlPlannerBenchmarkFactory: removed

Benchmarker: The class XmlPlannerBenchmarkFactory has been removed and replaced by static methods on PlannerBenchmarkFactory.

Before in *.java:

PlannerBenchmarkFactory plannerBenchmarkFactory = new XmlPlannerBenchmarkFactory(...);

After in *.java:

PlannerBenchmarkFactory plannerBenchmarkFactory = PlannerBenchmarkFactory.createFromXmlResource(...);

Note: If you used the method addXstreamAnnotations(), take a look at the non-public API class XStreamXmlPlannerBenchmarkFactory.

FreemarkerXmlPlannerBenchmarkFactory: removed

Benchmarker: The class FreemarkerXmlPlannerBenchmarkFactory has been removed and replaced by static methods on PlannerBenchmarkFactory.

Before in *.java:

PlannerBenchmarkFactory plannerBenchmarkFactory = new FreemarkerXmlPlannerBenchmarkFactory(...);

After in *.java:

PlannerBenchmarkFactory plannerBenchmarkFactory = PlannerBenchmarkFactory.createFromFreemarkerXmlResource(...);

<xstreamAnnotatedClass>: renamed

Benchmarker configuration: the element <xstreamAnnotatedClass> has been renamed to <xStreamAnnotatedClass>.

Before in *BenchmarkConfig.xml:

<problemBenchmarks>
  <xstreamAnnotatedClass>org.optaplanner.examples.nqueens.domain.NQueens</xstreamAnnotatedClass>
  ...
</problemBenchmarks>

After in *BenchmarkConfig.xml:

<problemBenchmarks>
  <xStreamAnnotatedClass>org.optaplanner.examples.nqueens.domain.NQueens</xStreamAnnotatedClass>
  ...
</problemBenchmarks>

Classpath resources configuration changed

All classpath resources must lose their leading slash, because OptaPlanner now expects them to adhere to ClassLoader.getResource(String) instead of Class.getResource(String).

SolverFactory.createFromXmlResource(String): changed

The SolverFactory.createFromXmlResource(String) parameter must lose its leading slash.

Before in *.java:

... = SolverFactory.createFromXmlResource(
        "/org/optaplanner/examples/cloudbalancing/solver/cloudBalancingSolverConfig.xml");

After in *.java:

... = SolverFactory.createFromXmlResource(
        "org/optaplanner/examples/cloudbalancing/solver/cloudBalancingSolverConfig.xml");

<scoreDrl>: changed

All elements <scoreDrl> must lose their leading slash.

Before in *SolverConfig.xml and *BenchmarkConfig.xml:

<scoreDrl>/org/optaplanner/examples/cloudbalancing/solver/cloudBalancingScoreRules.drl</scoreDrl>

After in *SolverConfig.xml and *BenchmarkConfig.xml:

<scoreDrl>org/optaplanner/examples/cloudbalancing/solver/cloudBalancingScoreRules.drl</scoreDrl>

PlannerBenchmarkFactory.createFromXmlResource(String): changed

The PlannerBenchmarkFactory.createFromXmlResource(String) parameter must lose its leading slash.

Before in *.java:

... = PlannerBenchmarkFactory.createFromXmlResource(
        "/org/optaplanner/examples/cloudbalancing/benchmark/cloudBalancingBenchmarkConfig.xml");

After in *.java:

... = PlannerBenchmarkFactory.createFromXmlResource(
        "org/optaplanner/examples/cloudbalancing/benchmark/cloudBalancingBenchmarkConfig.xml");

PlannerBenchmarkFactory.createFromFreemarkerXmlResource(String): changed

The PlannerBenchmarkFactory.createFromFreemarkerXmlResource(String) parameter must lose its leading slash.

Before in *.java:

... = PlannerBenchmarkFactory.createFromFreemarkerXmlResource(
        "/org/optaplanner/examples/cloudbalancing/benchmark/cloudBalancingBenchmarkConfigTemplate.xml.ftl");

After in *.java:

... = PlannerBenchmarkFactory.createFromFreemarkerXmlResource(
        "org/optaplanner/examples/cloudbalancing/benchmark/cloudBalancingBenchmarkConfigTemplate.xml.ftl");

SimpleScoreCalculator: renamed

The interface SimpleScoreCalculator has been renamed to EasyScoreCalculator to avoid confusion with SimpleScore and SimpleScore: it can return other Score types too. The package name has changed too.

Before in *.java:

import org.optaplanner.core.impl.score.director.simple.SimpleScoreCalculator;
public class CloudBalancingEasyScoreCalculator implements SimpleScoreCalculator<CloudBalance> {
    ...
}

After in *.java:

import org.optaplanner.core.impl.score.director.easy.EasyScoreCalculator;
public class CloudBalancingEasyScoreCalculator implements EasyScoreCalculator<CloudBalance> {
    ...
}

Before in *SolverConfig.xml and *BenchmarkConfig.xml:

<simpleScoreCalculatorClass>org.optaplanner.examples.cloudbalancing.optional.score.CloudBalancingEasyScoreCalculator<simpleScoreCalculatorClass>

After in *SolverConfig.xml and *BenchmarkConfig.xml:

<easyScoreCalculatorClass>org.optaplanner.examples.cloudbalancing.optional.score.CloudBalancingEasyScoreCalculator<easyScoreCalculatorClass>

From 6.1.0.Beta3 to 6.1.0.Beta4

Custom ScoreDefinition: Score changed

If you have a custom ScoreDefinition: the Score interface has an extra method negate().

Simulated Annealing with <bestScoreLimit>: behaviour changed

If you combine Simulated Annealing with <bestScoreLimit>: The timeGradient (used only by Simulated Annealing) calculation has changed for BestScoreTermination. On average, this should be for the better.

BestSolutionChangedEvent and SolverEventListener: generified

BestSolutionChangedEvent and SolverEventListener now have a generic parameter which you can optionally use.

Before in *.java:

solver.addEventListener(new SolverEventListener() {
    public void bestSolutionChanged(BestSolutionChangedEvent event) {
        CloudBalance solution = (CloudBalance) event.getNewBestSolution();
    }
});

After in *.java:

solver.addEventListener(new SolverEventListener<CloudBalance>() {
    public void bestSolutionChanged(BestSolutionChangedEvent<CloudBalance> event) {
        CloudBalance solution = event.getNewBestSolution();
    }
});

BestSolutionChangedEvent: isNewBestSolutionInitialized() and isEveryProblemFactChangeProcessed() added

BestSolutionChangedEvent now has the methods isNewBestSolutionInitialized() and isEveryProblemFactChangeProcessed(). In real-time planning, if you’re only interested in processing valid solutions, you’ll want to filter and check those.

Note: in 6.0, filtering BestSolutionChangedEvents for only valid solutions was cumbersome.

Note: often you’re interested in invalid, uninitialized solutions too, to show to the user you’ve processed his problem fact changes.

After in *.java:

    public void bestSolutionChanged(BestSolutionChangedEvent<CloudBalance> event) {
        // Ignore invalid solutions
        if (event.isEveryProblemFactChangeProcessed()
                && event.isNewBestSolutionInitialized()
                && event.getNewBestSolution().getScore().isFeasible()) {
            ...
        }
    }

<writeOutputSolutionEnabled>: output location changed

A benchmark configuration with <writeOutputSolutionEnabled>true</…​> now writes the solution files in the single benchmark directory (instead of the problem benchmark directory) and no longer alters the filename.

<subChainChangeMoveSelector> and <subChainSwapMoveSelector>: default parameters changed

<subChainChangeMoveSelector> and <subChainSwapMoveSelector>'s <subChainSelector>s now default to a <minimumSubChainSize> of 1 instead of 2. This is to enable <subChainSwapMoveSelector> to swap a subchain of size 1 and a subchain of at least size 2 too.

<pillarSwapMoveSelector>: default parameters changed

<pillarSwapMoveSelector>'s <pillarSelector> now selects subpillars too by default. Normally, that’s an improvement.

Before in *SolverConfig.xml and *BenchmarkConfig.xml:

  <pillarSwapMoveSelector/>

After in *SolverConfig.xml and *BenchmarkConfig.xml (if you don’t want this new behaviour):

  <pillarSwapMoveSelector>
    <pillarSelector>
      <subPillarEnabled>false</subPillarEnabled>
    </pillarSelector>
  </pillarSwapMoveSelector>

Note: <pillarChangeMoveSelector> is not supported too

SolverPhase: renamed

SolverPhase has been renamed to Phase. SolverPhaseConfig has been renamed to PhaseConfig.

Before in *.java:

    List<SolverPhaseConfig> solverPhaseConfigList = new ArrayList<SolverPhaseConfig>();
    ConstructionHeuristicSolverPhaseConfig solverPhaseConfig = new ConstructionHeuristicSolverPhaseConfig();
    ...
    solverPhaseConfigList.add(solverPhaseConfig);
    ...
    solverConfig.setPhaseConfigList(phaseConfigList);

After in *.java:

    List<PhaseConfig> phaseConfigList = new ArrayList<PhaseConfig>();
    ConstructionHeuristicPhaseConfig phaseConfig = new ConstructionHeuristicPhaseConfig();
    ...
    phaseConfigList.add(phaseConfig);
    ...
    solverConfig.setPhaseConfigList(phaseConfigList);

CustomSolverPhaseCommand: renamed

The interface CustomSolverPhaseCommand has been renamed to CustomPhaseCommand. The element <customSolverPhase> has been renamed to <customPhase>. The element <customSolverPhaseCommandClass> has been renamed to <customPhaseCommandClass>.

Before in *.java:

public class ToOriginalMachineSolutionInitializer implements CustomSolverPhaseCommand {
    ...
}

After in *.java:

public class ToOriginalMachineSolutionInitializer implements CustomPhaseCommand {
    ...
}

Before in *SolverConfig.xml and *BenchmarkConfig.xml:

  <customSolverPhase>
<customSolverPhaseCommandClass>...ToOriginalMachineSolutionInitializer</customSolverPhaseCommandClass>
  </customSolverPhase>

After in *SolverConfig.xml and *BenchmarkConfig.xml:

  <customPhase>
<customPhaseCommandClass>....ToOriginalMachineSolutionInitializer</customPhaseCommandClass>
  </customPhase>

From 6.1.0.Beta4 to 6.1.0.CR1

ScoreDefinition: getLevelCount() renamed

The method ScoreDefinition.getLevelCount() has been renamed to ScoreDefinition.getLevelsSize().

BendableScore: configuration changed

BendableScore: the configuration has changed: …​LevelCount has been renamed to …​LevelsSize

Before in *SolverConfig.xml and *BenchmarkConfig.xml:

  <scoreDirectorFactory>
<scoreDefinitionType>BENDABLE</scoreDefinitionType>
<bendableHardLevelCount>2</bendableHardLevelCount>
<bendableSoftLevelCount>3</bendableSoftLevelCount>
...
  </scoreDirectorFactory>

After in *SolverConfig.xml and *BenchmarkConfig.xml:

  <scoreDirectorFactory>
<scoreDefinitionType>BENDABLE</scoreDefinitionType>
<bendableHardLevelsSize>2</bendableHardLevelsSize>
<bendableSoftLevelsSize>3</bendableSoftLevelsSize>
...
  </scoreDirectorFactory>

SolverRankingWeightFactory: moved

The interface SolverRankingWeightFactory has moved package (but almost nobody uses that).

Programmatic configuration: classes moved

Configuration by Java (instead of XML): Enums for the Config classes have been moved into the config package and any inner classes of those enums have been moved to the top level.

Before in *.java:

import org.optaplanner.core.config.score.director.ScoreDirectorFactoryConfig.ScoreDefinitionType;
import org.optaplanner.core.config.solver.termination.TerminationConfig.TerminationCompositionStyle;
import org.optaplanner.core.impl.heuristic.selector.common.SelectionCacheType;
import org.optaplanner.core.impl.heuristic.selector.common.decorator.SelectionSorterOrder;
import org.optaplanner.core.config.constructionheuristic.ConstructionHeuristicPhaseConfig.ConstructionHeuristicType;
import org.optaplanner.core.impl.constructionheuristic.decider.forager.ConstructionHeuristicPickEarlyType;
import org.optaplanner.core.impl.localsearch.decider.forager.PickEarlyType;
import org.optaplanner.core.config.localsearch.decider.acceptor.AcceptorConfig.AcceptorType;
import org.optaplanner.benchmark.impl.statistic.ProblemStatisticType;
import org.optaplanner.benchmark.api.ranking.SolverRankingType;

After in *.java:

import org.optaplanner.core.config.score.definition.ScoreDefinitionType;
import org.optaplanner.core.config.solver.termination.TerminationCompositionStyle;
import org.optaplanner.core.config.heuristic.selector.common.SelectionCacheType;
import org.optaplanner.core.config.heuristic.selector.common.decorator.SelectionSorterOrder;
import org.optaplanner.core.config.constructionheuristic.ConstructionHeuristicType;
import org.optaplanner.core.config.constructionheuristic.decider.forager.ConstructionHeuristicPickEarlyType;
import org.optaplanner.core.config.localsearch.decider.forager.LocalSearchPickEarlyType;
import org.optaplanner.core.config.localsearch.decider.acceptor.AcceptorType;
import org.optaplanner.benchmark.config.statistic.ProblemStatisticType;
import org.optaplanner.benchmark.config.ranking.SolverRankingType;

ForagerConfig: renamed

ForagerConfig has been renamed to LocalSearchForagerConfig

Solution: moved

The interface Solution has been promoted to the public API. It has also moved package from impl.solution to api.domain.solution

Before in *.java:

import org.optaplanner.core.impl.solution.Solution;

After in *.java:

import org.optaplanner.core.api.domain.solution.Solution;

@PlanningVariable: chained refactored

The @PlanningVariable property chained has been refactored to graphType. This is to allow support for other graph types (such as TREE) in the future.

Before in *.java:

@PlanningVariable(chained = true, ...)
public Standstill getPreviousStandstill() {
    return previousStandstill;
}

After in *.java:

@PlanningVariable(graphType = PlanningVariableGraphType.CHAINED, ...)
public Standstill getPreviousStandstill() {
    return previousStandstill;
}

BEST_FIT: renamed

The constructionHeuristicType BEST_FIT has been renamed into WEAKEST_FIT. The terminology "Best Fit" was not correct and did not allow for STRONGEST_FIT.

Before in *SolverConfig.xml and *BenchmarkConfig.xml:

  <constructionHeuristic>
    <constructionHeuristicType>BEST_FIT</constructionHeuristicType>
  </constructionHeuristic>

After in *SolverConfig.xml and *BenchmarkConfig.xml:

  <constructionHeuristic>
    <constructionHeuristicType>WEAKEST_FIT</constructionHeuristicType>
  </constructionHeuristic>

BEST_FIT_DECREASING: renamed

The constructionHeuristicType BEST_FIT_DECREASING has been renamed into WEAKEST_FIT_DECREASING. The terminology "Best Fit" was not correct and did not allow for STRONGEST_FIT_DECREASING.

Before in *SolverConfig.xml and *BenchmarkConfig.xml:

  <constructionHeuristic>
    <constructionHeuristicType>BEST_FIT_DECREASING</constructionHeuristicType>
  </constructionHeuristic>

After in *SolverConfig.xml and *BenchmarkConfig.xml:

  <constructionHeuristic>
    <constructionHeuristicType>WEAKEST_FIT_DECREASING</constructionHeuristicType>
  </constructionHeuristic>

@PlanningVariable(mappedBy) renamed

For the shadow variable of a bi-directional relationship, the declaration has changed from @PlanningVariable(mappedBy) to @InverseRelationShadowVariable(sourceVariableName).

Before in *.java:

@PlanningVariable(mappedBy = "previousStandstill")
Customer getNextCustomer();
void setNextCustomer(Customer nextCustomer);

After in *.java:

@InverseRelationShadowVariable(sourceVariableName = "previousStandstill")
Customer getNextCustomer();
void setNextCustomer(Customer nextCustomer);

VariableListener: usage changed

VariableListener: the VariableListener is now declared on the shadow side, instead of the @PlanningVariable side. This way, OptaPlanner recognizes the shadow variables, and all shadow variables are declared in a consistent matter. Furthermore, it allows a shadow variable to based on other shadow variable.

Before in *.java:

@PlanningVariable(valueRangeProviderRefs = {"vehicleRange", "customerRange"},
        graphType = PlanningVariableGraphType.CHAINED,
        variableListenerClasses = {VehicleUpdatingVariableListener.class, ArrivalTimeUpdatingVariableListener.class})
public Standstill getPreviousStandstill() {
    return previousStandstill;
}
public Vehicle getVehicle() {
    return vehicle;
}
public Integer getArrivalTime() {
    return arrivalTime;
}

After in *.java:

@PlanningVariable(...)
public Standstill getPreviousStandstill() {
    return previousStandstill;
}
@CustomShadowVariable(variableListenerClass = VehicleUpdatingVariableListener.class,
        sources = {@CustomShadowVariable.Source(variableName = "previousStandstill")})
public Vehicle getVehicle() {
    return vehicle;
}
@CustomShadowVariable(variableListenerClass = ArrivalTimeUpdatingVariableListener.class,
        sources = {@CustomShadowVariable.Source(variableName = "previousStandstill")})
public Integer getArrivalTime() {
    return arrivalTime;
}

Shadow entities

Even classes that only have shadow variables (and extend a planning entity class), now need to be explicitly registered as planning entities. Previously, it was only required for inverse relationship shadow variables. Now it’s required for all shadow variables.

Before in *.java:

public class TimeWindowedCustomer extends Customer {

After in *.java:

@PlanningEntity
public class TimeWindowedCustomer extends Customer {

After in *SolverConfig.xml and *BenchmarkConfig.xml:

<planningEntityClass>org.optaplanner.examples.vehiclerouting.domain.timewindowed.TimeWindowedCustomer</planningEntityClass>

<planningEntityClass>: ordering changed

Multiple <planningEntityClass> elements now need to be ordered by superclasses (and superinterfaces) first, instead of superclasses (and superinterfaces) last.

Before in *SolverConfig.xml and *BenchmarkConfig.xml:

<planningEntityClass>...TimeWindowedCustomer</planningEntityClass>
<planningEntityClass>...Customer</planningEntityClass>
<planningEntityClass>...Standstill</planningEntityClass>

After in *SolverConfig.xml and *BenchmarkConfig.xml:

<planningEntityClass>...Standstill</planningEntityClass>
<planningEntityClass>...Customer</planningEntityClass>
<planningEntityClass>...TimeWindowedCustomer</planningEntityClass>

<planningEntityClass>: renamed

The element <planningEntityClass> has been renamed to <entityClass>.

Before in *SolverConfig.xml and *BenchmarkConfig.xml:

<planningEntityClass>org.optaplanner.examples.cloudbalancing.domain.CloudProcess</planningEntityClass>

After in *SolverConfig.xml and *BenchmarkConfig.xml:

<entityClass>org.optaplanner.examples.cloudbalancing.domain.CloudProcess</entityClass>

XStreamScoreConverter and XStreamBendableScoreConverter: moved

XStreamScoreConverter and XStreamBendableScoreConverter have moved package.

Before in *.java:

import org.optaplanner.persistence.xstream.XStreamScoreConverter;

After in *.java:

import org.optaplanner.persistence.xstream.api.score.XStreamScoreConverter;

Before in *.java:

import org.optaplanner.persistence.xstream.XStreamBendableScoreConverter;

After in *.java:

import org.optaplanner.persistence.xstream.api.score.XStreamBendableScoreConverter;

ProblemIO: renamed

ProblemIO has been renamed to SolutionFileIO and moved package (into the public API).

Before in *.java:

import org.optaplanner.core.impl.solution.ProblemIO;
public class MachineReassignmentFileIO implements ProblemIO {
    ...
}

After in *.java:

import org.optaplanner.persistence.common.api.domain.solution.SolutionFileIO;
public class MachineReassignmentFileIO implements SolutionFileIO {
    ...
}

Before in *SolverConfig.xml and *BenchmarkConfig.xml:

<problemBenchmarks>
  <problemIOClass>...MachineReassignmentProblemIO</problemIOClass>
  ...
</problemBenchmarks>

After in *SolverConfig.xml and *BenchmarkConfig.xml:

<problemBenchmarks>
  <solutionFileIOClass>...MachineReassignmentFileIO</solutionFileIOClass>
  ...
</problemBenchmarks>

Before in *.java:

import org.optaplanner.persistence.xstream.XStreamProblemIO;

After in *.java:

import org.optaplanner.persistence.xstream.impl.domain.solution.XStreamSolutionFileIO;

SolutionFileIO: getFileExtension() split up

The method SolutionFileIO.getFileExtension() has been split up in getInputFileExtension() and getOutputFileExtension(); It’s still highly recommended to use the same input and output file extension.

Before in *.java:

public String getFileExtension() {
    return FILE_EXTENSION;
}

After in *.java:

public String getInputFileExtension() {
    return FILE_EXTENSION;
}
public String getOutputFileExtension() {
    return FILE_EXTENSION;
}

From 6.1.0.CR1 to 6.1.0.CR2

SolutionDescriptor: getEntityDescriptor(…​) renamed

SolutionDescriptor.getEntityDescriptor(…​) has been renamed to SolutionDescriptor.findEntityDescriptorOrFail(…​)

Comments

Visit our forum to comment
Latest release
  • 8.5.0.Final released
    Thu 15 April 2021
Paid support and consulting

Want to talk to the experts? Red Hat offers certified binaries with enterprise consulting. Contact optaplanner-info for more information.

Upcoming events
  • SouJava MOTU
    Worldwide - Thu 15 April 2021
    • Planejamento de Recursos com OptaPlanner by Karina Varela, Otávio Santana
Add event / Archive
Latest blog posts
  • Batch solving an ActiveMQ queue that contains planning problem data sets in a scalable way
    Thu 25 March 2021
     Radovan Synek
  • Optimizing COVID-19 vaccination appointment scheduling
    Thu 4 March 2021
     Paul Brown
  • How much faster is Java 15?
    Tue 26 January 2021
     Michal Tomčo
  • Solve the facility location problem
    Fri 9 October 2020
     Jiří Locker
  • OptaPlanner Week 2020 recordings
    Mon 7 September 2020
     Geoffrey De Smet
  • Let’s OptaPlan your jBPM tasks (part 1) - Integrating the two worlds
    Fri 3 July 2020
     Walter Medvedeo
  • AI versus Covid-19: How Java helps nurses and doctors in this fight
    Fri 8 May 2020
     Christopher Chianelli
Blog archive
Latest videos
  • YT Unit testing constraints
    Tue 9 March 2021
     Lukáš Petrovický
  • YT Maintenance scheduling
    Wed 24 February 2021
     Julian Cui
  • YT Vaccination appointment scheduling
    Wed 3 February 2021
     Geoffrey De Smet
  • YT Shadow variables
    Tue 19 January 2021
     Geoffrey De Smet
  • YT Domain modeling and design patterns
    Tue 17 November 2020
     Geoffrey De Smet
  • YT Quarkus insights: AI constraint solving
    Tue 20 October 2020
     Geoffrey De Smet
  • YT AI in kotlin
    Wed 23 September 2020
     Geoffrey De Smet
Video archive

KIE projects

  • Drools rule engine
  • OptaPlanner constraint solver
  • jBPM workflow engine

Community

  • Blog
  • Get Help
  • Team
  • Governance
  • Academic research

Code

  • Build from source
  • Submit a bug
  • License (Apache-2.0)
  • Release notes
  • Upgrade recipes
Sponsored by
Red Hat
More coder content at
Red Hat Developers
© Copyright 2006-2021, Red Hat, Inc. or third-party contributors - Privacy statement - Terms of use - Website info