[[releaseNotes-8.x]]
== OptaPlanner 8.x Release Notes

[[releaseNotes-8.37.0.Final]]
=== OptaPlanner 8.37.0.Final

==== `PlanningListVariable` supports nearby selection

xref:move-and-neighborhood-selection/move-and-neighborhood-selection.adoc#nearbySelection[Nearby selection] is now available for planning domains using a planning list variable.

==== AbstractScoreHibernateType and its subtypes become deprecated

The `AbstractScoreHibernateType` as well as all its subtypes have been deprecated. The parallel OptaPlanner 9
releases are going to introduce Hibernate 6, which unfortunately breaks backward compatibility
of the `CompositeUserType` that the `AbstractScoreHibernateType` depends on.

The `AbstractScoreHibernateType` and its subtypes remain available in the OptaPlanner 8 releases to provide
integration with Hibernate 5 but have been removed from the equivalent OptaPlanner 9.x release.

To integrate the `PlanningScore` of your choice with Hibernate 6, either use the score converters available in the
`org.optaplanner.persistence.jpa.api.score.buildin` package or https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#embeddable-mapping-custom[implement the `CompositeUserType`] yourself.

[[releaseNotes-8.36.0.Final]]
=== OptaPlanner 8.36.0.Final

==== OptaWeb Vehicle Routing demo application abandoned

The codebase for OptaWeb Vehicle Routing demo application has been frozen and will no longer receive any updates.

We encourage users to check out the https://github.com/kiegroup/optaplanner-quickstarts/tree/stable/use-cases/vehicle-routing[OptaPlanner Vehicle Routing Quickstart] for a simple and straight-forward way of integrating OptaPlanner in your application.

[[releaseNotes-8.35.0.Final]]
=== OptaPlanner 8.35.0.Final

==== `PlanningListVariable` gets support for K-Opt Moves

A new move selector for list variables, `KOptListMoveSelector`, has been added.
The `KOptListMoveSelector` selects a single entity, removes `k` edges from its route, and add `k` new edges from the removed edges' endpoints.
The `KOptListMoveSelector` can help the solver escape local optima in vehicle routing problems.
Configuration options are xref:move-and-neighborhood-selection/move-and-neighborhood-selection.adoc#kOptListMoveSelector[available in the documentation].

==== `SolutionManager` gets support for updating shadow variables

`SolutionManager` (formerly `ScoreManager`) methods such as `explain(solution)` and `update(solution)`  received a new overload with an extra argument, `SolutionUpdatePolicy`.
This has often been requested by users who load their solutions from persistent storage (such as a relational database), where these solutions do not include the information carried by xref:shadow-variable/shadow-variable.adoc[shadow variables] or even the score.
By calling these new overloads and picking the right policy,
OptaPlanner will automatically compute values for all the shadow variables in the given solution
and/or recalculate the score.

Similarly, `ProblemChangeDirector` received a new method called `updateShadowVariables(), so that you can update shadow variables on demand in xref:repeated-planning/repeated-planning.adoc#realTimePlanning[real-time planning].

[[releaseNotes-8.34.0.Final]]
=== OptaPlanner 8.34.0.Final

==== Performance improvements in pillar moves and nearby selection

OptaPlanner can now auto-detect situations where multiple xref:move-and-neighborhood-selection/move-and-neighborhood-selection.adoc#pillarMoveSelectors[pillar move selectors] can share a pre-computed pillar cache and reuse it instead of recomputing it for each move selector.
Users who combine different pillar moves (such as `PillarChangeMove` and `PillarSwapMove`) should see significant benefits.

The same applies to users of xref:move-and-neighborhood-selection/move-and-neighborhood-selection.adoc#nearbySelection[nearby selection].
OptaPlanner can now auto-detect situations where a pre-computed distance matrix can be shared between multiple move selectors, saving a considerable amount of memory and CPU processing time.

As a consequence, implementations of the following interfaces are expected to be stateless:

* `org.optaplanner.core.impl.heuristic.selector.common.nearby.NearbyDistanceMeter`
* `org.optaplanner.core.impl.heuristic.selector.common.decorator.SelectionFilter`
* `org.optaplanner.core.impl.heuristic.selector.common.decorator.SelectionProbabilityWeightFactory`
* `org.optaplanner.core.impl.heuristic.selector.common.decorator.SelectionSorter`
* `org.optaplanner.core.impl.heuristic.selector.common.decorator.SelectionSorterWeightFactory`

In general, if solver configuration asks the user to implement an interface,
the expectation is that the implementation will be stateless
or at the very least not try to include external state.
With the aforementioned performance improvements,
failing to follow this requirement will result in subtle bugs and score corruption
as the solver will now reuse these instances as it sees fit.

==== OptaPlanner configuration becomes even more fluent

Various configuration classes, such as `EntitySelectorConfig` and `ValueSelectorConfig`,
received new builder methods which make it easier than ever
to replace XML-based solver config with fluent Java code.


[[releaseNotes-8.33.0.Final]]
=== OptaPlanner 8.33.0.Final

==== Value range auto-detection

In most cases, links between planning variables and value ranges can now be auto-detected.
Therefore, ``@ValueRangeProvider`` no longer needs to provide an ``id`` property.
Likewise, planning variables no longer need to reference value range providers via ``valueRangeProviderRefs`` property.

No code changes or configuration changes are required.
Users who prefer clarity over brevity may continue to explicitly reference their value range providers.


[[releaseNotes-8.32.0.Final]]
=== OptaPlanner 8.32.0.Final

==== XStream support deprecated

Given that XStream has multiple CVEs against it and no recent releases,
we have decided to deprecate OptaPlanner's support for serializing into XML using XStream.
To continue serializing into XML, please switch to the `optaplanner-persistence-jaxb` module.

All classes in the `optaplanner-persistence-xstream`, as well as the module itself, are now deprecated and will be removed in a future major version of OptaPlanner.

All examples in the `optaplanner-examples` module have been refactored to  JSON using the `optaplanner-persistance-jackson` module.
Quickstarts were not affected by these changes, as they already were serializing into JSON.

[[releaseNotes-8.31.0.Final]]
=== OptaPlanner 8.31.0.Final

==== Several OptaPlanner examples removed from the distribution

In an ongoing effort to clean up code and reduce technical debt, the following examples were removed the `optaplanner-examples` module:

- Batch Scheduling,
- Cheap Time,
- Coach Shuttle Gathering,
- Investment
- and Rock Tour.

We believe these examples were rarely used if ever, and they did not showcase any unique feature of OptaPlanner that would not be showcased already in any of the 16 remaining examples and many quickstarts.

No OptaPlanner feature was removed or deprecated in the process.

==== Multiple entity classes with chained planning variables

Fixed a https://issues.redhat.com/browse/PLANNER-2798[bug] that prevented using two or more chained planning variables, each defined on a different planning entity class.

[[releaseNotes-8.30.0.Final]]
=== OptaPlanner 8.30.0.Final

==== OptaPlanner operator (experimental) is available in the distribution

While the OptaPlanner operator remains experimental, it has now become a part of the https://download.jboss.org/optaplanner/release/latestFinal[OptaPlanner distribution].

If you want to learn more about the operator, follow the https://github.com/kiegroup/optaplanner-quickstarts/tree/development/technology/kubernetes[Kubernetes demo].

[[releaseNotes-8.29.0.Final]]
=== OptaPlanner 8.29.0.Final

==== Custom justifications and indictments in Constraint Streams

With a new Constraint Streams API, it is now easy to define custom constraint justifications and indictments in your constraints:

[source,java,options="nowrap"]
----
    protected Constraint vehicleCapacity(ConstraintFactory factory) {
        return factory.forEach(Customer.class)
                .filter(customer -> customer.getVehicle() != null)
                .groupBy(Customer::getVehicle, sum(Customer::getDemand))
                .filter((vehicle, demand) -> demand > vehicle.getCapacity())
                .penalizeLong(HardSoftLongScore.ONE_HARD,
                        (vehicle, demand) -> demand - vehicle.getCapacity())
                .justifyWith((vehicle, demand, score) ->
                    new VehicleDemandOveruse(vehicle, demand, score))
                .indictWith((vehicle, demand) -> List.of(vehicle))
                .asConstraint("vehicleCapacity");
    }
----

Note the new methods: `justifyWith(...)` and `indictWith(...)`. To find out more, see xref:constraint-streams/constraint-streams.adoc#constraintStreamsCustomizingJustificationsAndIndictments[customizing justifications and indictments].

==== Compatible with JDK 19

https://jdk.java.net/19/[OpenJDK 19] was recently released and OptaPlanner is fully compatible with it.

We always test our releases against the long-term supported versions of the JDK, currently 11 and 17, as well as against the latest release. We encourage you to upgrade your JDK regularly to benefit from the enhancements that come with the new releases.

==== New `@ShadowVariable` and `@PiggybackShadowVariable` annotations replace the `@CustomShadowVariable`

`@ShadowVariable` annotation is repeatable and allows to specify 1 listener per source variable.

`@PiggybackShadowVariable` is a specialized annotation to mark shadow variables that are updated by another shadow variable's listener.

The `@CustomShadowVariable` has been deprecated.

Read more about xref:shadow-variable/shadow-variable.adoc#customVariableListener[custom shadow variables] in the documentation.


==== Planning list variable

OptaPlanner now adds a limited support for planning list variables that can hold multiple planning values.
The planning list variable provides an alternative approach to modeling planning problems that were previously modeled using the xref:planner-configuration/planner-configuration.adoc#chainedPlanningVariable[chained planning variable].

Both the planning list variable and the chained planning variable should be used with problems where the goal is to distribute a number of workload elements among limited resources in a specific order.
For example, in vehicle routing, vehicles represent the limited resource and customers represent the workload elements.

The chained planning variable defines a recursive data structure, in which customers form chains ending with vehicles.
On the other hand, the planning list variable allows for a more intuitive model where each vehicle holds a list of customers it goes to.
It is defined using the new `@PlaningListVariable` annotation.

WARNING: The planning list variable is a new feature and lacks some advanced features, that are available with the chained planning variable.

See xref:planner-configuration/planner-configuration.adoc#planningListVariable[planning list variable].

[[releaseNotes-8.27.0.Final]]
=== OptaPlanner 8.27.0.Final

==== Bavet is feature complete

The alternative constraint streams implementation Bavet is feature complete.
You can now use it as an alternative to Drools (which is still the default).

Bavet will not be supported in Red Hat's support offering.
Drools intends to catch up performance wise.


[[releaseNotes-8.24.0.Final]]
=== OptaPlanner 8.24.0.Final

==== OptaWeb Employee Rostering demo application abandoned

The codebase for OptaWeb Employee Rostering demo application has been frozen and will no longer receive any updates.

We encourage users to check out the https://github.com/kiegroup/optaplanner-quickstarts/tree/stable/use-cases/employee-scheduling[OptaPlanner Employee Rostering Quickstart] for a simple and straight-forward way of integrating OptaPlanner in your application.


[[releaseNotes-8.23.0.Final]]
=== OptaPlanner 8.23.0.Final

==== Score DRL deprecated in favor of Constraint Streams

Support for Score DRL has been deprecated and users are encouraged to migrate to xref:constraint-streams/constraint-streams.adoc#constraintStreams[Constraint Streams] at their earliest convenience.
link:https://www.optaplanner.org/download/upgradeRecipe/[Read the migration guide from score DRL to Constraint Streams].
Score DRL is not going away in OptaPlanner 8.


[[releaseNotes-8.20.0.Final]]
=== OptaPlanner 8.20.0.Final

==== `SolverManager.addProblemChange()` now returns `CompletableFuture<Void>`

`SolverManager.addProblemChange()` returns `CompletableFuture<Void>`, which completes when a new best solution containing
the problem change has been passed to a user-defined `Consumer`.


[[releaseNotes-8.17.0.Final]]
=== OptaPlanner 8.17.0.Final

==== Real-time planning available on the `SolverManager`

The `SolverManager` now accepts problem changes via the `addProblemChange()` method,
allowing for xref:repeated-planning/repeated-planning.adoc#realTimePlanning[real-time planning]
without much boilerplate code.

==== Faster `Solver` creation

`SolverFactory` newly caches some internal data structures, leading to much faster `Solver` creation times.
This is beneficial if you instantiate multiple `Solver` instances in quick succession.


[[releaseNotes-8.12.0.Final]]
=== OptaPlanner 8.12.0.Final

==== Documentation website

The latest final OptaPlanner documentation is now available on a new
https://www.optaplanner.org/docs[documentation website] built using https://antora.org[Antora].
The single-HTML and PDF documentation will continue to be published in the https://docs.optaplanner.org/[archive].

==== Monitoring Support

OptaPlanner now uses Micrometer to monitor key metrics such as active solver count, solve durations, and error count.


[[releaseNotes-8.10.0.Final]]
=== OptaPlanner 8.10.0.Final

==== Support for Quarkus 2.0

OptaPlanner is now fully compatible with the recently released https://quarkus.io/quarkus2/[Quarkus 2.0].


[[releaseNotes-8.7.0.Final]]
=== OptaPlanner 8.7.0.Final

==== OptaPlanner quickstarts repository

There is a new `quarkus-call-center` quickstart that shows xref:repeated-planning/repeated-planning.adoc#realTimePlanning[real-time planning] of incoming calls in a call center.

image:release-notes/quarkusCallCenter.png[Quarkus Call Center]


[[releaseNotes-8.5.0.Final]]
=== OptaPlanner 8.5.0.Final

==== Mapping in Constraint Streams

The xref:constraint-streams/constraint-streams.adoc#constraintStreams[Constraint Streams API] received a major new functionality.
You can now modify your streams using xref:constraint-streams/constraint-streams.adoc#constraintStreamsMappingTuples[mapping functions].

==== Ready for OpenJDK 16

We have made some tweaks under the hood
so that your experience with the recently released link:https://openjdk.java.net/projects/jdk/16/[OpenJDK 16] continues to be smooth.

==== Inject and Autowire ConstraintVerifier in Quarkus and Spring Boot

You can now xref:constraint-streams/constraint-streams.adoc#constraintStreamsTestingQuarkus[inject the Constraint Verifier in Quarkus] and
xref:constraint-streams/constraint-streams.adoc#constraintStreamsTestingSpringBoot[autowire the Constraint Verifier in Spring Boot], allowing
you to xref:constraint-streams/constraint-streams.adoc#constraintStreamsTesting[test your constraint streams] more easily.

==== OptaWebs on Quarkus

OptaWeb Vehicle Routing and OptaWeb Employee Rostering have been migrated from Spring Boot to Quarkus.

Other noteworthy changes done during the migration to Quarkus:

* OptaWeb Vehicle Routing back end has a new RESTful API.
Client-server communication, that was previously done using WebSockets, now uses a combination of REST calls and Server-Sent Events.
* OptaWeb Employee Rostering now uses Constraint Streams instead of DRL for score calculation.

==== Faster domain accessors and cloning with Gizmo

We have added xref:planner-configuration/planner-configuration.adoc#domainAccess[Gizmo generated domain accessors and solution
cloners], which offer better performance than the reflection based
domain accessors and solution cloners.

==== OptaPlanner quickstarts repository

There is a new `activemq-quarkus-school-timetabling` quickstart that shows how to integrate ActiveMQ with OptaPlanner to horizontally scale when solving multiple data sets.


[[releaseNotes-8.3.0.Final]]
=== OptaPlanner 8.3.0.Final

==== Major performance improvements for Constraint Streams

The default implementation of the xref:constraint-streams/constraint-streams.adoc#constraintStreams[Constraint Streams API]
has seen major performance improvements.
Use cases with tri and quad streams may experience order of magnitude speedups.
Use cases with xref:constraint-streams/constraint-streams.adoc#constraintStreamsGroupingAndCollectors[grouping]
are likely to experience some speedups too, albeit comparatively smaller.

Kudos to the link:https://drools.org/[Drools] team for helping make this possible!

==== Constraint Streams `groupBy()` overloads for multiple collectors

The xref:constraint-streams/constraint-streams.adoc#constraintStreams[Constraint Streams API]
has been extended to allow using more than 2 collectors in a single xref:constraint-streams/constraint-streams.adoc#constraintStreamsGroupingAndCollectors[grouping].
The following is now possible:

[source,java]
----
return constraintFactory.from(ProductPrice.class)
    .groupBy(min(), max(), sum())
    .penalize(..., SimpleScore.ONE, (minPrice, maxPrice, sumPrices) -> ...);
----


[[releaseNotes-8.0.0.Final]]
=== OptaPlanner 8.0.0.Final

==== OptaPlanner quickstarts repository

The new https://github.com/kiegroup/optaplanner-quickstarts[OptaPlanner Quickstarts repository]
contains pretty web demos for several use cases.
It also shows you how to integrate OptaPlanner with different technologies:

* *School timetabling*: Assign lessons to timeslots and rooms to produce a better schedule for teachers and students.
+
This application connects to a relational database and exposes a REST API, rendered by a pretty JavaScript UI.
+
** `quarkus-school-timetabling`: Java, Maven or Gradle, Quarkus, H2
** `spring-boot-school-timetabling`: Java, Maven or Gradle, Spring Boot, H2
** `kotlin-quarkus-school-timetabling`: Kotlin, Maven, Quarkus, H2
* *Facility location problem (FLP)*: Pick the best geographical locations for new stores, distribution centers, COVID-19 test centers or telco masts.
** `quarkus-facility-location`: Java, Maven, Quarkus
* *Factorio layout*: Assign machines to assembly line locations to design the best factory layout.
** `quarkus-factorio-layout`: Java, Maven, Quarkus
* Maintenance scheduling: Coming soon

https://github.com/kiegroup/optaplanner-quickstarts[Clone the quickstarts repo now!]

==== Future Java compatibility

The OptaPlanner 8 API has been groomed to maximize compatibility
with the latest https://openjdk.java.net/[OpenJDK] and https://www.graalvm.org/[GraalVM] releases
and game-changing platforms such as https://quarkus.io/[Quarkus].
Meanwhile, we still fully support OpenJDK 11 and platforms such as Spring Boot or plain Java.

For example, when running OptaPlanner in Java 11 or higher with a classpath,
OptaPlanner no longer triggers `WARNING: An illegal reflective access operation has occurred` for XStream.

==== Code completion for solverConfig.xml and benchmarkConfig.xml through XSD

To validate XML configuration during development,
add the new XML Schema Definition (XSD) on the solver or benchmark configuration:

[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<solver xmlns="https://www.optaplanner.org/xsd/solver" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://www.optaplanner.org/xsd/solver https://www.optaplanner.org/xsd/solver/solver.xsd">
  ...
</solver>
----

This enables code completion for XML in most IDEs:

image:release-notes/solverConfigCompletion.png[SolverConfigCodeCompletion]

==== Improved Quarkus extension

The OptaPlanner Quarkus extension is now stable
and displays no warnings when compiling Java to a native executable.

==== ScoreManager now supports score explanation

The `ScoreManager` can now also explain why a solution has a certain score:

[source,java]
----
ScoreManager<TimeTable, HardSoftScore> scoreManager = ScoreManager.create(solverFactory);
...
ScoreExplanation<TimeTable, HardSoftScore> scoreExplanation = scoreManager.explain(timeTable);
System.out.println(scoreExplanation.getSummary());
...
----

Additionally, use `scoreExplanation.getConstraintMatchTotalMap()` and `scoreExplanation.getIndictmentMap()`
to extract the `ConstraintMatchTotal<HardSoftScore>` and `Indictment<HardSoftScore>` information without triggering a new score calculation.

==== Various improvements

* The ConstraintStreams API is now richer, more stable with better error messages and faster.
* The `SolverManager` API now supports to listen to both best solution events and the solving ended event.
* OptaPlanner no longer depends on Guava or Reflections.
