Package com.barrybecker4.puzzle.tantrix.solver.path

Source Code of com.barrybecker4.puzzle.tantrix.solver.path.PathEvaluator

// Copyright by Barry G. Becker, 2012. Licensed under MIT License: http://www.opensource.org/licenses/MIT
package com.barrybecker4.puzzle.tantrix.solver.path;


import com.barrybecker4.common.geometry.Location;
import com.barrybecker4.puzzle.tantrix.model.HexTile;
import com.barrybecker4.puzzle.tantrix.model.HexUtil;
import com.barrybecker4.puzzle.tantrix.model.Tantrix;
import com.barrybecker4.puzzle.tantrix.model.TilePlacement;
import com.barrybecker4.puzzle.tantrix.model.verfication.ConsistencyChecker;
import com.barrybecker4.puzzle.tantrix.model.verfication.InnerSpaceDetector;

import java.util.HashSet;
import java.util.Set;


/**
* Evaluates the fitness of a tantrix path.
* It gets the top score if it is a loop and all the path colors match
*
* @author Barry Becker
*/
public class PathEvaluator {

    /** When reached, the puzzle is solved. */
    public static final double SOLVED_THRESH = 3.1;

    /** How close are the endpoints of the primary path from forming a loop. */
    private static final double LOOP_PROXIMITY_WEIGHT = 0.3;

    /** Weight to give if we actually have a primary path loop. */
    private static final double LOOP_WEIGHT = 0.3;

    /** Weight to give matching paths (includes secondary paths) */
    private static final double PATH_MATCH_WEIGHT = 1.0;

    /** We have a loop and all paths match */
    private static final double CONSISTENT_LOOP_BONUS = 0.6;

    /** consistent loop and no inner spaces. */
    private static final double PERFECT_LOOP_BONUS = 2.0;

    /** A measure of compactness. Avoids inner spaces. */
    private static final double COMPACTNESS = 0.2;


    /**
     * The main criteria for quality of the path is
     *  1) How close the ends of the path are to each other. Perfection achieved when we have a closed loop.
     *  2) Better if more matching secondary path colors
     *  3) Fewer inner spaces and a bbox with less area.
     * @return  the number of different ways we have tried to fit pieces together so far.
     */
    public double evaluateFitness(TantrixPath path) {

        int numTiles = path.size();
        double distance = path.getEndPointDistance();
        boolean isLoop = distance == 0 && path.isLoop();

        ConsistencyChecker checker = new ConsistencyChecker(path.getTilePlacements(), path.getPrimaryPathColor());
        int numFits = checker.numFittingTiles();
        boolean allFit = numFits == numTiles;
        boolean consistentLoop = isLoop && allFit;
        boolean perfectLoop = false;
        double compactness = determineCompactness(path);

        if (consistentLoop) {
            Tantrix tantrix = new Tantrix(path.getTilePlacements());
            InnerSpaceDetector innerDetector = new InnerSpaceDetector(tantrix);
            perfectLoop = !innerDetector.hasInnerSpaces();
            //System.out.println("perfect loop");
        }

        double fitness =
                LOOP_PROXIMITY_WEIGHT * (numTiles - distance) / (0.1 + numTiles)
                + (isLoop ? LOOP_WEIGHT : 0)
                + (double)numFits / numTiles * PATH_MATCH_WEIGHT
                + compactness * COMPACTNESS
                + (consistentLoop ? CONSISTENT_LOOP_BONUS : 0)
                + (perfectLoop ? PERFECT_LOOP_BONUS : 0);
        //System.out.println("fitness=" + fitness);
        assert !Double.isNaN(fitness) :
                "Invalid fitness  isLoop=" + isLoop + " consistentLoop=" + consistentLoop
                + " numTiles=" + numTiles + " distance=" + distance;
        return fitness;
    }

    /**
     * First dd all the tiles to a hash keyed on location.
     * Then for every one of the six sides of each tile, add one if the
     * neighbor is in the hash. Return (num nbrs in hash - 2(numTiles-1))/numTiles
     * @param path
     * @return measure of path compactness between 0 and ~1
     */
    private double determineCompactness(TantrixPath path) {
        Set<Location> locationHash = new HashSet<Location>();
        int numTiles = path.size();
        for (TilePlacement p : path.getTilePlacements()) {
            locationHash.add(p.getLocation());
        }
        int ct = 0;
        for (TilePlacement p : path.getTilePlacements()) {
            for (int i = 0; i < HexTile.NUM_SIDES; i++)   {
                if (locationHash.contains(HexUtil.getNeighborLocation(p.getLocation(), i))) {
                    ct++;
                }
            }
        }
        return (ct - 2.0 * (numTiles-1))/numTiles * 0.5;
    }
}
TOP

Related Classes of com.barrybecker4.puzzle.tantrix.solver.path.PathEvaluator

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.