Package org.drools.planner.core.localsearch

Source Code of org.drools.planner.core.localsearch.DefaultLocalSearchSolver

/**
* Copyright 2010 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.localsearch;

import java.util.Random;

import org.drools.RuleBase;
import org.drools.planner.core.localsearch.bestsolution.BestSolutionRecaller;
import org.drools.planner.core.localsearch.decider.Decider;
import org.drools.planner.core.localsearch.termination.Termination;
import org.drools.planner.core.move.Move;
import org.drools.planner.core.score.calculator.ScoreCalculator;
import org.drools.planner.core.score.definition.ScoreDefinition;
import org.drools.planner.core.solution.Solution;
import org.drools.planner.core.solution.initializer.StartingSolutionInitializer;
import org.drools.planner.core.AbstractSolver;

/**
* Default implementation of {@link LocalSearchSolver}.
* @author Geoffrey De Smet
*/
public class DefaultLocalSearchSolver extends AbstractSolver implements LocalSearchSolver,
        LocalSearchSolverLifecycleListener {

    protected Long randomSeed; // TODO refactor to AbstractSolver

    protected StartingSolutionInitializer startingSolutionInitializer = null; // TODO refactor to AbstractSolver
    protected BestSolutionRecaller bestSolutionRecaller;
    protected Termination termination;
    protected Decider decider;

    protected boolean assertStepScoreIsUncorrupted = false;

    protected LocalSearchSolverScope localSearchSolverScope = new LocalSearchSolverScope(); // TODO remove me

    public void setRandomSeed(long randomSeed) {
        this.randomSeed = randomSeed;
    }

    public void setRuleBase(RuleBase ruleBase) {
        localSearchSolverScope.setRuleBase(ruleBase);
    }

    public void setScoreDefinition(ScoreDefinition scoreDefinition) {
        localSearchSolverScope.setScoreDefinition(scoreDefinition);
    }

    public ScoreDefinition getScoreDefinition() {
        return localSearchSolverScope.getScoreDefinition();
    }

    public void setScoreCalculator(ScoreCalculator scoreCalculator) {
        localSearchSolverScope.setWorkingScoreCalculator(scoreCalculator);
    }

    public StartingSolutionInitializer getStartingSolutionInitializer() {
        return startingSolutionInitializer;
    }

    public void setStartingSolutionInitializer(StartingSolutionInitializer startingSolutionInitializer) {
        this.startingSolutionInitializer = startingSolutionInitializer;
    }

    public void setBestSolutionRecaller(BestSolutionRecaller bestSolutionRecaller) {
        this.bestSolutionRecaller = bestSolutionRecaller;
        this.bestSolutionRecaller.setLocalSearchSolver(this);
        this.bestSolutionRecaller.setSolverEventSupport(solverEventSupport);
    }

    public void setTermination(Termination termination) {
        this.termination = termination;
        this.termination.setLocalSearchSolver(this);
    }

    public Decider getDecider() {
        return decider;
    }

    public void setDecider(Decider decider) {
        this.decider = decider;
        this.decider.setLocalSearchSolver(this);
    }

    public void setAssertStepScoreIsUncorrupted(boolean assertStepScoreIsUncorrupted) {
        this.assertStepScoreIsUncorrupted = assertStepScoreIsUncorrupted;
    }

    public void setStartingSolution(Solution startingSolution) {
        localSearchSolverScope.setWorkingSolution(startingSolution);
    }

    public Solution getBestSolution() {
        return this.localSearchSolverScope.getBestSolution();
    }

    public long getTimeMillisSpend() {
        return this.localSearchSolverScope.calculateTimeMillisSpend();
    }

    public LocalSearchSolverScope getLocalSearchSolverScope() {
        return localSearchSolverScope;
    }

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

    @Override
    protected void solveImplementation() {
        LocalSearchSolverScope localSearchSolverScope = this.localSearchSolverScope;
        solvingStarted(localSearchSolverScope);

        StepScope stepScope = createNextStepScope(localSearchSolverScope, null);
        while (!terminatedEarly.get() && !termination.isTerminated(stepScope)) {
            stepScope.setTimeGradient(termination.calculateTimeGradient(stepScope));
            beforeDeciding(stepScope);
            decider.decideNextStep(stepScope);
            Move nextStep = stepScope.getStep();
            if (nextStep == null) {
                // TODO JBRULES-2213 do not terminate, but warn and try again
                logger.warn("No move accepted for step index ({}) out of {} accepted moves. Terminating by exception.",
                        stepScope.getStepIndex(), decider.getForager().getAcceptedMovesSize());
                break;
            }
            logger.info("Step index ({}), time spend ({}) taking step ({}) out of {} accepted moves.",
                    new Object[]{stepScope.getStepIndex(), localSearchSolverScope.calculateTimeMillisSpend(),
                            nextStep, decider.getForager().getAcceptedMovesSize()});
            stepDecided(stepScope);
            nextStep.doMove(stepScope.getWorkingMemory());
            // there is no need to recalculate the score, but we still need to set it
            localSearchSolverScope.getWorkingSolution().setScore(stepScope.getScore());
            if (assertStepScoreIsUncorrupted) {
                localSearchSolverScope.assertWorkingScore(stepScope.getScore());
            }
            stepTaken(stepScope);
            stepScope = createNextStepScope(localSearchSolverScope, stepScope);
        }
        solvingEnded(localSearchSolverScope);
    }

    private StepScope createNextStepScope(LocalSearchSolverScope localSearchSolverScope, StepScope completedStepScope) {
        if (completedStepScope == null) {
            completedStepScope = new StepScope(localSearchSolverScope);
            completedStepScope.setScore(localSearchSolverScope.getStartingScore());
            completedStepScope.setStepIndex(-1);
            completedStepScope.setTimeGradient(0.0);
        }
        localSearchSolverScope.setLastCompletedStepScope(completedStepScope);
        StepScope stepScope = new StepScope(localSearchSolverScope);
        stepScope.setStepIndex(completedStepScope.getStepIndex() + 1);
        return stepScope;
    }

    public void solvingStarted(LocalSearchSolverScope localSearchSolverScope) {
        localSearchSolverScope.reset();
        if (randomSeed != null) {
            logger.info("Solving with random seed ({}).", randomSeed);
            localSearchSolverScope.setWorkingRandom(new Random(randomSeed));
        } else {
            logger.info("Solving with a non-fixed random seed.");
            localSearchSolverScope.setWorkingRandom(new Random());
        }
        if (startingSolutionInitializer != null) {
            if (!startingSolutionInitializer.isSolutionInitialized(localSearchSolverScope)) {
                logger.info("Initializing solution.");
                startingSolutionInitializer.initializeSolution(localSearchSolverScope);
            } else {
                logger.debug("Solution is already initialized.");
            }
        }
        localSearchSolverScope.setStartingScore(localSearchSolverScope.calculateScoreFromWorkingMemory());
        bestSolutionRecaller.solvingStarted(localSearchSolverScope);
        termination.solvingStarted(localSearchSolverScope);
        decider.solvingStarted(localSearchSolverScope);
    }

    public void beforeDeciding(StepScope stepScope) {
        bestSolutionRecaller.beforeDeciding(stepScope);
        termination.beforeDeciding(stepScope);
        decider.beforeDeciding(stepScope);
    }

    public void stepDecided(StepScope stepScope) {
        bestSolutionRecaller.stepDecided(stepScope);
        termination.stepDecided(stepScope);
        decider.stepDecided(stepScope);
    }

    public void stepTaken(StepScope stepScope) {
        bestSolutionRecaller.stepTaken(stepScope);
        termination.stepTaken(stepScope);
        decider.stepTaken(stepScope);
    }

    public void solvingEnded(LocalSearchSolverScope localSearchSolverScope) {
        bestSolutionRecaller.solvingEnded(localSearchSolverScope);
        termination.solvingEnded(localSearchSolverScope);
        decider.solvingEnded(localSearchSolverScope);
        long timeMillisSpend = localSearchSolverScope.calculateTimeMillisSpend();
        long averageCalculateCountPerSecond = localSearchSolverScope.getCalculateCount() * 1000L / timeMillisSpend;
        logger.info("Solved at step index ({}) with time spend ({}) for best score ({})"
                + " with average calculate count per second ({}).",
                new Object[] {
                localSearchSolverScope.getLastCompletedStepScope().getStepIndex(),
                timeMillisSpend,
                localSearchSolverScope.getBestScore(),
                averageCalculateCountPerSecond
        });
    }

}
TOP

Related Classes of org.drools.planner.core.localsearch.DefaultLocalSearchSolver

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.