On Github JJ / cloudy-ga
console.log('¡Hola, chavales!')
alert('¿Qué pasa, coleguis?');A gentle introduction to JavaScript to get a idea of what it's like
console.log('Buenos días'.length)
console.log(['Buenos días','Buenas tardes','Buenas noches'].pop())
var chromosome = '1001100110011'; var fitness_of = new Object; fitness_of[chromosome] = chromosome.match(/1/g).length; var rr = function (chromosome) { var fitness = 0; for (var i = 0; i < chromosome.length; i+=4 ) { var ones = (chromosome.substr(i, 4).match(/1/g) || []).length; fitness += ( ones == 0 || ones == 4 ); } return fitness; };What is the way of representing a chromosome then? What's the fastest way of counting ones? This is a way of doing it, that besides proves that JS is a higher-order language that is able to deal with functions as first-class dwellers of the language
function do_ea() { eo.generation(); generation_count++; if( (eo.fitness_of[eo.population[0]] < traps*conf.fitness.b ) && ( generation_count*conf.population_size < conf.max_evaluations)) { setTimeout(do_ea, 5); } else { console.log( "Finished ", log ); } }This has nothing to do with the language, but with the implementation, which is usually single-threaded.
node.js is an asynchronous JS interpreter.
var eo = new nodeo.Nodeo( { population_size: population_size, chromosome_size: chromosome_size, fitness_func: utils.max_ones } ); do { eo.generation(); console.log( eo.population[0] ); } while ( eo.fitness_of[eo.population[0]] < chromosome_size );Nodeo can be downloaded from the Node modules repository with npm install nodeo. This is actually not the preferred way of doing a loop; it should be done asynchronously as above, since that will leave no time for I/O or other events. It's a single thread, same as in the browser. But it can be done alright if you need to do it. Good thing about JS, same programming model and language (but not the rest) in client and server. Very recently, in fact for this tutorial, version 0.2.2 has been released. And here's a loop which I said we shouldn't use. That does not mean we cannot use it from time to time. So just check it out and forget about it.
var hiff = new HIFF.HIFF(); var eo = new nodeo.Nodeo( { population_size: conf.population_size, chromosome_size: chromosome_size, fitness_func: hiff } ); logger.info( { start: process.hrtime() } );
evolve(generation_count, eo, logger, conf, check );
if ( typeof process.env.PAPERTRAIL_PORT !== 'undefined' && typeof process.env.PAPERTRAIL_HOST !== 'undefined' ) { logger.add(winston.transports.Papertrail, { host: process.env.PAPERTRAIL_HOST, port: process.env.PAPERTRAIL_PORT } ) }It can't run and log, so logs have to be taken to another different place. In this case, to a Software-as-a-Service, another cloud service.
var check = function( eo, logger, conf, generation_count ) { if ( (eo.fitness_of[eo.population[0]] < conf.fitness_max ) && (generation_count*conf.population_size < conf.max_evaluations )) { logger.info( { "chromosome": eo.population[0], "fitness" : eo.fitness_of[eo.population[0]]} ); evolve( generation_count, eo, logger, conf, check); } else { logger.info( {end: { time: process.hrtime(), generation: total_generations, best : { chromosome : eo.population[0], fitness : eo.fitness_of[eo.population[0]]}}} ); conf.output = conf.output_preffix+".json"; process.exit(); } };
{ "name": "hiffeitor", "scripts": { "test": "mocha", "start": "./callback-ea-HIFF.js" }, "dependencies": { "nodeo": "^0.2.1", "winston": "^2.2.0", "winston-logstash": "^0.2.11", "winston-papertrail": "^1.0.2" }, "devDependencies": { "flightplan": "^0.6.14" } }
FROM phusion/baseimage MAINTAINER JJ Merelo "jjmerelo@gmail.com" RUN echo "Building a docker environment for NodEO" ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get upgrade -y RUN apt-get install apt-utils -y RUN apt-get install nodejs npm -y
RUN mkdir app ADD https://github.com/JJ/cloudy-ga/raw/master/app/callback-ea-HIFF.js app ADD https://github.com/JJ/cloudy-ga/raw/master/app/package.json app ADD https://github.com/JJ/cloudy-ga/raw/master/app/hiff.json app WORKDIR /app RUN npm i RUN chmod +x callback-ea-HIFF.js
CMD npm start
sudo docker run -t jjmerelo/cloudy-ga:0.0.1 -e "PAPERTRAIL_PORT=7777" -e "PAPERTRAIL_HOST=logs77.papertrailapp.com"
do { eo.generation(); } while ( eo.fitness_of[eo.population[0]] < chromosome_size );
var random_chromosome = function() { return utils.random( chromosome_size ); }; var population = new Population(); population.initialize( population_size, random_chromosome);
var eo = new fluxeo( this_fitness, new Tournament( tournament_size, population_size-2 ), check);
eo.algorithm( population, function ( population ) { logger.info( { end: { time: process.hrtime(), generation: total_generations, best : { chromosome : population.best, fitness : population.fitness(population.best) } } }); });
- hosts: "{{target}}" tasks: - name: install prerrequisites command: apt-get update -y && apt-get upgrade -y - name: install packages apt: pkg={{ item}} with_items: - git - npm - name: Create profile copy: content="export PAPERTRAIL_PORT={{PAPERTRAIL_PORT}}}" dest=/home/cloudy/.profile
ansible-playbook git.playbook.yml -e "target=azuredeb" -u ubuntu -i ./hosts.txt -vvvv
plan.target('azure', { host: 'cloudy-ga.cloudapp.net', username: 'azureuser', agent: process.env.SSH_AUTH_SOCK }); // Local plan.local(function(local) { local.echo('Plan local: push changes'); local.exec('git push'); });
plan.remote(function(remote) { remote.log('Pull'); remote.with('cd cloudy-ga',function() { remote.exec('git pull'); remote.exec('cd app;npm install .'); }); remote.with('cd /home/azureuser/cloudy-ga/app',function() { remote.exec('npm start'); }); });Please note that we are using here infrastructure at several levels: the package.json that we declared at the beginning, that allowed us to run npm install and npm start
app.put('/experiment/:expid/one/:chromosome/:fitness/:uuid', function(req, res){ // stuff here logger.info("put", { chromosome: req.params.chromosome, fitness: parseInt(req.params.fitness), IP: client_ip, worker_uuid:req.params.uuid} ); res.send( { length : Object.keys(chromosomes).length }); }
app.get('/random', function(req, res){ var keys = Object.keys(chromosomes ); var one = keys[ Math.floor(keys.length*Math.random())]; res.send( { 'chromosome': one } ); logger.info('get'); });
rest.get( conf.url + 'random' ).on('complete', function( data ) { if ( data.chromosome ) { population.addAsLast( data.chromosome ); } });
var this_request = conf.url + 'experiment/0/one/' + population.best() + "/" + population.fitness(population.best()) + "/" + UUID; rest.put( this_request ).on("complete", function( result, response ) { if ( response.statusCode == 410 ) { finished = true; experiment_id = result.current_id; } });
Vagrant.configure("2") do |config| config.vm.box = "ubuntu/xenial64" config.vm.provision "shell", inline: <<-SHELL apt-get update apt-get upgrade -y SHELL config.vm.provision "main", type: "ansible" do |ansible| ansible.extra_vars = { target: "all" } ansible.playbook = "playbook.yml" end # and the rest... end