오늘은 To be or not to be 문구를 생성하는 프로그램의 내용을 좀더 자세하게 살펴보겠습니다~^^*
이 코드를 만들어 가며 배우는 과정이 아니라 만들어진 이 코드를 분석하며 배우는 과정이라서 단계별로 소화해서 다시 설명하기에는 시간이 많이 걸릴 것 같아요.
그래서 오늘은 , 코드 분석 동영상 강의를 시청자 모드로 편안하게 보시면 어떨까 합니다~^^*
그리고 관련 코드들을 또한 편안한 시선으로 한 번 훑어 보는 것으로 마무리를 하면 어떨까요~^^*
클래스 DNA 정의 파일입니다~^^*
function newChar() {
let c = floor(random(63, 122));
if (c === 63) c = 32;
if (c === 64) c = 46;
return String.fromCharCode(c);
}
// Constructor (makes a random DNA)
class DNA {
constructor(num) {
// The genetic sequence
this.genes = [];
this.fitness = 0;
for (let i = 0; i < num; i++) {
this.genes[i] = newChar(); // Pick from range of chars
}
}
// Converts character array to a String
getPhrase() {
return this.genes.join("");
}
// Fitness function (returns floating point % of "correct" characters)
calcFitness(target) {
let score = 0;
for (let i = 0; i < this.genes.length; i++) {
if (this.genes[i] == target.charAt(i)) {
score++;
}
}
this.fitness = score / target.length;
}
// Crossover
crossover(partner) {
// A new child
let child = new DNA(this.genes.length);
let midpoint = floor(random(this.genes.length)); // Pick a midpoint
// Half from one, half from the other
for (let i = 0; i < this.genes.length; i++) {
if (i > midpoint) child.genes[i] = this.genes[i];
else child.genes[i] = partner.genes[i];
}
return child;
}
// Based on a mutation probability, picks a new random character
mutate(mutationRate) {
for (let i = 0; i < this.genes.length; i++) {
if (random(1) < mutationRate) {
this.genes[i] = newChar();
}
}
}
}
클래스 Population 정의 파일입니다~
class Population {
constructor(p, m, num) {
this.population; // Array to hold the current population
this.matingPool; // ArrayList which we will use for our "mating pool"
this.generations = 0; // Number of generations
this.finished = false; // Are we finished evolving?
this.target = p; // Target phrase
this.mutationRate = m; // Mutation rate
this.perfectScore = 1;
this.best = "";
this.population = [];
for (let i = 0; i < num; i++) {
this.population[i] = new DNA(this.target.length);
}
this.matingPool = [];
this.calcFitness();
}
// Fill our fitness array with a value for every member of the population
calcFitness() {
for (let i = 0; i < this.population.length; i++) {
this.population[i].calcFitness(target);
}
}
// Generate a mating pool
naturalSelection() {
// Clear the ArrayList
this.matingPool = [];
let maxFitness = 0;
for (let i = 0; i < this.population.length; i++) {
if (this.population[i].fitness > maxFitness) {
maxFitness = this.population[i].fitness;
}
}
// Based on fitness, each member will get added to the mating pool a certain number of times
// a higher fitness = more entries to mating pool = more likely to be picked as a parent
// a lower fitness = fewer entries to mating pool = less likely to be picked as a parent
for (let i = 0; i < this.population.length; i++) {
let fitness = map(this.population[i].fitness, 0, maxFitness, 0, 1);
let n = floor(fitness * 100); // Arbitrary multiplier, we can also use monte carlo method
for (let j = 0; j < n; j++) {
// and pick two random numbers
this.matingPool.push(this.population[i]);
}
}
}
// Create a new generation
generate() {
// Refill the population with children from the mating pool
for (let i = 0; i < this.population.length; i++) {
let a = floor(random(this.matingPool.length));
let b = floor(random(this.matingPool.length));
let partnerA = this.matingPool[a];
let partnerB = this.matingPool[b];
let child = partnerA.crossover(partnerB);
child.mutate(this.mutationRate);
this.population[i] = child;
}
this.generations++;
}
getBest() {
return this.best;
}
// Compute the current "most fit" member of the population
evaluate() {
let worldrecord = 0.0;
let index = 0;
for (let i = 0; i < this.population.length; i++) {
if (this.population[i].fitness > worldrecord) {
index = i;
worldrecord = this.population[i].fitness;
}
}
this.best = this.population[index].getPhrase();
if (worldrecord === this.perfectScore) {
this.finished = true;
}
}
isFinished() {
return this.finished;
}
getGenerations() {
return this.generations;
}
// Compute average fitness for the population
getAverageFitness() {
let total = 0;
for (let i = 0; i < this.population.length; i++) {
total += this.population[i].fitness;
}
return total / this.population.length;
}
allPhrases() {
let everything = "";
let displayLimit = min(this.population.length, 50);
for (let i = 0; i < displayLimit; i++) {
everything += this.population[i].getPhrase() + "<br>";
}
return everything;
}
}
메인 파일입니다~^^*
let target;
let popmax;
let mutationRate;
let population;
let bestPhrase;
let allPhrases;
let stats;
function setup() {
bestPhrase = createP("Best phrase:");
//bestPhrase.position(10,10);
bestPhrase.class("best");
allPhrases = createP("All phrases:");
allPhrases.position(600, 10);
allPhrases.class("all");
stats = createP("Stats");
//stats.position(10,200);
stats.class("stats");
//createCanvas(640, 360);
target = "To be or not to be.";
popmax = 200;
mutationRate = 0.01;
// Create a population with a target phrase, mutation rate, and population max
population = new Population(target, mutationRate, popmax);
}
function draw() {
// Generate mating pool
population.naturalSelection();
//Create next generation
population.generate();
// Calculate fitness
population.calcFitness();
population.evaluate();
// If we found the target phrase, stop
if (population.isFinished()) {
//println(millis()/1000.0);
noLoop();
}
displayInfo();
}
function displayInfo() {
// Display current status of population
let answer = population.getBest();
bestPhrase.html("Best phrase:<br>" + answer);
let statstext =
"total generations: " + population.getGenerations() + "<br>";
statstext +=
"average fitness: " + nf(population.getAverageFitness()) + "<br>";
statstext += "total population: " + popmax + "<br>";
statstext += "mutation rate: " + floor(mutationRate * 100) + "%";
stats.html(statstext);
allPhrases.html("All phrases:<br>" + population.allPhrases());
}
코드 양이 많고, 이미 만들어진 것을 분석해서 이해하려니 좀 부담스럽기는 한데요~^^*
오늘은 이 내용과 좀더 친해지는 시간을 갖는 것에 의미를 두고~^^*
내일 동영상에서 분석 설명하는 부분들을 좀더 자세하게 살펴보면 어떨까요~^^*
오늘 저와 함께 양이 꽤 되는 코드를 편안한 시선으로 훑어봐 주셔서 감사합니다~^^*
내일 부분 부분 part by part and part to part 좀더 자세히 살펴보면 어떨까요~~^^*?
오늘도
멋진 아침 보내시고요!
점심 맛있게 드시고요!
오늘 하루도 삶의 the Best Part가 될 수 있으면 좋겠어요~^^*
네~~^^* 꿈은 이루어 집니다~~^^*
댓글 남기기