pour se familiariser avec optaplanner J'ai créé un projet de test simple. J'ai seulement une solution et une classe d'entité. L'entité n'a qu'une seule valeur entre 0 et 9. Il ne devrait y avoir que des nombres impairs et la somme de tous devrait être inférieure à 10 (ce ne sont que quelques contraintes aléatoires que j'ai trouvées).Exemple simple OptaPlaner ne peut pas trouver la solution possible
Comme Score j'utilise un HardSoftScore simple. Voici le code:
public class TestScoreCalculator implements EasyScoreCalculator<TestSolution>{
@Override
public HardSoftScore calculateScore(TestSolution sol) {
int hardScore = 0;
int softScore = 0;
int valueSum = 0;
for (TestEntity entity : sol.getTestEntities()) {
valueSum += entity.getValue() == null? 0 : entity.getValue();
}
// hard Score
for (TestEntity entity : sol.getTestEntities()) {
if(entity.getValue() == null || entity.getValue() % 2 == 0)
hardScore -= 1; // constraint: only odd numbers
}
if(valueSum > 10)
hardScore -= 2; // constraint: sum should be less than 11
// soft Score
softScore = valueSum; // maximize
return HardSoftScore.valueOf(hardScore, softScore);
}
}
et voici mon fichier de configuration:
<?xml version="1.0" encoding="UTF-8"?>
<solver>
<!-- Domain model configuration -->
<scanAnnotatedClasses/>
<!-- Score configuration -->
<scoreDirectorFactory>
<easyScoreCalculatorClass>score.TestScoreCalculator</easyScoreCalculatorClass>
</scoreDirectorFactory>
<!-- Optimization algorithms configuration -->
<termination>
<secondsSpentLimit>30</secondsSpentLimit>
</termination>
</solver>
pour une raison OptaPlanner ne peux pas trouver une solution réalisable. Il se termine par LS step (161217), time spent (29910), score (-2hard/10soft), best score (-2hard/10soft)...
et la solution 9 1 0 0
. Donc le hardScore est -2 car les deux 0 ne sont pas impairs. Une solution possible serait 7 1 1 1
par exemple. Pourquoi est-ce ? Cela devrait être un exemple très facile ...
(quand je mets les valeurs de début de 7 1 1 1
termine avec cette solution et un score de (0hard/10soft)
comment il devrait être)
Edit:
L'entité classe
@PlanningEntity
public class TestEntity {
private Integer value;
@PlanningVariable(valueRangeProviderRefs = {"TestEntityValueRange"})
public Integer getValue() {
return value;
}
public void setValue(Integer value) {
this.value = value;
}
@ValueRangeProvider(id = "TestEntityValueRange")
public CountableValueRange<Integer> getStartPeriodRange() {
return ValueRangeFactory.createIntValueRange(0, 10);
}
}
La solution classe
@PlanningSolution
public class TestSolution {
private List<TestEntity> TestEntities;
private HardSoftScore score;
@PlanningEntityCollectionProperty
public List<TestEntity> getTestEntities() {
return TestEntities;
}
public void setTestEntities(List<TestEntity> testEntities) {
TestEntities = testEntities;
}
@PlanningScore
public HardSoftScore getScore() {
return score;
}
public void setScore(HardSoftScore score) {
this.score = score;
}
@Override
public String toString() {
String str = "";
for (TestEntity testEntity : TestEntities)
str += testEntity.getValue()+" ";
return str;
}
}
La classe
Programme principalpublic class Main {
public static final String SOLVER_CONFIG = "score/TestConfig.xml";
public static int printCount = 0;
public static void main(String[] args) {
init();
}
private static void init() {
SolverFactory<TestSolution> solverFactory = SolverFactory.createFromXmlResource(SOLVER_CONFIG);
Solver<TestSolution> solver = solverFactory.buildSolver();
TestSolution model = new TestSolution();
List<TestEntity> list = new ArrayList<TestEntity>();
// list.add(new TestEntity(){{setValue(7);}});
// list.add(new TestEntity(){{setValue(1);}});
// list.add(new TestEntity(){{setValue(1);}});
// list.add(new TestEntity(){{setValue(1);}});
for (int i = 0; i < 4; i++) {
list.add(new TestEntity());
}
model.setTestEntities(list);
// Solve the problem
TestSolution solution = solver.solve(model);
// Display the result
System.out.println(solution);
}
}
Pouvez-vous joindre une source de solution/entité et un ensemble de jeux de données que vous utilisez? –