package cz.cvut.felk.cig.jcop.algorithm.randomsearch; import cz.cvut.felk.cig.jcop.algorithm.BaseAlgorithm; import cz.cvut.felk.cig.jcop.algorithm.CannotContinueException; import cz.cvut.felk.cig.jcop.algorithm.ChainAlgorithm; import cz.cvut.felk.cig.jcop.algorithm.InvalidProblemException; import cz.cvut.felk.cig.jcop.problem.Configuration; import cz.cvut.felk.cig.jcop.problem.ObjectiveProblem; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Random search algorithm. * <p /> * In each step of {@link #init(cz.cvut.felk.cig.jcop.problem.ObjectiveProblem)}, algorithm generates random solution. * <p /> * Useful as worst case benchmark. * * @author Oleg Kovarik */ public class RandomSearch extends BaseAlgorithm implements ChainAlgorithm { private static final Logger LOG = LoggerFactory.getLogger(RandomSearch.class); /** * Active configuration to be expanded */ protected Configuration activeConfiguration; /** * Fitness of active configuration */ protected double activeFitness; /** * Normalized fitness of active configuration */ protected double activeNormalizedFitness; public void init(ObjectiveProblem problem) throws InvalidProblemException { this.problem = problem; // RS requires either startingConfiguration or RandomStartingConfiguration problem if (!problem.hasStartingConfiguration() && !problem.hasRandomConfiguration()) { throw new InvalidProblemException( "RandomSearch algorithm requires either StartingConfigurationProblem or RandomConfigurationProblem"); } // fetch starting configuration if (problem.hasStartingConfiguration()) { this.activeConfiguration = problem.getStartingConfiguration(); } else { this.activeConfiguration = problem.getRandomConfiguration(); } this.initCommon(); } public void init(ObjectiveProblem problem, Configuration activeConfiguration) { this.problem = problem; this.activeConfiguration = activeConfiguration; this.initCommon(); } /** * Part of init common to all initialization types. */ protected void initCommon () { this.fitness = problem.getDefaultFitness(); this.bestConfiguration = this.activeConfiguration; this.bestFitness = this.fitness.getValue(this.activeConfiguration); // calculate fitness this.activeFitness = this.fitness.getValue(this.activeConfiguration); this.activeNormalizedFitness = this.fitness.normalize(activeFitness); } public void optimize() throws CannotContinueException { // generate new random configuration if (!problem.hasRandomConfiguration()) throw new InvalidProblemException("RandomSearch algorithm requires RandomConfigurationProblem"); Configuration newConfiguration = problem.getRandomConfiguration(); // calculate fitness double newFitness = this.fitness.getValue(newConfiguration); double newNormalizedFitness = this.fitness.normalize(newFitness); // set new configuration as active this.activeConfiguration = newConfiguration; this.activeFitness = newFitness; this.activeNormalizedFitness = newNormalizedFitness; // if it is best, set it as best if (newFitness > this.bestFitness) { LOG.debug("Better solution {}, {}", newFitness, newConfiguration); this.bestConfiguration = newConfiguration; this.bestFitness = newFitness; } } }