Repository where I mostly put random python scripts.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

432 lines
13 KiB

  1. <html>
  2. <head>
  3. <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
  4. <script
  5. src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
  6. integrity="sha256-3edrmyuQ0w65f8gfBsqowzjJe2iM6n0nKciPUp8y+7E="
  7. crossorigin="anonymous">
  8. </script>
  9. <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
  10. <script>
  11. class Gene
  12. {
  13. constructor(min, max, value)
  14. {
  15. this.min = min;
  16. this.max = max;
  17. this.value = value;
  18. }
  19. getRealValue()
  20. {
  21. return (this.max - this.min) * this.value + this.min;
  22. }
  23. getValue()
  24. {
  25. return this.value;
  26. }
  27. setValue(val)
  28. {
  29. this.value = val;
  30. }
  31. makeClone()
  32. {
  33. return new Gene(this.min, this.max, this.value);
  34. }
  35. makeRandomGene()
  36. {
  37. return new Gene(this.min, this.max, Math.random());
  38. }
  39. }
  40. class Chromosome
  41. {
  42. constructor(geneArray)
  43. {
  44. this.genes = [];
  45. for(let i = 0; i < geneArray.length; i++)
  46. {
  47. this.genes.push(geneArray[i].makeClone());
  48. }
  49. }
  50. getGenes()
  51. {
  52. return this.genes;
  53. }
  54. mutate()
  55. {
  56. this.genes[Math.round(Math.random() * (this.genes.length-1))].setValue(Math.random());
  57. }
  58. createRandomChromosome()
  59. {
  60. let geneAr = [];
  61. for(let i = 0; i < this.genes.length; i++)
  62. {
  63. geneAr.push(this.genes[i].makeRandomGene());
  64. }
  65. return new Chromosome(geneAr);
  66. }
  67. }
  68. const breed = function(father, mother)
  69. {
  70. let son = new Chromosome(father.getGenes());
  71. let daughter = new Chromosome(mother.getGenes());
  72. for(let i = 0;i < son.getGenes().length; i++)
  73. {
  74. let blendCoef = Math.random();
  75. blendGene(son.getGenes()[i], daughter.getGenes()[i], blendCoef);
  76. }
  77. return [son, daughter];
  78. };
  79. function predicateBy(prop)
  80. {
  81. return function(a,b)
  82. {
  83. var result;
  84. if(a[prop] > b[prop])
  85. {
  86. result = 1;
  87. }
  88. else if(a[prop] < b[prop])
  89. {
  90. result = -1;
  91. }
  92. return result;
  93. }
  94. }
  95. const naturalSelection = function(population, keepNumber, fitnessFunction)
  96. {
  97. let fitnessArray = [];
  98. for(let i = 0; i < population.length; i++)
  99. {
  100. const fitness = fitnessFunction(population[i]);
  101. console.log(fitness);
  102. fitnessArray.push({fit:fitness, chrom: population[i]});
  103. }
  104. fitnessArray.sort(predicateBy("fit"));
  105. let survivors = [];
  106. let bestFitness = fitnessArray[0].fit;
  107. let bestChromosome = fitnessArray[0].chrom;
  108. for(let i = 0; i < keepNumber; i++)
  109. {
  110. survivors.push(fitnessArray[i].chrom);
  111. }
  112. return {survivors: survivors, bestFit: bestFitness, bestChrom: bestChromosome};
  113. };
  114. const blendGene = function(gene1, gene2, blendCoef)
  115. {
  116. let value1 = (blendCoef * gene1.getValue()) +
  117. (gene2.getValue() * (1- blendCoef));
  118. let value2 = ((1-blendCoef) * gene1.getValue()) +
  119. (gene2.getValue() * blendCoef);
  120. gene1.setValue(value1);
  121. gene2.setValue(value2);
  122. };
  123. const matePopulation = function(population, desiredPopulationSize)
  124. {
  125. let pairsNeeded = (desiredPopulationSize - population.length)/2;
  126. const originalLength = population.length;
  127. for(let i = 0; i < pairsNeeded; i++)
  128. {
  129. let index1 = Math.round(Math.random() * (originalLength-1));
  130. let index2 = Math.round(Math.random() * (originalLength-1));
  131. if(index1 !== index2)
  132. {
  133. const babies = breed(population[index1], population[index2]);
  134. population.push(babies[0]);
  135. population.push(babies[1]);
  136. }
  137. }
  138. };
  139. const mutatePopulation = function(population, mutatePercentage)
  140. {
  141. if(population.length >= 2)
  142. {
  143. let mutations = mutatePercentage *
  144. population.length *
  145. population[0].getGenes().length;
  146. for(let i = 0; i < mutations; i++)
  147. {
  148. population[i].mutate();
  149. }
  150. }
  151. else
  152. {
  153. console.log("Error, population too small to mutate");
  154. }
  155. };
  156. const newBlood = function(population, immigrationSize)
  157. {
  158. for(let i = 0; i < immigrationSize; i++)
  159. {
  160. let geneticChromosome = population[0];
  161. population.push(geneticChromosome.createRandomChromosome());
  162. }
  163. };
  164. const basicCostFunction = function(chromosome)
  165. {
  166. console.log(chromosome);
  167. console.log((chromosome.getGenes()[0].getRealValue()));
  168. return Math.abs(chromosome.getGenes()[0].getRealValue() - 6) +
  169. Math.abs(chromosome.getGenes()[1].getRealValue() - 2);
  170. };
  171. const createRandomPopulation = function(geneticChromosome, populationSize)
  172. {
  173. let population = [];
  174. for(let i = 0; i < populationSize; i++)
  175. {
  176. population.push(geneticChromosome.createRandomChromosome());
  177. }
  178. return population;
  179. };
  180. const runGeneticOptimization = function(geneticChromosome, costFunction,
  181. populationSize, maxGenerations,
  182. desiredCost, mutationRate, keepNumber,
  183. newBloodNumber)
  184. {
  185. let population = createRandomPopulation(geneticChromosome, populationSize);
  186. let generation = 0;
  187. let bestCost = Number.MAX_VALUE;
  188. let bestChromosome = geneticChromosome;
  189. do
  190. {
  191. matePopulation(population, populationSize);
  192. newBlood(population, newBloodNumber);
  193. mutatePopulation(population, mutationRate);
  194. let generationResult = naturalSelection(population, keepNumber, costFunction);
  195. if(bestCost > generationResult.bestFit)
  196. {
  197. bestChromosome = generationResult.bestChrom;
  198. bestCost = generationResult.bestFit;
  199. }
  200. population = generationResult.survivors;
  201. generation++;
  202. console.log("Generation " + generation + " Best Cost: " + bestCost);
  203. console.log(generationResult);
  204. }while(generation < maxGenerations && bestCost > desiredCost);
  205. return bestChromosome;
  206. };
  207. let genericChromosomeG, costFunctionG,
  208. populationSizeG, maxGenerationsG,
  209. desiredCostG, mutationRateG, keepNumberG,
  210. newBloodNumberG, populationG, generationG,
  211. bestCostG = Number.MAX_VALUE, bestChromosomeG = genericChromosomeG;
  212. const runGeneticOptimizationforGraph = function()
  213. {
  214. let generationResult = naturalSelection(populationG, keepNumberG, costFunctionG);
  215. if(bestCostG > generationResult.bestFit)
  216. {
  217. bestChromosomeG = generationResult.bestChrom;
  218. bestCostG = generationResult.bestFit;
  219. }
  220. populationG = generationResult.survivors;
  221. generationG++;
  222. console.log("Generation " + generationG + " Best Cost: " + bestCostG);
  223. console.log(generationResult);
  224. matePopulation(populationG, populationSizeG);
  225. newBlood(populationG, newBloodNumberG);
  226. mutatePopulation(populationG, mutationRateG);
  227. createGraph();
  228. };
  229. const createGraph = function()
  230. {
  231. var dataPoints = [];
  232. console.log(dataPoints);
  233. var data = new google.visualization.DataTable();
  234. data.addColumn('number', 'Gene 1');
  235. data.addColumn('number', 'Gene 2');
  236. for(let i = 0; i < populationG.length; i++)
  237. {
  238. data.addRow([populationG[i].getGenes()[0].getRealValue(),
  239. populationG[i].getGenes()[1].getRealValue()]);
  240. }
  241. var options = {
  242. title: 'Genetic Evolution On Two Genes Generation: ' + generationG,
  243. hAxis: {title: 'Gene 1', minValue: 0, maxValue: 10},
  244. vAxis: {title: 'Gene 2', minValue: 0, maxValue: 10},
  245. };
  246. var chart = new google.visualization.ScatterChart(document.getElementById('chart_div'));
  247. chart.draw(data, options);
  248. };
  249. let gene1 = new Gene(1,10,10);
  250. let gene2 = new Gene(1,10,0.4);
  251. let geneList = [gene1, gene2];
  252. let exampleOrganism = new Chromosome(geneList);
  253. genericChromosomeG = exampleOrganism;
  254. costFunctionG = basicCostFunction;
  255. populationSizeG = 100;
  256. maxGenerationsG = 30;
  257. desiredCostG = 0.00001;
  258. mutationRateG = 0.3;
  259. keepNumberG = 30;
  260. newBloodNumberG = 10;
  261. generationG = 0;
  262. function resetPopulation()
  263. {
  264. autoRunning = false;
  265. $("#runAutoOptimizer").val("Auto Run");
  266. populationSizeG = $("#populationSize").val();
  267. mutationRateG = $("#mutationRate").val();
  268. keepNumberG = $("#survivalSize").val();
  269. newBloodNumberG = $("#newBlood").val();
  270. generationG = 0;
  271. populationG = createRandomPopulation(genericChromosomeG, populationSizeG);
  272. createGraph();
  273. }
  274. populationG = createRandomPopulation(genericChromosomeG, populationSizeG);
  275. window.onload = function () {
  276. google.charts.load('current', {'packages':['corechart']}).then(function()
  277. {
  278. createGraph();
  279. })
  280. };
  281. let autoRunning = false;
  282. function runAutoOptimizer()
  283. {
  284. if(autoRunning === true)
  285. {
  286. runGeneticOptimizationforGraph();
  287. setTimeout(runAutoOptimizer, 1000);
  288. }
  289. }
  290. function startStopAutoRun()
  291. {
  292. autoRunning = !autoRunning;
  293. if(autoRunning)
  294. {
  295. $("#runAutoOptimizer").val("Stop Auto Run");
  296. }
  297. else
  298. {
  299. $("#runAutoOptimizer").val("Resume Auto Run");
  300. }
  301. runAutoOptimizer();
  302. }
  303. //runGeneticOptimization(exampleOrganism, basicCostFunction, 100, 50, 0.01, 0.3, 20, 10);
  304. </script>
  305. </head>
  306. <body>
  307. <div id="chart_div" style="width: 900px; height: 500px;"></div>
  308. <input class='btn btn-primary' id="runOptimizer" onclick='runGeneticOptimizationforGraph()' type="button" value="Next Generation">
  309. <input class='btn btn-primary' id="runAutoOptimizer" onclick='startStopAutoRun()' type="button" value="Auto Run">
  310. <div class="card">
  311. <div class="card-header">
  312. <h2>Population Variables</h2>
  313. </div>
  314. <div class="card-body">
  315. <div class="row p-2">
  316. <div class="col">
  317. <label for="populationSize">Population Size</label>
  318. <input type="text" class="form-control" id="populationSize" placeholder="Population Size" required>
  319. </div>
  320. <div class="col">
  321. <label for="populationSize">Survival Size</label>
  322. <input type="text" class="form-control" id="survivalSize" placeholder="Survival Size" required>
  323. </div>
  324. </div>
  325. <div class="row p-2">
  326. <div class="col">
  327. <label for="populationSize">Mutation Rate</label>
  328. <input type="text" class="form-control" id="mutationRate" placeholder="Mutation Rate" required>
  329. </div>
  330. <div class="col">
  331. <label for="populationSize">New Organisms Per Generation</label>
  332. <input type="text" class="form-control" id="newBlood" placeholder="New Organisms" required>
  333. </div>
  334. </div>
  335. <br>
  336. <input class='btn btn-primary' id="reset" onclick='resetPopulation()' type="button" value="Reset Population">
  337. </div>
  338. </div>
  339. </body>
  340. </html>