Skip to content

Commit

Permalink
docs: Improve note on allows unassigned
Browse files Browse the repository at this point in the history
  • Loading branch information
Christopher-Chianelli authored and triceo committed Oct 23, 2024
1 parent 6f5f54f commit 1300d72
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,34 @@ To implement this:
. Add a score level (usually a medium level between the hard and soft level) by switching xref:constraints-and-score/overview.adoc#scoreType[`Score` type].
. Make the planning variable xref:using-timefold-solver/modeling-planning-problems.adoc#planningVariableAllowingUnassigned[allow unassigned values].
. Add a score constraint on the new level (usually a medium constraint) to penalize the number of unassigned entities (or a weighted sum of them).
Use xref:constraints-and-score/score-calculation.adoc#constraintStreamsForEach[`forEachIncludingUnassigned`] and check if the xref:using-timefold-solver/modeling-planning-problems.adoc#planningVariable[planning variable] or xref:using-timefold-solver/modeling-planning-problems.adoc#bidirectionalVariable[inverse relation shadow variable] is `null`:

[tabs]
====
Java::
+
[source,java,options="nowrap"]
----
private Constraint penalizeUnassignedVisits(ConstraintFactory factory) {
return factory.forEachIncludingUnassigned(Visit.class)
.filter(visit -> visit.getVehicle() == null)
.penalize(HardMediumSoftScore.ONE_MEDIUM)
.asConstraint("Unassigned Visit");
}
----
Python::
+
[source,python,options="nowrap"]
----
def penalize_unassigned_visits(factory: ConstraintFactory) -> Constraint:
return (factory.for_each_including_unassigned(Visit)
.filter(lambda visit: visit.vehicle is None)
.penalize(HardMediumSoftScore.ONE_MEDIUM)
.as_constraint("Unassigned Visit")
)
----
====

[#overconstrainedPlanningWithVirtualValues]
=== Overconstrained planning with virtual values
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -488,10 +488,13 @@ Use xref:constraints-and-score/score-calculation.adoc#constraintStreamsForEach[f
Timefold Solver will automatically add the value `null` to the value range.
There is no need to add `null` in a collection provided by a ``ValueRangeProvider``.
[NOTE]
[IMPORTANT]
====
Using a planning variable with unassigned values implies
that your score calculation is responsible for punishing (or even rewarding) variables with a `null` value.
Failure to penalize unassigned variables can cause a solution with *all* variables unassigned to be the best solution.
See the xref:responding-to-change/responding-to-change.adoc#overconstrainedPlanningWithNullValues[overconstrained planning with `null` variable values] section in the docs for more infomation.
====
[WARNING]
Expand Down Expand Up @@ -1676,12 +1679,15 @@ customers: Annotated[list[Customer], PlanningListVariable(allows_unassigned_valu
----
====
[NOTE]
[IMPORTANT]
====
Constraint Streams filter out unassigned planning values by default.
Use xref:constraints-and-score/score-calculation.adoc#constraintStreamsForEach[forEachIncludingUnassigned()] to avoid such unwanted behaviour.
Using a planning list variable with unassigned values implies
that your score calculation is responsible for punishing (or even rewarding) these unassigned values.
Failure to penalize unassigned values can cause a solution with *all* values unassigned to be the best solution.
See the xref:responding-to-change/responding-to-change.adoc#overconstrainedPlanningWithNullValues[overconstrained planning with `null` variable values] section in the docs for more infomation.
====
xref:responding-to-change/responding-to-change.adoc[Repeated planning]
Expand Down

0 comments on commit 1300d72

Please sign in to comment.