all files / lib/nodeo/ ops.js

85.71% Statements 36/42
80% Branches 8/10
60% Functions 3/5
85.71% Lines 36/42
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87                                              6562× 6562× 6562× 6562×     6562×         3281× 35×   3246× 3246× 3246× 3246× 3246× 4447× 4447×   4447×   3246× 3244× 3244× 3244×   3244×   3244×                           40× 40× 3281× 3281× 3281× 3281× 6562×     40×    
// A few operators that can be used here and there
/*jslint node: true */
'use strict';
// * @license GPL v3
// * @package nodeo
// * @author J. J. Merelo <jjmerelo@gmail.com>
 
 
// To avoid uncomprehensible radix complaint at charAt
/*jshint -W065 */
/*jshint smarttabs:true */
 
var ops = exports;
 
// Bit-flips the whole chromosome
ops.invert = function (chromosome) {
    var inverted = '';
    for (var i = 0; i < inverted.length; i ++ ) {
	inverted += chromosome.charAt(i).match(/1/)?"0":"1";
    }
    return inverted;
};
 
// Bit-flips a single bit. It's mainly used for tests, not a real genetic operator.
ops.mutate = function (chromosome ) {
 
    var mutation_point = Math.floor( Math.random() * chromosome.length);
    var temp = chromosome;
    var flip_bit = temp.charAt(mutation_point).match(/1/)?"0":"1";
    chromosome = temp.substring(0,mutation_point) +
	flip_bit + 
	temp.substring(mutation_point+1,temp.length) ;
    return chromosome;
};
 
// Interchanges a substring between the two parents
ops.crossover = function ( chrom1, chrom2 ) {
    // Do nothing if they are the same.
    if (chrom1 === chrom2) {
	return [chrom1,chrom2];
    }
    var length = chrom1.length;
    var xover_point;
    var range;
    var counter = 0;
    do {
	xover_point = Math.floor( Math.random() * length);
	range = 1 + Math.floor(Math.random() * (length - xover_point) );
//	console.log( "Snippets " + chrom1.substring(xover_point+range,length) + "===" + chrom2.substring(xover_point+range,length) ) ; 
	counter++;
    } while ( counter < chrom1.length && (chrom1.substring(xover_point+range,length) === chrom2.substring(xover_point+range,length) ) );
    if ( counter < chrom1.length ) {
	var new_chrom1 = chrom1.substr(0,xover_point);
	var new_chrom2 = chrom2.substr(0,xover_point);
	new_chrom1+= chrom2.substring(xover_point,xover_point+range) +
	    chrom1.substring(xover_point+range,length);
	new_chrom2+= chrom1.substring(xover_point,xover_point+range) +
	    chrom2.substring(xover_point+range,length);
	return [new_chrom1, new_chrom2];
    } else { // must be different, but very little... let's just swap
	return [chrom2, chrom1];
    }
};
 
  
// Mutate all chromosomes in the population
ops.mutate_population = function  ( pool ) {
    for ( var i in pool ) {
	pool[i] = ops.mutate( pool[i]);
    }
};
 
 
// Applies operators to the pool
ops.reproduction = function (  pool ) {
    var offspring = [];
    while (pool.length ) {
	var first = pool.splice( Math.floor(Math.random()*pool.length), 1 );
	var second = pool.splice( Math.floor(Math.random()*pool.length), 1 );
	var crossovers = ops.crossover( first[0], second[0] );
	for ( var i in crossovers ) {
	    offspring.push( ops.mutate(crossovers[i]));
	}
    }
    return offspring;
};