Repository navigation
Conversation
triceo
force-pushed
the
neighborhoods-value-range-draws
branch
from
November 10, 2026 06:52
2faa41d to
c04ced1
Compare
triceo
force-pushed
the
neighborhoods-value-range-draws
branch
from
November 10, 2026 06:57
c04ced1 to
fde3358
Compare
triceo
force-pushed
the
neighborhoods-value-range-draws
branch
from
November 10, 2026 08:07
fde3358 to
14c7032
Compare
triceo
marked this pull request as ready for review
November 10, 2026 12:54
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical issues can prematurely stop move generation, return incompatible entity types, and cause quadratic memory growth during swap candidate lookup.
4 open issues
What changed in this PR
This PR optimizes basic-variable neighborhoods by drawing values and swap partners from applicable value ranges, reducing rejected candidates.
Changes:
- Adds range-driven iterators for assign, change, swap, and pillar-swap moves.
- Adds cached lookups for movable entities that accept a value.
- Expands validity, pinning, and sampling tests, and documents range-based candidate selection.
| File | Description |
|---|---|
| docs/src/modules/ROOT/pages/optimization-algorithms/neighborhoods.adoc | Documents range-based candidate selection. |
| core/src/test/java/ai/timefold/solver/core/testdomain/valuerange/entityproviding/pinned/TestdataPinnedEntityProvidingSolution.java | Adds a solution fixture with entity ranges and pinning. |
| core/src/test/java/ai/timefold/solver/core/testdomain/valuerange/entityproviding/pinned/TestdataPinnedEntityProvidingEntity.java | Adds an entity-range fixture with pinning. |
| core/src/test/java/ai/timefold/solver/core/testdomain/inheritance/entity/single/baseannotated/classes/pinned/TestdataExtendedPinnedSolution.java | Adds an inheritance and pinning solution fixture. |
| core/src/test/java/ai/timefold/solver/core/testdomain/inheritance/entity/single/baseannotated/classes/pinned/TestdataExtendedPinnedEntity.java | Adds subclass-specific pinning to a test entity. |
| core/src/test/java/ai/timefold/solver/core/preview/api/move/builtin/SwapMoveProviderTest.java | Tests valid partners, pinning, and sampling frequency. |
| core/src/test/java/ai/timefold/solver/core/preview/api/move/builtin/SubPillarSwapMoveProviderTest.java | Tests subpillar sampling and move validity. |
| core/src/test/java/ai/timefold/solver/core/preview/api/move/builtin/PillarSwapMoveProviderTest.java | Tests pillar sampling frequency and validity. |
| core/src/test/java/ai/timefold/solver/core/preview/api/move/builtin/MoveProviderAssertions.java | Adds shared validity and sampling assertions. |
| core/src/test/java/ai/timefold/solver/core/preview/api/move/builtin/ChangeMoveProviderTest.java | Tests range-limited changes and sampling. |
| core/src/test/java/ai/timefold/solver/core/preview/api/move/builtin/AssignMoveProviderTest.java | Tests non-null assignments and sampling. |
| core/src/test/java/ai/timefold/solver/core/impl/move/MoveDirectorTest.java | Tests candidate lookup and pinning behavior. |
| core/src/test/java/ai/timefold/solver/core/impl/move/builtin/LeftDrivenMoveIteratorTest.java | Tests draw-budget overflow handling. |
| core/src/main/java/ai/timefold/solver/core/preview/api/move/SolutionView.java | Adds the movable-entity range lookup API. |
| core/src/main/java/ai/timefold/solver/core/preview/api/move/builtin/SwapMoveProvider.java | Uses the range-driven swap iterator. |
| core/src/main/java/ai/timefold/solver/core/preview/api/move/builtin/SubPillarSwapMoveProvider.java | Narrows candidate keys using value ranges. |
| core/src/main/java/ai/timefold/solver/core/preview/api/move/builtin/PillarSwapMoveProvider.java | Uses keyed pillar data and a dedicated iterator. |
| core/src/main/java/ai/timefold/solver/core/preview/api/move/builtin/ChangeMoveProvider.java | Draws changes from each entity’s range. |
| core/src/main/java/ai/timefold/solver/core/preview/api/move/builtin/AssignMoveProvider.java | Draws assignments from each entity’s range. |
| core/src/main/java/ai/timefold/solver/core/impl/score/director/ValueRangeState.java | Supplies movability filtering to range indexes. |
| core/src/main/java/ai/timefold/solver/core/impl/score/director/ValueRangeManager.java | Caches movable entities and handles subclass pins. |
| core/src/main/java/ai/timefold/solver/core/impl/neighborhood/stream/DefaultMoveStreamFactory.java | Removes filters replaced by range-driven selection. |
| core/src/main/java/ai/timefold/solver/core/impl/move/MoveDirector.java | Implements movable-entity range lookup. |
| core/src/main/java/ai/timefold/solver/core/impl/move/builtin/ValueRangeChangeMoveIterator.java | Adds direct value-range sampling. |
| core/src/main/java/ai/timefold/solver/core/impl/move/builtin/SwapMoveIterator.java | Adds range-filtered swap partner selection. |
| core/src/main/java/ai/timefold/solver/core/impl/move/builtin/PillarWithRanges.java | Extracts the cached pillar-and-ranges record. |
| core/src/main/java/ai/timefold/solver/core/impl/move/builtin/PillarSwapMoveIterator.java | Adds candidate-based pillar selection with size correction. |
| core/src/main/java/ai/timefold/solver/core/impl/move/builtin/MoveProviderUtil.java | Selects the smallest range-based candidate list. |
| core/src/main/java/ai/timefold/solver/core/impl/move/builtin/LeftDrivenMoveIterator.java | Adds shared bounded random-draw logic. |
| core/src/main/java/ai/timefold/solver/core/impl/heuristic/selector/common/ReachableValues.java | Caches movable entities for each value. |
Review effort: Balanced
triceo
force-pushed
the
neighborhoods-value-range-draws
branch
from
November 11, 2026 09:58
1acd6bb to
956ec4f
Compare
triceo
force-pushed
the
neighborhoods-value-range-draws
branch
from
November 11, 2026 10:07
956ec4f to
adbb86d
Compare
Collaborator
Author
|
Will be replaced by another PR. |
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Before this PR, the swap code would select all pairs, and only then knock out those who did not fill the other's value ranges. This was super-slow, and the move selectors do it in a much smarter way, which the neighborhoods now use as well - they only select left, and then look for the right partner in the static value ranges.
This changes the distribution of moves selected by some of the move providers - for example, longer sublists now have a significantly smaller chance of being picked, but that is not necessarily bad. (Long lists are bad for performance overall, and typically it is a good idea to limit the size of those lists.) That is a small price we have to pay for massive performance bumps - the decisions made now in terms of distribution are identical to move selectors, where possible.
This represents a speedup of 2x to 100x depending on dataset.
Validated with ESS, which now (on average across multiple seeds) reaches same or better results on all measured datasets, both in terms of score and move speed.