Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .mvn/maven.config
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
-ntp
-B
# timefold-solver-model-parent configures maven plugins required for Timefold models, but failing the build
# of that module itself. This way, we disable the plugin execution, while it remains active by default for models.
-Dai.timefold.sdk.model.processing.disabled
1 change: 0 additions & 1 deletion build/build-parent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,6 @@
<configuration>
<failOnWarning>true</failOnWarning>
<ignoreNonCompile>true</ignoreNonCompile>
<verbose>true</verbose>
</configuration>
</execution>
</executions>
Expand Down
42 changes: 42 additions & 0 deletions core/src/build/revapi-differences.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,48 @@
"extension": "revapi.differences",
"configuration": {
"differences": [
{
"ignore": true,
"code": "java.field.typeChanged",
"old": "field ai.timefold.solver.core.config.heuristic.selector.move.MoveSelectorConfig<Config_ extends ai.timefold.solver.core.config.heuristic.selector.move.MoveSelectorConfig<Config_>>.comparatorClass",
"new": "field ai.timefold.solver.core.config.heuristic.selector.move.MoveSelectorConfig<Config_ extends ai.timefold.solver.core.config.heuristic.selector.move.MoveSelectorConfig<Config_>>.comparatorClass",
"justification": "Internal protected fields; safe."
},
{
"ignore": true,
"code": "java.field.typeChanged",
"old": "field ai.timefold.solver.core.config.heuristic.selector.move.MoveSelectorConfig<Config_ extends ai.timefold.solver.core.config.heuristic.selector.move.MoveSelectorConfig<Config_>>.comparatorFactoryClass",
"new": "field ai.timefold.solver.core.config.heuristic.selector.move.MoveSelectorConfig<Config_ extends ai.timefold.solver.core.config.heuristic.selector.move.MoveSelectorConfig<Config_>>.comparatorFactoryClass",
"justification": "Internal protected fields; safe."
},
{
"ignore": true,
"code": "java.field.typeChanged",
"old": "field ai.timefold.solver.core.config.heuristic.selector.move.MoveSelectorConfig<Config_ extends ai.timefold.solver.core.config.heuristic.selector.move.MoveSelectorConfig<Config_>>.filterClass",
"new": "field ai.timefold.solver.core.config.heuristic.selector.move.MoveSelectorConfig<Config_ extends ai.timefold.solver.core.config.heuristic.selector.move.MoveSelectorConfig<Config_>>.filterClass",
"justification": "Internal protected fields; safe."
},
{
"ignore": true,
"code": "java.field.typeChanged",
"old": "field ai.timefold.solver.core.config.heuristic.selector.move.MoveSelectorConfig<Config_ extends ai.timefold.solver.core.config.heuristic.selector.move.MoveSelectorConfig<Config_>>.probabilityWeightFactoryClass",
"new": "field ai.timefold.solver.core.config.heuristic.selector.move.MoveSelectorConfig<Config_ extends ai.timefold.solver.core.config.heuristic.selector.move.MoveSelectorConfig<Config_>>.probabilityWeightFactoryClass",
"justification": "Internal protected fields; safe."
},
{
"ignore": true,
"code": "java.field.typeChanged",
"old": "field ai.timefold.solver.core.config.heuristic.selector.move.MoveSelectorConfig<Config_ extends ai.timefold.solver.core.config.heuristic.selector.move.MoveSelectorConfig<Config_>>.sorterClass",
"new": "field ai.timefold.solver.core.config.heuristic.selector.move.MoveSelectorConfig<Config_ extends ai.timefold.solver.core.config.heuristic.selector.move.MoveSelectorConfig<Config_>>.sorterClass",
"justification": "Internal protected fields; safe."
},
{
"ignore": true,
"code": "java.field.typeChanged",
"old": "field ai.timefold.solver.core.config.heuristic.selector.move.generic.AbstractPillarMoveSelectorConfig<Config_ extends ai.timefold.solver.core.config.heuristic.selector.move.generic.AbstractPillarMoveSelectorConfig<Config_>>.subPillarSequenceComparatorClass",
"new": "field ai.timefold.solver.core.config.heuristic.selector.move.generic.AbstractPillarMoveSelectorConfig<Config_ extends ai.timefold.solver.core.config.heuristic.selector.move.generic.AbstractPillarMoveSelectorConfig<Config_>>.subPillarSequenceComparatorClass",
"justification": "Internal protected fields; safe."
}
]
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
import ai.timefold.solver.core.api.score.Score;
import ai.timefold.solver.core.api.score.stream.ConstraintProvider;

import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

@NullMarked
public interface MultiConstraintAssertion {

/**
Expand All @@ -14,7 +15,7 @@ public interface MultiConstraintAssertion {
* @param score total score calculated for the given set of facts
* @throws AssertionError when the expected score does not match the calculated score
*/
default void scores(@NonNull Score<?> score) {
default void scores(Score<?> score) {
scores(score, null);
}

Expand All @@ -25,7 +26,7 @@ default void scores(@NonNull Score<?> score) {
* @param message description of the scenario being asserted
* @throws AssertionError when the expected score does not match the calculated score
*/
void scores(@NonNull Score<?> score, @Nullable String message);
void scores(Score<?> score, @Nullable String message);

/**
* Returns the {@link Score} produced by all constraints in the {@link ConstraintProvider} for the given set of facts.
Expand All @@ -39,16 +40,15 @@ default void scores(@NonNull Score<?> score) {
* {@snippet :
* HardSoftScore scoreA = constraintVerifier.verifyThat()
* .givenSolution(solutionA)
* .score();
* .getScore();
* HardSoftScore scoreB = constraintVerifier.verifyThat()
* .givenSolution(solutionB)
* .score();
* .getScore();
* assertThat(scoreA).isGreaterThan(scoreB);
* }
*
* @return the score produced by all constraints for the given facts, never null
*/
@NonNull
<S extends Score<S>> S score();
<S extends Score<S>> S getScore();
Comment thread
triceo marked this conversation as resolved.
Comment thread
triceo marked this conversation as resolved.

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
import ai.timefold.solver.core.api.score.stream.Constraint;
import ai.timefold.solver.core.api.score.stream.ConstraintJustification;

import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

@NullMarked
public interface SingleConstraintAssertion {

/**
Expand All @@ -19,9 +20,8 @@ public interface SingleConstraintAssertion {
* @param message description of the scenario being asserted
* @throws AssertionError when the expected penalty is not observed
*/
@NonNull
SingleConstraintAssertion justifiesWith(@Nullable String message,
@NonNull ConstraintJustification @NonNull... justifications);
ConstraintJustification... justifications);

/**
* Asserts that the {@link Constraint} being tested, given a set of facts, results in a given
Expand All @@ -30,7 +30,7 @@ SingleConstraintAssertion justifiesWith(@Nullable String message,
* @param justifications the expected justifications.
* @throws AssertionError when the expected penalty is not observed
*/
default @NonNull SingleConstraintAssertion justifiesWith(@NonNull ConstraintJustification @NonNull... justifications) {
default SingleConstraintAssertion justifiesWith(ConstraintJustification... justifications) {
return justifiesWith(null, justifications);
}

Expand All @@ -41,9 +41,8 @@ SingleConstraintAssertion justifiesWith(@Nullable String message,
* @param message description of the scenario being asserted
* @throws AssertionError when the expected penalty is not observed
*/
@NonNull
SingleConstraintAssertion justifiesWithExactly(@Nullable String message,
@NonNull ConstraintJustification @NonNull... justifications);
ConstraintJustification... justifications);

/**
* Asserts that the {@link Constraint} being tested, given a set of facts, results in a given
Expand All @@ -52,8 +51,8 @@ SingleConstraintAssertion justifiesWithExactly(@Nullable String message,
* @param justifications the expected justifications.
* @throws AssertionError when the expected penalty is not observed
*/
default @NonNull SingleConstraintAssertion
justifiesWithExactly(@NonNull ConstraintJustification @NonNull... justifications) {
default SingleConstraintAssertion
justifiesWithExactly(ConstraintJustification... justifications) {
return justifiesWithExactly(null, justifications);
}

Expand Down Expand Up @@ -126,7 +125,7 @@ default void penalizesBy(long matchWeightTotal) {
* @param matchWeightTotal at least 0, expected sum of match weights of matches of the constraint.
* @throws AssertionError when the expected penalty is not observed
*/
default void penalizesBy(@NonNull BigDecimal matchWeightTotal) {
default void penalizesBy(BigDecimal matchWeightTotal) {
penalizesBy(null, matchWeightTotal);
}

Expand All @@ -137,7 +136,7 @@ default void penalizesBy(@NonNull BigDecimal matchWeightTotal) {
* @param matchWeightTotal at least 0, expected sum of match weights of matches of the constraint.
* @throws AssertionError when the expected penalty is not observed
*/
void penalizesBy(@Nullable String message, @NonNull BigDecimal matchWeightTotal);
void penalizesBy(@Nullable String message, BigDecimal matchWeightTotal);

/**
* Asserts that the {@link Constraint} being tested, given a set of facts, results in a given number of penalties.
Expand Down Expand Up @@ -232,7 +231,7 @@ default void rewardsWith(long matchWeightTotal) {
* @param matchWeightTotal at least 0, expected sum of match weights of matches of the constraint.
* @throws AssertionError when the expected reward is not observed
*/
default void rewardsWith(@NonNull BigDecimal matchWeightTotal) {
default void rewardsWith(BigDecimal matchWeightTotal) {
rewardsWith(null, matchWeightTotal);
}

Expand All @@ -243,7 +242,7 @@ default void rewardsWith(@NonNull BigDecimal matchWeightTotal) {
* @param matchWeightTotal at least 0, expected sum of match weights of matches of the constraint.
* @throws AssertionError when the expected reward is not observed
*/
void rewardsWith(@Nullable String message, @NonNull BigDecimal matchWeightTotal);
void rewardsWith(@Nullable String message, BigDecimal matchWeightTotal);

/**
* Asserts that the {@link Constraint} being tested, given a set of facts, results in a given number of rewards.
Expand Down Expand Up @@ -341,7 +340,7 @@ default void penalizesByMoreThan(long matchWeightTotal) {
* @param matchWeightTotal at least 0, expected sum of match weights of matches of the constraint.
* @throws AssertionError when the expected penalty is not observed
*/
default void penalizesByMoreThan(@NonNull BigDecimal matchWeightTotal) {
default void penalizesByMoreThan(BigDecimal matchWeightTotal) {
penalizesByMoreThan(null, matchWeightTotal);
}

Expand All @@ -352,7 +351,7 @@ default void penalizesByMoreThan(@NonNull BigDecimal matchWeightTotal) {
* @param matchWeightTotal at least 0, expected sum of match weights of matches of the constraint.
* @throws AssertionError when the expected penalty is not observed
*/
void penalizesByMoreThan(@Nullable String message, @NonNull BigDecimal matchWeightTotal);
void penalizesByMoreThan(@Nullable String message, BigDecimal matchWeightTotal);

/**
* Asserts that the {@link Constraint} being tested, given a set of facts,
Expand Down Expand Up @@ -431,7 +430,7 @@ default void rewardsWithMoreThan(long matchWeightTotal) {
* @param matchWeightTotal at least 0, expected sum of match weights of matches of the constraint.
* @throws AssertionError when the expected reward is not observed
*/
default void rewardsWithMoreThan(@NonNull BigDecimal matchWeightTotal) {
default void rewardsWithMoreThan(BigDecimal matchWeightTotal) {
rewardsWithMoreThan(null, matchWeightTotal);
}

Expand All @@ -442,7 +441,7 @@ default void rewardsWithMoreThan(@NonNull BigDecimal matchWeightTotal) {
* @param matchWeightTotal at least 0, expected sum of match weights of matches of the constraint.
* @throws AssertionError when the expected reward is not observed
*/
void rewardsWithMoreThan(@Nullable String message, @NonNull BigDecimal matchWeightTotal);
void rewardsWithMoreThan(@Nullable String message, BigDecimal matchWeightTotal);

/**
* Asserts that the {@link Constraint} being tested, given a set of facts,
Expand Down Expand Up @@ -522,7 +521,7 @@ default void penalizesByLessThan(long matchWeightTotal) {
* @param matchWeightTotal at least 1, expected sum of match weights of matches of the constraint.
* @throws AssertionError when the expected penalty is not observed
*/
default void penalizesByLessThan(@NonNull BigDecimal matchWeightTotal) {
default void penalizesByLessThan(BigDecimal matchWeightTotal) {
penalizesByLessThan(null, matchWeightTotal);
}

Expand All @@ -533,7 +532,7 @@ default void penalizesByLessThan(@NonNull BigDecimal matchWeightTotal) {
* @param matchWeightTotal at least 1, expected sum of match weights of matches of the constraint.
* @throws AssertionError when the expected penalty is not observed
*/
void penalizesByLessThan(@Nullable String message, @NonNull BigDecimal matchWeightTotal);
void penalizesByLessThan(@Nullable String message, BigDecimal matchWeightTotal);

/**
* Asserts that the {@link Constraint} being tested, given a set of facts,
Expand Down Expand Up @@ -612,7 +611,7 @@ default void rewardsWithLessThan(long matchWeightTotal) {
* @param matchWeightTotal at least 1, expected sum of match weights of matches of the constraint.
* @throws AssertionError when the expected reward is not observed
*/
default void rewardsWithLessThan(@NonNull BigDecimal matchWeightTotal) {
default void rewardsWithLessThan(BigDecimal matchWeightTotal) {
rewardsWithLessThan(null, matchWeightTotal);
}

Expand All @@ -623,7 +622,7 @@ default void rewardsWithLessThan(@NonNull BigDecimal matchWeightTotal) {
* @param matchWeightTotal at least 1, expected sum of match weights of matches of the constraint.
* @throws AssertionError when the expected reward is not observed
*/
void rewardsWithLessThan(@Nullable String message, @NonNull BigDecimal matchWeightTotal);
void rewardsWithLessThan(@Nullable String message, BigDecimal matchWeightTotal);

/**
* Asserts that the {@link Constraint} being tested, given a set of facts,
Expand Down Expand Up @@ -662,22 +661,21 @@ default void rewardsLessThan(long times) {
* {@snippet :
* HardSoftScore scoreA = constraintVerifier.verifyThat(MyConstraints::roomConflict)
* .given(entity1, entity2)
* .score();
* .getScore();
* HardSoftScore scoreB = constraintVerifier.verifyThat(MyConstraints::roomConflict)
* .given(entity3, entity4)
* .score();
* .getScore();
* assertThat(scoreA).isLessThan(scoreB);
* }
*
* @return the score produced by this single constraint for the given facts, never null
*/
@NonNull
<S extends Score<S>> S score();
<S extends Score<S>> S getScore();
Comment thread
triceo marked this conversation as resolved.
Comment thread
triceo marked this conversation as resolved.

/**
* Returns the match weight total of the {@link Constraint} being tested for the given set of facts.
* <p>
* Unlike {@link #score()}, which returns the full score (match weight × constraint weight),
* Unlike {@link #getScore()}, which returns the full score (match weight × constraint weight),
* this method returns only the <b>match weight</b> — the same number you would pass
* to assertion methods like {@link #penalizesBy(int)} or {@link #rewardsWith(int)}.
* <p>
Expand All @@ -687,19 +685,18 @@ default void rewardsLessThan(long times) {
* Usage example:
*
* {@snippet :
* Number impactA = constraintVerifier.verifyThat(MyConstraints::roomConflict)
* var impactA = constraintVerifier.verifyThat(MyConstraints::roomConflict)
* .given(entity1, entity2)
* .impact();
* Number impactB = constraintVerifier.verifyThat(MyConstraints::roomConflict)
* .getImpact();
* var impactB = constraintVerifier.verifyThat(MyConstraints::roomConflict)
* .given(entity3, entity4)
Comment thread
triceo marked this conversation as resolved.
* .impact();
* .getImpact();
* assertThat(impactA.intValue()).isGreaterThan(impactB.intValue());
* }
*
* @return the match weight total produced by this single constraint, never null.
* Positive for rewards, negative for penalties, zero when there is no impact.
*/
@NonNull
Number impact();
Number getImpact();
Comment thread
triceo marked this conversation as resolved.

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public final class QueuedValuePlacerConfig extends EntityPlacerConfig<QueuedValu

public static final String XML_ELEMENT_NAME = "queuedValuePlacer";

private Class<?> entityClass = null;
private String entityClass = null;
Comment thread
triceo marked this conversation as resolved.

@XmlElement(name = "valueSelector")
private ValueSelectorConfig valueSelectorConfig = null;
Expand All @@ -50,11 +50,11 @@ public final class QueuedValuePlacerConfig extends EntityPlacerConfig<QueuedValu
private MoveSelectorConfig moveSelectorConfig = null;

public @Nullable Class<?> getEntityClass() {
return entityClass;
return ConfigUtils.resolveClass(entityClass, "entityClass", this);
}

public void setEntityClass(@Nullable Class<?> entityClass) {
this.entityClass = entityClass;
this.entityClass = entityClass == null ? null : entityClass.getName();
}

public @Nullable ValueSelectorConfig getValueSelectorConfig() {
Expand All @@ -78,7 +78,7 @@ public void setMoveSelectorConfig(@Nullable MoveSelectorConfig moveSelectorConfi
// ************************************************************************

public @NonNull QueuedValuePlacerConfig withEntityClass(@NonNull Class<?> entityClass) {
this.setEntityClass(entityClass);
this.entityClass = entityClass.getName();
return this;
}

Expand All @@ -98,7 +98,7 @@ public void setMoveSelectorConfig(@Nullable MoveSelectorConfig moveSelectorConfi

@Override
public @NonNull QueuedValuePlacerConfig inherit(@NonNull QueuedValuePlacerConfig inheritedConfig) {
entityClass = ConfigUtils.inheritOverwritableProperty(entityClass, inheritedConfig.getEntityClass());
entityClass = ConfigUtils.inheritOverwritableProperty(entityClass, inheritedConfig.entityClass);
valueSelectorConfig = ConfigUtils.inheritConfig(valueSelectorConfig, inheritedConfig.getValueSelectorConfig());
setMoveSelectorConfig(
ConfigUtils.inheritOverwritableProperty(getMoveSelectorConfig(), inheritedConfig.getMoveSelectorConfig()));
Expand All @@ -112,7 +112,7 @@ public void setMoveSelectorConfig(@Nullable MoveSelectorConfig moveSelectorConfi

@Override
public void visitReferencedClasses(@NonNull Consumer<Class<?>> classVisitor) {
classVisitor.accept(entityClass);
classVisitor.accept(getEntityClass());
if (valueSelectorConfig != null) {
valueSelectorConfig.visitReferencedClasses(classVisitor);
}
Expand Down
Loading
Loading