/* This file is part of Eternity II Editor. * * fuck yeah seaking */ package org.alcibiade.eternity.editor.solver.genetic; import java.util.Random; import java.util.ArrayList; import java.util.Collections; import org.alcibiade.eternity.editor.model.GridModel; import org.alcibiade.eternity.editor.solver.ClusterManager; public class ElitistGeneticSolver extends GeneticSolver { private Random randomGenerator; private int mutations; // number of mutations, defaults to gridModel.size() - 1 private GridModelComparator gridModelComparator; public ElitistGeneticSolver(GridModel grid, GridModel solutionGrid, ClusterManager clusterManager, int populationSize) { super(grid, solutionGrid, clusterManager, populationSize); this.randomGenerator = new Random(); this.mutations = grid.getSize() - 1; this.gridModelComparator = new GridModelComparator(); } public void setMutations(int s) { mutations = s; }; // solve @Override public void run() { notifyStart(); clusterManager.showStartMessage(); GridModel solution = null; boolean solved = false; while (!solved && !interrupted) { if (slowmotion) { try { Thread.sleep(SLOWMOTION_DELAY); } catch (InterruptedException e) { e.printStackTrace(); } } // select ArrayList<GridModel> breeders = elitistSelection(); GridModel bestGrid = breeders.get(0); // try to rotate pieces correctly once the solution reaches a certain threshold if(bestGrid.countPairs() >= bestGrid.countConnections() - 4) { enhanceSolution(bestGrid); } // update main grid to show best solution yet if (bestGrid.countPairs() > clusterManager.getBestScore()) { bestGrid.copyTo(problemGrid); } // check for correct board solved = clusterManager.submitSolution(bestGrid); if(solved) { solution = bestGrid; break; } // FIXME: should not be necessary mutate(bestGrid); // breed this.population = breed(breeders); bestGrid.copyTo(solutionGrid); iterations++; //System.out.printf("iterarion %d\n", iterations); } if (solved) { solution.copyTo(solutionGrid); clusterManager.showStats(iterations); } notifyEnd(solved); } // elitist selection function // returns the fittest half of the population private ArrayList<GridModel> elitistSelection() { ArrayList<GridModel> selection = (ArrayList<GridModel>)population.clone(); Collections.sort(selection, gridModelComparator); selection = new ArrayList<GridModel>(selection.subList(0, selection.size()/2)); return selection; } private ArrayList<GridModel> breed(ArrayList<GridModel> breeders) { ArrayList<GridModel> newPopulation = (ArrayList<GridModel>)breeders.clone(); int s = breeders.size(); for(int i = 0; i < s/2; i++) { int ra = randomGenerator.nextInt(s); int rb = randomGenerator.nextInt(s); newPopulation.addAll(crossover(breeders.get(ra), breeders.get(rb))); } return newPopulation; } // private ArrayList<GridModel> crossover(GridModel parentA, GridModel parentB) { ArrayList<GridModel> aFeatures = parentA.getFeatures(); ArrayList<GridModel> bFeatures = parentB.getFeatures(); //child A inherits the best feature from A with the best compatible feature (if it exists) from B GridModel childA = originalGrid.getCompatibleFeatures(aFeatures, bFeatures); //vice versa GridModel childB = originalGrid.getCompatibleFeatures(bFeatures, aFeatures); // remaining pieces for childA and childB GridModel remainingA = originalGrid.remainingPieces(childA); GridModel remainingB = originalGrid.remainingPieces(childB); //Fill the rest of child A with the remaning pieces of the original board childA.completeWith(remainingA); childB.completeWith(remainingB); // introduce mutations mutate(childA); mutate(childB); ArrayList<GridModel> children = new ArrayList<GridModel>(); children.add(childA); children.add(childB); return children; } public void mutate(GridModel individual) { for(int i = 0; i < mutations; i++) { // probablity check, 50% if(randomGenerator.nextInt(100) < 50) continue; // mutate int quadIndex = randomGenerator.nextInt(individual.getPositions()); //individual.optimizeQuadRotation(quadIndex); individual.getQuad(quadIndex).rotateClockwise(); } /*float r = randomGenerator.nextFloat(); if(r < GeneticSolver.fitness(individual)) { //System.out.printf("enhanced, %f < %f\n", r, GeneticSolver.fitness(individual)); enhanceSolution(individual); }*/ } @Override public String getSolverName() { return "Elitist Selection Genetic Solver"; } }