diff options
author | David Robillard <d@drobilla.net> | 2007-12-07 03:05:20 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2007-12-07 03:05:20 +0000 |
commit | ffb37e6de2934aa227c3483f8a00118e3604b5e5 (patch) | |
tree | 8c40493f8de562677e1e54cc4b26a1fbbb493d26 /src/engine | |
parent | 33e9991326a1cd90a4956f3221f5a48d03d5af89 (diff) | |
download | machina-ffb37e6de2934aa227c3483f8a00118e3604b5e5.tar.gz machina-ffb37e6de2934aa227c3483f8a00118e3604b5e5.tar.bz2 machina-ffb37e6de2934aa227c3483f8a00118e3604b5e5.zip |
It's evolution, baby.
git-svn-id: http://svn.drobilla.net/lad/machina@958 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/engine')
-rw-r--r-- | src/engine/Engine.cpp | 3 | ||||
-rw-r--r-- | src/engine/Evolver.cpp | 88 | ||||
-rw-r--r-- | src/engine/JackDriver.cpp | 2 | ||||
-rw-r--r-- | src/engine/Machine.cpp | 88 | ||||
-rw-r--r-- | src/engine/Makefile.am | 3 | ||||
-rw-r--r-- | src/engine/MidiAction.cpp | 3 | ||||
-rw-r--r-- | src/engine/Mutation.cpp | 14 | ||||
-rw-r--r-- | src/engine/Problem.cpp | 45 | ||||
-rw-r--r-- | src/engine/machina/Engine.hpp | 5 | ||||
-rw-r--r-- | src/engine/machina/Evolver.hpp | 57 | ||||
-rw-r--r-- | src/engine/machina/Machine.hpp | 16 | ||||
-rw-r--r-- | src/engine/machina/Makefile.am | 1 | ||||
-rw-r--r-- | src/engine/machina/Mutation.hpp | 23 | ||||
-rw-r--r-- | src/engine/machina/Problem.hpp | 24 |
14 files changed, 308 insertions, 64 deletions
diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index 1417e6e..1a2fe56 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -16,9 +16,10 @@ */ #include <glibmm/ustring.h> -#include "machina/Loader.hpp" #include "machina/Engine.hpp" #include "machina/JackDriver.hpp" +#include "machina/Loader.hpp" +#include "machina/Machine.hpp" #include "machina/SMFDriver.hpp" namespace Machina { diff --git a/src/engine/Evolver.cpp b/src/engine/Evolver.cpp new file mode 100644 index 0000000..1d4decc --- /dev/null +++ b/src/engine/Evolver.cpp @@ -0,0 +1,88 @@ +/* This file is part of Machina. + * Copyright (C) 2007 Dave Robillard <http://drobilla.net> + * + * Machina 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 2 of the License, or (at your option) any later + * version. + * + * Machina 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 details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <iostream> +#include <eugene/core/Mutation.hpp> +#include <eugene/core/HybridMutation.hpp> +#include <eugene/core/TournamentSelection.hpp> +#include <machina/Evolver.hpp> +#include <machina/Mutation.hpp> +#include <machina/Problem.hpp> + +using namespace std; +using namespace Eugene; +using namespace boost; + +namespace Machina { + + +Evolver::Evolver(const string& target_midi, SharedPtr<Machine> seed) + : _problem(new Problem(target_midi, seed)) + , _active_fitness(-FLT_MAX) +{ + SharedPtr<Eugene::HybridMutation<Machine> > m(new HybridMutation<Machine>()); + + m->append_mutation(1/7.0f, boost::shared_ptr< Eugene::Mutation<Machine> >( + new Mutation::Compress())); + m->append_mutation(1/7.0f, boost::shared_ptr< Eugene::Mutation<Machine> >( + new Mutation::AddNode())); + m->append_mutation(1/7.0f, boost::shared_ptr< Eugene::Mutation<Machine> >( + new Mutation::RemoveNode())); + m->append_mutation(1/7.0f, boost::shared_ptr< Eugene::Mutation<Machine> >( + new Mutation::AdjustNode())); + m->append_mutation(1/7.0f, boost::shared_ptr< Eugene::Mutation<Machine> >( + new Mutation::AddEdge())); + m->append_mutation(1/7.0f, boost::shared_ptr< Eugene::Mutation<Machine> >( + new Mutation::RemoveEdge())); + m->append_mutation(1/7.0f, boost::shared_ptr< Eugene::Mutation<Machine> >( + new Mutation::AdjustEdge())); + + boost::shared_ptr< Selection<Machine> > s(new TournamentSelection<Machine>(_problem, 3, 0.8)); + boost::shared_ptr< Crossover<Machine> > crossover; + _ga = SharedPtr<MachinaGA>(new MachinaGA(_problem, s, crossover, m, 10, 10, 2, 1.0, 0.0)); +} + + +void +Evolver::seed(SharedPtr<Machine> parent) +{ + /*_best = SharedPtr<Machine>(new Machine(*parent.get())); + _best_fitness = _problem->fitness(*_best.get());*/ + _problem->seed(parent); + _active_fitness = _problem->fitness(*parent.get()); +} + + +void +Evolver::_run() +{ + float old_best = _ga->best_fitness(); + + while (true) { + _ga->iteration(); + + if (_ga->best_fitness() > old_best) { + _improvement = true; + old_best = _ga->best_fitness(); + cout << "NEW BEST: " << old_best << endl; + } + } +} + + +} // namespace Machina + diff --git a/src/engine/JackDriver.cpp b/src/engine/JackDriver.cpp index 3517250..93145b0 100644 --- a/src/engine/JackDriver.cpp +++ b/src/engine/JackDriver.cpp @@ -100,6 +100,7 @@ JackDriver::detach() void JackDriver::set_machine(SharedPtr<Machine> machine) { + cout << "DRIVER MACHINE: " << machine.get() << endl; SharedPtr<Machine> last_machine = _last_machine; // Keep a reference _machine_changed.reset(0); assert(!last_machine.unique()); @@ -320,6 +321,7 @@ JackDriver::stop() finish_record(); _stop(); // waits + _machine->deactivate(); } diff --git a/src/engine/Machine.cpp b/src/engine/Machine.cpp index fbda9ad..1a9e3ae 100644 --- a/src/engine/Machine.cpp +++ b/src/engine/Machine.cpp @@ -31,7 +31,8 @@ namespace Machina { Machine::Machine() - : _is_activated(false) + : _active_nodes(MAX_ACTIVE_NODES, SharedPtr<Node>()) + , _is_activated(false) , _is_finished(false) , _time(0) { @@ -45,22 +46,60 @@ Machine::Machine() */ Machine::Machine(const Machine& copy) : Raul::Stateful() // don't copy RDF ID + , _active_nodes(MAX_ACTIVE_NODES, SharedPtr<Node>()) , _is_activated(false) , _is_finished(false) , _time(0) , _sink(copy._sink) { - for (Nodes::const_iterator i = copy._nodes.begin(); i != copy._nodes.end(); ++i) { - SharedPtr<Machina::Node> node(new Machina::Node(*i->get())); + map< SharedPtr<Node>, SharedPtr<Node> > replacements; + + for (Nodes::const_iterator n = copy._nodes.begin(); n != copy._nodes.end(); ++n) { + SharedPtr<Machina::Node> node(new Machina::Node(*n->get())); _nodes.push_back(node); + replacements[*n] = node; + } + + for (Nodes::const_iterator n = _nodes.begin(); n != _nodes.end(); ++n) { + for (Node::Edges::const_iterator e = (*n)->edges().begin(); e != (*n)->edges().end(); ++e) { + (*e)->set_tail(*n); + (*e)->set_head(replacements[(*e)->head()]); + assert((*e)->head()); + } } } - -Machine::~Machine() + +Machine& +Machine::operator=(const Machine& other) { -} + _active_nodes = std::vector< SharedPtr<Node> >(MAX_ACTIVE_NODES, SharedPtr<Node>()); + _is_activated = false; + _is_finished = false; + _time = 0; + _pending_learn = SharedPtr<LearnRequest>(); + _sink = other._sink; + _nodes.clear(); + + map< SharedPtr<Node>, SharedPtr<Node> > replacements; + + for (Nodes::const_iterator n = other._nodes.begin(); n != other._nodes.end(); ++n) { + SharedPtr<Machina::Node> node(new Machina::Node(*n->get())); + _nodes.push_back(node); + replacements[*n] = node; + } + for (Nodes::const_iterator n = _nodes.begin(); n != _nodes.end(); ++n) { + for (Node::Edges::const_iterator e = (*n)->edges().begin(); e != (*n)->edges().end(); ++e) { + (*e)->set_tail(*n); + (*e)->set_head(replacements[(*e)->head()]); + assert((*e)->head()); + } + } + + return *this; +} + /** Set the MIDI sink to be used for executing MIDI actions. * @@ -128,13 +167,12 @@ Machine::remove_node(SharedPtr<Node> node) void Machine::reset(Raul::BeatTime time) { - for (size_t i=0; i < MAX_ACTIVE_NODES; ++i) { - _active_nodes[i].reset(); - } + for (size_t i=0; i < MAX_ACTIVE_NODES; ++i) + _active_nodes.at(i).reset(); if (!_is_finished) { for (Nodes::const_iterator n = _nodes.begin(); n != _nodes.end(); ++n) { - const SharedPtr<Node> node = (*n); + SharedPtr<Node> node = (*n); if (node->is_active()) node->exit(_sink.lock(), time); @@ -156,7 +194,7 @@ Machine::earliest_node() const SharedPtr<Node> earliest; for (size_t i=0; i < MAX_ACTIVE_NODES; ++i) { - const SharedPtr<Node> node = _active_nodes[i]; + SharedPtr<Node> node = _active_nodes.at(i); if (node) { assert(node->is_active()); @@ -175,7 +213,7 @@ Machine::earliest_node() const * Returns true if node was entered, or false if the maximum active nodes has been reached. */ bool -Machine::enter_node(const SharedPtr<Raul::MIDISink> sink, const SharedPtr<Node> node) +Machine::enter_node(SharedPtr<Raul::MIDISink> sink, SharedPtr<Node> node) { assert(!node->is_active()); @@ -183,10 +221,10 @@ Machine::enter_node(const SharedPtr<Raul::MIDISink> sink, const SharedPtr<Node> * while all actions are still MIDI notes... */ size_t index = (rand() % MAX_ACTIVE_NODES); for (size_t i=0; i < MAX_ACTIVE_NODES; ++i) { - if (_active_nodes[index] == NULL) { + if (_active_nodes.at(index)== NULL) { node->enter(sink, _time); assert(node->is_active()); - _active_nodes[index] = node; + _active_nodes.at(index) = node; return true; } index = (index + 1) % MAX_ACTIVE_NODES; @@ -201,16 +239,14 @@ Machine::enter_node(const SharedPtr<Raul::MIDISink> sink, const SharedPtr<Node> /** Exit an active node at the current _time. */ void -Machine::exit_node(SharedPtr<Raul::MIDISink> sink, const SharedPtr<Node> node) +Machine::exit_node(SharedPtr<Raul::MIDISink> sink, SharedPtr<Node> node) { node->exit(sink, _time); assert(!node->is_active()); - for (size_t i=0; i < MAX_ACTIVE_NODES; ++i) { - if (_active_nodes[i] == node) { - _active_nodes[i].reset(); - } - } + for (size_t i=0; i < MAX_ACTIVE_NODES; ++i) + if (_active_nodes.at(i) == node) + _active_nodes.at(i).reset(); // Activate successors to this node // (that aren't aready active right now) @@ -237,13 +273,13 @@ Machine::exit_node(SharedPtr<Raul::MIDISink> sink, const SharedPtr<Node> node) } else { - for (Node::Edges::const_iterator s = node->edges().begin(); - s != node->edges().end(); ++s) { + for (Node::Edges::const_iterator e = node->edges().begin(); + e != node->edges().end(); ++e) { const double rand_normal = rand() / (double)RAND_MAX; // [0, 1] - if (rand_normal <= (*s)->probability()) { - SharedPtr<Node> head = (*s)->head(); + if (rand_normal <= (*e)->probability()) { + SharedPtr<Node> head = (*e)->head(); if ( ! head->is_active()) enter_node(sink, head); @@ -269,7 +305,7 @@ Machine::run(const Raul::TimeSlice& time) if (_is_finished) return 0; - const SharedPtr<Raul::MIDISink> sink = _sink.lock(); + SharedPtr<Raul::MIDISink> sink = _sink.lock(); const TickTime cycle_end_ticks = time.start_ticks() + time.length_ticks() - 1; const BeatCount cycle_end_beats = time.ticks_to_beats(cycle_end_ticks); @@ -330,7 +366,7 @@ Machine::run(const Raul::TimeSlice& time) } - assert(this_time <= time.length_beats()); + //assert(this_time <= time.length_beats()); return this_time; } diff --git a/src/engine/Makefile.am b/src/engine/Makefile.am index c46ffed..e79502e 100644 --- a/src/engine/Makefile.am +++ b/src/engine/Makefile.am @@ -3,13 +3,14 @@ SUBDIRS = machina lib_LTLIBRARIES = libmachina.la libmachina_la_CXXFLAGS = @EUGENE_CFLAGS@ @REDLANDMM_CFLAGS@ @RAUL_CFLAGS@ @JACK_CFLAGS@ @GLIBMM_CFLAGS@ -libmachina_la_LIBADD = @EUGENE_LIBS@ @RAUL_LIBS@ @JACK_LIBS@ @GLIBMM_LIBS@ +libmachina_la_LIBADD = @EUGENE_LIBS@ @REDLANDMM_LIBS@ @RAUL_LIBS@ @JACK_LIBS@ @GLIBMM_LIBS@ libmachina_la_SOURCES = \ Action.cpp \ ActionFactory.cpp \ Edge.cpp \ Engine.cpp \ + Evolver.cpp \ LearnRequest.cpp \ Loader.cpp \ Machine.cpp \ diff --git a/src/engine/MidiAction.cpp b/src/engine/MidiAction.cpp index ac96211..46985ce 100644 --- a/src/engine/MidiAction.cpp +++ b/src/engine/MidiAction.cpp @@ -44,8 +44,7 @@ MidiAction::MidiAction(size_t size, MidiAction::~MidiAction() { - if (_event.get()) - delete _event.get(); + delete[] _event.get(); } diff --git a/src/engine/Mutation.cpp b/src/engine/Mutation.cpp index c861810..95e31a3 100644 --- a/src/engine/Mutation.cpp +++ b/src/engine/Mutation.cpp @@ -31,6 +31,8 @@ namespace Mutation { void Compress::mutate(Machine& machine) { + //cout << "COMPRESS" << endl; + // Trim disconnected nodes for (Machine::Nodes::iterator i = machine.nodes().begin(); i != machine.nodes().end() ;) { Machine::Nodes::iterator next = i; @@ -47,6 +49,8 @@ Compress::mutate(Machine& machine) void AddNode::mutate(Machine& machine) { + //cout << "ADD NODE" << endl; + // Create random node SharedPtr<Node> node(new Node(1.0)); uint8_t note = rand() % 128; @@ -64,6 +68,8 @@ AddNode::mutate(Machine& machine) void RemoveNode::mutate(Machine& machine) { + //cout << "REMOVE NODE" << endl; + SharedPtr<Node> node = machine.random_node(); machine.remove_node(node); } @@ -72,6 +78,8 @@ RemoveNode::mutate(Machine& machine) void AdjustNode::mutate(Machine& machine) { + //cout << "ADJUST NODE" << endl; + SharedPtr<Node> node = machine.random_node(); if (node) { SharedPtr<MidiAction> enter_action = PtrCast<MidiAction>(node->enter_action()); @@ -89,6 +97,8 @@ AdjustNode::mutate(Machine& machine) void AddEdge::mutate(Machine& machine) { + //cout << "ADJUST EDGE" << endl; + SharedPtr<Node> tail = machine.random_node(); SharedPtr<Node> head = machine.random_node(); @@ -100,6 +110,8 @@ AddEdge::mutate(Machine& machine) void RemoveEdge::mutate(Machine& machine) { + //cout << "REMOVE EDGE" << endl; + SharedPtr<Node> tail = machine.random_node(); if (tail) tail->remove_edge(tail->random_edge()); @@ -109,6 +121,8 @@ RemoveEdge::mutate(Machine& machine) void AdjustEdge::mutate(Machine& machine) { + //cout << "ADJUST EDGE" << endl; + SharedPtr<Edge> edge = machine.random_edge(); if (edge) edge->set_probability(rand() / (float)RAND_MAX); diff --git a/src/engine/Problem.cpp b/src/engine/Problem.cpp index f57aa15..654d0a3 100644 --- a/src/engine/Problem.cpp +++ b/src/engine/Problem.cpp @@ -20,14 +20,16 @@ #include <machina/Machine.hpp> #include <raul/SMFReader.hpp> #include <raul/midi_events.h> +#include <eugene/core/Problem.hpp> using namespace std; namespace Machina { -Problem::Problem(const std::string& target_midi) +Problem::Problem(const std::string& target_midi, SharedPtr<Machine> seed) : _target(*this) + , _seed(new Machine(*seed.get())) { Raul::SMFReader smf; const bool opened = smf.open(target_midi); @@ -51,33 +53,40 @@ Problem::Problem(const std::string& target_midi) float -Problem::fitness(Machine& machine) +Problem::fitness(const Machine& const_machine) const { + // kluuudge + Machine& machine = const_cast<Machine&>(const_machine); + SharedPtr<Evaluator> eval(new Evaluator(*this)); machine.reset(0.0f); + machine.deactivate(); + machine.activate(); machine.set_sink(eval); // FIXME: timing stuff here isn't right at all... - unsigned ppqn = 19200; - Raul::TimeSlice time(ppqn, 120); + static const unsigned ppqn = 19200; + Raul::TimeSlice time(1.0/(double)ppqn, 120); time.set_start(0); - time.set_length(ppqn); + time.set_length(2*ppqn); while (time.start_ticks() < _target._n_notes * ppqn) { machine.run(time); - time.set_start(time.start_ticks() + ppqn); + time.set_start(time.start_ticks() + 2*ppqn); } eval->compute(); float f = 0; - // Punish for frequency differences. - // Optimal fitness = 0 (max) - for (uint8_t i=0; i < 128; ++i) - f -= fabs(_target._note_frequency[i] - eval->_note_frequency[i]); + for (uint8_t i=0; i < 128; ++i) { + if (eval->_note_frequency[i] <= _target._note_frequency[i]) + f += eval->_note_frequency[i]; + else + f -= _target._note_frequency[i] - eval->_note_frequency[i]; + } return f; } @@ -99,12 +108,24 @@ Problem::Evaluator::write_event(Raul::BeatTime time, void Problem::Evaluator::compute() { - for (uint8_t i=0; i < 128; ++i) { + /*for (uint8_t i=0; i < 128; ++i) { if (_note_frequency[i] > 0) { _note_frequency[i] /= (float)_n_notes; //cout << (int)i << ":\t" << _note_frequency[i] << endl; } - } + }*/ +} + + +boost::shared_ptr<Problem::Population> +Problem::initial_population(size_t gene_size, size_t pop_size) const +{ + boost::shared_ptr<Population> ret(new std::vector<Machine>()); + + for (size_t i = 0; i < pop_size; ++i) + ret->push_back(Machine(*_seed.get())); + + return ret; } diff --git a/src/engine/machina/Engine.hpp b/src/engine/machina/Engine.hpp index d8d16d9..effa4be 100644 --- a/src/engine/machina/Engine.hpp +++ b/src/engine/machina/Engine.hpp @@ -35,7 +35,8 @@ public: : _driver(driver) , _rdf_world(rdf_world) , _loader(_rdf_world) - { } + { + } Redland::World& rdf_world() { return _rdf_world; } @@ -51,7 +52,7 @@ public: private: SharedPtr<Driver> _driver; - Redland::World& _rdf_world; + Redland::World& _rdf_world; Loader _loader; }; diff --git a/src/engine/machina/Evolver.hpp b/src/engine/machina/Evolver.hpp new file mode 100644 index 0000000..051513b --- /dev/null +++ b/src/engine/machina/Evolver.hpp @@ -0,0 +1,57 @@ +/* This file is part of Machina. + * Copyright (C) 2007 Dave Robillard <http://drobilla.net> + * + * Machina 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 2 of the License, or (at your option) any later + * version. + * + * Machina 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 details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef MACHINA_EVOLVER_HPP +#define MACHINA_EVOLVER_HPP + +#include <raul/SharedPtr.hpp> +#include <raul/Thread.hpp> +#include <eugene/core/GAImpl.hpp> +#include "Schrodinbit.hpp" + +namespace Eugene { template <typename G> class HybridMutation; } + +namespace Machina { + +class Machine; +class Problem; + + +class Evolver : public Raul::Thread { +public: + Evolver(const string& target_midi, SharedPtr<Machine> seed); + + void seed(SharedPtr<Machine> parent); + bool improvement() { return _improvement; } + + SharedPtr<const Machine> best() { return _ga->best(); } + + typedef Eugene::GAImpl<Machine> MachinaGA; + +private: + void _run(); + + SharedPtr<MachinaGA> _ga; + SharedPtr<Problem> _problem; + float _active_fitness; + Schrodinbit _improvement; +}; + + +} // namespace Machina + +#endif // MACHINA_EVOLVER_HPP diff --git a/src/engine/machina/Machine.hpp b/src/engine/machina/Machine.hpp index 4544090..5c4df36 100644 --- a/src/engine/machina/Machine.hpp +++ b/src/engine/machina/Machine.hpp @@ -18,6 +18,7 @@ #ifndef MACHINA_MACHINE_HPP #define MACHINA_MACHINE_HPP +#include <vector> #include <boost/utility.hpp> #include <raul/SharedPtr.hpp> #include <raul/WeakPtr.hpp> @@ -37,7 +38,11 @@ class Machine : public Raul::Stateful { public: Machine(); Machine(const Machine& copy); - ~Machine(); + + Machine& operator=(const Machine& other); + + // Kluge to appease Eugene + bool operator==(const Machine& other) { return false; } // Main context void activate() { _is_activated = true; } @@ -64,7 +69,8 @@ public: void clear_pending_learn() { _pending_learn.reset(); } typedef Raul::List< SharedPtr<Node> > Nodes; - Nodes& nodes() { return _nodes; } + Nodes& nodes() { return _nodes; } + const Nodes& nodes() const { return _nodes; } SharedPtr<Node> random_node(); SharedPtr<Edge> random_edge(); @@ -75,11 +81,11 @@ private: // Audio context SharedPtr<Node> earliest_node() const; - bool enter_node(const SharedPtr<Raul::MIDISink> sink, const SharedPtr<Node> node); - void exit_node(const SharedPtr<Raul::MIDISink> sink, const SharedPtr<Node>); + bool enter_node(SharedPtr<Raul::MIDISink> sink, SharedPtr<Node> node); + void exit_node(SharedPtr<Raul::MIDISink> sink, SharedPtr<Node>); static const size_t MAX_ACTIVE_NODES = 128; - SharedPtr<Node> _active_nodes[MAX_ACTIVE_NODES]; + std::vector< SharedPtr<Node> > _active_nodes; bool _is_activated; bool _is_finished; diff --git a/src/engine/machina/Makefile.am b/src/engine/machina/Makefile.am index f37974c..e4f4bf0 100644 --- a/src/engine/machina/Makefile.am +++ b/src/engine/machina/Makefile.am @@ -6,6 +6,7 @@ libmachinainclude_HEADERS = \ Driver.hpp \ Edge.hpp \ Engine.hpp \ + Evolver.hpp \ JackDriver.hpp \ LearnRequest.hpp \ Loader.hpp \ diff --git a/src/engine/machina/Mutation.hpp b/src/engine/machina/Mutation.hpp index 0a9731c..52c02bc 100644 --- a/src/engine/machina/Mutation.hpp +++ b/src/engine/machina/Mutation.hpp @@ -18,6 +18,15 @@ #ifndef MACHINA_MACHINE_MUTATION_HPP #define MACHINA_MACHINE_MUTATION_HPP +#include CONFIG_H_PATH + +#if HAVE_EUGENE + #include <eugene/core/Mutation.hpp> + #define SUPER : public Eugene::Mutation<Machine> +#else + #define SUPER +#endif + namespace Machina { class Machine; @@ -26,13 +35,13 @@ namespace Mutation { struct Mutation { virtual void mutate(Machine& machine) = 0; }; -struct Compress { static void mutate(Machine& machine); }; -struct AddNode { static void mutate(Machine& machine); }; -struct RemoveNode { static void mutate(Machine& machine); }; -struct AdjustNode { static void mutate(Machine& machine); }; -struct AddEdge { static void mutate(Machine& machine); }; -struct RemoveEdge { static void mutate(Machine& machine); }; -struct AdjustEdge { static void mutate(Machine& machine); }; +struct Compress SUPER { void mutate(Machine& machine); }; +struct AddNode SUPER { void mutate(Machine& machine); }; +struct RemoveNode SUPER { void mutate(Machine& machine); }; +struct AdjustNode SUPER { void mutate(Machine& machine); }; +struct AddEdge SUPER { void mutate(Machine& machine); }; +struct RemoveEdge SUPER { void mutate(Machine& machine); }; +struct AdjustEdge SUPER { void mutate(Machine& machine); }; } // namespace Mutation diff --git a/src/engine/machina/Problem.hpp b/src/engine/machina/Problem.hpp index d221e5c..abfc534 100644 --- a/src/engine/machina/Problem.hpp +++ b/src/engine/machina/Problem.hpp @@ -19,21 +19,28 @@ #define MACHINA_PROBLEM_HPP #include <raul/MIDISink.hpp> +#include <eugene/core/Problem.hpp> +#include <machina/Machine.hpp> namespace Machina { -class Machine; - -class Problem { +class Problem : public Eugene::Problem<Machine> { public: - Problem(const std::string& target_midi); + Problem(const std::string& target_midi, SharedPtr<Machine> seed = SharedPtr<Machine>()); + + void seed(SharedPtr<Machine> parent) { _seed = parent; } - float fitness(Machine& machine); + float fitness(const Machine& machine) const; + + bool fitness_less_than(float a, float b) const { return a < b; } + + boost::shared_ptr<Population> + initial_population(size_t gene_size, size_t pop_size) const; private: struct Evaluator : public Raul::MIDISink { - Evaluator(Problem& problem) : _problem(problem), _n_notes(0) { + Evaluator(const Problem& problem) : _problem(problem), _n_notes(0) { for (uint8_t i=0; i < 128; ++i) _note_frequency[i] = 0; } @@ -41,13 +48,14 @@ private: size_t ev_size, const uint8_t* ev) throw (std::logic_error); void compute(); - Problem& _problem; + const Problem& _problem; float _note_frequency[128]; size_t _n_notes; }; - Evaluator _target; + Evaluator _target; + SharedPtr<Machine> _seed; }; |