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 likeconsole.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 languagefunction 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 startapp.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