Skip to content

feat: add public API for move evaluation - #2786

Open
zepfred wants to merge 8 commits into
TimefoldAI:mainfrom
zepfred:poc/evaluator
Open

zepfred wants to merge 8 commits into
TimefoldAI:mainfrom
zepfred:poc/evaluator

Conversation

@zepfred

@zepfred zepfred commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@triceo triceo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some decisions to be made around the API.

Comment on lines +263 to +264
RECOMMENDATIONS("Recommendations", "do not use SolutionManager's recommendAssignment() method"),
MOVE_EVALUATOR("Move evaluator", "do not use SolutionManager's moveEvaluator() method");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a bit ambivalent here.

First of all, we should reimplement recommendations using move evaluator, proving that it works. This part I am sure about.

But if we do, should we still expose recommendations as an enterprise feature? If they need the evaluator, which is an enterprise feature itself, then transitively recommendations are also an enterprise feature. Which would suggest we do not mention this here anymore.

That said, the error messages will be easier to understand if recommendations fails with an error mentioning recommendations, and not some abstract move evaluator.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to remove the recommendation feature and keep only the move evaluator. Let me first make sure we can reuse the move evaluator in the recommendation implementation.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After a thorough analysis of the recommendation feature, I found one major blocker. All requirements can be met in some way, except for the move generation phase. We use the CH internals, which require the score director. It does not make sense to me to reimplement that logic in a different way just to add the move evaluator.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see your point, but how can we be sure then that this API is powerful enough?
Models do not use our recommendations, as far as I know - they roll their own. Does this mean we cannot help them?

@timefold-automations

Copy link
Copy Markdown
Contributor

This pull request, as it stands, would leave the Solver documentation stale in the place below. An automated check found this and can be wrong.

  1. Code change: core/src/main/java/ai/timefold/solver/core/api/solver/MoveEvaluator.java:1-202 adds the public Enterprise-only MoveEvaluator API, and core/src/main/java/ai/timefold/solver/core/api/solver/SolutionManager.java:293-315 adds SolutionManager.moveEvaluator(...) (added).
    Docs location: no mention found for MoveEvaluator or moveEvaluator in docs/src/modules/ROOT/pages/.
    Confidence: high — the new public API has no documentation section or code sample.

    Suggested edit (for example, in pages/commercial-editions/performance-improvements.adoc):

    [#moveEvaluator]
    == Move evaluator
    
    include::./_only-enterprise.adoc[]
    
    Use `SolutionManager.moveEvaluator(...)` to create a stateful evaluator for executing planning moves on a working solution and calculating their score impact without running the solver. Close the evaluator when it is no longer needed.

The documentation fix goes into this timefold-solver pull request. A new commit on the branch updates this comment, and drift that is still there when the group merges gets a docs pull request against main.

Generated by Solver Docs Drift Review · copilot · gpt56 · 13.3 AIC · ⌖ 3.51 AIC · ⊞ 25.2K · ◷

@zepfred
zepfred marked this pull request as ready for review November 5, 2026 19:23
@zepfred
zepfred requested review from a team and a balanced review from Copilot November 5, 2026 19:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The unguarded describe() fallback can mask the original undo failure, and the new public API lacks required user-guide documentation.

2 open issues
What changed in this PR

Adds a public, Enterprise-only API to evaluate moves without running the solver. It supports permanent changes and temporary comparisons on a cloned working solution.

Changes:

  • Adds MoveEvaluator, its temporary-move context, and a SolutionManager factory method.
  • Adds rollback and failure reporting for temporary moves.
  • Tests score restoration, structural flaws, and undo failures.
File Description
core/​src/​test/​java/​ai/​timefold/​solver/​core/​impl/​move/​MoveDirectorTest.java Tests temporary-move rollback and failure handling.
core/​src/​main/​java/​ai/​timefold/​solver/​core/​preview/​api/​move/​Move.java Adds fallback formatting for error messages.
core/​src/​main/​java/​ai/​timefold/​solver/​core/​impl/​solver/​exception/​UndoMoveCorruptionException.java Identifies failed move undo operations.
core/​src/​main/​java/​ai/​timefold/​solver/​core/​impl/​solver/​DefaultSolutionManager.java Delegates evaluator creation to Enterprise services.
core/​src/​main/​java/​ai/​timefold/​solver/​core/​impl/​move/​StructurallyFlawedMoveException.java Identifies moves that cause structural flaws.
core/​src/​main/​java/​ai/​timefold/​solver/​core/​impl/​move/​MoveDirector.java Adds temporary execution with rollback after runtime failures.
core/​src/​main/​java/​ai/​timefold/​solver/​core/​enterprise/​TimefoldSolverEnterpriseService.java Adds the evaluator factory contract and feature identifier.
core/​src/​main/​java/​ai/​timefold/​solver/​core/​api/​solver/​SolutionManager.java Exposes evaluator creation.
core/​src/​main/​java/​ai/​timefold/​solver/​core/​api/​solver/​MoveEvaluatorContext.java Defines access to temporary state, score, and analysis.
core/​src/​main/​java/​ai/​timefold/​solver/​core/​api/​solver/​MoveEvaluator.java Defines move execution, evaluation, and resource lifecycle.
core/​src/​main/​java/​ai/​timefold/​solver/​core/​api/​domain/​variable/​InconsistentSolutionException.java Documents evaluator creation as another exception source.
core/​src/​build/​revapi-differences.json Records the new interface method as an accepted API difference.

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The Enterprise MoveEvaluator implementation and tests are unavailable, so clone isolation, failure invalidation, context lifecycle, and resource cleanup require human review and integration validation against the new API contracts.

No open issues 🎉

2 resolved since last review

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings November 5, 2026 19:44

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The move-printing fallback returns the fully qualified class name instead of the documented describe() output, causing the new undo-failure reporting test to fail.

1 open issue

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The Enterprise evaluator implementation is absent from this checkout, leaving clone isolation, context lifetime, resource cleanup, score caching, and failure recovery dependent on cross-repository review and runtime validation.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@triceo triceo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO there are significant flaws in the contract as it stands today. Score analysis is broken, without an easy fix. Recommendations cannot be reimplemented using this API.

We need to re-evaluate if we need all of these use cases, and if this API is sufficiently future-proof. We are doing this so that the models do not need to roll their own hacks. If this doesn't remove the hacks, it is pointless.

* do not change when the move is undone, and so they may be returned.
* The constraint justifications and indictments of the score analysis, however,
* reference entities and facts of the working solution, whose planning variables revert;
* see {@link MoveEvaluatorContext#getScoreAnalysis(ScoreAnalysisFetchPolicy)}.</li>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a major problem. You cannot return the score analysis, if it will change. This makes the entire API unusable - score analysis is the reason why we're doing this!

This requires cloning. I'm pretty sure we already had to solve this issue somewhere in recommendations.

* However, its constraint justifications and indictments may reference planning entities and problem facts
* of the working solution, whose planning variables revert once the move is undone;
* after that, they no longer show the state which the analysis describes.
* Extract what is needed from them inside the postprocessor.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bad advice. It is not practically possible to go over the score analysis and extract thousands, possibly millions of data points. This is a flawed design.

This branch was successfully deployed

1 active and 1 inactive deployments
documentation (preview) — 7ec60fe6 Deployed Nov 5, 2026 by zepfred via Build Documentation #854
internal — 7ec60fe6 Deployed Nov 5, 2026 by zepfred via approval_required #5231
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants