Package com.barrybecker4.puzzle.redpuzzle.solver

Source Code of com.barrybecker4.puzzle.redpuzzle.solver.GeneticSearchSolver

/** Copyright by Barry G. Becker, 2000-2011. Licensed under MIT License: http://www.opensource.org/licenses/MIT  */
package com.barrybecker4.puzzle.redpuzzle.solver;

import com.barrybecker4.optimization.OptimizationListener;
import com.barrybecker4.optimization.Optimizee;
import com.barrybecker4.optimization.Optimizer;
import com.barrybecker4.optimization.parameter.ParameterArray;
import com.barrybecker4.optimization.strategy.OptimizationStrategyType;
import com.barrybecker4.puzzle.common.Refreshable;
import com.barrybecker4.puzzle.redpuzzle.model.Piece;
import com.barrybecker4.puzzle.redpuzzle.model.PieceList;
import com.barrybecker4.puzzle.redpuzzle.model.PieceParameterArray;

import java.util.List;

/**
* Solve the red puzzle using a genetic search algorithm.
* Solves the puzzle in 3.5 seconds on Core2 duo system (6 generations).
*
* @author Barry Becker
*/
public class GeneticSearchSolver extends RedPuzzleSolver<PieceList, Piece>
                                 implements Optimizee, OptimizationListener {

    /** bonuses given to the scoring algorithm if 3 nubs fit on a side piece. */
    public static final double THREE_FIT_BOOST = 0.1;
    /** bonuses given to the scoring algorithm if 4 nubs on the center piece fit. */
    public static final double FOUR_FIT_BOOST = 0.6;

    /**
     * The puzzle is solved if we reach this score.
     * There are 24 nubs that need to fit for all the pieces.
     * There are 4 edge pieces that get THREE_FIT_BOOST if all 3 nubs fit.
     */
    public static final double MAX_FITS = 24 + 4 * THREE_FIT_BOOST + FOUR_FIT_BOOST;

    /** either genetic or concurrent genetic strategy. */
    private OptimizationStrategyType strategy;


    /** Constructor */
    public GeneticSearchSolver(PieceList pieces, Refreshable<PieceList, Piece> puzzlePanel,
                               boolean useConcurrency) {
        super(pieces);
        puzzlePanel_ = puzzlePanel;
        strategy = useConcurrency ? OptimizationStrategyType.CONCURRENT_GENETIC_SEARCH :
                                    OptimizationStrategyType.GENETIC_SEARCH;
    }

    /**
     * @return list of moves to a solution.
     */
    @Override
    public List<Piece> solve()  {

        ParameterArray initialGuess = new PieceParameterArray(pieces_);
        solution_ = pieces_;
        long startTime = System.currentTimeMillis();

        Optimizer optimizer = new Optimizer(this);

        optimizer.setListener(this);

        ParameterArray solution =
            optimizer.doOptimization(strategy, initialGuess, MAX_FITS);

        solution_ = ((PieceParameterArray)solution).getPieceList();
        List<Piece> moves;
        if (evaluateFitness(solution) >= MAX_FITS) {
            moves = solution_.getPieces();
        } else {
            moves = null;
        }
        long elapsedTime = System.currentTimeMillis() - startTime;
        puzzlePanel_.finalRefresh(moves, solution_, numTries_, elapsedTime);

        return moves;
    }

    public String getName() {
         return "Genetic Search Solver for Red Puzzle";
    }

    /**
     * terminate the solver if we find a solution with this fitness.
     */
    public double getOptimalFitness() {
        return MAX_FITS;
    }

    public boolean evaluateByComparison() {
        return false;
    }

    /**
     * Return a high score if there are a lot of fits among the pieces.
     * For every nub that fits we count 1
     *
     * @param params  parameters
     * @return fitness value. High is good.
     */
    public double evaluateFitness(ParameterArray params) {
        PieceList pieces = ((PieceParameterArray) params).getPieceList();
        double fitness = getNumFits(pieces);
        params.setFitness(fitness);
        return fitness;
    }

    public double compareFitness(ParameterArray params1, ParameterArray params2) {
        assert false : "compareFitness not used since we evaluate in an absolute way.";
        return 0;
    }

    /**
     * @return the number of matches for all the nubs.
     */
    private static double getNumFits(PieceList pieces) {
        double totalFits = 0;
        for (int i=0; i < pieces.size(); i++) {
            double nFits = pieces.getNumFits(i);
            totalFits += nFits;
            // give a boost if a give piece has 3 or 4 fits.
            if (nFits == 3) {
                totalFits += THREE_FIT_BOOST;
            } else if (nFits == 4) {
                // center piece
                totalFits += FOUR_FIT_BOOST;
            }
        }
        assert(totalFits <= MAX_FITS) :
                "fits exceeded " + MAX_FITS +". Fits="+totalFits +" pieces="+pieces;
        return totalFits;
    }

    /**
     * called when the optimizer has made some progress optimizing.
     * We show the current status.
     * @param params
     */
    public void optimizerChanged(ParameterArray params) {
        // update our current best guess at the solution.
        solution_ = ((PieceParameterArray) params).getPieceList();
        numTries_ ++;
        puzzlePanel_.refresh(solution_, numTries_);
    }
}
TOP

Related Classes of com.barrybecker4.puzzle.redpuzzle.solver.GeneticSearchSolver

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.