diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..27e1436 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ + + + + +git.sh \ No newline at end of file diff --git a/evolve.js b/evolve.js index ff5e411..2aed109 100644 --- a/evolve.js +++ b/evolve.js @@ -2,7 +2,7 @@ Evolutionary Algorithm modules, and supporting packages -2017 Christopher Polito v1.0 +2018 Christopher Polito v5.0.1 Implemented in a Frontend Angular web application, the Events and React Modules come in handy with respect to the web application but are not related to the evolutionary algorithm, including them simply reduces dependency requirements @@ -94,6 +94,7 @@ var obj = {}; self.fitness = 0; self.generation = params.gen; self.index = params.index; + self.currentGen = params.curentGen; self.parents = []; var input = params.input; var stepdataobj = { @@ -351,31 +352,13 @@ var obj = {}; } - self.setActive = function () { + self.setActive = function ($active) { - active = true; + active = $active; } - self.reproduce = function (mates) { - var offspring = []; - - if (crossoverMethod == methodTypes.multiParent) { - - mates.push(self); - - offspring = multiParentCrossover(mates); - - } - else if (crossoverMethod == methodTypes.multiOffspring) { - - offspring = multiOffspringCrossover(mates); - } - - return offspring; - } - - self.reproduceAsync = function (parents) { + self.reproduce = function (parents) { parents.push(self); @@ -553,7 +536,7 @@ var obj = {}; self.run = function (complete) { - // console.log("run org", self.index); + // console.log("run org", self.index, active); if (active) { @@ -579,9 +562,9 @@ var obj = {}; self.hardStop = function () { - console.log("individual hard stop", self.index); + // console.log("individual hard stop", self.index); - active = false; + self.setActive(false); self.runs = []; program.hardStop(); } @@ -688,7 +671,7 @@ var obj = {}; i = 1; while (i <= self.total) { - self.pop[i-1] = new individual({gen:self.index, index:i, input:input}); + self.pop.push(new individual({gen:self.index, index:i, input:input})); i++; } } @@ -714,51 +697,8 @@ var obj = {}; initializePop(); - var runPop = function (complete) { - - indi = 0; - var running = true; - active = true; - - // console.log("run population"); - - runtimer = setInterval(function () { - - - if (active) { - - if (running) { - - running = false; - - self.pop[indi].setActive(); - self.pop[indi].run(function () { - - indi++; - - if (indi < self.total) { - running = true; - } - else { - clearInterval(runtimer); - runtimer = {}; - runtimer = null; - - complete(); - } - }); - - } - } - - }, 10); - - - } - - - var runPopAsync = function (complete) { + var runPop = function (complete) { var runIndi = function (i) { @@ -767,15 +707,18 @@ var obj = {}; return new Promise(function (resolve, reject) { - // console.log("run indi", i); - self.pop[i].run() + // console.log("run indi", i, self.pop.length); + self.pop[i].run(function () { + + // console.log("resolve", i); + resolve(i); + }) - return resolve(i); }) } - active = true; + self.setActive(true); var i = 0; @@ -783,6 +726,8 @@ var obj = {}; while (i < self.total) { + // console.log("indi", i, active); + if (active) { runIndi(i) @@ -790,8 +735,12 @@ var obj = {}; finished.push(i); + // console.log("completed indi", finished.length, self.pop.length); + if (finished.length == self.pop.length) { + // console.log("run complete for generation", self.index); + complete(); } }) @@ -848,7 +797,8 @@ var obj = {}; worst:self.worst } } - + + var select = function (number, _pool) { @@ -871,67 +821,22 @@ var obj = {}; var index; - var getIndexAsync = function () { - - return new Promise(function (resolve, reject) { + do { + do { + index = Math.floor(Math.random()*$pool.length); - match = indexes.find(function(p) { return p == index; }); - console.log("match", index, indexes, match, typeof match == "undefined", match == undefined, match === undefined); - - if (match === undefined) { - - return resolve(index); - } - - }) - } - - - if (selectAsync) { - - while (indexes.length <= number) { - - getIndexAsync() - .then(function (index) { - - indexes.push(index); - - }) - .catch(function (err) { - - console.log("Error in promise:", err); - }) - - } - - } - else { - - do { + } while (match >= 0); - do { - - index = Math.floor(Math.random()*$pool.length); + indexes.push(index); - match = indexes.find(function(p) { - - return p == index; - }); - - } while (match >= 0); - - indexes.push(index); - - } while (indexes.length < number); - - } + } while (indexes.length < number); var parents = indexes.map(function (value, index) { @@ -949,103 +854,122 @@ var obj = {}; return parents; } + - var reproduce = function (_parents, _pool) { + // var select = function (number, _pool) { - var parents = []; - var mates = []; - var children = []; - var childrenPromise; - var i = 0; + // // var normalStand = _pool*self.total/100 - // console.log("reproduce", _parents, standard); + // var $pool = self.pop.filter(function (value, index) { - if (reproductionType == reproductionTypes.async) { + // return index < Math.floor(_pool*self.total); + // }) - if (active) { + // if (!$pool) { - while (i < self.total) { + // return; + // } - parents = select(_parents, _pool); + // var indexes = []; + // var match; + // var index; - if (parents.length == 0) { - break; - } + // var getIndexAsync = function ($indexes) { - // console.log("parents", num_parents, standard, parents.length, parents); + // return new Promise(function (resolve, reject) { - male = parents[0]; - mates = parents.slice(1); + // index = Math.floor(Math.random()*$pool.length); - // console.log("male", male); - childrenPromise = male.reproduceAsync(mates) - .then(function (offspring) { + // match = $indexes.find(function(p) { + // return p == index; + // }); - offspring.map(function (value, index) { + // // console.log("match", index, $indexes, match, typeof match === "undefined"); - value.index = children.length + index + 1; + // if (typeof match === "undefined") { - }); + // return resolve(index); + // } - children = children.concat(offspring); + // }) + // } - // console.log("children", children.length); - return children.length; - }) - .then(function (j) { + // while (indexes.length <= number) { + + // getIndexAsync(indexes) + // .then(function (index) { - if (j == self.total) { + // console.log("index", index); - return children - } - }) - .catch(function (err) { + // indexes.push(index); - console.log("Error in promise:", err); - }) + // console.log("index is", index, indexes); - // console.log("after then"); + // }) + // .catch(function (err) { - i++; + // console.log("Error in promise:", err); + // }) - } + // } + - return childrenPromise; + // var parents = indexes.map(function (value, index) { + // return $pool[value]; + // }) - } + // parents.sort(function (a, b) { + // return b.fitness - a.fitness; + // }) - } - else if (reproductionType == reproductionTypes.sync) { + // // console.log("select", self.pop.length, pool.length, number, parents.length); + // return parents; - if (active) { + // } - do { + var reproduce = function (_parents, _pool) { + var parents = []; + var mates = []; + var children = []; + var childrenPromise; - parents = select(_parents, _pool); + var i = 0; - if (parents.length == 0) { + // console.log("reproduce", _parents, _pool, active); + + if (active) { + + while (i < self.total) { - break; - } - // console.log("parents", num_parents, standard, parents.length); + parents = select(_parents, _pool); - male = parents[0]; - mates = parents.slice(1); + if (parents.length == 0) { - offspring = male.reproduce(mates); + break; + } + + // console.log("parents", num_parents, _pool, parents.length, parents); + + male = parents[0]; + mates = parents.slice(1); + + // console.log("male", male); + + childrenPromise = male.reproduce(mates) + .then(function (offspring) { offspring.map(function (value, index) { @@ -1056,17 +980,32 @@ var obj = {}; children = children.concat(offspring); - } while (children.length < self.total) + // console.log("children", children.length); + return children.length; - if (children.length == 0) { + }) + .then(function (j) { - return; - } + if (j == self.total) { - return children; + return children + } + }) + .catch(function (err) { + + console.log("Error in promise:", err); + }) + + // console.log("after then"); + + i++; + + } + + + return childrenPromise; - } } @@ -1081,78 +1020,44 @@ var obj = {}; getCrossoverParams(input); - var runPopComplete = function () { - // console.log("run pop complete"); + runPop(function () { var ext = rank(); - console.log("best", ext.best.fitness); - - var onComplete = function ($children) { - if ($children.length == 0) { - - complete({ - previous:{ - best:ext.best, - worst:ext.worst - }, - next:null - }) - } + reproduce(num_parents, pool) + .then(function ($children) { complete({ - previous:{ + rank:{ best:ext.best, worst:ext.worst }, - next:new generation({index:self.index + 1, input:input, pop:$children}) + previous:self, + next:($children.length == 0 ? self : (new generation({index:self.index + 1, input:input, pop:$children}))) }); + + }) + .catch(function (err) { - } - - - if (reproductionType == reproductionTypes.async) { - - reproduce(num_parents, pool) - .then(function ($children) { - - onComplete($children); - - }) - .catch(function (err) { - - console.log("Error in promise:", err); - }) - - } - else if (reproductionType == reproductionTypes.sync) { - - var $children = reproduce(num_parents, pool); - - onComplete($children); - - } - - - } - - + console.log("Error in promise:", err); + }) - if (type == types.sync) { - runPop(runPopComplete); + }); - } - else if (type == types.async) { + } - runPopAsync(runPopComplete); + this.setActive = function ($active) { - } + active = $active; + self.pop.forEach((p) => { + p.setActive($active); + }) } this.getstepdata = function (stepdata) { @@ -1166,13 +1071,15 @@ var obj = {}; this.hardStop = function () { - console.log("generation hard stop", indi); + // console.log("generation hard stop", indi); - active = false; + self.setActive(false); clearInterval(runtimer); runtimer = null; - if (self.pop[indi]) self.pop[indi].hardStop(); - //initializePop(); + self.pop.forEach((p) => { + + p.hardStop(); + }) } } @@ -1183,13 +1090,13 @@ var obj = {}; var self = this; - var era = []; + // var era = []; var now = 1; var active = true; var stepdataobj = { name:"", - gen:now + 1, + gen:now, org:1, run:1 } @@ -1201,7 +1108,12 @@ var obj = {}; pop:[] } + var rank; var previous; + var current; + + var check = 0; + var called = 0; self.input = {}; @@ -1210,6 +1122,13 @@ var obj = {}; return $now - 1; } + + var setActive = function ($active) { + + active = $active; + if (current.setActive) current.setActive($active); + if (previous.setActive) previous.setActive($active); + } var step = function () { @@ -1220,20 +1139,22 @@ var obj = {}; stepdataobj.gen = now; - era[index(now)].turnover(self.input, function (x) { + current.turnover(self.input, function (x) { now++; + rank = x.rank; previous = x.previous; - // console.log("best", previous.best.fitness); + console.log("best", rank.best.fitness); if (x.next) { - era[index(now)] = x.next; + // era[index(now)] = x.next; + current = x.next; // console.log("running evolve", self.input); - if (now <= self.input.gens && !previous.best.success) { + if (now <= self.input.gens && !rank.best.success) { setTimeout(function () { step(); }, self.input.programInput.evdelay); @@ -1256,14 +1177,16 @@ var obj = {}; self.getstepdata = function () { - stepdataobj = era[index(now)].getstepdata(stepdataobj); + // stepdataobj = era[index(now)].getstepdata(stepdataobj); + + stepdataobj = (typeof currrent !== "undefined") ? current.getstepdata(stepdataobj) : stepdataobj; return stepdataobj; } self.running = function () { - return active && (now < self.input.gens); + return active && (now <= self.input.gens); } self.getBest = function () { @@ -1271,14 +1194,14 @@ var obj = {}; return { index:self.index, best:{ - dna:previous.best.dna, - runs:previous.best.runs, - fitness:previous.best.fitness + dna:rank.best.dna, + runs:rank.best.runs, + fitness:rank.best.fitness }, worst:{ - dna:previous.best.dna, - runs:previous.worst.runs, - fitness:previous.worst.fitness + dna:rank.worst.dna, + runs:rank.worst.runs, + fitness:rank.worst.fitness } }; } @@ -1290,24 +1213,19 @@ var obj = {}; self.initialize = function (_input) { + console.log(" "); console.log("initialize evolve"); self.set(_input); - - era = null; - era = []; now = 1; - active = true; - - - era[index(now)] = new generation({index:now, input:self.input}); - - return era[index(now)].length == self.input.pop; - + current = new generation({index:now, input:self.input}); + setActive(true); + return now == self.input.pop; } self.run = function (_input) { + console.log(" "); console.log("restart evolve"); if (_input.goal != self.input.goal || _input.pop != self.input.pop) { @@ -1318,7 +1236,7 @@ var obj = {}; console.log("inputs are equal", _input.pop, self.input.pop, "run"); - active = true; + setActive(true); this.set(_input); step(); return true; @@ -1329,17 +1247,19 @@ var obj = {}; self.hardStop = function (_input) { - console.log("evolve hard stop", _input, self.input); + console.log("evolve hard stop", self.input.gens); self.set(_input); - active = false; - if (era[index(now)]) era[index(now)].hardStop(); + setActive(false); + + current.hardStop(); + previous.hardStop(); if (self.input && self.input.setEvdata) { self.input.setEvdata({ index:now, - best:previous.best, - worst:previous.worst + best:rank.best, + worst:rank.worst }) } diff --git a/package.json b/package.json index 2be6c11..e55332c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mc-evolve", - "version": "5.0.0", + "version": "5.0.1", "description": "An Evolutionary Algorithm in JavaScript that takes in a generic module that represents a problem to be optimized", "main": "evolve.js", "scripts": {