Differential Evolution Visualization

See the Differential Evolution process of getting the coefficients of our quartic polynomial right!

See code :).

The visualization code is not much, it’s actually basic d3js line graph plotting, with quadratic transitions between the sequential generations. If you have trouble understanding the d3js part I recommend you watch this tutorial and read these ones Also this code helped me alot


var SIZE_X = 712;
var SIZE_Y = 712;
var myWorker = null;
// define dimensions of graph
var m = [80, 80, 80, 80]; // margins
var w = SIZE_X - m[1] - m[3]; // width
var h = SIZE_Y - m[0] - m[2]; // height
var svg = null;
var dataset = null;
var frameNumber = 0;


function render(data)
{
  dataset = data;

  // create the scale functors that map the data domain to the pixel domain
  var scaleX = d3.scale.linear().domain(d3.extent(data, function(d) { return d.x; })).range([0,w]);
  var scaleY = d3.scale.linear().domain(d3.extent(data, function(d) { return d.y; })).range([h,0]);

  // create a line function that can convert data[] into x and y points
  var lineFunction = d3.svg.line().x(function(d) {return scaleX(d.x);})
                                  .y(function(d) {return scaleY(d.y);})
  // create x axis
  var xAxis = d3.svg.axis().scale(scaleX).tickSize(-h).tickSubdivide(true);

  // add it and make it transparent so it does not interfere with the actual info
	svg.append("svg:g")
	          .attr("class", "x axis")
			      .attr("transform", "translate(0," + h + ")")
            .style("stroke-opacity", 0.2)
			      .call(xAxis);

  // create y axis
  var yAxisLeft = d3.svg.axis().scale(scaleY).ticks(4).orient("left");
  // add the y-axis to the left
  svg.append("svg:g")
            .attr("class", "y axis")
            .attr("transform", "translate(-25,0)")
            .call(yAxisLeft);

  //add the title text element that will display the current generation
  textTitle = svg.append('svg:text');
  textTitle.attr("x", (w / 2))
           .attr("y",  -60)
           .attr("text-anchor", "middle")
           .style("font-size", "20px")
           .text("Generation "+frameNumber);

  //add the "best candidate so far" text
  textDetails = svg.append('svg:text');
  textDetails.attr("x", (w / 2))
             .attr("y",  -30)
             .attr("text-anchor", "middle")
             .style("font-size", "12px")
             .text("Generation "+frameNumber);

  //create the reference path (we load it from our data)
  path = svg.append('svg:path');
  path.attr('d',lineFunction(dataset))
      .style('stroke-width', 2)
      .style('stroke', 'steelblue');

  //create the evolution path (will be updated)
  pathEvolution = svg.append("path");
 // we check browser support for web workers
  if(typeof(Worker) !== "undefined")
  {
    //we create the web worker because the algorithm is intensive and we don't want it to block our interface
     myWorker = new Worker("diffevolution.js");
     function updateDiffEvo()
     {
       //keep track of the current generation
       frameNumber = frameNumber + 1;
       //posting the message advances the algorithm
       myWorker.postMessage(dataset);
     }
     //we do a generation every half a second
     setInterval(updateDiffEvo, 500);

     myWorker.onmessage = function(event)
     {
       // we received an end message
       if(event.data.graphdata == null)
       {
         myWorker.terminate();
         return;
       }

       textTitle.text("Generation "+frameNumber);
       textDetails.text( "BestFit: "
                    +event.data.bestCandidate[0].toFixed(4) + " \n"
                    +event.data.bestCandidate[1].toFixed(4) + " \n"
                    +event.data.bestCandidate[2].toFixed(4) + " \n"
                    +event.data.bestCandidate[3].toFixed(4) + " \n"
                    +event.data.bestCandidate[4].toFixed(4) + " \n"
                  +" Error: "+event.data.bestFitness.toFixed(2));

      pathEvolution.transition()
                   .attr("class", "line")
                   .style("stroke", "red")
                   .duration(500)
                   .ease("quad")
                   .attr("d", lineFunction(event.data.graphdata));
      };
   }
   else
   {
    // we don't support browsers that don't have web workers  :( )
    alert("Sorry no webworker support for your browser, the example will not work:( ")
   }
   // end of render function
}


// converts string data from the csv object entry to numeric values
function type(d)
{
  d.x = +d.x;
  d.y = +d.y;
  return d;
}

//load the reference function data from a csv file
function loadDataFromCSV(filename)
{
  data = d3.csv(filename,type,render);
}

// Reset the svg element
function resetSVGElement()
{
  var div = document.getElementById('d3-chartid');
  div.innerHTML = "";

}

function generateSVGElement()
{
  svg = d3.select(".d3-chart").append("svg")
                              .attr("width",SIZE_X)
                              .attr("height", SIZE_Y)
                              .append("svg:g")
                              .attr("transform", "translate(" + m[3] + "," + m[0] + ")");
}

//Function used to switch data inputs based on listbox selection
function onListElementClick(data,domid)
{
  // clear selection
  var oldSelectedListElements = document.getElementsByClassName("selectedul");
  for (i = 0; i < oldSelectedListElements.length; i++)
  {
    oldSelectedListElements[i].className ="";
  }

  listElement = document.getElementById(domid);
  listElement.className  = "selectedul";

  if(myWorker != null)
  {
//Clear the "screen" :)
    resetSVGElement();
//Regenerate the graph
    generateSVGElement()

//Terminate the current worker
    myWorker.terminate();
    myWorker = undefined;
//Clear dataset
    dataset  = null;
//Reset generation counter
    frameNumber = 0;
  }
//Load the data using the hash as a filename
  loadDataFromCSV(data);
}
//The initialization function
function visInit()
{
//Create the main graph element
  generateSVGElement();
//Start with the first element in the list
  onListElementClick('data/sin.csv','lst0');

};
// add the initialization function on the dom content loaded event
document.addEventListener("DOMContentLoaded",visInit);

Back to visualization

If you want to see about the differential evolution code you should go here

You can find the full source code on my github or “view source” :D.