Hi everybody.
I have a problem with chained planning variables.
I'm using optaplanner 5.5.0.Final.
I have a planning entity like:
@PlanningEntity()
public class Case implements Chained {
private Chained previous;
@PlanningVariable(chained = true)
@ValueRanges({
@ValueRange(type = ValueRangeType.FROM_SOLUTION_PROPERTY, solutionProperty = "doctors"),
@ValueRange(type = ValueRangeType.FROM_SOLUTION_PROPERTY,
solutionProperty = "cases", excludeUninitializedPlanningEntity = true)
})
public Chained getPrevious() {
return previous;
}
}
A fact class:
public class Doctor implements Chained {
...
}
An a solution class:
public class Plan extends implements Solution<HardAndSoftScore> {
private List<Doctor> doctors;
private List<Case> cases;
private HardAndSoftScore score;
@PlanningEntityCollectionProperty
public List<Case> getCases() {
return cases;
}
public Collection<? extends Object> getProblemFacts() {
return new ArrayList<Doctor>(doctors);
}
}
The equals / hashCode / clone methods are inspired on the TravelingSalesmanTour example.
I want that Optaplanner generates chains like:
DoctorA <- Case1 <- Case2
DoctorB <- Case3
This model tries to represent a list of Cases assigned to each Doctor.
Suppose I build a solution like:
Plan plan = new Plan();
plan.setDoctors(DoctorA, DoctorB); //pseudo-code
plan.setCases(Case1, Case2); //pseudo-code
Then I build a solver:
Solver solver = getSolverFactory().buildSolver();
solver.setPlanningProblem(plan);
solver.solve();
Plan bestPlan = (Plan) solver.getBestSolution();
The
problem is that, Optaplanner is not testing all the posible
combinations of chains. I mean, suppose that we know that the better
solution (based on the scoring rules) is:
DoctorA
DoctorB <- Case1 <- Case2
But Optaplanner seems to test only chains with DoctorA, so the result of calling getBestSolution() is:
DoctorA <- Case1 <- Case2
I guess that Optaplanner only test chains whit DoctorA, becouse it logs lines like:
...
DEBUG: org.drools.planner.core.localsearch.DefaultLocalSearchSolverPhase
- Step index (1), time spend (20002), score (1hard/2soft), best
score (1hard/2soft), accepted/selected move count (0/58187) for picked
step (Case [id=2, previous=Doctor [id=1]] => Case [id=1,
previous=Case [id=2, previous=Doctor [id=1]]]).
...
That is, no lines whith "DoctorB" are logged.
If the doctor list is inverted, the same problem happen (the DoctorA is no processed). That is:
Plan plan = new Plan();
plan.setDoctors(DoctorB, DoctorA); //pseudo-code
plan.setCases(Case1, Case2); //pseudo-code
Solver solver = getSolverFactory().buildSolver();
solver.setPlanningProblem(plan);
solver.solve(); // DoctorA is not part of chains
I guess the problem is on the solver configuration, specifically on the localSearch configuration:
<localSearch>
<unionMoveSelector>
<changeMoveSelector>
<valueSelector/>
</changeMoveSelector>
<swapMoveSelector />
<subChainChangeMoveSelector>
<selectReversingMoveToo>true</selectReversingMoveToo>
</subChainChangeMoveSelector>
<subChainSwapMoveSelector>
<selectReversingMoveToo>true</selectReversingMoveToo>
</subChainSwapMoveSelector>
</unionMoveSelector>
<acceptor>
<planningEntityTabuSize>9</planningEntityTabuSize>
</acceptor>
<forager>
<minimalAcceptedSelection>2000</minimalAcceptedSelection>
</forager>
</localSearch>
I tried some alternatives to this configuration, but with no success.
Do you know what I am doing wrong?
Thanks a lot.
Regards