Package org.drools.planner.core.heuristic.selector.move.generic

Source Code of org.drools.planner.core.heuristic.selector.move.generic.ChangeMoveSelector$OriginalChangeMoveIterator

/*
* Copyright 2012 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.drools.planner.core.heuristic.selector.move.generic;

import java.util.Iterator;

import org.drools.planner.core.domain.variable.PlanningVariableDescriptor;
import org.drools.planner.core.heuristic.selector.common.iterator.UpcomingSelectionIterator;
import org.drools.planner.core.heuristic.selector.entity.EntitySelector;
import org.drools.planner.core.heuristic.selector.move.generic.chained.ChainedChangeMove;
import org.drools.planner.core.heuristic.selector.value.iterator.ValueIterator;
import org.drools.planner.core.heuristic.selector.value.ValueSelector;
import org.drools.planner.core.move.Move;

public class ChangeMoveSelector extends GenericMoveSelector {

    protected final EntitySelector entitySelector;
    protected final ValueSelector valueSelector;
    protected final boolean randomSelection;

    protected final boolean chained;

    public ChangeMoveSelector(EntitySelector entitySelector, ValueSelector valueSelector,
            boolean randomSelection) {
        this.entitySelector = entitySelector;
        this.valueSelector = valueSelector;
        this.randomSelection = randomSelection;
        PlanningVariableDescriptor variableDescriptor = valueSelector.getVariableDescriptor();
        chained = variableDescriptor.isChained();
        solverPhaseLifecycleSupport.addEventListener(entitySelector);
        solverPhaseLifecycleSupport.addEventListener(valueSelector);
    }

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

    public boolean isContinuous() {
        return entitySelector.isContinuous() || valueSelector.isContinuous();
    }

    public boolean isNeverEnding() {
        return randomSelection || entitySelector.isNeverEnding() || valueSelector.isNeverEnding();
    }

    public long getSize() {
        return entitySelector.getSize() * valueSelector.getSize();
    }

    public Iterator<Move> iterator() {
        if (!randomSelection) {
            return new OriginalChangeMoveIterator();
        } else {
            return new RandomChangeMoveIterator();
        }
    }

    private class OriginalChangeMoveIterator extends UpcomingSelectionIterator<Move> {

        private Iterator<Object> entityIterator;
        private ValueIterator valueIterator;

        private Object upcomingEntity;

        private OriginalChangeMoveIterator() {
            entityIterator = entitySelector.iterator();
            valueIterator = valueSelector.iterator();
            // valueIterator.hasNext() returns true if there is a next for any entity parameter
            if (!entityIterator.hasNext() || !valueIterator.hasNext()) {
                upcomingSelection = null;
            } else {
                upcomingEntity = entityIterator.next();
                createUpcomingSelection();
            }
        }

        @Override
        protected void createUpcomingSelection() {
            while (!valueIterator.hasNext(upcomingEntity)) {
                if (!entityIterator.hasNext()) {
                    upcomingSelection = null;
                    return;
                }
                upcomingEntity = entityIterator.next();
                valueIterator = valueSelector.iterator();
            }
            Object toValue = valueIterator.next(upcomingEntity);
            upcomingSelection = chained
                    ? new ChainedChangeMove(upcomingEntity, valueSelector.getVariableDescriptor(), toValue)
                    : new ChangeMove(upcomingEntity, valueSelector.getVariableDescriptor(), toValue);
        }

    }

    private class RandomChangeMoveIterator extends UpcomingSelectionIterator<Move> {

        private Iterator<Object> entityIterator;
        private ValueIterator valueIterator;

        private RandomChangeMoveIterator() {
            entityIterator = entitySelector.iterator();
            valueIterator = valueSelector.iterator();
            // valueIterator.hasNext() returns true if there is a next for any entity parameter
            if (!entityIterator.hasNext() || !valueIterator.hasNext()) {
                upcomingSelection = null;
            } else {
                createUpcomingSelection();
            }
        }

        @Override
        protected void createUpcomingSelection() {
            // Ideally, this code should have read:
            //     Object entity = entityIterator.next();
            //     Object toValue = valueIterator.next(entity);
            // But empty selectors and ending selectors (such as non-random or shuffled) make it more complex
            if (!entityIterator.hasNext()) {
                entityIterator = entitySelector.iterator();
            }
            Object entity = entityIterator.next();
            int entityIteratorCreationCount = 0;
            // This loop is mostly only relevant when the entityIterator or valueIterator is non-random or shuffled
            while (!valueIterator.hasNext(entity)) {
                // First try to reset the valueIterator to get a next value
                valueIterator = valueSelector.iterator();
                // If that's not sufficient (that entity has an empty value list), then use the next entity
                if (!valueIterator.hasNext(entity)) {
                    if (!entityIterator.hasNext()) {
                        entityIterator = entitySelector.iterator();
                        entityIteratorCreationCount++;
                        if (entityIteratorCreationCount >= 2) {
                            // All entity-value combinations have been tried (some even more than once)
                            upcomingSelection = null;
                            return;
                        }
                    }
                    entity = entityIterator.next();
                }
            }
            Object toValue = valueIterator.next(entity);
            upcomingSelection = chained
                    ? new ChainedChangeMove(entity, valueSelector.getVariableDescriptor(), toValue)
                    : new ChangeMove(entity, valueSelector.getVariableDescriptor(), toValue);
        }

    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + "(" + entitySelector + ", " + valueSelector + ")";
    }

}
TOP

Related Classes of org.drools.planner.core.heuristic.selector.move.generic.ChangeMoveSelector$OriginalChangeMoveIterator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.