解决Optaplanner中不可移动实体的UnsupportedOperationException

时间:2016-07-14 04:16:15

标签: optaplanner

根据Optaplanner文档实现不可移动的实体时,我得到了UnsupportedOperationException。我使用的是6.4.0版本。

我的实体:

@PlanningEntity(difficultyComparatorClass=AssignmentCreditHoursComparator.class, movableEntitySelectionFilter=ImmovableChangeMoveFilter.class) public class Assignment{...}

我的过滤器

public class ImmovableChangeMoveFilter implements SelectionFilter<Assignment> {
@Override
public boolean accept(ScoreDirector scoreDirector, Assignment a) {
    if(a.isLocked())
        return false;
    else
        return true;    
}

}

例外:

Exception in thread "main" java.lang.UnsupportedOperationException
at org.optaplanner.core.impl.heuristic.selector.entity.decorator.FilteringEntitySelector.listIterator(FilteringEntitySelector.java:125)
at org.optaplanner.core.impl.heuristic.selector.common.iterator.AbstractOriginalSwapIterator.<init>(AbstractOriginalSwapIterator.java:49)
at org.optaplanner.core.impl.heuristic.selector.move.generic.SwapMoveSelector$1.<init>(SwapMoveSelector.java:129)
at org.optaplanner.core.impl.heuristic.selector.move.generic.SwapMoveSelector.iterator(SwapMoveSelector.java:129)
at org.optaplanner.core.impl.heuristic.selector.move.decorator.AbstractCachingMoveSelector.constructCache(AbstractCachingMoveSelector.java:76)
at org.optaplanner.core.impl.heuristic.selector.common.SelectionCacheLifecycleBridge.phaseStarted(SelectionCacheLifecycleBridge.java:49)
at org.optaplanner.core.impl.phase.event.PhaseLifecycleSupport.firePhaseStarted(PhaseLifecycleSupport.java:39)
at org.optaplanner.core.impl.heuristic.selector.AbstractSelector.phaseStarted(AbstractSelector.java:47)
at org.optaplanner.core.impl.phase.event.PhaseLifecycleSupport.firePhaseStarted(PhaseLifecycleSupport.java:39)
at org.optaplanner.core.impl.heuristic.selector.AbstractSelector.phaseStarted(AbstractSelector.java:47)
at org.optaplanner.core.impl.phase.event.PhaseLifecycleSupport.firePhaseStarted(PhaseLifecycleSupport.java:39)
at org.optaplanner.core.impl.heuristic.selector.AbstractSelector.phaseStarted(AbstractSelector.java:47)
at org.optaplanner.core.impl.localsearch.decider.LocalSearchDecider.phaseStarted(LocalSearchDecider.java:97)
at org.optaplanner.core.impl.localsearch.DefaultLocalSearchPhase.phaseStarted(DefaultLocalSearchPhase.java:122)
at org.optaplanner.core.impl.localsearch.DefaultLocalSearchPhase.solve(DefaultLocalSearchPhase.java:66)
at org.optaplanner.core.impl.solver.DefaultSolver.runPhases(DefaultSolver.java:215)
at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:176)

这取自Optaplanner代码......

public class FilteringEntitySelector extends AbstractEntitySelector {

protected final EntitySelector childEntitySelector;
protected final List<SelectionFilter> filterList;
protected final boolean bailOutEnabled;

protected ScoreDirector scoreDirector = null;

public FilteringEntitySelector(EntitySelector childEntitySelector, List<SelectionFilter> filterList) {
    this.childEntitySelector = childEntitySelector;
    this.filterList = filterList;
    bailOutEnabled = childEntitySelector.isNeverEnding();
    phaseLifecycleSupport.addEventListener(childEntitySelector);
}

// ************************************************************************
// Worker methods
// ************************************************************************

@Override
public void phaseStarted(AbstractPhaseScope phaseScope) {
    super.phaseStarted(phaseScope);
    scoreDirector = phaseScope.getScoreDirector();
}

@Override
public void phaseEnded(AbstractPhaseScope phaseScope) {
    super.phaseEnded(phaseScope);
    scoreDirector = null;
}

public EntityDescriptor getEntityDescriptor() {
    return childEntitySelector.getEntityDescriptor();
}

public boolean isCountable() {
    return childEntitySelector.isCountable();
}

public boolean isNeverEnding() {
    return childEntitySelector.isNeverEnding();
}

public long getSize() {
    return childEntitySelector.getSize();
}

public Iterator<Object> iterator() {
    return new JustInTimeFilteringEntityIterator(childEntitySelector.iterator());
}

protected class JustInTimeFilteringEntityIterator extends UpcomingSelectionIterator<Object> {

    private final Iterator<Object> childEntityIterator;
    private final long bailOutSize;

    public JustInTimeFilteringEntityIterator(Iterator<Object> childEntityIterator) {
        this.childEntityIterator = childEntityIterator;
        this.bailOutSize = determineBailOutSize();
    }

    @Override
    protected Object createUpcomingSelection() {
        Object next;
        long attemptsBeforeBailOut = bailOutSize;
        do {
            if (!childEntityIterator.hasNext()) {
                return noUpcomingSelection();
            }
            if (bailOutEnabled) {
                // if childEntityIterator is neverEnding and nothing is accepted, bail out of the infinite loop
                if (attemptsBeforeBailOut <= 0L) {
                    logger.warn("Bailing out of neverEnding selector ({}) to avoid infinite loop.",
                            FilteringEntitySelector.this);
                    return noUpcomingSelection();
                }
                attemptsBeforeBailOut--;
            }
            next = childEntityIterator.next();
        } while (!accept(scoreDirector, next));
        return next;
    }

}

protected long determineBailOutSize() {
    if (!bailOutEnabled) {
        return -1L;
    }
    return childEntitySelector.getSize() * 10L;
}

public ListIterator<Object> listIterator() {
    // TODO Not yet implemented
    throw new UnsupportedOperationException();
}

public ListIterator<Object> listIterator(int index) {
    // TODO Not yet implemented
    throw new UnsupportedOperationException();
}

public Iterator<Object> endingIterator() {
    return new JustInTimeFilteringEntityIterator(childEntitySelector.endingIterator());
}

private boolean accept(ScoreDirector scoreDirector, Object entity) {
    for (SelectionFilter filter : filterList) {
        if (!filter.accept(scoreDirector, entity)) {
            return false;
        }
    }
    return true;
}

@Override
public String toString() {
    return "Filtering(" + childEntitySelector + ")";
}

}

<solver>  
<scanAnnotatedClasses>
    <packageInclude>com.fast.planner.solution</packageInclude>
</scanAnnotatedClasses>

<scoreDirectorFactory>
    <scoreDefinitionType>HARD_SOFT</scoreDefinitionType>
    <scoreDrl>com/fast/planner/solution/rostering-rules.drl</scoreDrl>
    <initializingScoreTrend>ONLY_DOWN/ONLY_DOWN</initializingScoreTrend> 
</scoreDirectorFactory>



<localSearch>
    <unionMoveSelector>

        <cacheType>PHASE</cacheType>
        <selectionOrder>SHUFFLED</selectionOrder>

        <changeMoveSelector>
            <cacheType>PHASE</cacheType>

            <filterClass>com.fast.planner.solution.filter.ReserveRestrictionsChangeMoveFilter</filterClass>
            <fixedProbabilityWeight>1.0</fixedProbabilityWeight>
        </changeMoveSelector>
        <swapMoveSelector>
            <cacheType>PHASE</cacheType>
            <fixedProbabilityWeight>2.0</fixedProbabilityWeight>
        </swapMoveSelector>


    </unionMoveSelector>
    <acceptor>
        <simulatedAnnealingStartingTemperature>2hard/200soft</simulatedAnnealingStartingTemperature>
        <entityTabuSize>5</entityTabuSize>
    </acceptor>
    <forager>
        <acceptedCountLimit>4</acceptedCountLimit>
    </forager>
</localSearch>

1 个答案:

答案 0 :(得分:0)

这是一个错误,将在以后的版本中解决。