Saturday, January 14, 2012

Simulated Annealing - JAVA

//Simulated Annealing
//Author: Andrew Guandique 
//Objective: Solve N-queens game using simulated annealing (note: solution is not 'perfect' but closest to what a perfect solution would be)

import java.util.Random;

class Queen
{
int indexOfX, indexOfY;

public Queen(){}

public Queen(int indexOfX, int indexOfY)
{ this.indexOfX = indexOfX;
this.indexOfY = indexOfY;
}

public void setIndexOfX(int indexOfX)
{ this.indexOfX = indexOfX;
}

public void setIndexOfY(int indexOfY)
{ this.indexOfY = indexOfY;
}

public int getIndexOfX()
{ return indexOfX;
}

public int getIndexOfY()
{
return indexOfY;
}
}

class State
{
int boardSize;
int cost;
Queen q[];
Random randomGenerator = new Random();

public State(int boardSize)
{
        int i;
this.boardSize = boardSize;
q = new Queen[boardSize];

for(i=0; i<boardSize; i++)
{
q[i] = new Queen(i,  randomGenerator.nextInt(boardSize));
}

cost = 0;
}

public State(int boardSize, Queen q[])
{
this.boardSize = boardSize;
this.q = q;
cost = 0;
}

public State getNextState()
        int i;
Queen nextStateQueen[] = new Queen[boardSize];

int rand = randomGenerator.nextInt(boardSize);

for(i=0; i<boardSize; i++)
{
nextStateQueen[i] = new Queen( q[i].getIndexOfX(), q[i].getIndexOfY());

if(rand == i)
{
int temp = randomGenerator.nextInt(boardSize) ;

while(temp == q[i].getIndexOfY())
{
temp = randomGenerator.nextInt(boardSize);
}

nextStateQueen[i] = new Queen(q[i].getIndexOfX(), temp);
}
}
return new State(boardSize, nextStateQueen);
}

public void calculateCost()
{
        int i, j;
cost = 0;

for(i=0; i < boardSize; i++)
{
for(j=0; j < boardSize; j++)
{
if(
q[i].getIndexOfX() == q[j].getIndexOfX() || q[i].getIndexOfY() == q[j].getIndexOfY() ||
(q[i].getIndexOfX() - q[j].getIndexOfX() == q[i].getIndexOfY() - q[j].getIndexOfY()) ||
(q[i].getIndexOfX() - q[j].getIndexOfX() == q[j].getIndexOfY() - q[i].getIndexOfY())
)
{
cost++;
}
}
}
cost = cost / 2;
}

public int getCost()
{
        calculateCost();
return cost;
}

    public Queen[] getQueens()
    {
        return q;
    }
}

class NQueen
{
private int boardSize;
private State currentState, nextState;

public NQueen(int boardSize)
{
this.boardSize = boardSize;
currentState = new State(boardSize);
}

public void solve()
{
double temperature;
double delta;
double probability;
double rand;

        for( temperature = 10000; temperature > 0 && (currentState.getCost()!= 0) ; temperature--)
        {
nextState = currentState.getNextState();
delta = currentState.getCost() - nextState.getCost();
probability = Math.exp(delta / temperature);
rand = Math.random();

if(delta > 0)
{
currentState = nextState;
}
else if(rand <= probability)
{
currentState = nextState;
}
}
}

    public void show()
    {
        int temp = 0;
        Queen q[] = currentState.getQueens();
        boolean queen = false;
        System.out.println();

for (int i = 0; i < boardSize; i++) {
for (int j = 0; j < boardSize; j++) {
for (int k = 0; k < boardSize; k++) {
if (i == q[k].getIndexOfX() && j == q[k].getIndexOfY()) {
queen = true;
                        temp = k;
break;
}
}
if (queen) {
System.out.print("|"+temp);
queen = false;
}
else {
System.out.print("|_");
}
}
System.out.println("|");
        }
    }
}
public class SimulatedAnnealing {

    public static void main(String[] args) 
    {
        NQueen nq = new NQueen(8);
        for(int i = 1; i <= 12; i++){
        System.out.println("Solution: "+i);
        nq.solve();
        nq.show();
        System.out.println("");
        }
     }

}

Genetic Algorithm - JAVA

//Genetic Algorithm
//Author: Andrew Guandique
//Objective: Solve N-queens puzzle game using GA

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Random;


public class Genetic {
/* Genetic Algorithm:
* This implementation ensures that from the outset there are
* individuals with repeated genes. Based on this fact, the
* method uses PMX crossover operation.
* An implementation that allows repeated genes should
* use a new type of mixing (eg. one point, two point, etc.)
* /
*/
private static Random rand = new Random();
private static final int NUM_QUEENS = 8;
private static final int POP_DIM = 50;
private static int num_generation = 0;

public Genetic() {
//  1. create the initial population of randomly
Individual population [] = new Individual [POP_DIM];
for(int i=0;i<population.length;++i) {
int a[] = new int[NUM_QUEENS];
for(int j=0;j<NUM_QUEENS;++j) { 
int k = rand.nextInt(NUM_QUEENS) + 1; // nextInt =[0,8[ + 1 = [1,8]
if(contains(k,a)) { --j; } // if(repeated) re-roll
else { a[j] = k; }
}
population[i] = new Individual(a);
}
// kick off
begin(population);
}

/**
* Begin. 
*/
private void begin (Individual []population) {
// 2. Evaluate each individual through the function of adaptability 
int TotalFitness = 0;
for(int i = 0; i < POP_DIM; ++i) {
int adapt = fitness(population[i]);
population[i].setAdaptability(adapt);
TotalFitness += adapt;
}

// 3. repeat
// 3.1. select the most suitable individuals for reproduction
Individual parents[] = selection(population,TotalFitness);

// 3.2. generate the new population by crossover and mutation
Individual offspring[] = crossover(parents);
offspring = mutation(offspring);
// 3.3. population replacement
Individual new_generation[] = replace(population, parents, offspring);

// 4. end
for(Individual i : new_generation) {
if(perfect(i.getGenes())) { 
System.out.println(i);
return;
}
}
System.out.println("Generation nº: "+(++num_generation));
begin(new_generation);
}
/** 
*  Method that performs the function of adaptability
* @param e - evaluate individual
* @return - value of adaptability between [0, 100] 
*/
private int fitness(Individual e) {
int g[] = e.getGenes();
int fitness = 99; // assume that the individual is perfect

// Redundant, is not permitted to start and the mutation does not replicate genes
// If (horizontal_intersection (g))
// Fitness -= 99;
//  Discounts the number of imperfections (max. 49)
fitness -= diagonal_intersection(g);

// if(fitness < 0)
// fitness = 0;
// fitness € [50,99]
return fitness;
}

/** 
* Method of the individuals responsible for selecting parents 
* is performed using the method of roulette
* @param pop - population from which individuals are chosen
* @param TotalFitness -  the value used for normalization
* @return -  array dimension with the parents NUM_parents
*/
private Individual[] selection(Individual pop[], int TotalFitness) {
final int NUM_parents = (int)(((double)POP_DIM)*0.6);
Individual parents[] = new Individual[NUM_parents];
for(int i=0;i<NUM_parents;++i) {
int r = rand.nextInt(TotalFitness);
int s = 0;
for(Individual idv : pop) {
s += idv.getadaptability();
if(s>=r) { parents[i] = idv; break; }
}
}
return parents;
}
/**
* Method that performs the crossing between the parents
* @param progs - parents
* @return - the result of crossing parent
*/
private Individual[] crossover(Individual progs[]) {
Individual xover_result[] = new Individual[progs.length];

// 2 offspring for each pair of parents
for(int i=0,k=0;i<progs.length/2;++i) {
// randomly choose two parents
Individual p1 = (Individual)Array.get(progs,rand.nextInt(progs.length));
Individual p2 = (Individual)Array.get(progs,rand.nextInt(progs.length));
// Make the crossing between the two

int pmx1 = rand.nextInt(NUM_QUEENS); // select the first point of intersection
int pmx2 = rand.nextInt(NUM_QUEENS); // select the second point of intersection
if(pmx1>pmx2) {
int aux = pmx1;
pmx1 = pmx2;
pmx2 = aux;
}
// Get the genes from each parent
int e1[] = p1.getGenes();
int e2[] = p2.getGenes();

// Initialize the individuals of the new genes
int a1[] = new int[NUM_QUEENS];
int a2[] = new int[NUM_QUEENS];

// Fill the new individuals with:
// inner values of the points of intersection
for(int j=pmx1;j<pmx2;++j) {
a1[j] = e1[j];
a2[j] = e2[j];
}
// values of the left of the first crossing point
for(int j=0;j<pmx1;++j) {
a1[j] = pmx(e2[j],a1,e2,pmx1,pmx2);
a2[j] = pmx(e1[j],a2,e1,pmx1,pmx2);
}
// values of the right of the second crossing point
for(int j=pmx2;j<NUM_QUEENS;++j) {
a1[j] = pmx(e2[j],a1,e2,pmx1,pmx2);
a2[j] = pmx(e1[j],a2,e1,pmx1,pmx2);
}
// Create two individuals with the genetic code of the intersection
Individual idv1 = new Individual(a1);
Individual idv2 = new Individual(a2);
xover_result[k++] = idv1;
xover_result[k++] = idv2;
}
return xover_result;
}
/**
*  Randomly select three individuals who will suffer a mutation in its Genome
*/
private Individual[] mutation(Individual []desc) {
for(int i=0;i<3;++i) {
int k = rand.nextInt(desc.length);
int g[] = desc[k].getGenes();
int m = g[0];
for(int j=0;j<g.length-1;++j) {
g[j] = g[j+1];
}
g[g.length-1] = m;
desc[k].setGenes(g);
}
return desc;
}

/**
* Replacement of the old population by new generation
* We use a mix of crossover and direct promotion of the most adaptable of the older generation
*/
private Individual[] replace(Individual pop[], Individual progs[], Individual desc[]) {
Individual []new_generation = new Individual[POP_DIM];
for(int i=0;i<desc.length;++i) {
new_generation[i] = desc[i];
}
// Direct promotion of the best 40% of the older generation
Arrays.sort(pop); // sort in ascending order
for(int i=desc.length;i<pop.length;++i) {
new_generation[i] = pop[i];
}
return new_generation;
}

/**
*  Helper method that indicates whether a value is present in a given array 
*/
private static boolean contains(int i, int a[]) {
for(int k=0;k<a.length;++k) {
if(a[k]==i) return true;
}
return false;
}

/**
*  Method that validates the value of integration according to the technique PMX
*/
private static int pmx(int i, int a[], int b[], int pmx1, int pmx2) {
if(!contains(i,a)) {
return i;
}
else {
int v=0;
for(int k=pmx1;k<pmx2;++k) {
if(a[k]==i) {
v = b[k];
break;
}
}
if(!contains(v,a))
return v;
else
return pmx(v,a,b,pmx1,pmx2);
}
}
/** 
* Self-describing
*/
private static boolean horizontal_intersection(int g[]) {
for(int i=0;i<g.length;++i) {
for(int j=0;j<g.length;++j) {
if(i!=j && g[i]==g[j]) { 
return true;
}
}
}
return false;
}
/**
* Method that calculates the number of existing intersections diagonal 
*/
public static int diagonal_intersection(int g[]) {
int ret=0;
for(int i=0;i<g.length;++i) {
int x0 = i, y0 = g[i];

int xminus = x0-1, xplus = x0+1;
int yminus = y0-1, yplus = y0+1;
while(xminus>=0) {
if((yminus>=0 && g[xminus]==yminus) || (yplus<g.length && g[xminus]==yminus))
++ret;

--xminus;
--yminus;
++yplus;
}

yminus = y0-1; yplus = y0+1;
while(xplus<g.length) {
if((yminus>=0 && g[xplus]==yminus) || (yplus<g.length && g[xplus]==yplus))
++ret;

++xplus;
--yminus;
++yplus;
}
}
return ret;
}

/**
* Method that defines perfection (stop condition)
* @param - an individual's genes
* @return - true if the individual's genes are perfect 
*/
private boolean perfect(int g[]) {
// Check if they are on the same line
if(horizontal_intersection(g))
return false;
//  Check if they are on the same diagonal
if(diagonal_intersection(g)!=0)
return false;

return true;
}
public static void main(String []args) {
new Genetic();
}
}

class Individual implements Comparable {

private int genes[];
private int adaptability;

Individual(int i[]) { genes = i; }


public void setAdaptability(int adaptability) {
this.adaptability = adaptability;
}

public int getadaptability() {
return adaptability;
}
public void setGenes(int[] genes) {
this.genes = genes;
}

public int[] getGenes() {
return genes;
}

public String toString() {
StringBuffer sb = new StringBuffer("Genome Winner: ");
for(int i : genes) { sb.append(i); }
return sb.toString();
}

public int compareTo(Object arg0) {
Individual e = (Individual)arg0;
if(this.adaptability == e.getadaptability()) return 0;
else if(this.adaptability < e.getadaptability()) return -1;
else return 1;//if(>)
}

}