I see
Error was that this line was missing
population = newPopulation;
at the end of nextGeneration()
Chrisir
//
int totalCities = 12;
int popSize = 500;
Population population;
void setup()
{
size(800, 800);
population = new Population();
frameRate(1);
}
void draw()
{
background(0);
population.run();
population.show();
print(".");
}
// ==================================================================================================
class City
{
// PVector as the location of city on the screen
PVector loc; // position
float r; // circles radius
City(PVector p)
{
loc = p.copy();
r = 16;
}
}
// ==================================================================================================
class Order
{
IntList index;
int shuffleTimes = 10;
Order()
{
index = new IntList();
for (int i = 0; i < totalCities; i++)
{
index.append(i);
}
}
void shuffleOrder()
{
for (int i = 0; i < shuffleTimes; i++)
{
int numA = floor(random(index.size()));
int numB = floor(random(numA, index.size())); // Added numA here !!!
swap(index, numA, numB);
}
}
void swap(IntList list, int i, int j)
{
int tempA = list.get(i);
int tempB = list.get(j);
list.set(i, tempB);
list.set(j, tempA);
}
}
// ==================================================================================================
class Population
{
IntList[] population;
Order seqList;
City[] cities;
float[] fitness;
float recordDistance = Float.POSITIVE_INFINITY;
IntList bestEver;
IntList currentBest;
//PVector points;
Population()
{
fitness = new float[popSize];
cities = new City[totalCities];
for (int i = 0; i < totalCities; i++)
{
PVector v = new PVector(random(width), random(height/2));
cities[i] = new City(v);
//cities[i] = new City();
}
population = new IntList[popSize];
seqList = new Order();
for (int i = 0; i < popSize; i++)
{
seqList.shuffleOrder();
population[i] = seqList.index.copy();
}
}
float calcDistance(City[] cities, IntList list)
{
float sum = 0;
for (int i = 0; i < list.size()- 1; i++)
{
int cityAIndex = list.get(i);
City cityA = cities[cityAIndex];
int cityBIndex = list.get(i+1);
City cityB = cities[cityBIndex];
float d = dist(cityA.loc.x, cityA.loc.y,
cityB.loc.x, cityB.loc.y);
sum += d;
}
return sum;
}
void calculateFitness()
{
float currentRecord = Float.POSITIVE_INFINITY;
for (int i = 0; i < population.length; i++)
{
float d = calcDistance(cities, population[i]);
if (d < recordDistance)
{
recordDistance = d;
bestEver = population[i].copy();
}
if (d < currentRecord)
{
currentRecord = d;
currentBest = population[i].copy();
}
fitness[i] = 1/(pow(d, 8)+1);
}
}
void normalizeFitness()
{
float sum = 0;
for (int i = 0; i < fitness.length; i++)
{
sum += fitness[i];
}
for (int i = 0; i < fitness.length; i++)
{
fitness[i] = fitness[i]/sum;
}
}
void nextGeneration()
{
IntList[] newPopulation = new IntList[popSize];
for (int i = 0; i < population.length; i++)
{
IntList orderA = pickOne(population, fitness);
IntList orderB = pickOne(population, fitness);
IntList order = crossOver(orderA, orderB);
mutate(order, 0.01); // was 0.01
newPopulation[i] = order;
}
population = newPopulation;
}
IntList pickOne(IntList[] list, float[] prob)
{
int index = 0;
float r = random(1);
while (r > 0)
{
r = r - prob[index];
index++;
}
index--;
return list[index].copy();
}
IntList crossOver(IntList orderA, IntList orderB)
{
int start = floor(random(orderA.size()));
int end = floor(random(start+1, orderA.size()));
IntList neworder = new IntList();
for (int i = start; i < end; i++)
{
neworder.append(orderA.get(i));
}
for (int i = 0; i < orderB.size(); i++)
{
int city = orderB.get(i);
if (!neworder.hasValue(city))
{
neworder.append(city);
}
}
return neworder;
}
void mutate(IntList order, float mutationRate)
{
for (int i = 0; i < totalCities; i++)
{
if (random(1) < mutationRate)
{
int indexA = floor(random(order.size()));
int indexB = (indexA + 1) % totalCities;
//print("before: " );
//println(order);
swap(order, indexA, indexB);
//print("after: " );
//println(order);
//println("");
}
}
}
void swap(IntList a, int i, int j)
{
int temp1 = a.get(i);
int temp2 = a.get(j);
a.set(i, temp2);
a.set(j, temp1);
}
void run()
{
calculateFitness();
normalizeFitness();
nextGeneration();
}
void show()
{
pushMatrix();
stroke(250, 160, 0);
strokeWeight(4);
noFill();
beginShape();
for (int i = 0; i < bestEver.size(); i++)
{
int n = bestEver.get(i);
vertex(cities[n].loc.x, cities[n].loc.y);
ellipse(cities[n].loc.x, cities[n].loc.y, 16, 16);
}
endShape();
popMatrix();
pushMatrix();
translate(0, height/2);
stroke(250, 0, 160);
strokeWeight(4);
noFill();
beginShape();
for (int i = 0; i < currentBest.size(); i++)
{
int n = currentBest.get(i);
vertex(cities[n].loc.x, cities[n].loc.y);
ellipse(cities[n].loc.x, cities[n].loc.y, 16, 16);
}
endShape();
popMatrix();
}
//
}//class Population
//
keywords:
- object-oriented programming,
- OOP,
- Traveling Salesman Problem, Traveling Salesperson Problem (TSP),
- Travelling Salesman Problem, Travelling Salesperson Problem (TSP),
- an NP-hard problem in combinatorial optimization, important in theoretical computer science and operations research.