Beispiel #1
0
int main( int argc , char *argv[] )
{
    rng_type rng;

    trainings_data_type c = gpcxx::generate_evenly_spaced_test_data< 3 >( -5.0 , 5.0 + 0.1 , 0.4 , []( double x1 , double x2 , double x3 ) {
                        return  1.0 / ( 1.0 + pow( x1 , -4.0 ) ) + 1.0 / ( 1.0 + pow( x2 , -4.0 ) ) + 1.0 / ( 1.0 + pow( x3 , -4.0 ) ); } );
    gpcxx::normalize( c.y );
    

    std::ofstream fout1( "testdata.dat" );
    for( size_t i=0 ; i<c.x[0].size() ; ++i )
        fout1 << c.y[i] << " " << c.x[0][i] << " " << c.x[1][i] << " " << c.x[2][i] << "\n";
    fout1.close();
    
    auto eval = gpcxx::make_static_eval< value_type , symbol_type , eval_context_type >(
        fusion::make_vector(
            fusion::make_vector( 'x' , []( eval_context_type const& t ) { return t[0]; } )
          , fusion::make_vector( 'y' , []( eval_context_type const& t ) { return t[1]; } )
          , fusion::make_vector( 'z' , []( eval_context_type const& t ) { return t[2]; } )          
          ) ,
        fusion::make_vector(
            fusion::make_vector( 's' , []( double v ) -> double { return std::sin( v ); } )
          , fusion::make_vector( 'c' , []( double v ) -> double { return std::cos( v ); } ) 
          , fusion::make_vector( 'e' , []( double v ) -> double { return std::exp( v ); } ) 
          , fusion::make_vector( 'l' , []( double v ) -> double { return ( std::abs( v ) < 1.0e-20 ) ? log( 1.0e-20 ) : std::log( std::abs( v ) ); } ) 
          ) ,
        fusion::make_vector(
            fusion::make_vector( '+' , std::plus< double >() )
          , fusion::make_vector( '-' , std::minus< double >() )
          , fusion::make_vector( '*' , std::multiplies< double >() ) 
          , fusion::make_vector( '/' , std::divides< double >() ) 
          ) );
    typedef decltype( eval ) eval_type;
    typedef eval_type::node_attribute_type node_attribute_type;
    
    typedef gpcxx::basic_tree< node_attribute_type > tree_type;
    typedef std::vector< tree_type > population_type;
    typedef gpcxx::static_pipeline< population_type , fitness_type , rng_type > evolver_type;

    
    size_t population_size = 1000;
    size_t generation_size = 20;
    double number_elite = 1;
    double mutation_rate = 0.0;
    double crossover_rate = 0.6;
    double reproduction_rate = 0.3;
    size_t min_tree_height = 8 , max_tree_height = 8;
    size_t tournament_size = 15;


    // generators< rng_type > gen( rng );
    auto terminal_gen = eval.get_terminal_symbol_distribution();
    auto unary_gen = eval.get_unary_symbol_distribution();
    auto binary_gen = eval.get_binary_symbol_distribution();
    gpcxx::node_generator< node_attribute_type , rng_type , 3 > node_generator {
        { 2.0 * double( terminal_gen.num_symbols() ) , 0 , terminal_gen } ,
        { double( unary_gen.num_symbols() ) , 1 , unary_gen } ,
        { double( binary_gen.num_symbols() ) , 2 , binary_gen } };

    auto tree_generator = gpcxx::make_ramp( rng , node_generator , min_tree_height , max_tree_height , 0.5 );
    

    evolver_type evolver( number_elite , mutation_rate , crossover_rate , reproduction_rate , rng );
    std::vector< double > fitness( population_size , 0.0 );
    std::vector< tree_type > population( population_size );


    auto fitness_f = gpcxx::regression_fitness< eval_type >( eval );
    evolver.mutation_function() = gpcxx::make_mutation(
        gpcxx::make_simple_mutation_strategy( rng , node_generator ) ,
        gpcxx::make_tournament_selector( rng , tournament_size ) );
    evolver.crossover_function() = gpcxx::make_crossover( 
        gpcxx::make_one_point_crossover_strategy( rng , max_tree_height ) ,
        gpcxx::make_tournament_selector( rng , tournament_size ) );
    evolver.reproduction_function() = gpcxx::make_reproduce( gpcxx::make_tournament_selector( rng , tournament_size ) );
    
    gpcxx::timer timer;



    // initialize population with random trees and evaluate fitness
    timer.restart();
    for( size_t i=0 ; i<population.size() ; ++i )
    {
        tree_generator( population[i] );
        fitness[i] = fitness_f( population[i] , c );
    }
    std::cout << gpcxx::indent( 0 ) << "Generation time " << timer.seconds() << std::endl;
    std::cout << gpcxx::indent( 1 ) << "Best individuals" << std::endl << gpcxx::best_individuals( population , fitness , 1 , 10 ) << std::endl;
    std::cout << gpcxx::indent( 1 ) << "Statistics : " << gpcxx::calc_population_statistics( population ) << std::endl;
    std::cout << gpcxx::indent( 1 ) << std::endl << std::endl;

    timer.restart();
    for( size_t generation=1 ; generation<=generation_size ; ++generation )
    {
        gpcxx::timer iteration_timer;
        iteration_timer.restart();
        evolver.next_generation( population , fitness );
        double evolve_time = iteration_timer.seconds();
        iteration_timer.restart();
        std::transform( population.begin() , population.end() , fitness.begin() , [&]( tree_type const &t ) { return fitness_f( t , c ); } );
        double eval_time = iteration_timer.seconds();
        
        std::cout << gpcxx::indent( 0 ) << "Generation " << generation << std::endl;
        std::cout << gpcxx::indent( 1 ) << "Evolve time " << evolve_time << std::endl;
        std::cout << gpcxx::indent( 1 ) << "Eval time " << eval_time << std::endl;
        std::cout << gpcxx::indent( 1 ) << "Best individuals" << std::endl << gpcxx::best_individuals( population , fitness , 2 , 10 ) << std::endl;
        std::cout << gpcxx::indent( 1 ) << "Statistics : " << gpcxx::calc_population_statistics( population ) << std::endl << std::endl;
    }
    std::cout << "Overall time : " << timer.seconds() << std::endl;

    return 0;
}
int main(int argc, char** argv){
    
    int width = 800;
    int height = 600;
    bool fullscreen = false;

    // Device must be the very first thing created!
    Device device(width, height, fullscreen);

    //Default parameters
    
    MeshType meshType = TETRAHEDRON;
    // If meshType is MESH_FILE, load file from mesh stored in meshFile
    char* meshFile = NULL;
    
    // If true, run in visual mode. In this, all calculations are done on the GPU.
    // Otherwise, you get a pretty boring CSV outputted. Activate with -v
    bool visualization = false;
    
    // Number of times the shape is bisected (any number for tetrahedra, preset numbers for
    // icosahedra, and it means nothing for other meshes). Set with -n=##
    int idealTriangleCount = 400;
    
    // Times Update is called if running in non visual mode. Set with -i=##
    int iterations = 10;
    
    // If true, use the GPU for calculations. Else, use the CPU. Set with -cpu
    bool gpu = true;
    
    //Type of stuff to output, set with -o
    OutputType output[8];
    int outputLength = 0;
    
    // scale of the visualization, set with -s=##
    int scale = 5;

    // if timing is true, activate with -t
    bool timing = false;

    // Parse Command Line Arguments:
    for(int i=1;i<argc;i++){
        if(argMatch(argv[i], "-v")){
            visualization = true;
        }else if(argMatch(argv[i], "--help")){
            help();
            return 0;
        }else if(argMatch(argv[i], "-n=")){
            idealTriangleCount = atoi(argv[i]+3);
        }else if(argMatch(argv[i], "-i=")){
            iterations = atoi(argv[i]+3);
        }else if(argMatch(argv[i], "-iterations=")){
            iterations = atoi(argv[i]+12);
        }else if(argMatch(argv[i], "-m")){
            i++;
            if(argMatch(argv[i], "tetra")){
                meshType = TETRAHEDRON;
            }else if(argMatch(argv[i], "icosa")){
                meshType = ICOSAHEDRON;
            }else if(argMatch(argv[i], "jeep")){
                meshType = MESH_FILE;
                meshFile = "models/jeep.mtl";
            }else if(argMatch(argv[i], "dragon")){
                meshType = MESH_FILE;
                meshFile = "models/dragon.ply";
            }else{
                meshType = MESH_FILE;
                meshFile = argv[i];
            }
        }else if(argMatch(argv[i], "-cpu")){
            gpu = false;
		}
		else if (argMatch(argv[i], "-s=")){
			scale = atoi(argv[i] + 3);
		}
		else if (argMatch(argv[i], "-t")){
			timing = true;
		}
		else if (argMatch(argv[i], "-o")){
            do{
                i++;
                if(argMatch(argv[i], "SurfaceArea")){
                    output[outputLength++] = TOTAL_SURFACE_AREA;
                }else if(argMatch(argv[i], "Volume")){
                    output[outputLength++] = TOTAL_VOLUME;
                }else if(argMatch(argv[i], "MeanNetForce")){
                    output[outputLength++] = MEAN_NET_FORCE;
                }else if(argMatch(argv[i], "Curvature")){
                    output[outputLength++] = MEAN_CURVATURE;
                }else if(argMatch(argv[i], "AreaForces")){
                    output[outputLength++] = AREA_FORCES;
                }else if(argMatch(argv[i], "VolumeForces")){
                    output[outputLength++] = VOLUME_FORCES;
                }else if(argMatch(argv[i], "NetForces")){
                    output[outputLength++] = NET_FORCES;
                }else if(argMatch(argv[i], "Points")){
                    output[outputLength++] = POINTS;
                }
            } while(lastChar(argv[i]) == ',');
        }
    }
    
    Mesh* mesh;
    
    switch(meshType){
        case TETRAHEDRON:
            mesh = new TetrahedronMesh(ceil(sqrt(idealTriangleCount/4.0)));
            break;
        case ICOSAHEDRON:
            if(idealTriangleCount <= 100){
                meshFile = "models/icosa1.obj";
            }else if(idealTriangleCount <= 1000){
                meshFile = "models/icosa2.obj";
            }else if(idealTriangleCount <= 10000){
                meshFile = "models/icosa3.obj";
            }else if(idealTriangleCount <= 100000){
                meshFile = "models/icosa4.obj";
            }else{
                meshFile = "models/icosa5.obj";
            }
            mesh = new ExternalMesh(meshFile);
            break;
        default:
            mesh = new ExternalMesh(meshFile);
            break;
    }
    
    // visualization only applies to GPU calculation, so:
    if(visualization){
        
    
        SceneManager manager(&device);
        CameraNode camera(&device, width, height);
        camera.getTransform().setTranslation(20.0f, 20.0f, 20.0f);
        manager.addNode(&camera);

        ModelNode mn;
        //mn.getTransform().setScale(0.025f, 0.025f, 0.025f);
        mn.getTransform().setScale(scale, scale, scale);
        mn.getTransform().setTranslation(0.0f, 0.0f, 0.0f);
        mn.setMesh(mesh);
        manager.addNode(&mn);

        ShaderProgram geometryProgram;
        Shader geometryVertexShader("shaders/geometry_pass.vert", VERTEX);
        Shader geometryFragShader("shaders/geometry_pass.frag", FRAGMENT);
        geometryProgram.attachShader(&geometryVertexShader);
        geometryProgram.attachShader(&geometryFragShader);
        geometryProgram.link();
        manager.setGeometryProgram(&geometryProgram);

        GPUEvolver evolver(mesh, 10);

        while (device.run()) {
            evolver.update();
            evolver.synchronizeToMesh();
            manager.drawAll();
            device.endScene();
        }
    } else {
        if (gpu) {
            GPUEvolver evolver(mesh, 10);
            evolver.setOutputFormat(output, outputLength);
            std::clock_t    start;

            start = std::clock();
                        
            for(int i=0; i < iterations; i++){
                evolver.update();
                evolver.outputData();
            }
            if (timing){
                std::cout << "Time: " << (std::clock() - start) / (double)(CLOCKS_PER_SEC / 1000) << " ms" << std::endl;
            }
        } else {
            CPUEvolver evolver(mesh, 10);
            evolver.setOutputFormat(output, outputLength);
            std::clock_t    start;

            start = std::clock();
            for(int i=0; i < iterations; i++){
                evolver.update();
                evolver.outputData();
            }
            if (timing){
                std::cout << "Time: " << (std::clock() - start) / (double)(CLOCKS_PER_SEC / 1000) << " ms" << std::endl;
            }
        }
    }
    return 0;
}
Beispiel #3
0
int main( int argc , char** argv )
{
    auto options = dynsys::get_options();
    auto positional_options = dynsys::get_positional_options();
    
    po::options_description cmdline_options;
    cmdline_options.add( options ).add( positional_options.second );
    
    po::variables_map vm;
    try
    {
        po::store( po::command_line_parser( argc , argv ).options( cmdline_options ).positional( positional_options.first ).run() , vm );
        po::notify( vm );
    }
    catch( std::exception& e )
    {
        std::cerr << "Error " << e.what() << "\n\n";
        std::cerr << cmdline_options << "\n";
        return -1;
    }
    
    dynsys::rng_type rng;
    
    
    //[ create_lorenz_data
    auto training_data = dynsys::generate_data();
    
    std::array< std::pair< double , double > , dynsys::dim > xstat , ystat;
    for( size_t i=0 ; i<dynsys::dim ; ++i )
    {
        xstat[i].first = ystat[i].first = 0.0;
        xstat[i].second = ystat[i].second = 1.0;
    }
    if( vm.count( "normalize" ) )
    {
        xstat = dynsys::normalize_data( training_data.first );
        ystat = dynsys::normalize_data( training_data.second );
    }
    // plot_data( training_data );
    //]
    
    //[ lorenz_define_node_generator
    auto node_generator = dynsys::create_node_generator();
    //]
    
    
    //[ define_gp_parameters
//     size_t population_size = 256;
//     size_t generation_size = 20;
    size_t population_size = 512 * 32;
    size_t generation_size = 2000;
    
    
    size_t number_elite = 1;
    double mutation_rate = 0.2;
    double crossover_rate = 0.6;
    double reproduction_rate = 0.3;
    size_t min_tree_height = 1 , max_tree_height = 8;
    size_t tournament_size = 15;
    //]

    //[ define_population_and_fitness
    using population_type = std::vector< dynsys::tree_type >;
    using fitness_type = std::vector< double >;
    //]
    
    //[ define_evolution
    using evolver_type = gpcxx::dynamic_pipeline< population_type , fitness_type , dynsys::rng_type >;
    evolver_type evolver( rng , number_elite );
    //]
    
    //[define_evaluator
    using evaluator = struct {
        using context_type = gpcxx::regression_context< double , dynsys::dim >;
        using value_type = double;
        value_type operator()( dynsys::tree_type const& t , context_type const& c ) const {
            return t.root()->eval( c );
        } };
    //]
        
    //[define_genetic_operators
    auto tree_generator = gpcxx::make_ramp( rng , node_generator , min_tree_height , max_tree_height , 0.5 );
    auto fitness_f = gpcxx::make_regression_fitness( evaluator {} );
    evolver.add_operator(
        gpcxx::make_mutation(
            gpcxx::make_point_mutation( rng , tree_generator , max_tree_height , 20 ) ,
            gpcxx::make_tournament_selector( rng , tournament_size )
        ) , mutation_rate );
    evolver.add_operator(
        gpcxx::make_crossover( 
            gpcxx::make_one_point_crossover_strategy( rng , 10 ) ,
            gpcxx::make_tournament_selector( rng , tournament_size )
        ) , crossover_rate );
    evolver.add_operator(
        gpcxx::make_reproduce(
            gpcxx::make_tournament_selector( rng , tournament_size )
        ) , reproduction_rate );
    //]

    
    std::ofstream fout { vm[ "evolution" ].as< std::string >() };
    std::ofstream fout2 { vm[ "result" ].as< std::string >() };
    fout2.precision( 14 );
    for( size_t j=0 ; j<dynsys::dim ; ++j )
        fout2 << xstat[j].first << " " << xstat[j].second << " " << ystat[j].first << " " << ystat[j].second << "\n";
    fout2 << std::endl << std::endl;
    
    
    
    std::array< dynsys::tree_type , dynsys::dim > winner;
    for( size_t dimension = 0 ; dimension < dynsys::dim ; ++dimension )
    {
        fitness_type fitness ( population_size , 0.0 );
        population_type population ( population_size );

        gpcxx::regression_training_data< double , dynsys::dim > problem;
        for( size_t i=0 ; i<training_data.first.size() ; ++i )
        {
            problem.y.push_back( training_data.second[i][ dimension ] );
            for( size_t j=0 ; j<dynsys::dim ; ++j )
                problem.x[j].push_back( training_data.first[i][j] );
        }
        
        //[init_population
        for( size_t i=0 ; i<population.size() ; ++i )
        {
            tree_generator( population[i] );
            fitness[i] = fitness_f( population[i] , problem );
        }
        
        std::cout << "Best individuals" << std::endl << gpcxx::best_individuals( population , fitness ) << std::endl;
        std::cout << "Statistics : " << gpcxx::calc_population_statistics( population ) << std::endl;
        std::cout << std::endl << std::endl;
        //]
        
        //[main_loop
        for( size_t i=0 ; i<generation_size ; ++i )
        {
            evolver.next_generation( population , fitness );
            for( size_t i=0 ; i<population.size() ; ++i )
                fitness[i] = fitness_f( population[i] , problem );
            
            std::cout << "Iteration " << i << std::endl;
            std::cout << "Best individuals" << std::endl << gpcxx::best_individuals( population , fitness , 1 ) << std::endl;
            std::cout << "Statistics : " << gpcxx::calc_population_statistics( population ) << std::endl << std::endl;
            
            fout << "Iteration " << i << std::endl;
            fout << "Best individuals" << std::endl << gpcxx::best_individuals( population , fitness , 1 ) << std::endl;
            fout << "Statistics : " << gpcxx::calc_population_statistics( population ) << std::endl << std::endl;
            
            auto min_fitness = * ( std::min_element( fitness.begin() , fitness.end() ) );
            if( std::abs( min_fitness ) < 1.0e-7 )
            {
                std::cout << "Minimal fitness is small then 1.0e-7. Stopping now." << std::endl << std::endl << std::endl << std::endl;
                fout << "Minimal fitness is small then 1.0e-7. Stopping now." << std::endl << std::endl << std::endl << std::endl;
                break;
            }
        }
        //]
        
        fout2 << gpcxx::best_individuals( population , fitness , 0 ) << std::endl << std::endl;
        
        std::vector< size_t > idx;
        gpcxx::sort_indices( fitness , idx );
        winner[dimension] = population[ idx[0] ];
    }
    
    std::ofstream winner_out { vm[ "winner" ].as< std::string >() };
    winner_out << dynsys::serialize_winner( winner , xstat , ystat ) << "\n";
    
    
    return 0;
}
Beispiel #4
0
int main( int argc , char *argv[] )
{
    rng_type rng;
    
    trainings_data_type c;
    generate_test_data( c , -5.0 , 5.0 + 0.1 , 0.4 , []( double x1 , double x2 , double x3 ) {
                        return  1.0 / ( 1.0 + pow( x1 , -4.0 ) ) + 1.0 / ( 1.0 + pow( x2 , -4.0 ) ) + 1.0 / ( 1.0 + pow( x3 , -4.0 ) ); } );
    gpcxx::normalize( c.y );
    

    std::ofstream fout1( "testdata.dat" );
    for( size_t i=0 ; i<c.x[0].size() ; ++i )
        fout1 << c.y[i] << " " << c.x[0][i] << " " << c.x[1][i] << " " << c.x[2][i] << "\n";
    fout1.close();
    

	gpcxx::uniform_symbol< node_type > terminal_gen { std::vector< node_type >{
        node_type { gpcxx::array_terminal< 0 >{} , "x" } ,
        node_type { gpcxx::array_terminal< 1 >{} , "y" } ,
        node_type { gpcxx::array_terminal< 2 >{} , "z" } } };
    gpcxx::uniform_symbol< node_type > unary_gen { std::vector< node_type >{
        node_type { gpcxx::sin_func{} , "s" } ,
        node_type { gpcxx::cos_func{} , "c" } ,
        node_type { gpcxx::exp_func{} , "e" } ,
        node_type { gpcxx::log_func{} , "l" } } };
    gpcxx::uniform_symbol< node_type > binary_gen { std::vector< node_type > {
        node_type { gpcxx::plus_func{} , "+" } ,
        node_type { gpcxx::minus_func{} , "-" } ,
        node_type { gpcxx::multiplies_func{} , "*" } ,
        node_type { gpcxx::divides_func{} , "/" }    
    } };
    
    gpcxx::node_generator< node_type , rng_type , 3 > node_generator {
        { double ( terminal_gen.num_symbols() ) , 0 , terminal_gen } ,
        { double ( unary_gen.num_symbols() ) , 1 , unary_gen } ,
        { double ( binary_gen.num_symbols() ) , 2 , binary_gen } };
    
    size_t population_size = 512;
    size_t generation_size = 20;
    double number_elite = 1;
    double mutation_rate = 0.0;
    double crossover_rate = 0.6;
    double reproduction_rate = 0.3;
    size_t max_tree_height = 8;
    size_t tournament_size = 15;
    

    auto tree_generator = gpcxx::make_basic_generate_strategy( rng , node_generator , max_tree_height , max_tree_height );
    // size_t min_tree_height = 1
    // auto new_tree_generator = gpcxx::make_ramp( rng , node_generator , min_tree_height , max_tree_height , 0.5 );


    typedef gpcxx::static_pipeline< population_type , fitness_type , rng_type > evolver_type;
    evolver_type evolver( number_elite , mutation_rate , crossover_rate , reproduction_rate , rng );
    std::vector< double > fitness( population_size , 0.0 );
    std::vector< tree_type > population( population_size );


    evolver.mutation_function() = gpcxx::make_mutation(
        gpcxx::make_simple_mutation_strategy( rng , node_generator ) ,
        gpcxx::make_tournament_selector( rng , tournament_size ) );
    evolver.crossover_function() = gpcxx::make_crossover( 
        gpcxx::make_one_point_crossover_strategy( rng , max_tree_height ) ,
        gpcxx::make_tournament_selector( rng , tournament_size ) );
    evolver.reproduction_function() = gpcxx::make_reproduce(
        gpcxx::make_tournament_selector( rng , tournament_size ) );
    
    gpcxx::timer timer;
    auto fitness_f = gpcxx::make_regression_fitness( evaluator() );

    // initialize population with random trees and evaluate fitness
    timer.restart();
    for( size_t i=0 ; i<population.size() ; ++i )
    {
        tree_generator( population[i] );
        fitness[i] = fitness_f( population[i] , c );
    }
    std::cout << gpcxx::indent( 0 ) << "Generation time " << timer.seconds() << std::endl;
    std::cout << gpcxx::indent( 1 ) << "Best individuals" << std::endl << gpcxx::best_individuals( population , fitness , 1 , 10 ) << std::endl;
    std::cout << gpcxx::indent( 1 ) << "Statistics : " << gpcxx::calc_population_statistics( population ) << std::endl;
    std::cout << gpcxx::indent( 1 ) << std::endl << std::endl;
    
    write_height_hist( population , "initial_height.hist" );
    write_size_hist( population , "initial_size.hist" );
    
    timer.restart();
    for( size_t generation=1 ; generation<=generation_size ; ++generation )
    {
        gpcxx::timer iteration_timer;
        iteration_timer.restart();
        evolver.next_generation( population , fitness );
        double evolve_time = iteration_timer.seconds();
        iteration_timer.restart();
        std::transform( population.begin() , population.end() , fitness.begin() , [&]( tree_type const &t ) { return fitness_f( t , c ); } );
        double eval_time = iteration_timer.seconds();
        
        write_height_hist( population , "height_" + std::to_string( generation ) + ".hist" );
        write_size_hist( population , "size_" + std::to_string( generation ) + ".hist" );
        
        std::cout << gpcxx::indent( 0 ) << "Generation " << generation << std::endl;
        std::cout << gpcxx::indent( 1 ) << "Evolve time " << evolve_time << std::endl;
        std::cout << gpcxx::indent( 1 ) << "Eval time " << eval_time << std::endl;
        std::cout << gpcxx::indent( 1 ) << "Best individuals" << std::endl << gpcxx::best_individuals( population , fitness , 2 , 10 ) << std::endl;
        std::cout << gpcxx::indent( 1 ) << "Statistics : " << gpcxx::calc_population_statistics( population ) << std::endl << std::endl;
    }
    std::cout << "Overall time : " << timer.seconds() << std::endl;


// 	generate_data();
// 	init_constants();
// 	init_node_types();   // init generators
// 	init_population();
// 	evolve();
// 	report();

    return 0;
}
Beispiel #5
0
int main (int argc, char *argv[])
{
    /*************************
     * Initialisation de MPI *
     *************************/

    boost::mpi::environment env(argc, argv, MPI_THREAD_MULTIPLE, true);
    boost::mpi::communicator world;

    /****************************
     * Il faut au moins 4 nœuds *
     ****************************/

    const size_t ALL = world.size();
    const size_t RANK = world.rank();

    /************************
     * Initialisation de EO *
     ************************/

    eoParser parser(argc, argv);
    eoState state;    // keeps all things allocated
    dim::core::State state_dim;    // keeps all things allocated

    /*****************************
     * Definition des paramètres *
     *****************************/

    bool sync = parser.createParam(bool(true), "sync", "sync", 0, "Islands Model").value();
    bool smp = parser.createParam(bool(true), "smp", "smp", 0, "Islands Model").value();
    unsigned nislands = parser.createParam(unsigned(4), "nislands", "Number of islands (see --smp)", 0, "Islands Model").value();
    // a
    double alphaP = parser.createParam(double(0.2), "alpha", "Alpha Probability", 'a', "Islands Model").value();
    double alphaF = parser.createParam(double(0.01), "alphaF", "Alpha Fitness", 'A', "Islands Model").value();
    // b
    double betaP = parser.createParam(double(0.01), "beta", "Beta Probability", 'b', "Islands Model").value();
    // d
    double probaSame = parser.createParam(double(100./(smp ? nislands : ALL)), "probaSame", "Probability for an individual to stay in the same island", 'd', "Islands Model").value();
    // I
    bool initG = parser.createParam(bool(true), "initG", "initG", 'I', "Islands Model").value();

    bool update = parser.createParam(bool(true), "update", "update", 'U', "Islands Model").value();
    bool feedback = parser.createParam(bool(true), "feedback", "feedback", 'F', "Islands Model").value();
    bool migrate = parser.createParam(bool(true), "migrate", "migrate", 'M', "Islands Model").value();
    unsigned nmigrations = parser.createParam(unsigned(1), "nmigrations", "Number of migrations to do at each generation (0=all individuals are migrated)", 0, "Islands Model").value();
    unsigned stepTimer = parser.createParam(unsigned(1000), "stepTimer", "stepTimer", 0, "Islands Model").value();
    bool deltaUpdate = parser.createParam(bool(true), "deltaUpdate", "deltaUpdate", 0, "Islands Model").value();
    bool deltaFeedback = parser.createParam(bool(true), "deltaFeedback", "deltaFeedback", 0, "Islands Model").value();
    double sensitivity = 1 / parser.createParam(double(1.), "sensitivity", "sensitivity of delta{t} (1/sensitivity)", 0, "Islands Model").value();
    std::string rewardStrategy = parser.createParam(std::string("avg"), "rewardStrategy", "Strategy of rewarding: best or avg", 0, "Islands Model").value();

    std::vector<double> rewards(smp ? nislands : ALL, 1.);
    std::vector<double> timeouts(smp ? nislands : ALL, 1.);

    for (size_t i = 0; i < (smp ? nislands : ALL); ++i)
    {
        std::ostringstream ss;
        ss << "reward" << i;
        rewards[i] = parser.createParam(double(1.), ss.str(), ss.str(), 0, "Islands Model").value();
        ss.str("");
        ss << "timeout" << i;
        timeouts[i] = parser.createParam(double(1.), ss.str(), ss.str(), 0, "Islands Model").value();
    }

    /*********************************
     * Déclaration des composants EO *
     *********************************/

    unsigned chromSize = parser.getORcreateParam(unsigned(0), "chromSize", "The length of the bitstrings", 'n',"Problem").value();
    eoInit<EOT>& init = dim::do_make::genotype(parser, state, EOT(), 0);

    eoEvalFunc<EOT>* ptEval = NULL;
    ptEval = new SimulatedEval( rewards[RANK] );
    state.storeFunctor(ptEval);

    eoEvalFuncCounter<EOT> eval(*ptEval);

    unsigned popSize = parser.getORcreateParam(unsigned(100), "popSize", "Population Size", 'P', "Evolution Engine").value();
    dim::core::Pop<EOT>& pop = dim::do_make::detail::pop(parser, state, init);

    double targetFitness = parser.getORcreateParam(double(1000), "targetFitness", "Stop when fitness reaches",'T', "Stopping criterion").value();
    unsigned maxGen = parser.getORcreateParam(unsigned(0), "maxGen", "Maximum number of generations () = none)",'G',"Stopping criterion").value();
    dim::continuator::Base<EOT>& continuator = dim::do_make::continuator<EOT>(parser, state, eval);

    dim::core::IslandData<EOT> data(smp ? nislands : -1);

    std::string monitorPrefix = parser.getORcreateParam(std::string("result"), "monitorPrefix", "Monitor prefix filenames", '\0', "Output").value();
    dim::utils::CheckPoint<EOT>& checkpoint = dim::do_make::checkpoint<EOT>(parser, state, continuator, data, 1, stepTimer);

    /**************
     * EO routine *
     **************/

    make_parallel(parser);
    make_verbose(parser);
    make_help(parser);

    if (!smp) // no smp enabled use mpi instead
    {

        /****************************************
         * Distribution des opérateurs aux iles *
         ****************************************/

        eoMonOp<EOT>* ptMon = NULL;
        if (sync)
        {
            ptMon = new DummyOp;
        }
        else
        {
            ptMon = new SimulatedOp( timeouts[RANK] );
        }
        state.storeFunctor(ptMon);

        /**********************************
         * Déclaration des composants DIM *
         **********************************/

        dim::core::ThreadsRunner< EOT > tr;

        dim::evolver::Easy<EOT> evolver( /*eval*/*ptEval, *ptMon, false );

        dim::feedbacker::Base<EOT>* ptFeedbacker = NULL;
        if (feedback)
        {
            if (sync)
            {
                ptFeedbacker = new dim::feedbacker::sync::Easy<EOT>(alphaF);
            }
            else
            {
                ptFeedbacker = new dim::feedbacker::async::Easy<EOT>(alphaF, sensitivity, deltaFeedback);
            }
        }
        else
        {
            ptFeedbacker = new dim::algo::Easy<EOT>::DummyFeedbacker();
        }
        state_dim.storeFunctor(ptFeedbacker);

        dim::vectorupdater::Base<EOT>* ptUpdater = NULL;
        if (update)
        {
            dim::vectorupdater::Reward<EOT>* ptReward = NULL;
            if (rewardStrategy == "best")
            {
                ptReward = new dim::vectorupdater::Best<EOT>(alphaP, betaP);
            }
            else
            {
                ptReward = new dim::vectorupdater::Average<EOT>(alphaP, betaP, sensitivity, sync ? false : deltaUpdate);
            }
            state_dim.storeFunctor(ptReward);

            ptUpdater = new dim::vectorupdater::Easy<EOT>(*ptReward);
        }
        else
        {
            ptUpdater = new dim::algo::Easy<EOT>::DummyVectorUpdater();
        }
        state_dim.storeFunctor(ptUpdater);

        dim::memorizer::Easy<EOT> memorizer;

        dim::migrator::Base<EOT>* ptMigrator = NULL;
        if (migrate)
        {
            if (sync)
            {
                ptMigrator = new dim::migrator::sync::Easy<EOT>();
            }
            else
            {
                ptMigrator = new dim::migrator::async::Easy<EOT>(nmigrations);
            }
        }
        else
        {
            ptMigrator = new dim::algo::Easy<EOT>::DummyMigrator();
        }
        state_dim.storeFunctor(ptMigrator);

        dim::algo::Easy<EOT> island( evolver, *ptFeedbacker, *ptUpdater, memorizer, *ptMigrator, checkpoint, monitorPrefix );

        if (!sync)
        {
            tr.addHandler(*ptFeedbacker).addHandler(*ptMigrator).add(island);
        }

        /***************
         * Rock & Roll *
         ***************/

        /******************************************************************************
         * Création de la matrice de transition et distribution aux iles des vecteurs *
         ******************************************************************************/

        dim::core::MigrationMatrix probabilities( ALL );
        dim::core::InitMatrix initmatrix( initG, probaSame );

        if ( 0 == RANK )
        {
            initmatrix( probabilities );
            std::cout << probabilities;
            data.proba = probabilities(RANK);

            for (size_t i = 1; i < ALL; ++i)
            {
                world.send( i, 100, probabilities(i) );
            }

            std::cout << "Island Model Parameters:" << std::endl
                      << "alphaP: " << alphaP << std::endl
                      << "alphaF: " << alphaF << std::endl
                      << "betaP: " << betaP << std::endl
                      << "probaSame: " << probaSame << std::endl
                      << "initG: " << initG << std::endl
                      << "update: " << update << std::endl
                      << "feedback: " << feedback << std::endl
                      << "migrate: " << migrate << std::endl
                      << "sync: " << sync << std::endl
                      << "stepTimer: " << stepTimer << std::endl
                      << "deltaUpdate: " << deltaUpdate << std::endl
                      << "deltaFeedback: " << deltaFeedback << std::endl
                      << "sensitivity: " << sensitivity << std::endl
                      << "chromSize: " << chromSize << std::endl
                      << "popSize: " << popSize << std::endl
                      << "targetFitness: " << targetFitness << std::endl
                      << "maxGen: " << maxGen << std::endl
                      ;
        }
        else
        {
            world.recv( 0, 100, data.proba );
        }

        /******************************************
         * Get the population size of all islands *
         ******************************************/

        world.barrier();
        dim::utils::print_sum(pop);

        FitnessInit fitInit;

        apply<EOT>(fitInit, pop);

        if (sync)
        {
            island( pop, data );
        }
        else
        {
            tr( pop, data );
        }

        world.abort(0);

        return 0 ;

    }

    // smp

    /**********************************
     * Déclaration des composants DIM *
     **********************************/

    dim::core::ThreadsRunner< EOT > tr;

    std::vector< dim::core::Pop<EOT> > islandPop(nislands);
    std::vector< dim::core::IslandData<EOT> > islandData(nislands);

    dim::core::MigrationMatrix probabilities( nislands );
    dim::core::InitMatrix initmatrix( initG, probaSame );

    initmatrix( probabilities );
    std::cout << probabilities;

    FitnessInit fitInit;

    for (size_t i = 0; i < nislands; ++i)
    {
        std::cout << "island " << i << std::endl;

        islandPop[i].append(popSize, init);

        apply<EOT>(fitInit, islandPop[i]);

        islandData[i] = dim::core::IslandData<EOT>(nislands, i);

        std::cout << islandData[i].size() << " " << islandData[i].rank() << std::endl;

        islandData[i].proba = probabilities(i);
        apply<EOT>(eval, islandPop[i]);

        /****************************************
         * Distribution des opérateurs aux iles *
         ****************************************/

        eoMonOp<EOT>* ptMon = NULL;
        ptMon = new SimulatedOp( timeouts[islandData[i].rank()] );
        state.storeFunctor(ptMon);

        eoEvalFunc<EOT>* __ptEval = NULL;
        __ptEval = new SimulatedEval( rewards[islandData[i].rank()] );
        state.storeFunctor(__ptEval);

        dim::evolver::Base<EOT>* ptEvolver = new dim::evolver::Easy<EOT>( /*eval*/*__ptEval, *ptMon, false );
        state_dim.storeFunctor(ptEvolver);

        dim::feedbacker::Base<EOT>* ptFeedbacker = new dim::feedbacker::smp::Easy<EOT>(islandPop, islandData, alphaF);
        state_dim.storeFunctor(ptFeedbacker);

        dim::vectorupdater::Reward<EOT>* ptReward = NULL;
        if (rewardStrategy == "best")
        {
            ptReward = new dim::vectorupdater::Best<EOT>(alphaP, betaP);
        }
        else
        {
            ptReward = new dim::vectorupdater::Average<EOT>(alphaP, betaP, sensitivity, sync ? false : deltaUpdate);
        }
        state_dim.storeFunctor(ptReward);

        dim::vectorupdater::Base<EOT>* ptUpdater = new dim::vectorupdater::Easy<EOT>(*ptReward);
        state_dim.storeFunctor(ptUpdater);

        dim::memorizer::Base<EOT>* ptMemorizer = new dim::memorizer::Easy<EOT>();
        state_dim.storeFunctor(ptMemorizer);

        dim::migrator::Base<EOT>* ptMigrator = new dim::migrator::smp::Easy<EOT>(islandPop, islandData, monitorPrefix);
        state_dim.storeFunctor(ptMigrator);

        dim::utils::CheckPoint<EOT>& checkpoint = dim::do_make::checkpoint<EOT>(parser, state, continuator, islandData[i], 1, stepTimer);

        dim::algo::Base<EOT>* ptIsland = new dim::algo::smp::Easy<EOT>( *ptEvolver, *ptFeedbacker, *ptUpdater, *ptMemorizer, *ptMigrator, checkpoint, islandPop, islandData, monitorPrefix );
        state_dim.storeFunctor(ptIsland);

        ptEvolver->size(nislands);
        ptFeedbacker->size(nislands);
        ptReward->size(nislands);
        ptUpdater->size(nislands);
        ptMemorizer->size(nislands);
        ptMigrator->size(nislands);
        ptIsland->size(nislands);

        ptEvolver->rank(i);
        ptFeedbacker->rank(i);
        ptReward->rank(i);
        ptUpdater->rank(i);
        ptMemorizer->rank(i);
        ptMigrator->rank(i);
        ptIsland->rank(i);

        tr.add(*ptIsland);
    }

    tr(pop, data);

    return 0 ;
}