Silverback9

#야생으로

Creative Coding 독학 제283일 2024년01월04일(토)

오늘은 새해 첫 토요일입니다~~^^*

공연 1 작품 편안하게 감상하시고 계셔요~^^* 코딩 공부 정리해서 돌아올게요~^^* 쓩~^^*

네~~^^* crossover 교차작업이 잘 되고 있는 것 같습니다~~^^*

플레이를 해보시면~^^* (1) 200 frame 마다 세대교체가 되면서, maxfit 값이 화면 아래에 나올 것입니다~^^* width*2에 가까운 700 이상의 수가 유지가 되고 있고요~^^* (2) console창의 각 로켓들을 눌러 dna를 보시면 로켓의 fitness 값도 0에서 1 사이 구간으로 잘 나오고 있습니다~^^* (3) 어느 순간, target 목표물에 가까이 다가간 로켓이 나타난 이후의 세대 부터는 목표물에 가까이 다가가는 로켓들이 부쩍 증가하는 것을 느끼실 수 있나요~~^^*

즐겁게 플레이 해 보고 계셔요~~^^* 저는 전체 코드 주석 작업을 마무리하고 다시 돌아올게요~~^^* 쓩~~^^*

네~~^^* 전체 코드를 정리해 보았습니다~~^^*

var lifespan = 200; //200 프레임 동안 살아보겠습니다. 
var population;
var lifeP; //살아온 날 count 수치를 pharagraph 문단으로 보여줍니다. 
var count = 0; //살아온 날
var target; //드디어 우리에게 추구하고픈 목표가 생겼어요!!

function setup(){
  createCanvas(400, 400); 
  population = new Population();
  lifeP = createP();
  target = createVector(width/2, 100);
}

function draw(){
  background(0);
  population.run();
  lifeP.html(count); 
  
  count++;
  if (count == lifespan) {
    population.evaluate();
    population.selection();
    count = 0;
  }
  //200 frame이 되면 로켓들의 적합성을 기반으로 부모를 선정하여 유전자 교차 작업을 통해 다음세대 로켓을 생성합니다. 

  ellipse(target.x, target.y, 16, 16);
}


function DNA(genes) {

   if(genes) {
     this.genes = genes;
   } else {
     this.genes = [];
     for(var i = 0; i < lifespan; i++) {
       this.genes[i] = p5.Vector.random2D();
       this.genes[i].setMag(0.1);
     }
   }
   
  this.crossover = function(partner) {
    var newgenes = [];
    var mid = floor(random(this.genes.length));
    for(i = 0; i < this.genes.length; i++) {
      if(i > mid) {
        newgenes[i] = this.genes[i];
      } else {
        newgenes[i] = partner.genes[i]
      }
    }
    return new DNA(newgenes);
  }
} 
//맨처음 세대는 무작위로 genes 데이터를 만들어 DNA를 생성하고, 다음 세대 DNA 생성을 할 때는 genes 정보를 전달 받아 생성합니다. 


function Population () {
  
  this.rockets = [];
  this.popsize = 200;
  this.matingpool = [];

  for (var i = 0; i < this.popsize; i++) {
    this.rockets[i] = new Rocket();
  }

  this.evaluate = function() {

    var maxfit = 0;
    for (var i = 0; i < this.popsize; i++) {
      this.rockets[i].calcFitness();
      if (this.rockets[i].fitness > maxfit) {
        maxfit = this.rockets[i].fitness;
      }
    }
    
    createP(maxfit);
    console.log(this.rockets);
    
    for (var i = 0; i < this.popsize; i++) {
      this.rockets[i].fitness /= maxfit;
    }

    this.matingpool = [];
    for (var i = 0; i < this.popsize; i++) {
      var n = this.rockets[i].fitness * 100;
      for (var j = 0; j < n; j++) {
        this.matingpool.push(this.rockets[i]);
      }
    }
  }
  //로켓들의 최고 fitness 값을 기반으로 각 로켓의 fitness 값을 <0-1>로 정규화하고, 이를 바탕으로 더 높은 fitness 값을 가진 로켓들을 후보자군에 더 많이 넣습니다. 
  
  this.selection = function() {
    var newRockets = [];
    for (var i = 0; i < this.rockets.length; i++) {
      var parentA = random(this.matingpool).dna;
      var parentB = random(this.matingpool).dna;
      var child = parentA.crossover(parentB);
      newRockets[i] = new Rocket(child);
    }
    this.rockets = newRockets;
  }  
  //후보자군에서 무작위로 부모를 선택하여 교차작업을 하여 자녀 로켓을 생성합니다. 로켓집합의 세대교체를 합니다. 
    
  this.run = function() {
    for (var i = 0; i < this.popsize; i++) {
      this.rockets[i].update();
      this.rockets[i].show();
    }
  }
}  
//로켓의 움직임 변화를 반영하여 시각화합니다. 

  
function Rocket(dna) {
  this.pos = createVector(width/2, height);
  this.vel = createVector(); 
  this.acc = createVector();
  
  if (dna) {
    this.dna = dna;
  } else {
    this.dna = new DNA();
  }
  this.fitness = 0;

  this.count = 0; 
  //this.dna.genes[this.count]에 쓰이며, 배열의 순서를 나타내게 될 것입니다. 
  
  this.calcFitness = function() {
    var d = dist(this.pos.x, this.pos.y, target.x, target.y);
    this.fitness = map( d, 0, width*2, width*2, 0);
  }
  
  this.applyForce = function(force) {
    this.acc.add(force);
  }
  
  this.update = function() {
    this.applyForce(this.dna.genes[this.count]);
    //this.dna.genes[this.count]에 서로 다른 속도가 저장되어 있으므로
    //프레임마다 서로 다른 속도값이 힘에 적용되어 가속도에 더해집니다.  
    
    this.count++;    
 
    this.vel.add(this.acc);
    this.pos.add(this.vel);
    this.acc.mult(0);
  }

  this.show = function() {
    push();
    noStroke();
    fill(255, 150); 
    translate(this.pos.x, this.pos.y);
    rotate(this.vel.heading());
    rectMode(CENTER);
    rect(0, 0, 25, 5); 
    pop();
  } 
}
//첫 세대 로켓은 무작위 DNA로 다음 세대 로켓부터는 교차작업을 통해 만들어진 DNA 정보로 생성합니다. 
//목표물에 가장 가까운 로켓이 가장 큰 fitness값을 가질 수 있도록, 로켓과 목표물 사이의 거리 <0 - width*2>를 <width*2 - 0>으로 mapping합니다. 

와우!! 우리손으로 뚜닥뚜닥 코드작업을 하면서 crossover 교차작업까지 해내다니!! 뿌듯하고 감사한 마음이 들어요~~^^*

오늘 저와 함께 crossover 교차작업 코드 테스트를 해주셔서 감사합니다~~^^*

우리 이 작은 성공의 경험을 발판으로 내일은 mutation 돌연변이생성 작업도 도전해 볼까요~~^^*

이 작은 로켓집단도 자신을 계속 혁신해 나가면서 놀라운 성장을 계속해 나가는데~^^*

우리도 우리 자신 안에서 자기 혁신을 해낼 수 있을 것 같아요~~^^*

우리 자신 안에도 다양한 재능들이 더 성장하기를 기대하며~~^^*

잠재적 로켓집단으로서 부릉부릉 우리의 출발 신호를 기다리고 있을 것 같아요~~^^*

자 이제 플레이 버튼을 눌러 볼까요~~^^* 우리 안의 로켓집단~~ 자~~ 출발~~^^*

우리 안의 고유한 그 어떤 것들을 소중하게 여기고 계속 성장시켜 나가는 멋진 2025년이 되면 좋을 것 같아요~~^^*

우리 안의 Maximum을 이끌어내는 새해를 우리 함께 응원하면 좋겠어요~^^* Maximum!!!

올해 마지막 토요일에는 “잘 했군. 잘 했어.” 우리 스스로를 뿌듯해 할 수 있으면 좋겠어요~^^*

새해 첫 토요일 즐겁게 보내시고요~~^^*

편안하고 따뜻한 밤 보내시고요~~^^*

우리 내일 또 만나는 거예요~~^^* 그죠~~^^* 아이 좋아라~~^^*

네~~^^* 꿈은 이루어 집니다~~^^*

댓글 남기기