view src/main.cpp @ 0:add35537fdbb tip

Initial import
author irh <ian.r.hobson@gmail.com>
date Thu, 25 Aug 2011 11:05:55 +0100
parents
children
line wrap: on
line source
//  Copyright 2011, Ian Hobson.
//
//  This file is part of gpsynth.
//
//  gpsynth is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  gpsynth is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with gpsynth in the file COPYING. 
//  If not, see http://www.gnu.org/licenses/.

#include "file_comparer.hpp"
#include "graph_helpers.hpp"
#include "logger.hpp"
#include "population.hpp"
#include "program_options.hpp"
#include "sc_converter.hpp"
#include "sc_default_grammar.hpp"
#include "sc_evaluator.hpp"
#include "sc_grammar.hpp"

#include "boost/filesystem.hpp"
#include "boost/shared_array.hpp"

#include <algorithm>
#include <ctime>
#include <fstream>
#include <iostream>
#include <sstream>

const std::string g_test_grammar_path = "/tmp/sc.json";

template<typename T>
void SaveToFile(const T& value, const std::string& file_path) {
  std::ofstream file(file_path.c_str());
  file << value;
}

void TestCrossover() {
  sc::Grammar grammar(g_test_grammar_path);
  sc::Converter converter(grammar);
  sg::Graph parent_1;
  sg::Graph parent_2;
  grammar.SetMaximumDepth(2);
  grammar.RandomGraph(parent_1);
  grammar.RandomGraph(parent_2);
  sg::Vertex crossover_1;
  sg::Vertex crossover_2;
  grammar.PickCrossoverNodes(parent_1, parent_2, &crossover_1, &crossover_2);
  // swap the subtrees
  sg::Graph child_1;
  sg::Graph child_2;
  SwapSubTrees(crossover_1, crossover_2, parent_1, parent_2, child_1, child_2);
  SaveToFile(converter.ToDOT(parent_1), "/tmp/parent1.dot");
  SaveToFile(converter.ToDOT(parent_2), "/tmp/parent2.dot");
  SaveToFile(converter.ToDOT(child_1), "/tmp/child1.dot");
  SaveToFile(converter.ToDOT(child_2), "/tmp/child2.dot");
}

void TestMutationReplaceSubtree() {
  sc::Grammar grammar(g_test_grammar_path);
  sc::Converter converter(grammar);
  sg::Graph graph;
  grammar.RandomGraph(graph);
  SaveToFile(converter.ToDOT(graph), "/tmp/mutation_str_before.dot");
  grammar.MutationReplaceSubTree(graph);
  SaveToFile(converter.ToDOT(graph), "/tmp/mutation_str_after.dot");
}

void TestMutationReplaceCommand() {
  sc::Grammar grammar(g_test_grammar_path);
  sc::Converter converter(grammar);
  sg::Graph graph;
  grammar.SetMaximumDepth(3);
  grammar.RandomGraph(graph);
  SaveToFile(converter.ToDOT(graph), "/tmp/mutation_str_before.dot");
  SaveToFile(converter.ToSynthDef(graph, "before"),
             "/tmp/mutation_str_before.sc");
  grammar.MutationReplaceCommand(graph);
  SaveToFile(converter.ToDOT(graph), "/tmp/mutation_str_after.dot");
  SaveToFile(converter.ToSynthDef(graph, "after"),
             "/tmp/mutation_str_after.sc");
}

void TestMutationInsertCommand() {
  sc::Grammar grammar(g_test_grammar_path);
  sc::Converter converter(grammar);
  sg::Graph graph;
  grammar.SetMaximumDepth(4);
  grammar.RandomGraph(graph);
  SaveToFile(converter.ToDOT(graph), "/tmp/mutation_str_before.dot");
  SaveToFile(converter.ToSynthDef(graph, "before"),
             "/tmp/mutation_str_before.sc");
  grammar.MutationInsertCommand(graph);
  SaveToFile(converter.ToDOT(graph), "/tmp/mutation_str_after.dot");
  SaveToFile(converter.ToSynthDef(graph, "after"),
             "/tmp/mutation_str_after.sc");
}

void DoEvolution(const ProgramOptions& settings) {
  // prepare the file comparer
  dsp::FileComparer target(settings.fitness_features_,
                           static_cast<int>(settings.analysis_window_size_),
                           static_cast<int>(settings.analysis_hop_size_));
  target.SetTargetFile(settings.target_path_);
  // prepare the supercollider objects
  std::string grammar_json;
  if (settings.grammar_path_.empty()) {
    grammar_json.assign(sc::g_default_grammar);
  } else {
    grammar_json = stdx::LoadFile(settings.grammar_path_);
  }
  sc::Grammar grammar(grammar_json);
  grammar.SetMaximumDepth(static_cast<int>(settings.maximum_tree_depth_));
  sc::Evaluator evaluator(grammar,
                          settings.sc_app_path_,
                          target,
                          static_cast<int>(settings.core_limit_));
  sc::Converter converter(grammar);
  // set up the population
  Population population(&grammar, &converter, &evaluator);
  population.SetWorkFolder(settings.work_folder_);
  population.SetFitnessThreshold(settings.fitness_threshold_);
  population.SetCrossoverRate(settings.crossover_rate_);
  population.SetMutationRate(settings.mutation_rate_);
  population.SetTournamentSize(static_cast<int>(settings.tournament_size_));
  population.SetReproduceBest(settings.reproduce_best_individual_);
  population.InitializePopulation(settings.population_size_);
  population.SetKeepTempFolders(settings.keep_temp_folders_);
  // run the evolution loop
  population.Evolve(static_cast<int>(settings.generations_));
}

int main(int argument_count, const char* arguments[])
{
  srand(static_cast<unsigned int>(time(NULL)));
  try {
    // parse the command line options
    ProgramOptions settings;
    ParseCommandLine(argument_count, arguments, &settings);
    DoEvolution(settings);
    
    //TestCrossover();
    //TestMutationReplaceSubtree();
    //TestMutationInsertCommand();
    //TestMutationReplaceCommand();
  } catch (const std::exception& e) {
    std::stringstream message;
    message << "Exception: " << e.what() << '\n';
    logger::Log(message.str());
    logger::Flush();
    return -1;
  }
  logger::Flush();
}