我正在尝试使用 Node 实现遗传算法,我查看了此处发布的其他问题,它似乎不相关。当我尝试调用determine_fitness
时我的方法populant
类我收到此错误:
Creating new population
Starting iteration 1
/home/aaron/Documents/workspace/playground/screeps_ga/ga.js:116
p.determine_fitness();
^
TypeError: p.determine_fitness is not a function
at population.fitness (/home/aaron/Documents/workspace/playground/screeps_ga/ga.js:116:15)
at population.train (/home/aaron/Documents/workspace/playground/screeps_ga/ga.js:130:18)
我对 javascript 很陌生,所以我不知道除了跟踪堆栈跟踪之外还能做什么,但它没有给我任何答案。
但是,当我查看我的类(class)时:
class populant {
constructor(genes) {
this.genes = genes;
this.score = -1;
}
mutate() {
if(this.genes.length == 0)
this.genes += random_char();
else {
let r = getRndInteger(0, 3);
let i = getRndInteger(0, this.genes.length);
switch(r) {
case 0:
// Remove a character
let before = this.genes.substring(0, i);
let after = this.genes.substring(i + 1);
this.genes = before + after;
break;
case 1:
// Replace a character
let c = random_char();
let before = this.genes.substring(0, i);
let after = this.genes.substring(i + 1);
this.genes = before + c + after;
break;
case 2:
// Add a character
let c = random_char();
let before = this.genes.substring(0, i);
let after = this.genes.substring(i);
this.genes = before + c + after;
break;
}
}
}
mate(other, mutate) {
let i = 0;
let temp = '';
for(i = 0; i < this.genes.length; i++)
{
if(getRndInteger(0, 2) == 0)
temp += other.genes.substring(i, i + 1);
else
temp += this.genes.substring(i, i + 1);
}
this.genes = temp;
if(mutate)
this.mutate();
}
determine_fitness() {
return null;
}
}
正如你所看到的,它在这里定义得非常清楚,而且它与我的任何其他属性名称都不冲突,所以我真的很困惑。
class population {
constructor(count, mutation_rate, populant_type) {
this.count = count;
this.mutation_rate = mutation_rate;
this.populant = populant_type;
this.pop = [];
}
initialize(parent_pool) {
this.pop = [];
if(parent_pool.length == 0)
for(let i = 0; i < this.count; i++)
this.pop.push(new this.populant(random_gene()));
else if(parent_pool.length == 1)
for(let i = 0; i < this.count; i++)
this.pop.push(new this.populant(parent_pool[0].genes));
else
{
for(let i = 0; i < this.count; i++)
{
let pai = getRndInteger(0, parent_pool.length);
let pbi = getRndInteger(0, parent_pool.length);
let temp_pa = new this.populant(parent_pool[pai].genes);
let should_mute = Math.random() < this.mutation_rate;
temp_pa.mate(parent_pool[pbi], should_mute);
this.pop.push(temp_pa);
}
}
}
fitness() {
for(let p in this.pop)
p.determine_fitness();
}
select_parents(count) {
this.pop.sort(function(a, b){ return a.score - b.score; });
return this.pop.slice(0, count);
}
train(iterations, crossover_size, initial_parents) {
let selected_parents = initial_parents;
for(let i = 0; i < iterations; i++)
{
this.initialize(selected_parents);
this.fitness();
selected_parents = this.select_parents(crossover_size);
}
return selected_parents;
}
}
我现在组织类(class)的方式是 populant
类和 population
类在自己的文件中 ga.js
然后我将它们导入到我的 test.js
中文件。因为determine_fitness()
方法populant
默认情况下未定义,我创建了一个子类并覆盖它,如下所示:
let ga = require('./ga');
class StringPop extends ga.populant {
constructor(genes) {
super(genes);
}
determine_fitness() {
let sum = 0;
for(let i = 0; i < this.genes.length; i++)
sum += this.genes.charCodeAt(i);
this.score = sum;
return sum;
}
}
然后我正在测试如图所示的结构:
pop = new ga.population(20, 0.25, StringPop);
let iteration = 1;
let parents = []
while(true)
{
console.log('\nStarting iteration ' + iteration.toString());
parents = pop.train(1, 5, parents);
console.log('Population after iteration');
print_pops(pop);
}
哪里print_pops()
只是打印出 genes
每个居民都拥有自己的属性(property)。
最佳答案
您可以尝试在尝试调用 certain_fitness 之前通过记录 p 的类型来检查 p 的类型是否是您所期望的:
fitness() {
for(let p in this.pop) {
console.log(typeof p);
p.determine_fitness();
}
}
另外,由于 pop 是一个列表,我认为您将一个对象推送到它,您可以使用 for ... of 语法:
fitness() {
for (p of this.pop) {
p.determine_fitness();
}
}
Given that for...in is built for iterating object properties, not recommended for use with arrays, and options like Array.prototype.forEach() and for...of exist, what might be the use of for...in at all? [Emphasis mine]
关于Javascript 说我的类方法不是函数,尽管它显然是,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58669793/