Max Fitness stuck at local maxima in genetic algorithm implementation - java

Having trouble with this code below. It is implementation of population evolution. In my case the max fitness is struck at a local maxima everytime and is unable to reach max possible value. Kindly suggest necessary edits and reason for the same.
Individual.java
package genetic.algorithm.project;
import java.util.Random;
public class Individual {
public static int SIZE = 300;
private int[] genes = new int[SIZE];
private double fitnessValue = 0.0;
// Getters and Setters
public void setGene(int index,int gene){
this.genes[index] = gene;
}
public int getGene(int index){
return this.genes[index];
}
public void setFitnessValue(double fitness){
this.fitnessValue = fitness;
}
public double getFitnessValue(){
return this.fitnessValue;
}
//Function to generate a new individual with random set of genes
public void generateIndividual(){
Random rand = new Random();
for(int i=0;i<SIZE;i++){
this.setGene(i, rand.nextInt(2));
}
}
//Mutation Function
public void mutate(){
Random rand = new Random();
int index = rand.nextInt(SIZE);
this.setGene(index, 1-this.getGene(index)); // Flipping value of gene
}
//Function to set Fitness value of an individual
public int evaluate(){
int fitness = 0;
for(int i=0; i<SIZE; ++i) {
fitness += this.getGene(i);
}
this.setFitnessValue(fitness);
return fitness;
}
}
Population.java
import java.util.Random;
public class Population {
final static int ELITISM = 1;
final static int POP_SIZE = 200+ELITISM; //Population size + Elitism (1)
final static int MAX_ITER = 2000;
final static double MUTATION_RATE = 0.05;
final static double CROSSOVER_RATE = 0.7;
private static Random rand = new Random();
private double totalFitness;
private Individual[] pop;
//Constructor
public Population(){
pop = new Individual[POP_SIZE];
//Initialising population
for(int i=0;i<POP_SIZE;i++){
pop[i] = new Individual();
pop[i].generateIndividual();
}
this.evaluate();
}
//Storing new generation in population
public void setPopulation(Individual[] newPop) {
this.pop = newPop;
}
//Method to find total fitness of population
public double evaluate(){
this.totalFitness = 0.0;
for (int i = 0; i < POP_SIZE; i++) {
this.totalFitness += pop[i].evaluate();
}
return this.totalFitness;
}
//Getters
public Individual getIndividual(int index) {
return pop[index];
}
//Function to find fittest individual for elitism
public Individual getFittest() {
Individual fittest = pop[0];
for (int i = 0; i < POP_SIZE; i++) {
if (fittest.getFitnessValue() <= getIndividual(i).getFitnessValue()) {
fittest = getIndividual(i);
}
}
return fittest;
}
//CROSSOVER Function : Takes 2 individuals and returns 2 new individuals
public static Individual[] crossover(Individual indiv1,Individual indiv2) {
Individual[] newIndiv = new Individual[2];
newIndiv[0] = new Individual();
newIndiv[1] = new Individual();
int randPoint = rand.nextInt(Individual.SIZE);
int i;
for (i=0; i<randPoint; ++i) {
newIndiv[0].setGene(i, indiv1.getGene(i));
newIndiv[1].setGene(i, indiv2.getGene(i));
}
for (; i<Individual.SIZE; ++i) {
newIndiv[0].setGene(i, indiv2.getGene(i));
newIndiv[1].setGene(i, indiv1.getGene(i));
}
return newIndiv;
}
//Roulette Wheel Selection Function
public Individual rouletteWheelSelection() {
double randNum = rand.nextDouble() * this.totalFitness;
int idx;
for (idx=0; idx<POP_SIZE && randNum>0; idx++) {
randNum -= pop[idx].getFitnessValue();
}
return pop[idx-1];
}
//Main method
public static void main(String[] args) {
Population pop = new Population();
Individual[] newPop = new Individual[POP_SIZE];
Individual[] indiv = new Individual[2];
//Current Population Stats
System.out.println("Total Fitness = "+pop.totalFitness);
System.out.println("Best Fitness = "+pop.getFittest().getFitnessValue());
int count;
for(int iter=0;iter<MAX_ITER;iter++){
count =0;
//Elitism
newPop[count] = pop.getFittest();
count++;
//Creating new population
while(count < POP_SIZE){
//Selecting parents
indiv[0] = pop.rouletteWheelSelection();
indiv[1] = pop.rouletteWheelSelection();
// Crossover
if (rand.nextDouble() < CROSSOVER_RATE ) {
indiv = crossover(indiv[0], indiv[1]);
}
// Mutation
if ( rand.nextDouble() < MUTATION_RATE ) {
indiv[0].mutate();
}
if ( rand.nextDouble() < MUTATION_RATE ) {
indiv[1].mutate();
}
// add to new population
newPop[count] = indiv[0];
newPop[count+1] = indiv[1];
count += 2;
}
// Saving new population in pop
pop.setPopulation(newPop);
//Evaluating new population
pop.evaluate();
System.out.print("Total Fitness = " + pop.totalFitness);
System.out.println(" ; Best Fitness = " +pop.getFittest().getFitnessValue());
}
Individual bestIndiv = pop.getFittest();
}
}
The max possible value of fitness is 300 in my case but it always stucks around 200-230.

Replaced this function :
public void setPopulation(Individual[] newPop) {
this.pop = newPop;
}
with
public void setPopulation(Individual[] newPop) {
System.arraycopy(newPop, 0, this.pop, 0, POP_SIZE);
}
and it works fine now.

Related

Issues with setting values in arrays

I'm new to java and making a hotel system. I have three major classes Room, Floor, and Hotel. Each floor has same type of rooms except for their room number. So I only make say 10 rooms and then give them all to my 5 floors and then assign the room number to each room in the respective floor.
The room number has its first digit as that of the floor no and the remaining digit(s) are from 1-10.
However, all my rooms in the hotel get assigned with the 5th floor number.
Heres snippets of my code.
class Floor
{
private int floorNo;
private Room[] Rooms;
public Floor()
{
floorNo = 0;
Rooms = null;
}
public Floor(int f, int t)
{
floorNo = f;
Rooms = new Room[t];
}
public void createRooms(Room[] R)
{
for (int i = 0; i < 10; i++)
{
Rooms[i] = new Room();
Rooms[i] = R[i];
}
}
public void setRoom(int i, int f, int r)
{
Rooms[i].setFloorNo(f);
Rooms[i].setRoomno(r);
}
}
public class Main
{
public static void main(String[] args)
{
Room[] Rooms = new Room[10];
for (int n = 0; n < 10; n++)
{
Rooms[n] = new Room();
}
}
Floor[] Floors = new Floor[5];
for (int n = 0; n < 5; n++)
{
Floors[n] = new Floor(n + 1, 10);
Floors[n].createRooms(Rooms);
for (int i = 0; i < 10; i++)
{
Floors[n].setRoom(i, n + 1, i + 1);
}
for (int n = 0; n < 5; n++)
{
Floors[n].print();
}
}
}
class Floor
{
private int floorNo;
private Room[] Rooms;
public Floor()
{
floorNo=0;
Rooms=null;
}
public Floor(int f, int t)
{
floorNo=f;
Rooms = new Room[t];
}
public void createRooms(Room[] R)
{
for(int i = 0 ; i < 10; i ++)
{
Rooms[i] = new Room();
Rooms[i] = R[i];
}
}
public void setRoom(int i, int f, int r)
{
Rooms[i].setFloorNo(f);
Rooms[i].setRoomno(r,f);
}
}
class Room
{
public void setFloorNo(int i)
{
System.out.println("floor no is "+i);
}
public void setRoomno(int j,int k)
{
System.out.println("room no is "+k+""+j);
}
}
public class main
{
public static void main(String[] args)
{
Room [] Rooms= new Room[10];
for(int n = 0; n < 10; n++)
{
Rooms[n] = new Room ();
}
Floor [] Floors= new Floor[5];
for(int n=0; n<5; n++)
{
Floors[n] = new Floor (n+1,10);
Floors[n].createRooms(Rooms);
}
for(int n=0; n < 5; n++)
{
for(int i=0;i<10;i++)
Floors[n].setRoom(i, n+1, i+1);
enter code here
}
}
}
You can try smth like this:
public class Hotel {
private List<Floor> floors = new ArrayList<>();
public boolean addFloor(Floor floor) {
return floors.add(floor);
}
public static void main(String[] args) {
int totalFloors = 5;
int totalRoomsOnAFloor = 10;
final Hotel hotel = new Hotel();
int roomNumber = 0;
for (int floorNumber = 0; floorNumber < totalFloors; floorNumber++) {
Floor floor = new Floor(floorNumber);
for (int floorRoomNumber = 0; floorRoomNumber < totalRoomsOnAFloor; floorRoomNumber++) {
Room room = new Room(floor, roomNumber++);
floor.addRoom(room);
System.out.println("Added " + room.toString());
}
}
}
public static class Floor {
private List<Room> rooms = new ArrayList<>();
private int number;
public Floor(int number) {
this.number = number;
}
public boolean addRoom(Room room) {
return rooms.add(room);
}
public int getNumber() {
return number;
}
#Override
public String toString() {
return "Floor{" +
"number=" + number +
'}';
}
}
public class Room {
private final Floor floor;
private final int number;
public Room(Floor floor, int number) {
this.floor = floor;
this.number = number;
}
public int getNumber() {
return number;
}
public Floor getFloor() {
return floor;
}
#Override
public String toString() {
return "Room{" +
"number=" + number +
", on the floor=" + floor +
'}';
}
}
}
Output:
Added Room{number=0, on the floor=Floor{number=0}}
Added Room{number=1, on the floor=Floor{number=0}}
Added Room{number=2, on the floor=Floor{number=0}}
...
Added Room{number=47, on the floor=Floor{number=4}}
Added Room{number=48, on the floor=Floor{number=4}}
Added Room{number=49, on the floor=Floor{number=4}}

Simple prisoner's dilemma genetic algorithm

I have used an existing genetic algorithm from
here
and reworked it I but don't know what I'm doing wrong
This is the error that I get
Exception in thread "main" java.lang.NullPointerException at
simpleGa.Algorithm.crossover(Algorithm.java:69) at
simpleGa.Algorithm.evolvePopulation(Algorithm.java:34) at
simpleGa.GAprisonerdilemma.main(GAprisonerdilemma.java:41)
I can't figure out exactly where the mistake is. Read a lot about NullPointerException but couldn't figure it out
package simpleGa;
public class Population {
public static Individual[] individuals;
/*
* Constructors
*/
// Create a population
public Population(int populationSize, boolean initialise) {
individuals = new Individual[populationSize];
// Initialise population
if (initialise) {
// Loop and create individuals
for (int i = 0; i < size(); i++) {
Individual newIndividual = new Individual();
newIndividual.generateIndividual();
saveIndividual(i, newIndividual);
}
for(int i=0;i<size();i++)
{
if(i%2==1){Individual individual1=individuals[i-1];
Individual individual2=individuals[i];
if(individuals[i-1].getGene(i-1)==0 && individuals[i].getGene(i)==0){
individuals[i-1].fitness=individual1.fitness+1;
individuals[i].fitness=individual2.fitness+1;
}
if(individuals[i-1].getGene(i-1)==1 && individuals[i].getGene(i)==1){
individuals[i-1].fitness=individual1.fitness+2;
individuals[i].fitness=individual2.fitness+2;
}
if(individuals[i-1].getGene(i-1)==0 && individuals[i].getGene(i)==1){
individuals[i-1].fitness=individual1.fitness+3;
individuals[i].fitness=individual2.fitness+0;
}
if(individuals[i-1].getGene(i-1)==1 && individuals[i].getGene(i)==0){
individuals[i-1].fitness=individual1.fitness+0;
individuals[i].fitness=individual2.fitness+3;
}
}}}
}
/* Getters */
public Individual getIndividual(int index) {
return individuals[index];
}
public Individual getFittest() {
Individual fittest = individuals[0];
// Loop through individuals to find fittest
for (int i = 1; i < size(); i++) {
if (fittest.getFitness() <= getIndividual(i).getFitness()) {
fittest = getIndividual(i);
}
}
return fittest;
}
/* Public methods */
// Get population size
public int size() {
return individuals.length;
}
// Save individual
public void saveIndividual(int index, Individual indiv) {
individuals[index] = indiv;
}
}
package simpleGa;
public class Individual {
static int defaultGeneLength = 1000;
private long[] genes =new long [defaultGeneLength];
// Cache
public static int fitness = 0;
// Create a random individual
public void generateIndividual() {
for (int i = 0; i < size(); i++) {
long gene = Math.round(Math.random());
genes[i] = gene;
}
}
/* Getters and setters */
// Use this if you want to create individuals with different gene lengths
public static void setDefaultGeneLength(int length) {
defaultGeneLength = length;
}
public long getGene(int i) {
return genes[i];
}
public void setGene(int index, long value) {
genes[index] = value;
fitness = 0;
}
/* Public methods */
public int size() {
return genes.length;
}
public static int getFitness() {
return fitness;
}
public void setFitness(int i) {
fitness=i;
}
#Override
public String toString() {
String geneString = "";
for (int i = 0; i < size(); i++) {
geneString += getGene(i);
}
return geneString;
}
}
package simpleGa;
public class Algorithm {
/* GA parameters */
private static final double uniformRate = 0.5;
private static final double mutationRate = 0.015;
private static final int tournamentSize = 5;
private static final boolean elitism = true;
/* Public methods */
// Evolve a population
public static Population evolvePopulation(Population pop) {
Population newPopulation = new Population(pop.size(), false);
// Keep our best individual
if (elitism) {
newPopulation.saveIndividual(0, pop.getFittest());
}
// Crossover population
int elitismOffset;
if (elitism) {
elitismOffset = 1;
} else {
elitismOffset = 0;
}
// Loop over the population size and create new individuals with
// crossover
for (int i = elitismOffset; i < pop.size(); i++) {
Individual indiv1 = tournamentSelection(pop);
Individual indiv2 = tournamentSelection(pop);
Individual newIndiv = crossover(indiv1, indiv2);
newPopulation.saveIndividual(i, newIndiv);
}
// Mutate population
for (int i = elitismOffset; i < newPopulation.size(); i++) {
mutate(newPopulation.getIndividual(i));
}
for(int i=0;i<pop.size();i++)
{for(int j=0;j<pop.getIndividual(i).size();j++)
{if(i%2==1){Individual individual1=Population.individuals[i-1];
Individual individual2=Population.individuals[i];
if(Population.individuals[i-1].getGene(i-1)==0 && Population.individuals[i].getGene(i)==0){
Population.individuals[i-1].fitness=individual1.fitness+1;
Population.individuals[i].fitness=individual2.fitness+1;
}
if(Population.individuals[i-1].getGene(i-1)==1 && Population.individuals[i].getGene(i)==1){
Population.individuals[i-1].fitness=individual1.fitness+2;
Population.individuals[i].fitness=individual2.fitness+2;
}
if(Population.individuals[i-1].getGene(i-1)==0 && Population.individuals[i].getGene(i)==1){
Population.individuals[i-1].fitness=individual1.fitness+3;
Population.individuals[i].fitness=individual2.fitness+0;
}
if(Population.individuals[i-1].getGene(i-1)==1 && Population.individuals[i].getGene(i)==0){
Population.individuals[i-1].fitness=individual1.fitness+0;
Population.individuals[i].fitness=individual2.fitness+3;
} }}}``
return newPopulation;
}
// Crossover individuals
private static Individual crossover(Individual indiv1, Individual indiv2) {
Individual newSol = new Individual();
// Loop through genes
for (int i = 0; i < indiv1.size(); i++) {
// Crossover
if (Math.random() <= uniformRate) {
newSol.setGene(i, indiv1.getGene(i));
} else {
newSol.setGene(i, indiv2.getGene(i));
}
}
return newSol;
}
// Mutate an individual
private static void mutate(Individual indiv) {
// Loop through genes
for (int i = 0; i < indiv.size(); i++) {
if (Math.random() <= mutationRate) {
// Create random gene
long gene = Math.round(Math.random());
indiv.setGene(i, gene);
}
}
}
// Select individuals for crossover
private static Individual tournamentSelection(Population pop) {
// Create a tournament population
Population tournament = new Population(tournamentSize, false);
// For each place in the tournament get a random individual
for (int i = 0; i < tournamentSize; i++) {
int randomId = (int) (Math.random() * pop.size());
tournament.saveIndividual(i, pop.getIndividual(randomId));
}
// Get the fittest
Individual fittest = tournament.getFittest();
return fittest;
}
package simpleGa;
public class FitnessCalc {
/* Public methods */
// Set a candidate solution as a byte array
// To make it easier we can use this method to set our candidate solution
// with string of 0s and 1s
// Calculate inidividuals fittness by comparing it to our candidate solution
static int getFitness(Individual individual) {
int fitness = 0;
// Loop through our individuals genes and compare them to our cadidates
fitness=Individual.fitness;
return fitness;
}
}
// Get optimum fitness
}
package simpleGa;
import java.util.Scanner;
public class GAprisonerdilemma {
public static void main(String[] args) {
// Set a candidate solution
Scanner keyboard = new Scanner(System.in);
System.out.println("Input number of games!");
int k = keyboard.nextInt();
Individual.setDefaultGeneLength(k);
// Create an initial population
System.out.println("Input number of individuals in the population!");
int p = keyboard.nextInt();
Population myPop = new Population(p, true);
System.out.println("Input acceptable number of generations!");
int l = keyboard.nextInt();
// Evolve our population until we reach an optimum solution
int generationCount = 0;
int j=l+1;
System.out.println("Input requiered fitness value !");
int f = keyboard.nextInt();
int h=0;
// Evolve our population until we reach an optimum solution
for(int i=0;i<j;i++)
{
if(i==0){}
else{
if(myPop.getFittest().getFitness()>=f){if(h==0){h++;}
else{ System.out.println("Solution found!");
System.out.println("Generation: " + generationCount);
System.out.println( "Fitness(Points): " + myPop.getFittest().getFitness());
break;}
}else {myPop = Algorithm.evolvePopulation(myPop);
generationCount++;
System.out.println("Generation: " + generationCount + " Fittest: " + myPop.getFittest().getFitness());
}
if(i==j-1){ if(myPop.getFittest().getFitness()>=f)System.out.println("Solution found !");
else System.out.println("Solution not found closest solution is!");
System.out.println("Generation: " + generationCount);
System.out.println( " Fitness(Points): " + myPop.getFittest().getFitness());}
}
}
System.out.println("0 for betrays in that turn 1 for cooperates!");
System.out.println("Turns:");
System.out.println(myPop.getFittest());
}
}

Can't locate the problems in this simple Genetic Algorithm program

I have written a simple genetic algorithm program in java. What it is does is maximize the decimal value represented by the bits in the chromosome. Somehow mutation is not working as expected, e.g. causing two genes to mutate when just one is to change. The print statements I have included there show which to mutate, but in addition to that some more chromosomes get mutated. I can't figure out what the problem is :-(
Here are my java classes.
Gene.java
public class Gene {
private int value;
public Gene() {
value = Math.random() < 0.5 ? 0 : 1;
}
public Gene(int value) {
if (value != 0 && value != 1) {
throw new IllegalArgumentException("value must be either 0 or 1");
}
else {
this.value = value;
}
}
public void mutate() {
value = 1 - value;
}
public int value() {
return value;
}
#Override
public String toString() {
return String.valueOf(value);
}
}
Chromosome.java
import java.util.ArrayList;
import java.util.List;
public class Chromosome implements Comparable {
private ArrayList<Gene> genes;
private final int chromosomeLength;
public Chromosome(int length) {
this.genes = new ArrayList<>();
this.chromosomeLength = length > 0 ? length : 16;
for (int i = 0; i < chromosomeLength; i++) {
this.genes.add(i, new Gene());
}
}
public List<Gene> getAllele(int fromIndex, int toIndex) {
return new ArrayList<>(genes.subList(fromIndex, toIndex));
}
public void setAllele(int fromIndex, List<Gene> allele) {
int lastIndex = fromIndex + allele.size();
if (lastIndex > chromosomeLength) {
throw new IndexOutOfBoundsException("the allele exceeds beyond the size of the chromosome");
}
for (int i = fromIndex, j = 0; i < lastIndex; i++, j++) {
genes.set(i, allele.get(j));
}
}
public int getChromosomeLength() {
return chromosomeLength;
}
public void setGeneAt(int index, Gene gene) {
genes.set(index, gene);
}
public Gene getGeneAt(int index) {
return genes.get(index);
}
public int value() {
return Integer.parseInt(this.toString(), 2);
}
#Override
public String toString() {
StringBuilder chromosome = new StringBuilder("");
genes.stream().forEach((Gene g) -> chromosome.append(g));
return chromosome.toString();
}
#Override
public int compareTo(Object anotherChromosome) {
Chromosome c = (Chromosome) anotherChromosome;
return this.value() - c.value();
}
}
GenePool.java
import java.util.ArrayList;
import java.util.Arrays;
public class GenePool {
private final ArrayList<Chromosome> genePool;
private final int genePoolSize;
private final int chromosomeLength;
private final double crossOverRate;
private final double mutationRate;
private int[] crossPoints;
public GenePool(int numOfChromosome, int chromosomeLength, double crossOverRate, double mutationRate) {
this.genePoolSize = numOfChromosome;
this.chromosomeLength = chromosomeLength > 0 ? chromosomeLength : 16;
this.crossOverRate = crossOverRate;
this.mutationRate = mutationRate;
crossPoints = new int[1];
crossPoints[0] = this.chromosomeLength / 2;
genePool = new ArrayList<>();
for (int i = 0; i < numOfChromosome; i++) {
genePool.add(new Chromosome(chromosomeLength));
}
}
public int getGenePoolSize() {
return genePoolSize;
}
public Chromosome getChromosomeAt(int index) {
return genePool.get(index);
}
public void setChromosomeAt(int index, Chromosome c) {
genePool.set(index, c);
}
public int getChromosomeLength() {
return chromosomeLength;
}
public Chromosome[] crossOver(Chromosome c1, Chromosome c2) {
Chromosome[] offsprings = new Chromosome[2];
offsprings[0] = new Chromosome(c1.getChromosomeLength());
offsprings[1] = new Chromosome(c1.getChromosomeLength());
Chromosome[] parentChromosomes = {c1, c2};
int selector = 0;
for (int i = 0, start = 0; i <= crossPoints.length; i++) {
int crossPoint = i == crossPoints.length ? c1.getChromosomeLength() : crossPoints[i];
offsprings[0].setAllele(start, parentChromosomes[selector].getAllele(start, crossPoint));
offsprings[1].setAllele(start, parentChromosomes[1 - selector].getAllele(start, crossPoint));
selector = 1 - selector;
start = crossPoint;
}
return offsprings;
}
public void mutateGenePool() {
int totalGeneCount = genePoolSize * chromosomeLength;
System.out.println("Mutating genes:");
for (int i = 0; i < totalGeneCount; i++) {
double prob = Math.random();
if (prob < mutationRate) {
System.out.printf("Chromosome#: %d\tGene#: %d\n", i / chromosomeLength, i % chromosomeLength);
genePool.get(i / chromosomeLength).getGeneAt(i % chromosomeLength).mutate();
}
}
System.out.println("");
}
public int getLeastFitIndex() {
int index = 0;
int min = genePool.get(index).value();
int currentValue;
for (int i = 1; i < genePoolSize; i++) {
currentValue = genePool.get(i).value();
if (currentValue < min) {
index = i;
min = currentValue;
}
}
return index;
}
public void saveFittest(ArrayList<Chromosome> offsprings) {
// sort in ascending order
offsprings.sort(null);
offsprings.stream().forEach((offspring) -> {
int leastFitIndex = getLeastFitIndex();
if (offspring.value() > genePool.get(leastFitIndex).value()) {
genePool.set(leastFitIndex, offspring);
}
});
}
public void evolve(int noOfGeneration) {
for (int generation = 1; generation <= noOfGeneration; generation++) {
System.out.println("Generation :" + generation);
ArrayList<Integer> selection = new ArrayList<>();
for (int i = 0; i < genePoolSize; i++) {
if (Math.random() <= crossOverRate) {
selection.add(i);
}
}
if (selection.size() % 2 == 1) {
selection.remove(selection.size() - 1);
}
ArrayList<Chromosome> offsprings = new ArrayList<>();
for (int i = 0; i < selection.size(); i += 2) {
int index1 = selection.get(i);
int index2 = selection.get(i + 1);
offsprings.addAll(Arrays.asList(crossOver(genePool.get(index1), genePool.get(index2))));
}
System.out.println("Before saving the offsprings");
displayChromosomes(genePool, "GenePool");
displayChromosomes(offsprings, "Offsprings");
saveFittest(offsprings);
System.out.println("Before mutation:");
displayChromosomes(genePool, "GenePool");
mutateGenePool();
System.out.println("After mutation:");
displayChromosomes(genePool, "GenePool");
System.out.println("\n\n");
}
}
public void displayChromosomes(ArrayList<Chromosome> geneList, String name) {
System.out.println(name);
if (geneList.isEmpty()) {
System.out.println("Empty list");
}
geneList.stream().forEach((c) -> {
System.out.println(c + " -> " + c.value());
});
System.out.println("");
}
}
GADemo.java
public class GADemo {
public static void main(String[] args) {
GenePool gp = new GenePool(6, 8, 0.25, 0.01);
gp.evolve(10);
}
}
After evolving for a number of generations, the chromosomes all tend to become exactly the same, or very similar. And the problem is that that value is not the maximum for that many bits, and sometimes even a small value. For example, for 8 bits the values should (tend to) approach 255, but this doesn't do so in my code. Someone please provide a hint where/how to look for and solve the problem.
Focus on these lines and imagine the references. These are from setAllele()
for (int i = fromIndex, j = 0; i < lastIndex; i++, j++) {
genes.set(i, allele.get(j));
}
You are basically copying the reference from one onto the other. They are the same Gene so whatever mutation you do on those genes, will also affect even other Chromosomes.
You must produce a deep copy here.
Initially each chromosome has an own list of genes. But when you do the crossover operation you set gene objects from one chromosome into the gene list of other chromosome.
When you evolve the system, the number of shared genes will rise and therefore ultimately all chromosomes will share the same genes. No matter how you mutate a gene the chromosomes are not affected.
EDIT:
As Incognito also answered the setAllele method seems to be the culprit where gene sharing starts. You may want to introduce a method in the gene class where you can set its value given another gene.

How to perform n-fold cross validation (Mahout)?

Does Apache Mahout provide a way to perform n-fold cross-validation, instead of the random hold-out test? If not, what other Java framework do you suggest (with available code samples / good documentation, and that you have personally used if possible)?
My current code (uses random hold-out):
RecommenderEvaluator evaluator = new AverageAbsoluteDifferenceRecommenderEvaluator();
double result = evaluator.evaluate(builder, null, model, 0.9, 1.0);
System.out.println("Evaluation : " + result);
Here is a custom implementation that I did extending the AbstractDifferenceRecommenderEvaluator from Mahout. I just copy and paste the code. Please check if it satisfy your needs. I think I have enough comments in the class.
public abstract class AbstractKFoldRecommenderEvaluator extends AbstractDifferenceRecommenderEvaluator {
private final Random random;
public double noEstimateCounterAverage = 0.0;
public double totalEstimateCount = 0.0;
public double totalEstimateCountAverage = 0.0;
private static final Logger log = LoggerFactory
.getLogger(AbstractKFoldRecommenderEvaluator.class);
public AbstractKFoldRecommenderEvaluator() {
super();
random = RandomUtils.getRandom();
}
public double getNoEstimateCounterAverage(){
return noEstimateCounterAverage;
}
public double getTotalEstimateCount(){
return totalEstimateCount;
}
public double getTotalEstimateCountAverage(){
return totalEstimateCountAverage;
}
/**
* We use the same evaluate function from the RecommenderEvaluator interface
* the trainingPercentage is used as the number of folds, so it can have
* values bigger than 0 to the number of folds.
*/
#Override
public double evaluate(RecommenderBuilder recommenderBuilder,
DataModelBuilder dataModelBuilder, DataModel dataModel,
double trainingPercentage, double evaluationPercentage)
throws TasteException {
Preconditions.checkNotNull(recommenderBuilder);
Preconditions.checkNotNull(dataModel);
Preconditions.checkArgument(trainingPercentage >= 0.0,
"Invalid trainingPercentage: " + trainingPercentage);
Preconditions.checkArgument(evaluationPercentage >= 0.0
&& evaluationPercentage <= 1.0,
"Invalid evaluationPercentage: " + evaluationPercentage);
log.info("Beginning evaluation using {} of {}", trainingPercentage,
dataModel);
int numUsers = dataModel.getNumUsers();
// Get the number of folds
int noFolds = (int) trainingPercentage;
// Initialize buckets for the number of folds
List<FastByIDMap<PreferenceArray>> folds = new ArrayList<FastByIDMap<PreferenceArray>>();
for (int i = 0; i < noFolds; i++) {
folds.add(new FastByIDMap<PreferenceArray>(
1 + (int) (i / noFolds * numUsers)));
}
// Split the dataModel into K folds per user
LongPrimitiveIterator it = dataModel.getUserIDs();
while (it.hasNext()) {
long userID = it.nextLong();
if (random.nextDouble() < evaluationPercentage) {
splitOneUsersPrefs2(noFolds, folds, userID, dataModel);
}
}
double result = Double.NaN;
List<Double> intermediateResults = new ArrayList<>();
List<Integer> unableToRecoomend = new ArrayList<>();
List<Integer> averageEstimateCounterIntermediate = new ArrayList<>();
noEstimateCounterAverage = 0.0;
totalEstimateCount = 0.0;
totalEstimateCountAverage = 0.0;
int totalEstimateCounter = 0;
// Rotate the folds. Each time only one is used for testing and the rest
// k-1 folds are used for training
for (int k = 0; k < noFolds; k++) {
FastByIDMap<PreferenceArray> trainingPrefs = new FastByIDMap<PreferenceArray>(
1 + (int) (evaluationPercentage * numUsers));
FastByIDMap<PreferenceArray> testPrefs = new FastByIDMap<PreferenceArray>(
1 + (int) (evaluationPercentage * numUsers));
for (int i = 0; i < folds.size(); i++) {
// The testing fold
testPrefs = folds.get(k);
// Build the training set from the remaining folds
if (i != k) {
for (Map.Entry<Long, PreferenceArray> entry : folds.get(i)
.entrySet()) {
if (!trainingPrefs.containsKey(entry.getKey())) {
trainingPrefs.put(entry.getKey(), entry.getValue());
} else {
List<Preference> userPreferences = new ArrayList<Preference>();
PreferenceArray existingPrefs = trainingPrefs
.get(entry.getKey());
for (int j = 0; j < existingPrefs.length(); j++) {
userPreferences.add(existingPrefs.get(j));
}
PreferenceArray newPrefs = entry.getValue();
for (int j = 0; j < newPrefs.length(); j++) {
userPreferences.add(newPrefs.get(j));
}
trainingPrefs.remove(entry.getKey());
trainingPrefs.put(entry.getKey(),
new GenericUserPreferenceArray(
userPreferences));
}
}
}
}
DataModel trainingModel = dataModelBuilder == null ? new GenericDataModel(
trainingPrefs) : dataModelBuilder
.buildDataModel(trainingPrefs);
Recommender recommender = recommenderBuilder
.buildRecommender(trainingModel);
Double[] retVal = getEvaluation(testPrefs, recommender);
double intermediate = retVal[0];
int noEstimateCounter = ((Double)retVal[1]).intValue();
totalEstimateCounter += ((Double)retVal[2]).intValue();
averageEstimateCounterIntermediate.add(((Double)retVal[2]).intValue());
log.info("Evaluation result from fold {} : {}", k, intermediate);
log.info("Average Unable to recommend for fold {} in: {} cases out of {}", k, noEstimateCounter, ((Double)retVal[2]).intValue());
intermediateResults.add(intermediate);
unableToRecoomend.add(noEstimateCounter);
}
double sum = 0;
double noEstimateSum = 0;
double totalEstimateSum = 0;
// Sum the results in each fold
for (int i = 0; i < intermediateResults.size(); i++) {
if (!Double.isNaN(intermediateResults.get(i))) {
sum += intermediateResults.get(i);
noEstimateSum+=unableToRecoomend.get(i);
totalEstimateSum+=averageEstimateCounterIntermediate.get(i);
}
}
if (sum > 0) {
// Get an average for the folds
result = sum / intermediateResults.size();
}
double noEstimateCount = 0;
if(noEstimateSum>0){
noEstimateCount = noEstimateSum / unableToRecoomend.size();
}
double avgEstimateCount = 0;
if(totalEstimateSum>0){
avgEstimateCount = totalEstimateSum / averageEstimateCounterIntermediate.size();
}
log.info("Average Evaluation result: {} ", result);
log.info("Average Unable to recommend in: {} cases out of avg. {} cases or total {} ", noEstimateCount, avgEstimateCount, totalEstimateCounter);
noEstimateCounterAverage = noEstimateCount;
totalEstimateCount = totalEstimateCounter;
totalEstimateCountAverage = avgEstimateCount;
return result;
}
/**
* Split the preference values for one user into K folds, randomly
* Generate random number until is not the same as the previously generated on
* in order to make sure that at least two buckets are populated.
*
* #param k
* #param folds
* #param userID
* #param dataModel
* #throws TasteException
*/
private void splitOneUsersPrefs(int k,
List<FastByIDMap<PreferenceArray>> folds, long userID,
DataModel dataModel) throws TasteException {
List<List<Preference>> oneUserPrefs = Lists
.newArrayListWithCapacity(k + 1);
for (int i = 0; i < k; i++) {
oneUserPrefs.add(null);
}
PreferenceArray prefs = dataModel.getPreferencesFromUser(userID);
int size = prefs.length();
int previousBucket = -1;
Double rand = -2.0;
for (int i = 0; i < size; i++) {
Preference newPref = new GenericPreference(userID,
prefs.getItemID(i), prefs.getValue(i));
do {
rand = random.nextDouble() * k * 10;
rand = (double) Math.floor(rand / 10);
// System.out.println("inside Rand "+rand);
} while (rand.intValue() == previousBucket);
// System.out.println("outside rand "+rand);
if (oneUserPrefs.get(rand.intValue()) == null) {
oneUserPrefs.set(rand.intValue(), new ArrayList<Preference>());
}
oneUserPrefs.get(rand.intValue()).add(newPref);
previousBucket = rand.intValue();
}
for (int i = 0; i < k; i++) {
if (oneUserPrefs.get(i) != null) {
folds.get(i).put(userID,
new GenericUserPreferenceArray(oneUserPrefs.get(i)));
}
}
}
/**
* Split the preference values for one user into K folds, by shuffling.
* First Shuffle the Preference array for the user. Then distribute the item-preference pairs
* starting from the first buckets to the k-th bucket, and then start from the beggining.
*
* #param k
* #param folds
* #param userID
* #param dataModel
* #throws TasteException
*/
private void splitOneUsersPrefs2(int k, List<FastByIDMap<PreferenceArray>> folds, long userID, DataModel dataModel) throws TasteException {
List<List<Preference>> oneUserPrefs = Lists.newArrayListWithCapacity(k + 1);
for (int i = 0; i < k; i++) {
oneUserPrefs.add(null);
}
PreferenceArray prefs = dataModel.getPreferencesFromUser(userID);
int size = prefs.length();
List<Preference> userPrefs = new ArrayList<>();
Iterator<Preference> it = prefs.iterator();
while (it.hasNext()) {
userPrefs.add(it.next());
}
// Shuffle the items
Collections.shuffle(userPrefs);
int currentBucket = 0;
for (int i = 0; i < size; i++) {
if (currentBucket == k) {
currentBucket = 0;
}
Preference newPref = new GenericPreference(userID, userPrefs.get(i).getItemID(), userPrefs.get(i).getValue());
if (oneUserPrefs.get(currentBucket) == null) {
oneUserPrefs.set(currentBucket, new ArrayList<Preference>());
}
oneUserPrefs.get(currentBucket).add(newPref);
currentBucket++;
}
for (int i = 0; i < k; i++) {
if (oneUserPrefs.get(i) != null) {
folds.get(i).put(userID, new GenericUserPreferenceArray(oneUserPrefs.get(i)));
}
}
}
private Double[] getEvaluation(FastByIDMap<PreferenceArray> testPrefs, Recommender recommender) throws TasteException {
reset();
Collection<Callable<Void>> estimateCallables = Lists.newArrayList();
AtomicInteger noEstimateCounter = new AtomicInteger();
AtomicInteger totalEstimateCounter = new AtomicInteger();
for (Map.Entry<Long, PreferenceArray> entry : testPrefs.entrySet()) {
estimateCallables.add(new PreferenceEstimateCallable(recommender, entry.getKey(), entry.getValue(), noEstimateCounter, totalEstimateCounter));
}
log.info("Beginning evaluation of {} users", estimateCallables.size());
RunningAverageAndStdDev timing = new FullRunningAverageAndStdDev();
execute(estimateCallables, noEstimateCounter, timing);
Double[] retVal = new Double[3];
retVal[0] = computeFinalEvaluation();
retVal[1] = (double) noEstimateCounter.get();
retVal[2] = (double) totalEstimateCounter.get();
//retVal.put(computeFinalEvaluation(), noEstimateCounter.get());
//return computeFinalEvaluation();
return retVal;
}}
And here is actual implementation class:
public class RMSRecommenderEvaluatorModified extends AbstractKFoldRecommenderEvaluator {
private RunningAverage average;
#Override
protected void reset() {
average = new FullRunningAverage();
}
#Override
protected void processOneEstimate(float estimatedPreference, Preference realPref) {
double diff = realPref.getValue() - estimatedPreference;
average.addDatum(diff * diff);
}
#Override
protected double computeFinalEvaluation() {
return Math.sqrt(average.getAverage());
}
#Override
public String toString() {
return "RMSRecommenderEvaluator";
}}

Collections.sort compile error - incompatible types

I have been developing an implementation of the neighbourhood algorithm in Java for a physics project I am working on. I'm brand new to Java so I apologize for any idiocy that results.
I have been getting the error
''
incompatible types
found : void
required: java.util.List<VoronoiPoint>
'' on line 22 from the Java compiler in attempting to compile the program shown below. I cannot figure out why the variable ''thelist'' somehow turns into a void when I declared it to be of type List<VoronoiPoint>. If anybody can explain to me what is going on it would be much appreciated!
import java.lang.Double;
import java.util.*;
public class VoronoiTiling
{
public static void main(String args[])
{
Integer n = 10; //Number of dimensions of model parameter space
Integer ns = 20; //Number of points per iteration
Integer nr = 4; //Number of cells to populate
Integer iterations = 5; //Number of iterations
List<VoronoiPoint> thelist = VoronoiList.startlist(ns,n);
//System.out.println(thelist);
//System.out.println(thelist.get(1).misfit);
for (Integer i=0 ; i<thelist.size() ; i++)
{
thelist.get(i).setmisfit();
}
List<VoronoiPoint> orderedlist = Collections.sort(thelist);
Double distance = EuclidianDistance((thelist.get(1)).location,(thelist.get(2)).location);
System.out.println(distance);
}
public static Double EuclidianDistance(Double[] point1, Double[] point2)
{
Double distance=0.0;
for (int i = 0; i < point1.length; i++)
{
distance = distance + Math.pow((point1[i]-point2[i]),2);
}
return Math.sqrt(distance);
}
}
The other classes I used are here:
The VoronoiList class:
import java.util.*;
public class VoronoiList
{
public static List<VoronoiPoint> startlist(Integer ns, Integer n)
{
List<VoronoiPoint> thestartlist = new ArrayList<VoronoiPoint>();
for (int i = 0; i < ns; i++)
{
thestartlist.add(new VoronoiPoint(0.,n));
}
return thestartlist;
}
}
The VoronoiPoint class:
import java.util.Random;
public class VoronoiPoint implements Comparable<VoronoiPoint>
{
Double[] location;
private Random generator = new Random();
Double misfit = -1.;
//***************************************************************
public VoronoiPoint(Double misfit, Integer n)
{
location = new Double[n];
ParameterBoundaries boundaries = new ParameterBoundaries(n);
for(int i = 0; i < n; i++)
{
location[i] = boundaries.getboundaries(2*i)+2*generator.nextDouble();
}
}
//***************************************************************
//public Double[] getlocation()
//{
//return location;
//}
public void setlocationi(Integer i, Double j)
{
location[i] = j;
}
//***************************************************************
public void setmisfit()
{
Integer n = location.length;
Double tempmisfit = 0.0;
for(Integer i = 0; i < n; i++)
{
tempmisfit = tempmisfit + Math.pow((location[i]),2);
}
misfit = Math.sqrt(tempmisfit); // Temporarily just distance to centre
}
//public Double getmisfit()
//{
//return misfit;
//}
public int compareTo(VoronoiPoint b)
{
if (this.misfit<b.misfit) return -1;
else if (this.misfit==b.misfit) return 0;
return 1;
}
}
And the parameter boundaries class:
public class ParameterBoundaries
{
private Double[] boundaries; /*Set to 2n where n is dimensions of parameter space,
* it just makes it easier*/
public ParameterBoundaries(Integer n)
{
boundaries = new Double[2*n];
for(Integer i = 0; i<n; i++)
{
boundaries[2*i] = -1.0;
boundaries[2*i+1] = 1.0;
}
}
public Double getboundaries(Integer i)
{
return boundaries[i];
}
}
Collections.sort(..) sorts the original list. It doesn't return a new list. (Its return type is void)
Your code is wrong. Collections.sort() is an in-place sort function; it modifies the given list argument and returns nothing (void).

Categories

Resources