问题
I'm working on a solution of a problem that is close to the Nurse Rostering Example in optaplanner .
Employees are assigned to shifts as in the Nurse Roster but the main difference is that there are also skill requirements (assignments) that last lets say 20 minutes. An employee can be assigned to a skill requirement if he gets assigned to a shift that covers the given skill requirement time. Lets say we have a skill requirement for Skill1 from 12:00 to 12:20 and an employee is assigned on a shift from 08:00 to 16:00 then he can be assigned to that skill requirement only if he has that skill.
I have 2 planning entity classes. The default shift assignment in the example, and i have implemented 2 more classes SkillRequirement class which will hold one skill requirement in the given time frame (this will be a planning fact) , and the second planning entity class will be between the Employee and the SkillRequirement class and the name of it will be EmployeeSkillRequirement.
By now i think i have done everything good i annotated the EmployeeSkillRequirement class as @PlanningEntity and the planning variable with the appropriate value range, in the planning solution i added the lists for the skill requirements(which are facts and also go into drools working memory) and the list of employees on skill requirements which are the planning entities and are properly annotated with @PlanningEntitySolutionProperty
I'm having a hard time configuring the solver, i have tried many different solver configurations, i read in the documentation that when there are more planning entities and/or planning variables a union of move selectors should be used where you tell OptaPlanner the name of the planning entity class and planning variable, because it cant find it by default.
None seem to work and i get this exception all the time
Exception in thread "main" java.lang.IllegalArgumentException: Unmarshalling of solverConfigResource (org/optaplanner/examples/nurserostering/solver/nurseRosteringSolverConfig.xml) fails.
Here are the configurations i' have been trying to use:
Config 1:
In this configuration the default move selectors are used for the planning entity shift assignment class in local search and move selectors are added for the planning entity class "EmployeeSkillRequirement" and everything is combined in a and the construction heuristic is replaced with move selectors combined in a union to.
<?xml version="1.0" encoding="UTF-8"?>
<solver>
<!--<environmentMode>FAST_ASSERT</environmentMode> -->
<solutionClass>org.optaplanner.examples.nurserostering.domain.NurseRoster
</solutionClass>
<entityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
</entityClass>
<entityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
</entityClass>
<scoreDirectorFactory>
<scoreDefinitionType>HARD_SOFT</scoreDefinitionType>
<scoreDrl>org/optaplanner/examples/nurserostering/solver/nurseRosteringScoreRules.drl
</scoreDrl>
</scoreDirectorFactory>
<termination>
<!-- Official benchmark secondsSpentLimit allowed on: - ge0ffrey's main
pc: sprint 11, medium 700, long 42000 -->
<secondsSpentLimit>700</secondsSpentLimit>
<!--<bestScoreLimit>-0hard/-999999soft</bestScoreLimit> -->
</termination>
<constructionHeuristic>
<queuedEntityPlacer>
<unionMoveSelector>
<changeMoveSelector>
<entitySelector>
<entityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
</entityClass>
</entitySelector>
<valueSelector>
<downcastEntityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
</downcastEntityClass>
<variableName>employee</variableName>
</valueSelector>
</changeMoveSelector>
<swapMoveSelector>
<entitySelector>
<entityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
</entityClass>
</entitySelector>
<valueSelector>
<downcastEntityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
</downcastEntityClass>
<variableName>employee</variableName>
</valueSelector>
</swapMoveSelector>
<changeMoveSelector>
<entitySelector>
<entityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
</entityClass>
</entitySelector>
<valueSelector>
<variableName>employee</variableName>
</valueSelector>
</changeMoveSelector>
<swapMoveSelector>
<entitySelector>
<entityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
</entityClass>
</entitySelector>
<valueSelector>
<variableName>employee</variableName>
</valueSelector>
</swapMoveSelector>
</unionMoveSelector>
</queuedEntityPlacer>
</constructionHeuristic>
<localSearch>
<unionMoveSelector>
<!-- Move Selectors for ShiftAssignment this was the default configuration
from the example -->
<moveListFactory>
<cacheType>PHASE</cacheType>
<moveListFactoryClass>org.optaplanner.examples.nurserostering.solver.move.factory.EmployeeChangeMoveFactory
</moveListFactoryClass>
</moveListFactory>
<moveListFactory>
<cacheType>PHASE</cacheType>
<moveListFactoryClass>org.optaplanner.examples.nurserostering.solver.move.factory.ShiftAssignmentSwapMoveFactory
</moveListFactoryClass>
</moveListFactory>
<moveListFactory>
<cacheType>STEP</cacheType>
<moveListFactoryClass>org.optaplanner.examples.nurserostering.solver.move.factory.ShiftAssignmentPillarPartSwapMoveFactory
</moveListFactoryClass>
</moveListFactory>
<!-- The move selectors for the second plannig entity class EmployeeSkillRequirement -->
<changeMoveSelector>
<entitySelector>
<entityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
</entityClass>
</entitySelector>
<valueSelector>
<variableName>employee</variableName>
</valueSelector>
</changeMoveSelector>
<swapMoveSelector>
<entitySelector>
<entityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
</entityClass>
</entitySelector>
<valueSelector>
<variableName>employee</variableName>
</valueSelector>
</swapMoveSelector>
</unionMoveSelector>
<acceptor>
<entityTabuSize>7</entityTabuSize>
</acceptor>
<forager>
<acceptedCountLimit>800</acceptedCountLimit>
</forager>
</localSearch>
Config 2:
Second i looked at the documentation and found this hint that says that it is easier to deal with multiple planning entity classes if there are two different construction heuristic parts for each of them http://docs.jboss.org/optaplanner/release/6.3.0.Final/optaplanner-docs/html_single/index.html#allocateEntityFromQueueMultipleEntityClasses so i tried this configuration too.
<?xml version="1.0" encoding="UTF-8"?>
<solver>
<!--<environmentMode>FAST_ASSERT</environmentMode> -->
<solutionClass>org.optaplanner.examples.nurserostering.domain.NurseRoster
</solutionClass>
<entityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
</entityClass>
<entityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
</entityClass>
<scoreDirectorFactory>
<scoreDefinitionType>HARD_SOFT</scoreDefinitionType>
<scoreDrl>org/optaplanner/examples/nurserostering/solver/nurseRosteringScoreRules.drl
</scoreDrl>
</scoreDirectorFactory>
<termination>
<!-- Official benchmark secondsSpentLimit allowed on: - ge0ffrey's main
pc: sprint 11, medium 700, long 42000 -->
<secondsSpentLimit>700</secondsSpentLimit>
<!--<bestScoreLimit>-0hard/-999999soft</bestScoreLimit> -->
</termination>
<constructionHeuristic>
<queuedEntityPlacer>
<unionMoveSelector>
<changeMoveSelector>
<entitySelector>
<entityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
</entityClass>
</entitySelector>
<valueSelector>
<downcastEntityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
</downcastEntityClass>
<variableName>employee</variableName>
</valueSelector>
</changeMoveSelector>
<swapMoveSelector>
<entitySelector>
<entityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
</entityClass>
</entitySelector>
<valueSelector>
<downcastEntityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
</downcastEntityClass>
<variableName>employee</variableName>
</valueSelector>
</swapMoveSelector>
</unionMoveSelector>
</queuedEntityPlacer>
</constructionHeuristic>
<constructionHeuristic>
<queuedEntityPlacer>
<unionMoveSelector>
<changeMoveSelector>
<entitySelector>
<entityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
</entityClass>
</entitySelector>
<valueSelector>
<downcastEntityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
</downcastEntityClass>
<variableName>employee</variableName>
</valueSelector>
</changeMoveSelector>
<swapMoveSelector>
<entitySelector>
<entityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
</entityClass>
</entitySelector>
<valueSelector>
<downcastEntityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
</downcastEntityClass>
<variableName>employee</variableName>
</valueSelector>
</swapMoveSelector>
</unionMoveSelector>
</queuedEntityPlacer>
</constructionHeuristic>
<localSearch>
<unionMoveSelector>
<!-- Move Selectors for ShiftAssignment this was the default configuration
from the example -->
<moveListFactory>
<cacheType>PHASE</cacheType>
<moveListFactoryClass>org.optaplanner.examples.nurserostering.solver.move.factory.EmployeeChangeMoveFactory
</moveListFactoryClass>
</moveListFactory>
<moveListFactory>
<cacheType>PHASE</cacheType>
<moveListFactoryClass>org.optaplanner.examples.nurserostering.solver.move.factory.ShiftAssignmentSwapMoveFactory
</moveListFactoryClass>
</moveListFactory>
<moveListFactory>
<cacheType>STEP</cacheType>
<moveListFactoryClass>org.optaplanner.examples.nurserostering.solver.move.factory.ShiftAssignmentPillarPartSwapMoveFactory
</moveListFactoryClass>
</moveListFactory>
<!-- besides this default configuration from optaplaner i also tried this here
<changeMoveSelector>
<entitySelector>
<entityClass>org.optaplanner.examples.nurserostering.domain.
</entityClass>
</entitySelector>
<valueSelector>
<downcastEntityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
</downcastEntityClass>
<variableName>employee</variableName>
</valueSelector>
</changeMoveSelector>
<swapMoveSelector>
<entitySelector>
<entityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
</entityClass>
</entitySelector>
<valueSelector>
<downcastEntityClass>org.optaplanner.examples.nurserostering.domain.ShiftAssignment
</downcastEntityClass>
<variableName>employee</variableName>
</valueSelector>
</swapMoveSelector>-->
<!-- The move selectors for the second plannig entity class EmployeeSkillRequirement -->
<changeMoveSelector>
<entitySelector>
<entityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
</entityClass>
</entitySelector>
<valueSelector>
<downcastEntityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
</downcastEntityClass>
<variableName>employee</variableName>
</valueSelector>
</changeMoveSelector>
<swapMoveSelector>
<entitySelector>
<entityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
</entityClass>
</entitySelector>
<valueSelector>
<downcastEntityClass>org.optaplanner.examples.nurserostering.domain.EmployeeSkillRequirement
</downcastEntityClass>
<variableName>employee</variableName>
</valueSelector>
</swapMoveSelector>
</unionMoveSelector>
<acceptor>
<entityTabuSize>7</entityTabuSize>
</acceptor>
<forager>
<acceptedCountLimit>800</acceptedCountLimit>
</forager>
</localSearch>
I also tried some other configurations that are similar to these ones, still, no luck.
How can i fix this and make it working?
Edit:
Exception in thread "main" java.lang.IllegalArgumentException: Unmarshalling of solverConfigResource (org/optaplanner/examples/nurserostering/solver/nurseRosteringSolverConfig.xml) fails.
at org.optaplanner.core.impl.solver.XStreamXmlSolverFactory.configure(XStreamXmlSolverFactory.java:114)
at org.optaplanner.core.api.solver.SolverFactory.createFromXmlResource(SolverFactory.java:66)
at org.optaplanner.examples.nurserostering.app.NurseRosteringApp.createSolver(NurseRosteringApp.java:50)
at org.optaplanner.examples.common.app.CommonApp.createSolutionBusiness(CommonApp.java:90)
at org.optaplanner.examples.common.app.CommonApp.init(CommonApp.java:77)
at org.optaplanner.examples.common.app.CommonApp.init(CommonApp.java:73)
at org.optaplanner.examples.nurserostering.app.NurseRosteringApp.main(NurseRosteringApp.java:38)
Caused by: " com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$UnknownFieldException: No such field org.optaplanner.core.config.heuristic.selector.move.generic.SwapMoveSelectorConfig.valueSelector
---- Debugging information ----
field : valueSelector
class : org.optaplanner.core.config.heuristic.selector.move.generic.SwapMoveSelect orConfig
required-type : org.optaplanner.core.config.heuristic.selector.move.generic.SwapMoveSelect orConfig
converter-type : com.thoughtworks.xstream.converters.reflection.ReflectionConverter
line number : 98
class[1] : org.optaplanner.core.config.heuristic.selector.move.composite.UnionMoveSel ectorConfig
class[2] : org.optaplanner.core.config.localsearch.LocalSearchPhaseConfig
class[3] : org.optaplanner.core.config.solver.SolverConfig
version : 1.4.7
-------------------------------
at org.optaplanner.core.impl.solver.XStreamXmlSolverFactory.configure(XStreamXmlSolverFactory.java:114)
at org.optaplanner.core.api.solver.SolverFactory.createFromXmlResource(SolverFactory.java:66)
at org.optaplanner.examples.nurserostering.app.NurseRosteringApp.createSolver(NurseRosteringApp.java:50)
at org.optaplanner.examples.common.app.CommonApp.createSolutionBusiness(CommonApp.java:90)
at org.optaplanner.examples.common.app.CommonApp.init(CommonApp.java:77)
at org.optaplanner.examples.common.app.CommonApp.init(CommonApp.java:73)
at org.optaplanner.examples.nurserostering.app.NurseRosteringApp.main(NurseRosteringApp.java:38)
回答1:
A common mistake is to add whitespace in classname properties that doesn't get parsed correctly. This fails during parsing:
<solutionClass>org.optaplanner.examples.nurserostering.domain.NurseRoster
</solutionClass>
but this succeeds in getting parsed:
<solutionClass>org.optaplanner.examples.nurserostering.domain.NurseRoster</solutionClass>
来源:https://stackoverflow.com/questions/36049363/problems-with-the-solver-configuration-for-two-planning-entity-classes