Skip to content

Commit

Permalink
refactor: Tournament based on ranking #46 #52
Browse files Browse the repository at this point in the history
Since I need to made modification on tournament method, I took that opportunity to modify the tournament based on the meetings feedback
  • Loading branch information
sergiomrebelo committed Jul 24, 2023
1 parent 003d768 commit edabdb1
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 46 deletions.
85 changes: 52 additions & 33 deletions src/client/controllers/Population.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {Params} from "../Params.js";
import Poster, {Grid} from "./Poster.js";
import {randomScheme} from "./ColorGenerator.js";
import {swap} from "../utils.js";
import {shuffleArr, sumArr, sus, swap} from "../utils.js";

const SIZE_MUTATION_ADJUST = 5;
const TOURNAMENT_SIZE = 5;
const TOURNAMENT_SIZE = 10;

export class Population {
#typefaces;
Expand Down Expand Up @@ -66,17 +66,32 @@ export class Population {
offspring.push(this.population[i].copy());
}

let fitness = this.population.map((ind) => ind.fitness);
let constraints = this.population.map((ind) => ind.constraint);

// select the indices using Stochastic Ranking
const rank = await this.#stochasticRanking(fitness, constraints);


// sort population
// const newPopulation = [];
// for (let i=0; i<indices.length; i++) {
// newPopulation.push(this.population[indices[i]].copy());
// }
// this.population = newPopulation;



// crossover
for (let i = eliteSize; i < this.params["evo"]["popSize"]; i++) {
if (Math.random() <= this.params["evo"]["crossoverProb"]) {
const parentA = this.tournament(TOURNAMENT_SIZE);
const parentB = this.tournament(TOURNAMENT_SIZE);
const parents = this.#rankingTournament(rank, TOURNAMENT_SIZE, 2);
// crossover method
const child = await this.uniformCrossover(parentA, parentB);
const child = await this.uniformCrossover(this.population[parents[0]], this.population[parents[1]]);
offspring.push(child);
} else {
const ind = this.tournament();
offspring.push(ind);
const ind = this.#rankingTournament(rank, TOURNAMENT_SIZE, 1);
offspring.push(this.population[ind[0]].copy());
}
}

Expand Down Expand Up @@ -295,22 +310,11 @@ export class Population {
await individual.evaluate();
}

let fitness = this.population.map((ind) => ind.fitness);
let constraints = this.population.map((ind) => ind.constraint);

// const indices = await this.#stochasticRanking(fitness, constraints);
const indices = await this.#staticPenalty(fitness, constraints);

// sort population
const newPopulation = [];
for (let i=0; i<indices.length; i++) {
newPopulation.push(this.population[indices[i]].copy());
}
this.population = newPopulation;


// still sort the population based on staticPenalty
// sort individuals in the population by fitness (fittest first)
// this.population = this.population.sort((a,b) => b.fitness - a.fitness);

// TODO: const indices = await this.#staticPenalty(fitness, constraints);
}


Expand Down Expand Up @@ -340,31 +344,46 @@ export class Population {
noSwap = true;
}
}

return indices;
}

#staticPenalty = async () => {

}

copy = (obj) => {
return JSON.parse(JSON.stringify(obj));
}

tournament = (size = 2) => {
// ranking based
// return n individuals
// More the selection pressure more will be the Convergence rate
#rankingTournament = (rank, tournamentSize = 5, parentSize = 2, sp = 2) => {
// check the tournament size and parentSize
tournamentSize = tournamentSize < parentSize ? parentSize : tournamentSize;
let parents = [];
// select the pool of parents
let pool = [];
for (let i = 0; i < size; i++) {
const r = Math.round(Math.random()*(this.population.length-1));
pool.push(this.population[r]);
for (let i = 0; i < tournamentSize; i++) {
const r = Math.round(Math.random() * (rank.length - 1));
pool.push(r);
}
let fittest = pool[0];
for (let i=1; i <pool.length; i++) {
if (pool[i].fitness > fittest.fitness) {
fittest = pool[i];
}
// sort by ranking
pool.sort((a, b) => a - b);
// define the probability based on ranking fitness
let probabilities = pool.map((ind) => {
return sp - (2 * ind * (sp - 1.0)) / (this.population.length - 1);
});
// normalize to sum up to 1
const probabilitiesSum = sumArr(probabilities);
probabilities = probabilities.map((p) => p / probabilitiesSum);
probabilities = shuffleArr(probabilities);
for (let j = 0; j < parentSize; j++) {
let ix = sus(probabilities);
// sus
parents.push(parseInt(ix));
}
return fittest;
return parents;
}

// draw aux function
Expand Down
24 changes: 24 additions & 0 deletions src/client/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,30 @@ export const swap = (arr, i, j) => {
return arr;
}

export const sumArr = (arr) => {
return arr.reduce((partialSum, a) => partialSum + a, 0);
}

export const sus = (probs, max=1) => {
const r = Math.random()*max;
let c = 0;
for (let i in probs) {
c += probs[i];
if (r < c) {
return i;
}
}

}

export const shuffleArr = (arr) => {
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[arr[i], arr[j]] = [arr[j], arr[i]];
}
return arr;
}

export default () => {
console.log (`default export utils`);
}
Loading

0 comments on commit edabdb1

Please sign in to comment.