如何 sequentially/separately 对对象数组应用相同的函数?
How to sequentially/separately apply the same function on array of objects?
在单个项目上成功应用 this 遗传算法后,我想优化对象数组的值。
为此,我尝试按以下方式使用 forEach 循环:
function getOptimalValues(req, res){
mdl.getItems({limit: 5}, function(err, items){//this function retrieves 5 items from database
items.forEach(function (elem) {
var queryObj = {
properties: elem,
targetEnergy: req.targetEnergy
};
genetic.getOptimalQuantities(queryObj, function (err, optimalValues) {
geneticResults.push(optimalValues);
if (geneticResults.length == items.length) {
res(null, geneticResults);
}
});
});
});
}
genetic.getOptimalQuantities定义如下:
function getOptimalQuantities(req, res){
var properties = req.properties;
var targetEnergy = req.targetEnergy;
var targetValues = {energy: targetEnergy, properties: properties};
var Task = require('genetic').Task;
var options = { getRandomSolution : getCandidateQuantities // previously described to produce random solution
, popSize : 100 // population size
, stopCriteria : stopCriteria // previously described to act as stopping criteria for entire process (set to 100 generations)
, fitness : getFitnessValue // previously described to measure how good your solution is
, minimize : false // whether you want to minimize fitness function. default is `false`, so you can omit it
, mutateProbability : 0.1 // mutation chance per single child generation
, mutate : mutate // previously described to implement mutation
, crossoverProbability : 0.3 // crossover chance per single child generation
, crossover : crossoverFunction // previously described to produce child solution by combining two parents
};
var t = new Task(options);
t.targetValues = targetValues;
//t.on('mutate', function () { console.log('MUTATION!') });
t.on('statistics', function (statistics) {
console.log('statistics',statistics.maxScore);
});
t.on('iteration start', function (generation) {
console.log('iteration start - ',generation)
});
t.run(function (stats) {
var dataObj = {quantities: stats.max, items: t.bestCombination}
res(null, dataObj);
});
}
虽然 运行 这个程序,我得到以下输出:
iteration start - 1
statistics 0.008126878121533886
iteration start - 1
iteration start - 1
statistics 0.007777620410591467
statistics 0.007777620410591467
iteration start - 1
iteration start - 1
iteration start - 1
statistics 0.008133385505205764
statistics 0.008133385505205764
statistics 0.008133385505205764
iteration start - 1
iteration start - 1
iteration start - 1
iteration start - 1
statistics 0.0093968469349952
statistics 0.0093968469349952
statistics 0.0093968469349952
statistics 0.0093968469349952
iteration start - 1
iteration start - 1
iteration start - 1
iteration start - 1
iteration start - 1
statistics 0.008431076204956763
statistics 0.008431076204956763
statistics 0.008431076204956763
statistics 0.008431076204956763
statistics 0.008431076204956763
iteration start - 2
iteration start - 2
iteration start - 2
iteration start - 2
iteration start - 2
...
对于传递给函数 getOptimalQuantities 的五个项目中的每一个,应该有 100 次迭代,并且每次迭代中每个项目的适应度值(输出为统计数据)应该是不同的(所有元素相等的机会是接近于零)。通过观察输出,因此我猜想遗传算法对于这个例子中传递的 5 个项目中的每一个都没有 运行。
有谁知道如何确保函数(在本例中为遗传算法)不会弄乱来自多个输入的数据?直觉上,更容易想象每个调用分别按顺序执行(这就是为什么要求按顺序执行的原因),但一般来说,任何建议的方法,无论是顺序的还是并行的,都会非常有帮助。
感谢您的帮助。
妮可
我认为这是您使用的库中的错误。它的 Task
class inherits from node's EventEmitter
class,其中包含一个名为 init
的方法,用于设置每个对象的侦听器哈希。但是 Task
用它自己的 init
方法覆盖了这个方法:
Task.prototype.init = function (callback) {
var self = this
self.emit('init start')
async.until(function () { return (self.population.length == self.popSize)}
, function (callback) { self.getRandomSolution(function (solution) { self.population.push(solution); callback() }) }
, function (err) {
if (err!=null) { self.emit('error', err) }
else {
self.emit('init end', self.population)
callback()
}
}
)
}
这意味着 EventEmitter.init()
不会被调用,这意味着 Task
的每个实例都没有自己的侦听器数据结构,而是使用相同的全局数据结构。当你只有一个 Task
的实例时,这很好用,但是一旦你同时处理了多个实例,那么它们中的每一个都会被添加到同一个事件监听器哈希中,并且只要它们中的任何一个发出事件,它们都会得到通知.
在单个项目上成功应用 this 遗传算法后,我想优化对象数组的值。
为此,我尝试按以下方式使用 forEach 循环:
function getOptimalValues(req, res){
mdl.getItems({limit: 5}, function(err, items){//this function retrieves 5 items from database
items.forEach(function (elem) {
var queryObj = {
properties: elem,
targetEnergy: req.targetEnergy
};
genetic.getOptimalQuantities(queryObj, function (err, optimalValues) {
geneticResults.push(optimalValues);
if (geneticResults.length == items.length) {
res(null, geneticResults);
}
});
});
});
}
genetic.getOptimalQuantities定义如下:
function getOptimalQuantities(req, res){
var properties = req.properties;
var targetEnergy = req.targetEnergy;
var targetValues = {energy: targetEnergy, properties: properties};
var Task = require('genetic').Task;
var options = { getRandomSolution : getCandidateQuantities // previously described to produce random solution
, popSize : 100 // population size
, stopCriteria : stopCriteria // previously described to act as stopping criteria for entire process (set to 100 generations)
, fitness : getFitnessValue // previously described to measure how good your solution is
, minimize : false // whether you want to minimize fitness function. default is `false`, so you can omit it
, mutateProbability : 0.1 // mutation chance per single child generation
, mutate : mutate // previously described to implement mutation
, crossoverProbability : 0.3 // crossover chance per single child generation
, crossover : crossoverFunction // previously described to produce child solution by combining two parents
};
var t = new Task(options);
t.targetValues = targetValues;
//t.on('mutate', function () { console.log('MUTATION!') });
t.on('statistics', function (statistics) {
console.log('statistics',statistics.maxScore);
});
t.on('iteration start', function (generation) {
console.log('iteration start - ',generation)
});
t.run(function (stats) {
var dataObj = {quantities: stats.max, items: t.bestCombination}
res(null, dataObj);
});
}
虽然 运行 这个程序,我得到以下输出:
iteration start - 1
statistics 0.008126878121533886
iteration start - 1
iteration start - 1
statistics 0.007777620410591467
statistics 0.007777620410591467
iteration start - 1
iteration start - 1
iteration start - 1
statistics 0.008133385505205764
statistics 0.008133385505205764
statistics 0.008133385505205764
iteration start - 1
iteration start - 1
iteration start - 1
iteration start - 1
statistics 0.0093968469349952
statistics 0.0093968469349952
statistics 0.0093968469349952
statistics 0.0093968469349952
iteration start - 1
iteration start - 1
iteration start - 1
iteration start - 1
iteration start - 1
statistics 0.008431076204956763
statistics 0.008431076204956763
statistics 0.008431076204956763
statistics 0.008431076204956763
statistics 0.008431076204956763
iteration start - 2
iteration start - 2
iteration start - 2
iteration start - 2
iteration start - 2
...
对于传递给函数 getOptimalQuantities 的五个项目中的每一个,应该有 100 次迭代,并且每次迭代中每个项目的适应度值(输出为统计数据)应该是不同的(所有元素相等的机会是接近于零)。通过观察输出,因此我猜想遗传算法对于这个例子中传递的 5 个项目中的每一个都没有 运行。
有谁知道如何确保函数(在本例中为遗传算法)不会弄乱来自多个输入的数据?直觉上,更容易想象每个调用分别按顺序执行(这就是为什么要求按顺序执行的原因),但一般来说,任何建议的方法,无论是顺序的还是并行的,都会非常有帮助。
感谢您的帮助。
妮可
我认为这是您使用的库中的错误。它的 Task
class inherits from node's EventEmitter
class,其中包含一个名为 init
的方法,用于设置每个对象的侦听器哈希。但是 Task
用它自己的 init
方法覆盖了这个方法:
Task.prototype.init = function (callback) {
var self = this
self.emit('init start')
async.until(function () { return (self.population.length == self.popSize)}
, function (callback) { self.getRandomSolution(function (solution) { self.population.push(solution); callback() }) }
, function (err) {
if (err!=null) { self.emit('error', err) }
else {
self.emit('init end', self.population)
callback()
}
}
)
}
这意味着 EventEmitter.init()
不会被调用,这意味着 Task
的每个实例都没有自己的侦听器数据结构,而是使用相同的全局数据结构。当你只有一个 Task
的实例时,这很好用,但是一旦你同时处理了多个实例,那么它们中的每一个都会被添加到同一个事件监听器哈希中,并且只要它们中的任何一个发出事件,它们都会得到通知.