|
|
- <html>
- <head>
- <script>
- class Gene
- {
- constructor(min, max, value)
- {
- this.min = min;
- this.max = max;
- this.value = value;
- }
-
- getRealValue()
- {
- return (this.max - this.min) * this.value + this.min;
- }
-
- getValue()
- {
- return this.value;
- }
-
- setValue(val)
- {
- this.value = val;
- }
-
- makeClone()
- {
- return new Gene(this.min, this.max, this.value);
- }
-
- makeRandomGene()
- {
- return new Gene(this.min, this.max, Math.random());
- }
- }
-
-
- class Chromosome
- {
- constructor(geneArray)
- {
- this.genes = [];
- for(let i = 0; i < geneArray.length; i++)
- {
- this.genes.push(geneArray[i].makeClone());
- }
- }
-
- getGenes()
- {
- return this.genes;
- }
-
- mutate()
- {
- this.genes[Math.round(Math.random() * (this.genes.length-1))].setValue(Math.random());
- }
-
- createRandomChromosome()
- {
- let geneAr = [];
- for(let i = 0; i < this.genes.length; i++)
- {
- geneAr.push(this.genes[i].makeRandomGene());
- }
- return new Chromosome(geneAr);
- }
- }
-
-
- const breed = function(father, mother)
- {
- let son = new Chromosome(father.getGenes());
- let daughter = new Chromosome(mother.getGenes());
-
- for(let i = 0;i < son.getGenes().length; i++)
- {
- let blendCoef = Math.random();
- blendGene(son.getGenes()[i], daughter.getGenes()[i], blendCoef);
- }
-
- return [son, daughter];
- };
-
- function predicateBy(prop)
- {
- return function(a,b)
- {
- var result;
- if(a[prop] > b[prop])
- {
- result = 1;
- }
- else if(a[prop] < b[prop])
- {
- result = -1;
- }
- return result;
- }
- }
-
-
- const naturalSelection = function(population, keepNumber, fitnessFunction)
- {
- let fitnessArray = [];
- for(let i = 0; i < population.length; i++)
- {
- const fitness = fitnessFunction(population[i]);
- console.log(fitness);
- fitnessArray.push({fit:fitness, chrom: population[i]});
- }
-
- fitnessArray.sort(predicateBy("fit"));
-
- let survivors = [];
- let bestFitness = fitnessArray[0].fit;
- let bestChromosome = fitnessArray[0].chrom;
- for(let i = 0; i < keepNumber; i++)
- {
- survivors.push(fitnessArray[i].chrom);
- }
- return {survivors: survivors, bestFit: bestFitness, bestChrom: bestChromosome};
- };
-
- const blendGene = function(gene1, gene2, blendCoef)
- {
- let value1 = (blendCoef * gene1.getValue()) +
- (gene2.getValue() * (1- blendCoef));
- let value2 = ((1-blendCoef) * gene1.getValue()) +
- (gene2.getValue() * blendCoef);
-
- gene1.setValue(value1);
- gene2.setValue(value2);
- };
-
- const matePopulation = function(population, desiredPopulationSize)
- {
- let pairsNeeded = (desiredPopulationSize - population.length)/2;
- const originalLength = population.length;
- for(let i = 0; i < pairsNeeded; i++)
- {
- let index1 = Math.round(Math.random() * (originalLength-1));
- let index2 = Math.round(Math.random() * (originalLength-1));
- if(index1 !== index2)
- {
- const babies = breed(population[index1], population[index2]);
- population.push(babies[0]);
- population.push(babies[1]);
- }
- }
- };
-
-
- const mutatePopulation = function(population, mutatePercentage)
- {
- if(population.length >= 2)
- {
- let mutations = mutatePercentage *
- population.length *
- population[0].getGenes().length;
- for(let i = 0; i < mutations; i++)
- {
- population[i].mutate();
- }
- }
- else
- {
- console.log("Error, population too small to mutate");
- }
- };
-
- const newBlood = function(population, immigrationSize)
- {
- for(let i = 0; i < immigrationSize; i++)
- {
- let geneticChromosome = population[0];
- population.push(geneticChromosome.createRandomChromosome());
- }
- };
-
-
- const basicCostFunction = function(chromosome)
- {
- console.log(chromosome);
- console.log((chromosome.getGenes()[0].getRealValue()));
- return Math.abs(chromosome.getGenes()[0].getRealValue() - 6) +
- Math.abs(chromosome.getGenes()[1].getRealValue() - 2);
- };
-
-
- const createRandomPopulation = function(geneticChromosome, populationSize)
- {
- let population = [];
- for(let i = 0; i < populationSize; i++)
- {
- population.push(geneticChromosome.createRandomChromosome());
- }
- return population;
- };
-
-
- const runGeneticOptimization = function(geneticChromosome, constFunction,
- populationSize, maxGenerations,
- desiredCost, mutationRate, keepNumber,
- newBloodNumber)
- {
- let population = createRandomPopulation(geneticChromosome, populationSize);
-
- let generation = 0;
-
- let bestCost = Number.MAX_VALUE;
- let bestChromosome = geneticChromosome;
-
- do
- {
- matePopulation(population, populationSize);
- newBlood(population, newBloodNumber);
- mutatePopulation(population, mutationRate);
- let generationResult = naturalSelection(population, keepNumber, constFunction);
-
- if(bestCost > generationResult.bestFit)
- {
- bestChromosome = generationResult.bestChrom;
- bestCost = generationResult.bestFit;
- }
- population = generationResult.survivors;
-
- generation++;
- console.log("Generation " + generation + " Best Cost: " + bestCost);
-
- console.log(generationResult);
- }while(generation < maxGenerations && bestCost > desiredCost);
- return bestChromosome;
- };
-
- let gene1 = new Gene(1,10,10);
- let gene2 = new Gene(1,10,0.4);
- let geneList = [gene1, gene2];
-
- let exampleOrganism = new Chromosome(geneList);
-
- runGeneticOptimization(exampleOrganism, basicCostFunction, 100, 50, 0.01, 0.3, 20, 10);
-
- </script>
- </head>
-
-
- <body>
- </body>
-
-
- </html>
|