public abstract class AbstractScoreDirector<Solution_,Factory_ extends AbstractScoreDirectorFactory<Solution_>> extends Object implements InnerScoreDirector<Solution_>, Cloneable
ScoreDirector
.
Implementation note: Extending classes should follow these guidelines:
ScoreDirector
Modifier and Type | Field and Description |
---|---|
protected boolean |
allChangesWillBeUndoneBeforeStepEnds |
protected long |
calculationCount |
protected boolean |
constraintMatchEnabledPreference |
protected org.slf4j.Logger |
logger |
protected boolean |
lookUpEnabled |
protected LookUpManager |
lookUpManager |
protected Factory_ |
scoreDirectorFactory |
protected VariableListenerSupport<Solution_> |
variableListenerSupport |
protected long |
workingEntityListRevision |
protected Integer |
workingInitScore |
protected Solution_ |
workingSolution |
Modifier | Constructor and Description |
---|---|
protected |
AbstractScoreDirector(Factory_ scoreDirectorFactory,
boolean lookUpEnabled,
boolean constraintMatchEnabledPreference) |
Modifier and Type | Method and Description |
---|---|
void |
afterEntityAdded(EntityDescriptor<Solution_> entityDescriptor,
Object entity) |
void |
afterEntityAdded(Object entity) |
void |
afterEntityRemoved(EntityDescriptor<Solution_> entityDescriptor,
Object entity) |
void |
afterEntityRemoved(Object entity) |
void |
afterProblemFactAdded(Object problemFact) |
void |
afterProblemFactRemoved(Object problemFact) |
void |
afterProblemPropertyChanged(Object problemFactOrEntity) |
void |
afterVariableChanged(Object entity,
String variableName) |
void |
afterVariableChanged(VariableDescriptor variableDescriptor,
Object entity) |
void |
assertExpectedUndoMoveScore(Move move,
Score beforeMoveScore)
Asserts that if the
Score is calculated for the current working solution
in the current ScoreDirector (with incremental calculation residue),
it is equal to the parameter beforeMoveScore . |
void |
assertExpectedWorkingScore(Score expectedWorkingScore,
Object completedAction)
Asserts that if the
Score is calculated for the current working solution
in the current ScoreDirector (with possibly incremental calculation residue),
it is equal to the parameter expectedWorkingScore . |
void |
assertPredictedScoreFromScratch(Score workingScore,
Object completedAction)
Asserts that if the
Score is calculated for the current working solution
in a fresh ScoreDirector (with no incremental calculation residue),
it is equal to the parameter predictedScore . |
void |
assertShadowVariablesAreNotStale(Score expectedWorkingScore,
Object completedAction)
Asserts that if all
VariableListener s are forcibly triggered,
and therefore all shadow variables are updated if needed,
that none of the shadow variables of the working solution change,
Then also asserts that the Score calculated for the working solution afterwards
is equal to the parameter expectedWorkingScore . |
void |
assertWorkingScoreFromScratch(Score workingScore,
Object completedAction)
Asserts that if the
Score is calculated for the current working solution
in a fresh ScoreDirector (with no incremental calculation residue),
it is equal to the parameter workingScore . |
void |
beforeEntityAdded(EntityDescriptor<Solution_> entityDescriptor,
Object entity) |
void |
beforeEntityAdded(Object entity) |
void |
beforeEntityRemoved(EntityDescriptor<Solution_> entityDescriptor,
Object entity) |
void |
beforeEntityRemoved(Object entity) |
void |
beforeProblemFactAdded(Object problemFact) |
void |
beforeProblemFactRemoved(Object problemFact) |
void |
beforeProblemPropertyChanged(Object problemFactOrEntity) |
void |
beforeVariableChanged(Object entity,
String variableName) |
void |
beforeVariableChanged(VariableDescriptor variableDescriptor,
Object entity) |
protected String |
buildScoreCorruptionAnalysis(ScoreDirector<Solution_> uncorruptedScoreDirector,
boolean predicted) |
protected String |
buildShadowVariableAnalysis(boolean predicted) |
void |
changeVariableFacade(VariableDescriptor variableDescriptor,
Object entity,
Object newValue) |
AbstractScoreDirector<Solution_,Factory_> |
clone()
Clones this
ScoreDirector and its working solution . |
Solution_ |
cloneSolution(Solution_ originalSolution)
Returns a planning clone of the solution,
which is not a shallow clone nor a deep clone nor a partition clone.
|
Solution_ |
cloneWorkingSolution()
Returns a planning clone of the solution,
which is not a shallow clone nor a deep clone nor a partition clone.
|
void |
close()
Needs to be called after use because some implementations need to clean up their resources.
|
InnerScoreDirector<Solution_> |
createChildThreadScoreDirector(ChildThreadType childThreadType) |
protected String |
createShadowVariablesViolationMessage() |
Score |
doAndProcessMove(Move<Solution_> move,
boolean assertMoveScoreFromScratch) |
void |
doAndProcessMove(Move<Solution_> move,
boolean assertMoveScoreFromScratch,
Consumer<Score> moveProcessor) |
String |
explainScore()
Returns a diagnostic text that explains the
Score through the ConstraintMatch API
to identify which constraints or planning entities cause that score quality. |
long |
getCalculationCount() |
ScoreDefinition |
getScoreDefinition() |
Factory_ |
getScoreDirectorFactory() |
SolutionDescriptor<Solution_> |
getSolutionDescriptor() |
SupplyManager |
getSupplyManager() |
int |
getWorkingEntityCount() |
List<Object> |
getWorkingEntityList() |
long |
getWorkingEntityListRevision() |
Solution_ |
getWorkingSolution()
The
PlanningSolution that is used to calculate the Score . |
int |
getWorkingValueCount() |
boolean |
isAllChangesWillBeUndoneBeforeStepEnds() |
boolean |
isConstraintMatchEnabledPreference() |
boolean |
isLookUpEnabled() |
boolean |
isWorkingEntityListDirty(long expectedWorkingEntityListRevision) |
<E> E |
lookUpWorkingObject(E externalObject)
Translates an entity or fact instance (often from another
Thread or JVM)
to this ScoreDirector 's internal working instance. |
<E> E |
lookUpWorkingObjectOrReturnNull(E externalObject)
As defined by
ScoreDirector.lookUpWorkingObject(Object) ,
but doesn't fail fast if no workingObject was ever added for the externalObject. |
void |
overwriteConstraintMatchEnabledPreference(boolean constraintMatchEnabledPreference) |
void |
resetCalculationCount() |
void |
setAllChangesWillBeUndoneBeforeStepEnds(boolean allChangesWillBeUndoneBeforeStepEnds)
Do not waste performance by propagating changes to step (or higher) mechanisms.
|
protected void |
setCalculatedScore(Score score) |
protected void |
setWorkingEntityListDirty() |
void |
setWorkingSolution(Solution_ workingSolution)
The
working solution must never be the same instance as the
best solution , it should be a (un)changed clone. |
String |
toString() |
void |
triggerVariableListeners() |
equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
calculateScore, dispose, getConstraintMatchTotalMap, getConstraintMatchTotals, getIndictmentMap, isConstraintMatchEnabled
protected final transient org.slf4j.Logger logger
protected final Factory_ extends AbstractScoreDirectorFactory<Solution_> scoreDirectorFactory
protected final boolean lookUpEnabled
protected final LookUpManager lookUpManager
protected boolean constraintMatchEnabledPreference
protected final VariableListenerSupport<Solution_> variableListenerSupport
protected Solution_ workingSolution
protected long workingEntityListRevision
protected Integer workingInitScore
protected boolean allChangesWillBeUndoneBeforeStepEnds
protected long calculationCount
protected AbstractScoreDirector(Factory_ scoreDirectorFactory, boolean lookUpEnabled, boolean constraintMatchEnabledPreference)
public Factory_ getScoreDirectorFactory()
getScoreDirectorFactory
in interface InnerScoreDirector<Solution_>
public SolutionDescriptor<Solution_> getSolutionDescriptor()
getSolutionDescriptor
in interface InnerScoreDirector<Solution_>
public ScoreDefinition getScoreDefinition()
getScoreDefinition
in interface InnerScoreDirector<Solution_>
public boolean isLookUpEnabled()
public boolean isConstraintMatchEnabledPreference()
public void overwriteConstraintMatchEnabledPreference(boolean constraintMatchEnabledPreference)
overwriteConstraintMatchEnabledPreference
in interface InnerScoreDirector<Solution_>
constraintMatchEnabledPreference
- false if a ScoreDirector
implementation
should not do ConstraintMatch
tracking even if it supports it.public Solution_ getWorkingSolution()
ScoreDirector
PlanningSolution
that is used to calculate the Score
.
Because a Score
is best calculated incrementally (by deltas),
the ScoreDirector
needs to be notified when its working solution
changes.
If the working solution
has been changed since ScoreDirector.calculateScore()
was called,
its Score
won't be correct.
getWorkingSolution
in interface ScoreDirector<Solution_>
public long getWorkingEntityListRevision()
getWorkingEntityListRevision
in interface InnerScoreDirector<Solution_>
InnerScoreDirector.isWorkingEntityListDirty(long)
later onpublic boolean isAllChangesWillBeUndoneBeforeStepEnds()
public void setAllChangesWillBeUndoneBeforeStepEnds(boolean allChangesWillBeUndoneBeforeStepEnds)
InnerScoreDirector
setAllChangesWillBeUndoneBeforeStepEnds
in interface InnerScoreDirector<Solution_>
allChangesWillBeUndoneBeforeStepEnds
- true if all changes will be undonepublic long getCalculationCount()
getCalculationCount
in interface InnerScoreDirector<Solution_>
public void resetCalculationCount()
resetCalculationCount
in interface InnerScoreDirector<Solution_>
public SupplyManager getSupplyManager()
getSupplyManager
in interface InnerScoreDirector<Solution_>
public void setWorkingSolution(Solution_ workingSolution)
ScoreDirector
working solution
must never be the same instance as the
best solution
, it should be a (un)changed clone.
Only call this method on a separate ScoreDirector
instance,
built by SolverFactory.getScoreDirectorFactory()
,
not on the one used inside the Solver
itself.
setWorkingSolution
in interface ScoreDirector<Solution_>
workingSolution
- never nullpublic Score doAndProcessMove(Move<Solution_> move, boolean assertMoveScoreFromScratch)
doAndProcessMove
in interface InnerScoreDirector<Solution_>
move
- never nullassertMoveScoreFromScratch
- true will hurt performancepublic void doAndProcessMove(Move<Solution_> move, boolean assertMoveScoreFromScratch, Consumer<Score> moveProcessor)
doAndProcessMove
in interface InnerScoreDirector<Solution_>
move
- never nullassertMoveScoreFromScratch
- true will hurt performancemoveProcessor
- never null, use this to store the score as well as call the acceptor and foragerpublic boolean isWorkingEntityListDirty(long expectedWorkingEntityListRevision)
isWorkingEntityListDirty
in interface InnerScoreDirector<Solution_>
expectedWorkingEntityListRevision
- anprotected void setWorkingEntityListDirty()
public Solution_ cloneWorkingSolution()
InnerScoreDirector
cloneWorkingSolution
in interface InnerScoreDirector<Solution_>
public Solution_ cloneSolution(Solution_ originalSolution)
InnerScoreDirector
cloneSolution
in interface InnerScoreDirector<Solution_>
originalSolution
- never nullpublic int getWorkingEntityCount()
getWorkingEntityCount
in interface InnerScoreDirector<Solution_>
>= 0
public List<Object> getWorkingEntityList()
getWorkingEntityList
in interface InnerScoreDirector<Solution_>
public int getWorkingValueCount()
getWorkingValueCount
in interface InnerScoreDirector<Solution_>
>= 0
public void triggerVariableListeners()
triggerVariableListeners
in interface ScoreDirector<Solution_>
protected void setCalculatedScore(Score score)
public String explainScore()
ScoreDirector
Score
through the ConstraintMatch
API
to identify which constraints or planning entities cause that score quality.
In case of an infeasible
solution,
this can help diagnose the cause of that.
Do not parse this string.
Instead, to provide this information in a UI or a service,
use ScoreDirector.getConstraintMatchTotalMap()
and ScoreDirector.getIndictmentMap()
and convert those into a domain specific API.
This automatically calls ScoreDirector.calculateScore()
first.
explainScore
in interface ScoreDirector<Solution_>
public AbstractScoreDirector<Solution_,Factory_> clone()
InnerScoreDirector
ScoreDirector
and its working solution
.
Use ScoreDirector.getWorkingSolution()
to retrieve the working solution
of that clone.
This is heavy method, because it usually breaks incremental score calculation. Use it sparingly. Therefore it's best to clone lazily by delaying the clone call as long as possible.
clone
in interface InnerScoreDirector<Solution_>
clone
in class Object
public InnerScoreDirector<Solution_> createChildThreadScoreDirector(ChildThreadType childThreadType)
createChildThreadScoreDirector
in interface InnerScoreDirector<Solution_>
public void close()
ScoreDirector
close
in interface AutoCloseable
close
in interface ScoreDirector<Solution_>
public final void beforeEntityAdded(Object entity)
beforeEntityAdded
in interface ScoreDirector<Solution_>
public final void afterEntityAdded(Object entity)
afterEntityAdded
in interface ScoreDirector<Solution_>
public final void beforeVariableChanged(Object entity, String variableName)
beforeVariableChanged
in interface ScoreDirector<Solution_>
public final void afterVariableChanged(Object entity, String variableName)
afterVariableChanged
in interface ScoreDirector<Solution_>
public final void beforeEntityRemoved(Object entity)
beforeEntityRemoved
in interface ScoreDirector<Solution_>
public final void afterEntityRemoved(Object entity)
afterEntityRemoved
in interface ScoreDirector<Solution_>
public void beforeEntityAdded(EntityDescriptor<Solution_> entityDescriptor, Object entity)
public void afterEntityAdded(EntityDescriptor<Solution_> entityDescriptor, Object entity)
public void beforeVariableChanged(VariableDescriptor variableDescriptor, Object entity)
beforeVariableChanged
in interface ScoreDirector<Solution_>
public void afterVariableChanged(VariableDescriptor variableDescriptor, Object entity)
afterVariableChanged
in interface ScoreDirector<Solution_>
public void changeVariableFacade(VariableDescriptor variableDescriptor, Object entity, Object newValue)
changeVariableFacade
in interface ScoreDirector<Solution_>
public void beforeEntityRemoved(EntityDescriptor<Solution_> entityDescriptor, Object entity)
public void afterEntityRemoved(EntityDescriptor<Solution_> entityDescriptor, Object entity)
public void beforeProblemFactAdded(Object problemFact)
beforeProblemFactAdded
in interface ScoreDirector<Solution_>
public void afterProblemFactAdded(Object problemFact)
afterProblemFactAdded
in interface ScoreDirector<Solution_>
public void beforeProblemPropertyChanged(Object problemFactOrEntity)
beforeProblemPropertyChanged
in interface ScoreDirector<Solution_>
public void afterProblemPropertyChanged(Object problemFactOrEntity)
afterProblemPropertyChanged
in interface ScoreDirector<Solution_>
public void beforeProblemFactRemoved(Object problemFact)
beforeProblemFactRemoved
in interface ScoreDirector<Solution_>
public void afterProblemFactRemoved(Object problemFact)
afterProblemFactRemoved
in interface ScoreDirector<Solution_>
public <E> E lookUpWorkingObject(E externalObject)
ScoreDirector
Thread
or JVM)
to this ScoreDirector
's internal working instance.
Useful for Move.rebase(ScoreDirector)
and in a ProblemFactChange
.
Matching is determined by the LookUpStrategyType
on PlanningSolution
.
Matching uses a PlanningId
by default.
lookUpWorkingObject
in interface ScoreDirector<Solution_>
E
- the object typeexternalObject
- sometimes nullpublic <E> E lookUpWorkingObjectOrReturnNull(E externalObject)
ScoreDirector
ScoreDirector.lookUpWorkingObject(Object)
,
but doesn't fail fast if no workingObject was ever added for the externalObject.
It's recommended to use ScoreDirector.lookUpWorkingObject(Object)
instead,
especially in a Move.rebase(ScoreDirector)
code.lookUpWorkingObjectOrReturnNull
in interface ScoreDirector<Solution_>
E
- the object typeexternalObject
- sometimes nullpublic void assertExpectedWorkingScore(Score expectedWorkingScore, Object completedAction)
InnerScoreDirector
Score
is calculated for the current working solution
in the current ScoreDirector
(with possibly incremental calculation residue),
it is equal to the parameter expectedWorkingScore
.
Used to assert that skipping ScoreDirector.calculateScore()
(when the score is otherwise determined) is correct.
assertExpectedWorkingScore
in interface InnerScoreDirector<Solution_>
expectedWorkingScore
- never nullcompletedAction
- sometimes null, when assertion fails then the completedAction's Object.toString()
is included in the exception messagepublic void assertShadowVariablesAreNotStale(Score expectedWorkingScore, Object completedAction)
InnerScoreDirector
VariableListener
s are forcibly triggered,
and therefore all shadow variables are updated if needed,
that none of the shadow variables of the working solution
change,
Then also asserts that the Score
calculated for the working solution
afterwards
is equal to the parameter expectedWorkingScore
.
Used to assert that the shadow variables' state is consistent with the genuine variables' state.
assertShadowVariablesAreNotStale
in interface InnerScoreDirector<Solution_>
expectedWorkingScore
- never nullcompletedAction
- sometimes null, when assertion fails then the completedAction's Object.toString()
is included in the exception messageprotected String buildShadowVariableAnalysis(boolean predicted)
predicted
- true if the score was predicted and might have been calculated on another threadprotected String createShadowVariablesViolationMessage()
public void assertWorkingScoreFromScratch(Score workingScore, Object completedAction)
InnerScoreDirector
Score
is calculated for the current working solution
in a fresh ScoreDirector
(with no incremental calculation residue),
it is equal to the parameter workingScore
.
Furthermore, if the assert fails, a score corruption analysis might be included in the exception message.
assertWorkingScoreFromScratch
in interface InnerScoreDirector<Solution_>
workingScore
- never nullcompletedAction
- sometimes null, when assertion fails then the completedAction's Object.toString()
is included in the exception messageInnerScoreDirectorFactory.assertScoreFromScratch(Solution_)
public void assertPredictedScoreFromScratch(Score workingScore, Object completedAction)
InnerScoreDirector
Score
is calculated for the current working solution
in a fresh ScoreDirector
(with no incremental calculation residue),
it is equal to the parameter predictedScore
.
Furthermore, if the assert fails, a score corruption analysis might be included in the exception message.
assertPredictedScoreFromScratch
in interface InnerScoreDirector<Solution_>
workingScore
- never nullcompletedAction
- sometimes null, when assertion fails then the completedAction's Object.toString()
is included in the exception messageInnerScoreDirectorFactory.assertScoreFromScratch(Solution_)
public void assertExpectedUndoMoveScore(Move move, Score beforeMoveScore)
InnerScoreDirector
Score
is calculated for the current working solution
in the current ScoreDirector
(with incremental calculation residue),
it is equal to the parameter beforeMoveScore
.
Furthermore, if the assert fails, a score corruption analysis might be included in the exception message.
assertExpectedUndoMoveScore
in interface InnerScoreDirector<Solution_>
move
- never nullbeforeMoveScore
- never nullprotected String buildScoreCorruptionAnalysis(ScoreDirector<Solution_> uncorruptedScoreDirector, boolean predicted)
uncorruptedScoreDirector
- never nullpredicted
- true if the score was predicted and might have been calculated on another threadCopyright © 2006–2020 JBoss by Red Hat. All rights reserved.