2017-06-22 7 views
2

私は(ほぼ)指定された文字列を見つけるための遺伝的アルゴリズムを作成できましたが、何らかの理由で半ば頻繁にエラーが発生します。単語検索遺伝アルゴリズムで時折間違い

Cannot read property 'dna' of undefined at Population.populate 

私は、この問題の原因が何度か分かりません。

<!DOCTYPE html> 
 
<html> 
 
<head> 
 
\t <title>Word Search</title> 
 
\t <link href='https://fonts.googleapis.com/css?family=Ubuntu' rel='stylesheet'> 
 
</head> 
 
<body style ='font-family: Ubuntu, sans-serif'> 
 
\t Target: <input type='text' value='Hello World!' id='target'> <br> 
 
\t Population Size: <input type='number' id='size' min='0' max='100' step='1' value='10'><br> 
 
\t Mutation Rate: <input type='number' id='rate' min='0' max='100' step='1' value='10'>%<br> 
 
\t <input type='submit' id='submit' onclick='evolution()'> 
 
\t <div style='border-width: 2px; border-style: dashed; width: 250px'> 
 
\t \t <div style='text-align: center;' id='value'> 
 
\t \t \t <p id='generation';>Generation | 0</p> 
 
\t \t \t <div id='pop'> 
 
\t \t \t </div> 
 
\t \t </div> 
 
\t </div> 
 

 
<script type="text/javascript"> 
 

 

 

 
window.onload = function() { 
 
\t evolution(); 
 
} 
 

 
function evolution() { 
 

 
\t var population = new Population(
 
\t \t document.getElementById('target').value, 
 
\t \t document.getElementById('rate').value/100, 
 
\t \t document.getElementById('size').value); 
 

 
\t var running = setInterval(function() { 
 
\t \t document.getElementById('submit').disabled = true; 
 
\t \t population.natSelection(); 
 
\t \t population.populate(); 
 
\t \t population.evaluate(); 
 
\t \t population.display(); 
 
\t \t if(population.completed) { 
 
\t \t \t clearInterval(running); 
 
\t \t \t document.getElementById('submit').disabled = false; 
 
\t \t } 
 
\t }, 50); 
 
} 
 

 
function Population(target, mutationRate, size) { 
 
\t this.target = target; 
 
\t this.mutationRate = mutationRate; 
 
\t this.size = size; 
 
\t this.members = []; 
 
\t this.genePool = []; 
 
\t this.completed = false; 
 
\t this.generation = 0; 
 

 
\t for(var i = 0; i < this.size; i++) 
 
\t \t this.members.push(new Genome(this.target, this.mutationRate)); 
 

 
\t this.natSelection = function() { 
 
\t \t for(var i = 0; i < this.members.length; i++) 
 
\t \t \t this.members[i].calcFitness(); 
 
\t \t 
 
\t \t this.genePool = []; 
 

 
\t \t for(var i = 0; i < this.members.length; i++) 
 
\t \t \t for(var j = 0; j < this.members[i].fitness*10; j++) 
 
\t \t \t \t this.genePool.push(this.members[i]); 
 
\t } 
 

 
\t this.populate = function() { 
 
\t \t this.generation++; 
 
\t \t this.members = []; 
 
\t \t for(var i = 0; i < this.size; i++) { 
 
\t \t \t var a = this.genePool[Math.floor(Math.random()*this.genePool.length)].dna; 
 
\t \t \t var b = this.genePool[Math.floor(Math.random()*this.genePool.length)].dna; 
 
\t \t \t this.members.push(new Genome(this.target, this.mutationRate, a, b)); 
 
\t \t } 
 
\t } 
 

 
\t this.evaluate = function() { 
 
\t \t for(var i = 0; i < this.members.length; i++) { 
 
\t \t \t if(this.members[i].dna === this.target) 
 
\t \t \t \t this.completed = true; 
 
\t \t } 
 
\t } 
 

 
\t this.calcMaxFitness = function() { 
 
\t \t var fittest = this.memebers[0].fitness; 
 
\t \t for(var i = 1; i < this.members.length; i++) 
 
\t \t \t if(this.memebers[i].fitness > fittest) 
 
\t \t \t \t fittest = this.memebers[i].fitness; 
 
\t \t return fittest; 
 
\t } 
 

 
\t this.display = function() { 
 
\t \t document.getElementById('generation').innerHTML = 'Generation | '+this.generation; 
 
\t \t var div = document.getElementById('pop'); 
 
\t \t div.innerHTML = ''; 
 
\t \t for(var i = 0; i < this.members.length; i++) { 
 
\t \t \t div.innerHTML += this.members[i].dna+'<br>' 
 
\t \t } 
 
\t } 
 
} 
 

 
function Genome(target, mutationRate, parentA, parentB) { 
 
\t this.dna = ''; 
 
\t this.fitness = 0; 
 
\t this.target = target; 
 
\t this.mutationRate = mutationRate; 
 

 
\t this.mutate = function() { 
 
\t \t for(var i = 0; i < this.target.length; i++) { 
 
\t \t \t if(this.dna.charCodeAt(i) != this.target.charCodeAt(i)) 
 
\t \t \t \t if(Math.random() > this.mutationRate) 
 
\t \t \t \t \t this.dna = this.dna.replaceAt(i, String.fromCharCode(Math.floor(Math.random()*94+32))); 
 
\t \t } 
 
\t } 
 

 
\t if(!parentA && !parentB) { 
 
\t \t for(var i = 0; i < this.target.length; i++) 
 
\t \t \t this.dna += String.fromCharCode(Math.floor(Math.random()*94+32)); 
 
\t } else { 
 
\t \t var mid = Math.floor(Math.random()*this.target.length); 
 
\t \t this.dna = parentA.substr(0, mid) + parentB.substr(mid, parentB.length); 
 
\t \t this.mutate(); 
 
\t } 
 
\t 
 
\t this.calcFitness = function() { 
 
\t \t this.fitness = 0; 
 
\t \t for(var i = 0; i < this.target.length; i++) { 
 
\t \t \t if(this.dna.charCodeAt(i) === this.target.charCodeAt(i)) 
 
\t \t \t \t this.fitness++; 
 
\t \t } 
 
\t } 
 

 
} 
 

 
Number.prototype.map = function (in_min, in_max, out_min, out_max) { 
 
    return (this - in_min) * (out_max - out_min)/(in_max - in_min) + out_min; 
 
} 
 

 
String.prototype.replaceAt=function(index, replacement) { 
 
    return this.substr(0, index) + replacement+ this.substr(index + replacement.length); 
 
} 
 

 
</script> 
 

 
</body> 
 
</html>

答えて

3

すべてのメンバーが、その後natSelection関数内のループがゼロなので、何のループと何がgenePoolに追加されていないj < this.members[i].fitness*10までループされ、ゼロの適合性を持っている場合、このエラーが発生します。

これが発生すると、明らかにthis.genePool[Math.floor(Math.random()*this.genePool.length)]は未定義となり、プロパティdnaにアクセスしようとするとエラーが発生します。

これを解決するには、いくつかの検証を追加する必要があります。そうすれば、すべてのメンバーが適性がゼロのときに何かします。あるいは、natSelection関数の最後に、genePool.lengthをチェックし、それでもゼロの場合は、少なくとも1つの項目を追加します。

+0

もちろん!今はとても分かりました。私はそれについても考えていませんでした。助けてくれてありがとう。 私が実装したソリューションは、各ゲノムの適合度を0からthis.target.length、this.target.lengthの0.1にマッピングします。 –

1

まず、我々は完全に誤りを理解していることを確認しましょう。

populateメソッドで、プロパティdnaが未定義です。

は、別の方法を言った:

// Your populate method 
this.populate = function() { 
    this.generation++; 
    this.members = []; 
    for(var i = 0; i < this.size; i++) { 
     var a = this.genePool[Math.floor(Math.random()*this.genePool.length)].dna; 
     var b = this.genePool[Math.floor(Math.random()*this.genePool.length)].dna; 
     this.members.push(new Genome(this.target, this.mutationRate, a, b)); 
    } 
} 

JavasScriptはundefined

として

this.genePool[Math.floor(Math.random()*this.genePool.length)] 

を見て、その後、あなたはundefineddnaプロパティを読み取るためにはJavaScriptを求めています。

undefined.dna

それでは、我々は、エラーをデバッグすることができます方法を見つけ出すてみましょう。

個人的に、私は次のようにログになります。

// Your populate method 
this.populate = function() { 
    this.generation++; 
    this.members = []; 

    console.log('SIZE', this.size); 

    for(var i = 0; i < this.size; i++) { 

     console.log('I', i); 
     console.log('this.genePool', this.genePool); 
     console.log('this.genePool.length', this.genePool.length); 

     var a = this.genePool[Math.floor(Math.random()*this.genePool.length)].dna; 
     var b = this.genePool[Math.floor(Math.random()*this.genePool.length)].dna; 
     this.members.push(new Genome(this.target, this.mutationRate, a, b)); 
    } 
} 

次は、ログを分析してみましょう。

i < this.size - 1などの別の場所で使用する必要がある場合は、i < this.sizeを使用している可能性があります(別名オフラインエラー)。

this.genePoolは、時には未定義です。

問題が解決しない場合は、ログ出力で質問を更新してください。

+0

アドバイスいただきありがとうございますが、私はこの問題を今修正するために取り組んでおり、まだ解決できないようです。私の最近の試みは、(this.genePool.length <1) の場合、 という行を追加することになります。 \tnatSelection(); そのため、genePool配列が存在しない場合、その自然選択関数を再び通過し、genePoolを作成しますが、何らかの理由でそれが解決されない場合もあります。 –

+0

オフ・バイ・ワンのエラーを考えましたか? –

関連する問題