diff options
Diffstat (limited to 'src/engine')
-rw-r--r-- | src/engine/Action.hpp | 5 | ||||
-rw-r--r-- | src/engine/Edge.hpp | 4 | ||||
-rw-r--r-- | src/engine/Evolver.cpp | 67 | ||||
-rw-r--r-- | src/engine/Machine.cpp | 12 | ||||
-rw-r--r-- | src/engine/Mutation.cpp | 16 | ||||
-rw-r--r-- | src/engine/Node.cpp | 18 | ||||
-rw-r--r-- | src/engine/Node.hpp | 8 | ||||
-rw-r--r-- | src/engine/Problem.cpp | 47 | ||||
-rw-r--r-- | src/engine/Problem.hpp | 15 | ||||
-rw-r--r-- | src/engine/machina/Evolver.hpp | 24 | ||||
-rw-r--r-- | src/engine/machina/Machine.hpp | 9 | ||||
-rw-r--r-- | src/engine/machina/Mutation.hpp | 26 |
12 files changed, 155 insertions, 96 deletions
diff --git a/src/engine/Action.hpp b/src/engine/Action.hpp index 79b7fca..90f8664 100644 --- a/src/engine/Action.hpp +++ b/src/engine/Action.hpp @@ -34,7 +34,10 @@ namespace machina { */ struct Action : public Raul::Maid::Manageable - , public Stateful { + , public Stateful +{ + bool operator==(const Action& rhs) const { return false; } + virtual void execute(MIDISink* sink, Raul::TimeStamp time) = 0; virtual void write_state(Sord::Model& model) {} diff --git a/src/engine/Edge.hpp b/src/engine/Edge.hpp index db91ca7..e2ddb98 100644 --- a/src/engine/Edge.hpp +++ b/src/engine/Edge.hpp @@ -18,7 +18,6 @@ #define MACHINA_EDGE_HPP #include <list> -#include <boost/utility.hpp> #include "raul/DoubleBuffer.hpp" @@ -31,8 +30,7 @@ namespace machina { class Node; -class Edge - : public Stateful +class Edge : public Stateful { public: Edge(WPtr<Node> tail, SPtr<Node> head, float probability=1.0f) diff --git a/src/engine/Evolver.cpp b/src/engine/Evolver.cpp index eb697b6..906e888 100644 --- a/src/engine/Evolver.cpp +++ b/src/engine/Evolver.cpp @@ -26,8 +26,7 @@ #include "Problem.hpp" using namespace std; -using namespace Eugene; -using namespace boost; +using namespace eugene; namespace machina { @@ -37,39 +36,51 @@ Evolver::Evolver(TimeUnit unit, : _problem(new Problem(unit, target_midi, seed)) , _seed_fitness(-FLT_MAX) { - SPtr<Eugene::HybridMutation<Machine> > m(new HybridMutation<Machine>()); + SPtr<eugene::HybridMutation<Machine> > m(new HybridMutation<Machine>()); - m->append_mutation(1 / 6.0f, boost::shared_ptr< Eugene::Mutation<Machine> >( - new Mutation::Compress())); - m->append_mutation(1 / 6.0f, boost::shared_ptr< Eugene::Mutation<Machine> >( - new Mutation::AddNode())); - //m->append_mutation(1/6.0f, boost::shared_ptr< Eugene::Mutation<Machine> >( + m->append_mutation(1 / 6.0f, std::shared_ptr< eugene::Mutation<Machine> >( + new Mutation::Compress())); + m->append_mutation(1 / 6.0f, std::shared_ptr< eugene::Mutation<Machine> >( + new Mutation::AddNode())); + //m->append_mutation(1/6.0f, std::shared_ptr< eugene::Mutation<Machine> >( // new Mutation::RemoveNode())); - //m->append_mutation(1/6.0f, boost::shared_ptr< Eugene::Mutation<Machine> >( + //m->append_mutation(1/6.0f, std::shared_ptr< eugene::Mutation<Machine> >( // new Mutation::AdjustNode())); - m->append_mutation(1 / 6.0f, boost::shared_ptr< Eugene::Mutation<Machine> >( - new Mutation::SwapNodes())); - m->append_mutation(1 / 6.0f, boost::shared_ptr< Eugene::Mutation<Machine> >( - new Mutation::AddEdge())); - m->append_mutation(1 / 6.0f, boost::shared_ptr< Eugene::Mutation<Machine> >( - new Mutation::RemoveEdge())); - m->append_mutation(1 / 6.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; + m->append_mutation(1 / 6.0f, std::shared_ptr< eugene::Mutation<Machine> >( + new Mutation::SwapNodes())); + m->append_mutation(1 / 6.0f, std::shared_ptr< eugene::Mutation<Machine> >( + new Mutation::AddEdge())); + m->append_mutation(1 / 6.0f, std::shared_ptr< eugene::Mutation<Machine> >( + new Mutation::RemoveEdge())); + m->append_mutation(1 / 6.0f, std::shared_ptr< eugene::Mutation<Machine> >( + new Mutation::AdjustEdge())); + + std::shared_ptr< Selection<Machine> > s( + new TournamentSelection<Machine>(*_problem.get(), 3, 0.8)); + std::shared_ptr< Crossover<Machine> > crossover; + size_t gene_length = 20; // FIXME + Problem::Population pop; _ga = SPtr<MachinaGA>( - new MachinaGA(_problem, s, crossover, m, 20, 20, 2, 1.0, 0.0)); + new MachinaGA(_rng, + _problem, + s, + crossover, + m, + pop, + gene_length, + 20, + 2, + 1.0, + 0.0)); } void Evolver::seed(SPtr<Machine> parent) { /*_best = SPtr<Machine>(new Machine(*parent.get())); - _best_fitness = _problem->fitness(*_best.get());*/ + _best_fitness = _problem->fitness(*_best.get());*/ _problem->seed(parent); - _seed_fitness = _problem->fitness(*parent.get()); + _seed_fitness = _problem->evaluate(*parent.get()); } void @@ -89,10 +100,10 @@ Evolver::_run() float new_best = _ga->best_fitness(); /*cout << _problem->fitness_less(old_best, *_ga->best().get()) << endl; - cout << "best: " << _ga->best().get() << endl; - cout << "best fitness: " << _problem->fitness(*_ga->best().get()) << endl; - cout << "old best: " << old_best << endl; - cout << "new best: " << new_best << endl;*/ + cout << "best: " << _ga->best().get() << endl; + cout << "best fitness: " << _problem->fitness(*_ga->best().get()) << endl; + cout << "old best: " << old_best << endl; + cout << "new best: " << new_best << endl;*/ cout << "generation best: " << new_best << endl; if (_problem->fitness_less_than(old_best, new_best)) { diff --git a/src/engine/Machine.cpp b/src/engine/Machine.cpp index 3cb85c1..155ef86 100644 --- a/src/engine/Machine.cpp +++ b/src/engine/Machine.cpp @@ -38,7 +38,8 @@ using namespace Raul; namespace machina { Machine::Machine(TimeUnit unit) - : _initial_node(new Node(TimeStamp(unit, 0, 0), true)) + : fitness(0.0) + , _initial_node(new Node(TimeStamp(unit, 0, 0), true)) , _active_nodes(MAX_ACTIVE_NODES, SPtr<Node>()) , _time(unit, 0, 0) , _is_finished(false) @@ -71,6 +72,7 @@ Machine::assign(const Machine& copy) Machine::Machine(const Machine& copy) : Stateful() // don't copy RDF ID + , fitness(0.0) , _initial_node(new Node(TimeStamp(copy.time().unit(), 0, 0), true)) , _active_nodes(MAX_ACTIVE_NODES, SPtr<Node>()) , _time(copy.time()) @@ -87,6 +89,8 @@ Machine::operator=(const Machine& copy) return *this; } + fitness = copy.fitness; + _active_nodes = std::vector< SPtr<Node> >(MAX_ACTIVE_NODES, SPtr<Node>()); _is_finished = false; _time = copy._time; @@ -99,6 +103,12 @@ Machine::operator=(const Machine& copy) return *this; } +bool +Machine::operator==(const Machine& rhs) const +{ + return false; +} + void Machine::merge(const Machine& machine) { diff --git a/src/engine/Mutation.cpp b/src/engine/Mutation.cpp index 878205d..776142d 100644 --- a/src/engine/Mutation.cpp +++ b/src/engine/Mutation.cpp @@ -30,7 +30,7 @@ namespace machina { namespace Mutation { void -Compress::mutate(Machine& machine) +Compress::mutate(Random& rng, Machine& machine) { //cout << "COMPRESS" << endl; @@ -49,7 +49,7 @@ Compress::mutate(Machine& machine) } void -AddNode::mutate(Machine& machine) +AddNode::mutate(Random& rng, Machine& machine) { //cout << "ADD NODE" << endl; @@ -88,7 +88,7 @@ AddNode::mutate(Machine& machine) } void -RemoveNode::mutate(Machine& machine) +RemoveNode::mutate(Random& rng, Machine& machine) { //cout << "REMOVE NODE" << endl; @@ -99,7 +99,7 @@ RemoveNode::mutate(Machine& machine) } void -AdjustNode::mutate(Machine& machine) +AdjustNode::mutate(Random& rng, Machine& machine) { //cout << "ADJUST NODE" << endl; @@ -119,7 +119,7 @@ AdjustNode::mutate(Machine& machine) } void -SwapNodes::mutate(Machine& machine) +SwapNodes::mutate(Random& rng, Machine& machine) { //cout << "SWAP NODE" << endl; @@ -148,7 +148,7 @@ SwapNodes::mutate(Machine& machine) } void -AddEdge::mutate(Machine& machine) +AddEdge::mutate(Random& rng, Machine& machine) { //cout << "ADJUST EDGE" << endl; @@ -164,7 +164,7 @@ AddEdge::mutate(Machine& machine) } void -RemoveEdge::mutate(Machine& machine) +RemoveEdge::mutate(Random& rng, Machine& machine) { //cout << "REMOVE EDGE" << endl; @@ -175,7 +175,7 @@ RemoveEdge::mutate(Machine& machine) } void -AdjustEdge::mutate(Machine& machine) +AdjustEdge::mutate(Random& rng, Machine& machine) { //cout << "ADJUST EDGE" << endl; diff --git a/src/engine/Node.cpp b/src/engine/Node.cpp index 8ee92e7..cf326a1 100644 --- a/src/engine/Node.cpp +++ b/src/engine/Node.cpp @@ -57,6 +57,24 @@ Node::Node(const Node& copy) } } +static inline bool +action_equals(SPtr<const Action> a, SPtr<const Action> b) +{ + return (a == b) || (a && b && *a.get() == *b.get()); +} + +bool +Node::operator==(const Node& rhs) const +{ + return _duration == rhs._duration && + _is_initial == rhs._is_initial && + _is_selector == rhs._is_selector && + _is_active == rhs._is_active && + action_equals(_enter_action, rhs.enter_action()) && + action_equals(_exit_action, rhs.exit_action()); + // TODO: compare edges +} + /** Always returns an edge, unless there are none */ SPtr<Edge> Node::random_edge() diff --git a/src/engine/Node.hpp b/src/engine/Node.hpp index 3b22d81..8a76bf7 100644 --- a/src/engine/Node.hpp +++ b/src/engine/Node.hpp @@ -47,11 +47,15 @@ public: Node(TimeDuration duration, bool initial=false); Node(const Node& copy); + bool operator==(const Node& rhs) const; + void set_enter_action(SPtr<Action> action); void set_exit_action(SPtr<Action> action); - SPtr<Action> enter_action() { return _enter_action; } - SPtr<Action> exit_action() { return _exit_action; } + SPtr<const Action> enter_action() const { return _enter_action; } + SPtr<Action> enter_action() { return _enter_action; } + SPtr<const Action> exit_action() const { return _exit_action; } + SPtr<Action> exit_action() { return _exit_action; } void enter(MIDISink* sink, TimeStamp time); void exit(MIDISink* sink, TimeStamp time); diff --git a/src/engine/Problem.cpp b/src/engine/Problem.cpp index cbb360b..3b05fed 100644 --- a/src/engine/Problem.cpp +++ b/src/engine/Problem.cpp @@ -17,21 +17,23 @@ #define __STDC_LIMIT_MACROS 1 #include <stdint.h> + #include <set> #include <vector> #include <iostream> +#include "lv2/lv2plug.in/ns/ext/midi/midi.h" + #include "eugene/Problem.hpp" -#include "machina/Edge.hpp" #include "machina/Machine.hpp" -#include "raul/SMFReader.hpp" -#include "raul/midi_events.h" - -#include "machina_config.h" #include "ActionFactory.hpp" +#include "Edge.hpp" +#include "MidiAction.hpp" #include "Problem.hpp" +#include "SMFReader.hpp" +#include "machina_config.h" using namespace std; @@ -74,8 +76,9 @@ Problem::Problem(TimeUnit unit, } float -Problem::fitness(const Machine& const_machine) const +Problem::evaluate(const Machine& const_machine) const { + #if 0 //cout << "("; // kluuudge @@ -89,8 +92,6 @@ Problem::fitness(const Machine& const_machine) const SPtr<Evaluator> eval(new Evaluator(*this)); //machine.reset(); - machine.deactivate(); - machine.activate(); machine.set_sink(eval); // FIXME: timing stuff here isn't right at all... @@ -167,6 +168,8 @@ Problem::fitness(const Machine& const_machine) const _fitness[&machine] = f; return f; + #endif + return 0.0f; } void @@ -174,7 +177,7 @@ Problem::Evaluator::write_event(Raul::TimeStamp time, size_t ev_size, const uint8_t* ev) throw (std::logic_error) { - if ((ev[0] & 0xF0) == MIDI_CMD_NOTE_ON) { + if ((ev[0] & 0xF0) == LV2_MIDI_MSG_NOTE_ON) { const uint8_t note = ev[1]; @@ -197,9 +200,9 @@ Problem::Evaluator::write_event(Raul::TimeStamp time, for (size_t i = 0; i < _read.length(); ++i) { const string pattern = _read.substr(i); - Patterns::iterator i = _patterns.find(pattern); - if (i != _patterns.end()) { - ++(i->second); + Patterns::iterator p = _patterns.find(pattern); + if (p != _patterns.end()) { + ++(p->second); } else { _patterns[pattern] = 1; } @@ -223,11 +226,12 @@ Problem::Evaluator::compute() }*/ } -boost::shared_ptr<Problem::Population> -Problem::initial_population(size_t gene_size, size_t pop_size) const +void +Problem::initial_population(eugene::Random& rng, + Population& pop, + size_t gene_size, + size_t pop_size) const { - boost::shared_ptr<Population> ret(new std::vector<Machine>()); - // FIXME: ignores _seed and builds based on MIDI // evolution of the visible machine would be nice.. SPtr<Machine> base = SPtr<Machine>(new Machine(_unit)); @@ -247,20 +251,19 @@ Problem::initial_population(size_t gene_size, size_t pop_size) const Machine m(*base.get()); set< SPtr<Node> > unreachable; - SPtr<Node> initial; for (Machine::Nodes::iterator i = m.nodes().begin(); i != m.nodes().end(); ++i) { if (dynamic_ptr_cast<MidiAction>((*i)->enter_action())->event()[1] == _target.first_note()) { - (*i)->set_initial(true); - initial = *i; + m.initial_node()->add_edge( + SPtr<Edge>(new Edge(m.initial_node(), *i))); } else { unreachable.insert(*i); } } - SPtr<Node> cur = initial; + SPtr<Node> cur = m.initial_node(); unreachable.erase(cur); SPtr<Node> head; @@ -278,13 +281,11 @@ Problem::initial_population(size_t gene_size, size_t pop_size) const } } - ret->push_back(m); + pop.push_back(m); /*cout << "initial # nodes: " << m.nodes().size(); cout << "initial fitness: " << fitness(m) << endl;*/ } - - return ret; } /** levenshtein distance (edit distance) */ diff --git a/src/engine/Problem.hpp b/src/engine/Problem.hpp index ced3675..81e67d7 100644 --- a/src/engine/Problem.hpp +++ b/src/engine/Problem.hpp @@ -17,7 +17,10 @@ #ifndef MACHINA_PROBLEM_HPP #define MACHINA_PROBLEM_HPP +#include <stdint.h> + #include <map> +#include <stdexcept> #include "machina/Machine.hpp" #include "eugene/Problem.hpp" @@ -26,7 +29,7 @@ namespace machina { -class Problem : public Eugene::Problem<Machine> { +class Problem : public eugene::Problem<Machine> { public: Problem(TimeUnit unit, const std::string& target_midi, @@ -35,14 +38,16 @@ public: void seed(SPtr<Machine> parent) { _seed = parent; } - float fitness(const Machine& machine) const; + float evaluate(const Machine& machine) const; bool fitness_less_than(float a, float b) const { return a < b; } void clear_fitness_cache() { _fitness.clear(); } - boost::shared_ptr<Population> - initial_population(size_t gene_size, size_t pop_size) const; + void initial_population(eugene::Random& rng, + Population& pop, + size_t gene_size, + size_t pop_size) const; private: size_t distance(const std::vector<uint8_t>& source, @@ -83,7 +88,7 @@ private: float _counts[128]; };*/ - struct Evaluator : public Raul::MIDISink { + struct Evaluator : public MIDISink { explicit Evaluator(const Problem& problem) : _problem(problem) , _order(4) diff --git a/src/engine/machina/Evolver.hpp b/src/engine/machina/Evolver.hpp index 17fae05..e14fc4a 100644 --- a/src/engine/machina/Evolver.hpp +++ b/src/engine/machina/Evolver.hpp @@ -17,41 +17,41 @@ #ifndef MACHINA_EVOLVER_HPP #define MACHINA_EVOLVER_HPP -#include "eugene/GAImpl.hpp" +#include "eugene/GA.hpp" +#include "eugene/Random.hpp" #include "machina/types.hpp" #include "raul/Thread.hpp" #include "raul/TimeStamp.hpp" +#include "Machine.hpp" #include "Schrodinbit.hpp" -namespace Eugene { -template<typename G> -class HybridMutation; +namespace eugene { +template<typename G> class HybridMutation; } namespace machina { -class Machine; class Problem; -class Evolver - : public Raul::Thread +class Evolver : public Raul::Thread { public: - Evolver(Raul::TimeUnit unit, - const string& target_midi, - SPtr<Machine> seed); + Evolver(Raul::TimeUnit unit, + const std::string& target_midi, + SPtr<Machine> seed); void seed(SPtr<Machine> parent); bool improvement() { return _improvement; } - SPtr<const Machine> best() { return _ga->best(); } + const Machine& best() { return _ga->best(); } - typedef Eugene::GAImpl<Machine> MachinaGA; + typedef eugene::GA<Machine> MachinaGA; private: void _run(); + eugene::Random _rng; SPtr<MachinaGA> _ga; SPtr<Problem> _problem; float _seed_fitness; diff --git a/src/engine/machina/Machine.hpp b/src/engine/machina/Machine.hpp index a4d0262..cd94391 100644 --- a/src/engine/machina/Machine.hpp +++ b/src/engine/machina/Machine.hpp @@ -19,7 +19,6 @@ #include <vector> #include <set> -#include <boost/utility.hpp> #include "machina/types.hpp" #include "raul/Atom.hpp" @@ -37,8 +36,7 @@ class LearnRequest; /** A (Finite State) Machine. */ -class Machine - : public Stateful +class Machine : public Stateful { public: explicit Machine(TimeUnit unit); @@ -53,6 +51,8 @@ public: /** Completely replace this machine's contents with a deep copy. */ Machine& operator=(const Machine& copy); + bool operator==(const Machine& rhs) const; + /** Merge another machine into this machine. */ void merge(const Machine& machine); @@ -95,6 +95,8 @@ public: SPtr<Node> random_node(); SPtr<Edge> random_edge(); + float fitness; // For GA + private: // Audio context SPtr<Node> earliest_node() const; @@ -117,6 +119,7 @@ private: SPtr<LearnRequest> _pending_learn; Nodes _nodes; Raul::TimeStamp _time; + bool _is_finished; }; diff --git a/src/engine/machina/Mutation.hpp b/src/engine/machina/Mutation.hpp index d811a50..69f5ee4 100644 --- a/src/engine/machina/Mutation.hpp +++ b/src/engine/machina/Mutation.hpp @@ -21,13 +21,19 @@ #ifdef HAVE_EUGENE # include "eugene/Mutation.hpp" -# define SUPER : public Eugene::Mutation <Machine> +# define SUPER : public eugene::Mutation<Machine> #else # define SUPER : public Mutation #endif namespace machina { +#ifdef HAVE_EUGENE +typedef eugene::Random Random; +#else +struct Random {}; +#endif + class Machine; namespace Mutation { @@ -35,17 +41,17 @@ namespace Mutation { struct Mutation { virtual ~Mutation() {} - virtual void mutate(Machine& machine) = 0; + virtual void mutate(Random& rng, Machine& machine) = 0; }; -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 SwapNodes 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); }; +struct Compress SUPER { void mutate(Random& rng, Machine& machine); }; +struct AddNode SUPER { void mutate(Random& rng, Machine& machine); }; +struct RemoveNode SUPER { void mutate(Random& rng, Machine& machine); }; +struct AdjustNode SUPER { void mutate(Random& rng, Machine& machine); }; +struct SwapNodes SUPER { void mutate(Random& rng, Machine& machine); }; +struct AddEdge SUPER { void mutate(Random& rng, Machine& machine); }; +struct RemoveEdge SUPER { void mutate(Random& rng, Machine& machine); }; +struct AdjustEdge SUPER { void mutate(Random& rng, Machine& machine); }; } // namespace Mutation |