-
Notifications
You must be signed in to change notification settings - Fork 228
chore: add docs, fail fast on execute for structural flawed solutions, make ScoreAnalysis not fail fact on structural flawed input #2609
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
triceo
merged 9 commits into
TimefoldAI:no-loops
from
Christopher-Chianelli:chore/structural-score-fail-fasts
Sep 1, 2026
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
43984ee
chore: rename InnerScore.isInvalid to InnerScore.isStructuallyFlawed
Christopher-Chianelli b50b721
chore: add test for DefaultPhaseCommandContext
Christopher-Chianelli 358de72
docs: document changes relating to structural score
Christopher-Chianelli dd5283f
chore: return a ScoreAnalysis on a structurally flawed solution inste…
Christopher-Chianelli 188f101
docs: update docs
Christopher-Chianelli db4867e
chore: review comments
Christopher-Chianelli 95bfe00
docs: update docs
Christopher-Chianelli 8407344
chore: review comments
Christopher-Chianelli 8ac4b36
chore: make InconsistentSolutionException final
Christopher-Chianelli File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
16 changes: 8 additions & 8 deletions
16
.../main/java/ai/timefold/solver/core/api/domain/variable/InconsistentSolutionException.java
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,28 +1,28 @@ | ||
| package ai.timefold.solver.core.api.domain.variable; | ||
|
|
||
| import java.util.Collection; | ||
| import java.util.List; | ||
|
|
||
| import ai.timefold.solver.core.api.score.analysis.VariableLoop; | ||
|
|
||
| import org.jspecify.annotations.NullMarked; | ||
|
|
||
| @NullMarked | ||
| public class InconsistentSolutionException extends RuntimeException { | ||
| public final class InconsistentSolutionException extends RuntimeException { | ||
| private final Object solution; | ||
| private final Collection<Object> involvedEntityCollection; | ||
| private final List<VariableLoop> variableLoops; | ||
|
|
||
| public InconsistentSolutionException(String feature, Object solution, Collection<Object> involvedEntityCollection) { | ||
| public InconsistentSolutionException(String feature, Object solution, List<VariableLoop> variableLoops) { | ||
| super("The solution (%s) is inconsistent. %s requires a consistent solution.".formatted(solution, feature)); | ||
| this.solution = solution; | ||
| this.involvedEntityCollection = involvedEntityCollection; | ||
| this.variableLoops = variableLoops; | ||
| } | ||
|
|
||
| @SuppressWarnings("unchecked") | ||
| public <T> T getSolution() { | ||
| return (T) solution; | ||
| } | ||
|
|
||
| @SuppressWarnings("unchecked") | ||
| public <T> List<T> getInvolvedEntityCollection() { | ||
| return (List<T>) involvedEntityCollection; | ||
| public List<VariableLoop> getVariableLoops() { | ||
| return variableLoops; | ||
| } | ||
| } |
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
17 changes: 17 additions & 0 deletions
17
core/src/main/java/ai/timefold/solver/core/api/score/analysis/EntityVariablePair.java
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| package ai.timefold.solver.core.api.score.analysis; | ||
|
|
||
| import org.jspecify.annotations.NullMarked; | ||
|
|
||
| /** | ||
| * A pair of an entity and a variable on it. | ||
| * | ||
| * @param entity The entity. | ||
| * @param variableName The variable on the entity. | ||
| */ | ||
| @NullMarked | ||
| public record EntityVariablePair(Object entity, String variableName) { | ||
| @Override | ||
| public String toString() { | ||
| return "%s.%s".formatted(entity, variableName); | ||
| } | ||
| } | ||
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
17 changes: 17 additions & 0 deletions
17
core/src/main/java/ai/timefold/solver/core/api/score/analysis/StructuralFlawAnalysis.java
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| package ai.timefold.solver.core.api.score.analysis; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| import org.jspecify.annotations.NullMarked; | ||
|
|
||
| /** | ||
| * Represents a breakdown of the structural flaws of a solution. | ||
| */ | ||
| @NullMarked | ||
| public interface StructuralFlawAnalysis { | ||
| /** | ||
| * Return a list of independent {@link VariableLoop} | ||
| * that form cycles and thus cause inconsistencies in the solution. | ||
| */ | ||
| List<VariableLoop> getVariableLoops(); | ||
| } |
31 changes: 31 additions & 0 deletions
31
core/src/main/java/ai/timefold/solver/core/api/score/analysis/VariableLoop.java
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| package ai.timefold.solver.core.api.score.analysis; | ||
|
|
||
| import java.util.Set; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| import org.jspecify.annotations.NullMarked; | ||
|
|
||
| /** | ||
| * A set of entity-variable pairs that form a cycle. | ||
| * | ||
| * @param involvedVariableSet | ||
| */ | ||
| @NullMarked | ||
| public record VariableLoop(Set<EntityVariablePair> involvedVariableSet) { | ||
| /** | ||
| * Get the set of involved entities in the cycle | ||
| */ | ||
| @SuppressWarnings("unchecked") | ||
| public <T> Set<T> getEntitySet() { | ||
| return (Set<T>) involvedVariableSet.stream() | ||
| .map(EntityVariablePair::entity) | ||
| .collect(Collectors.toSet()); | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| return involvedVariableSet.stream() | ||
| .map(EntityVariablePair::toString) | ||
| .collect(Collectors.joining(", ", "[", "]")); | ||
| } | ||
| } |
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
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
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
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
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
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will lead to a very verbose JSON.
I question if we need the variable information at all.
If we do, then arguably we can list entities per variable, as opposed to listing the variable with every entity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want the individual loops, you need the variables, and the loop might be
entity1:a -> entity2:b -> entity1:c.