오늘은 Genotype 유전형 Phenotype 표현형 코드 공부를 본격적으로 시작하는 날~~^^*
본격적으로 공부한다고 생각하니~^^* 뭔가 설레고 다부진 마음이 드는 걸요~^^*
음…크리스마스가 17일 남아서 그런 건가요~~^^*
아름다운 종이 17번 울립니다~^^*
따뜻하고 포근한 차 한 잔 하시며~^^*
은쟁반에 옥구슬 굴러가는 이 노래를 한 소절 한 소절 따라 부르고 계시겠어요?~~^^*
저는 코딩 공부 정리해서 곧 돌아올게요~~^^*
네~~^^* 새로운 도전! 코딩 공부 자료를 가지고 돌아왔습니다~^^*
DNA에 기록된 내용 Genotype 유전자형과 실제 외부에 보여지는 Phenotype 표현형 개념을 이해하기 위해~^^*
모나리자 초상을 Genetic Algorithm으로 구현하는 프로그램도 소개되네요~^^*
이 때 fitness 적합성은 모나리자 초상을 얼마나 닮았는지에 대한 것 같구요~^^*
Setup a random DNA string (application start)
1. Copy the current DNA sequence and mutate it slightly
2. Use the new DNA to render polygons onto a canvas
3. Compare the canvas to the source image
4. If the new painting looks more like the source image than the previous
painting did, then overwrite the current DNA with the new DNA
5. Repeat from 1
=>
무작위 DNA 스트링을 준비한다.
1. 현재 DNA 시퀀스를 복제한 후 살짝 돌연변이 시킨다.
2. 새롭게 된 이 DNA를 사용해서 화면 위에 다각형을 표현한다.
3. 화면을 원천 이미지와 비교한다.
4. 만약 이 새로운 그림이 이전 그림보다 원천 이미지를 더 많이 닮았다면, 이 새로운 DNA로 현재 DNA을 덮어쓴다.
5. 1번부터 작업과정을 반복한다.
Now to the interesting part:
Could you paint a replica of the Mona Lisa using only 50 semi transparent polygons?
=> 이 작품의 재미있는 부분: 50개의 반투명 다각형만을 사용하여 모나리자 복제품을 그릴 수 있는가?

50개의 불투명 다각형으로, 모나리자 초상을, 스스로 그려나가는 프로그램 신기하네요~^^*
프로그램이 뭔가….생명력을 가지게 된 것 같은 느낌….^^*
그런데~~^^*
우리가 앞으로 분석해 볼 프로그램은~~^^* 바로 이것이예요~~^^*
Genotype 유전자형은 클래스 DNA에서~~^^* 다루고 있는 것 같아요~^^*
class DNA {
constructor(newgenes) {
// The maximum strength of the forces
this.maxforce = 0.1;
// The genetic sequence
if (newgenes) {
this.genes = newgenes;
} else {
this.genes = [];
// Constructor (makes a DNA of random PVectors)
for (let i = 0; i < lifetime; i++) {
let angle = random(TWO_PI);
this.genes[i] = createVector(cos(angle), sin(angle));
this.genes[i].mult(random(0, this.maxforce));
}
}
// Let's give each Rocket an extra boost of strength for its first frame
this.genes[0].normalize();
}
// CROSSOVER
// Creates new DNA sequence from two (this & and a partner)
crossover(partner) {
let child = new Array(this.genes.length);
// Pick a midpoint
let crossover = int(random(this.genes.length));
// Take "half" from one and "half" from the other
for (let i = 0; i < this.genes.length; i++) {
if (i > crossover) child[i] = this.genes[i];
else child[i] = partner.genes[i];
}
let newgenes = new DNA(child);
return newgenes;
}
// Based on a mutation probability, picks a new random Vector
mutate(m) {
for (let i = 0; i < this.genes.length; i++) {
if (random(1) < m) {
let angle = random(TWO_PI);
this.genes[i] = createVector(cos(angle), sin(angle));
this.genes[i].mult(random(0, this.maxforce));
// let angle = random(-0.1,0.1);
// genes[i].rotate(angle);
// let factor = random(0.9,1.1);
// genes[i].mult(factor);
if (i == 0) this.genes[i].normalize();
}
}
}
}
Phenotype 표현형은 클래스 Rocket에서 다루고 있는 것 같구요~^^*
class Rocket {
constructor(pos, dna, totalRockets) {
// All of our physics stuff
this.acceleration = createVector();
this.velocity = createVector();
this.position = pos.copy();
this.r = 4;
this.dna = dna;
this.finishTime = 0; // We're going to count how long it takes to reach target
this.recordDist = 10000; // Some high number that will be beat instantly
this.fitness = 0;
this.geneCounter = 0;
this.hitObstacle = false; // Am I stuck on an obstacle?
this.hitTarget = false; // Did I reach the target
}
// FITNESS FUNCTION
// distance = distance from target
// finish = what order did i finish (first, second, etc. . .)
// f(distance,finish) = (1.0f / finish^1.5) * (1.0f / distance^6);
// a lower finish is rewarded (exponentially) and/or shorter distance to target (exponetially)
calcFitness() {
if (this.recordDist < 1) this.recordDist = 1;
// Reward finishing faster and getting close
this.fitness = 1 / (this.finishTime * this.recordDist);
// Make the function exponential
this.fitness = pow(this.fitness, 4);
if (this.hitObstacle) this.fitness *= 0.1; // lose 90% of fitness hitting an obstacle
if (this.hitTarget) this.fitness *= 2; // twice the fitness for finishing!
}
// Run in relation to all the obstacles
// If I'm stuck, don't bother updating or checking for intersection
run(os) {
if (!this.hitObstacle && !this.hitTarget) {
this.applyForce(this.dna.genes[this.geneCounter]);
this.geneCounter = (this.geneCounter + 1) % this.dna.genes.length;
this.update();
// If I hit an edge or an obstacle
this.obstacles(os);
}
// Draw me!
if (!this.hitObstacle) {
this.display();
}
}
// Did I make it to the target?
checkTarget() {
let d = dist(
this.position.x,
this.position.y,
target.position.x,
target.position.y
);
if (d < this.recordDist) this.recordDist = d;
if (target.contains(this.position) && !this.hitTarget) {
this.hitTarget = true;
} else if (!this.hitTarget) {
this.finishTime++;
}
}
// Did I hit an obstacle?
obstacles(os) {
for (let i = 0; i < os.length; i++) {
let obs = os[i];
if (obs.contains(this.position)) {
this.hitObstacle = true;
}
}
}
applyForce(f) {
this.acceleration.add(f);
}
update() {
this.velocity.add(this.acceleration);
this.position.add(this.velocity);
this.acceleration.mult(0);
}
display() {
//background(255,0,0);
let theta = this.velocity.heading() + PI / 2;
fill(200, 100);
stroke(0);
strokeWeight(1);
push();
translate(this.position.x, this.position.y);
rotate(theta);
// Thrusters
rectMode(CENTER);
fill(0);
rect(-this.r / 2, this.r * 2, this.r / 2, this.r);
rect(this.r / 2, this.r * 2, this.r / 2, this.r);
// Rocket body
fill(175);
beginShape(TRIANGLES);
vertex(0, -this.r * 2);
vertex(-this.r, this.r * 2);
vertex(this.r, this.r * 2);
endShape();
pop();
}
getFitness() {
return this.fitness;
}
getDNA() {
return this.dna;
}
stopped() {
return this.hitObstacle;
}
}
Fitness 적합성은 클래스 Population에서 다루고 있는 것 같습니다~~^^*
class Population {
constructor(m, num) {
this.mutationRate = m; // Mutation rate
this.population = new Array(num); // Array to hold the current population
this.matingPool = []; // ArrayList which we will use for our "mating pool"
this.generations = 0; // Number of generations
//make a new set of creatures
for (let i = 0; i < this.population.length; i++) {
let position = createVector(width / 2, height + 20);
this.population[i] = new Rocket(
position,
new DNA(),
this.population.length
);
}
}
live(os) {
// For every creature
for (let i = 0; i < this.population.length; i++) {
// If it finishes, mark it down as done!
this.population[i].checkTarget();
this.population[i].run(os);
}
}
// Did anything finish?
targetReached() {
for (let i = 0; i < this.population.length; i++) {
if (this.population[i].hitTarget) return true;
}
return false;
}
// Calculate fitness for each creature
calcFitness() {
for (let i = 0; i < this.population.length; i++) {
this.population[i].calcFitness();
}
}
// Generate a mating pool
selection() {
// Clear the ArrayList
this.matingPool = [];
// Calculate total fitness of whole population
let maxFitness = this.getMaxFitness();
// Calculate fitness for each member of the population (scaled to value between 0 and 1)
// 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 fitnessNormal = map(
this.population[i].getFitness(),
0,
maxFitness,
0,
1
);
let n = int(fitnessNormal * 100); // Arbitrary multiplier
for (let j = 0; j < n; j++) {
this.matingPool.push(this.population[i]);
}
}
}
// Making the next generation
reproduction() {
// Refill the population with children from the mating pool
for (let i = 0; i < this.population.length; i++) {
// Sping the wheel of fortune to pick two parents
let m = int(random(this.matingPool.length));
let d = int(random(this.matingPool.length));
// Pick two parents
let mom = this.matingPool[m];
let dad = this.matingPool[d];
// Get their genes
let momgenes = mom.getDNA();
let dadgenes = dad.getDNA();
// Mate their genes
let child = momgenes.crossover(dadgenes);
// Mutate their genes
child.mutate(this.mutationRate);
// Fill the new population with the new child
let position = createVector(width / 2, height + 20);
this.population[i] = new Rocket(position, child, this.population.length);
}
this.generations++;
}
getGenerations() {
return this.generations;
}
// Find highest fitness for the population
getMaxFitness() {
let record = 0;
for (let i = 0; i < this.population.length; i++) {
if (this.population[i].getFitness() > record) {
record = this.population[i].getFitness();
}
}
return record;
}
}
이 코드에 대한 본격적인 분석은~~^^* 화요일에 우리 같이 해 볼까요~~^^*
네??
내일은 왜 안하냐구요?
아이 참~~^^* 월요일이잖아요~~^^*
월요일은 음악 함께 듣는 날~~이잖아요~~^^*
네~~^^* 오늘 저와 함께 새로운 도전~~! Genotype-Phenotype-Fitness~~! 코드 분석 공부를 시작해 주셔서 감사합니다~~^^*
오늘도 점심 맛있게 드시고요~^^*
기쁨 나누는 만남~^^*
흥겹게 누리시며~^^*
멋진 하루 보내시기 바래요~^^*
네~^^* 꿈은 이루어 집니다~~^^*
댓글 남기기