19 #ifndef EMP_AVIDA_GP_H 20 #define EMP_AVIDA_GP_H 26 #include "../base/array.h" 27 #include "../base/Ptr.h" 28 #include "../base/vector.h" 29 #include "../tools/File.h" 30 #include "../tools/map_utils.h" 31 #include "../tools/Random.h" 32 #include "../tools/string_utils.h" 38 template <
typename HARDWARE>
62 Instruction(
size_t _id=0,
size_t a0=0,
size_t a1=0,
size_t a2=0)
63 : id(_id), args() { args[0] = a0; args[1] = a1; args[2] = a2; }
70 return std::tie(
id, args) < std::tie(other.
id, other.
args);
73 void Set(
size_t _id,
size_t _a0=0,
size_t _a1=0,
size_t _a2=0)
74 {
id = _id; args[0] = _a0; args[1] = _a1; args[2] = _a2; }
87 : inst_lib(_inst_lib), sequence(_seq) { ; }
89 : inst_lib(&_inst_lib), sequence(_seq) { ; }
95 std::size_t seed = sequence.
size();
96 for(
auto& i : sequence) {
97 seed ^= i.id + 0x9e3779b9 + (seed << 6) + (seed >> 2);
130 RegBackup(
size_t _s,
size_t _r,
double _v) : scope(_s), reg_id(_r), value(_v) { ; }
158 regs[reg_stack.
back().reg_id] = reg_stack.
back().value;
170 const size_t cur_scope =
CurScope();
173 if (new_scope > cur_scope) {
180 inst_ptr = scope_stack.
back().start_pos;
189 inst_ptr = call_stack.
back();
190 if (inst_ptr >= genome.sequence.size()) {
213 while (inst_ptr+1 < genome.sequence.size()) {
215 const size_t test_scope =
InstScope(genome.sequence[inst_ptr]);
218 if (test_scope && test_scope <= scope) {
228 : genome(in_genome), regs(), inputs(), outputs(), stacks(), fun_starts()
229 , inst_ptr(0), scope_stack(), reg_stack(), call_stack(), errors(0), traits()
232 for (
size_t i = 0; i <
CPU_SIZE; i++) {
233 regs[i] = (double) i;
255 return genome < other.
genome;
260 genome.sequence.resize(0);
268 for (
size_t i = 0; i <
CPU_SIZE; i++) {
269 regs[i] = (double) i;
287 while (reg_stack.
size()) {
288 regs[reg_stack.
back().reg_id] = reg_stack.
back().value;
298 const size_t GetSize()
const {
return genome.sequence.size(); }
299 double GetReg(
size_t id)
const {
return regs[
id]; }
320 void SetInst(
size_t pos,
const inst_t & inst) { genome.sequence[pos] = inst; }
321 void SetInst(
size_t pos,
size_t id,
size_t a0=0,
size_t a1=0,
size_t a2=0) {
322 genome.sequence[pos].Set(
id, a0, a1, a2);
325 void SetReg(
size_t id,
double val) { regs[
id] = val; }
326 void SetInput(
int input_id,
double value) { inputs[input_id] = value; }
327 void SetInputs(
const std::unordered_map<int,double> & vals) { inputs = vals; }
328 void SetInputs(std::unordered_map<int,double> && vals) { inputs = std::move(vals); }
329 void SetOutput(
int output_id,
double value) { outputs[output_id] = value; }
330 void SetOutputs(
const std::unordered_map<int,double> & vals) { outputs = vals; }
331 void SetOutputs(std::unordered_map<int,double> && vals) { outputs = std::move(vals); }
333 if (stacks[
id].size() == 0)
return 0.0;
334 double out = stacks[
id].
back();
339 if (stacks[
id].size() >= STACK_CAP)
return;
343 void SetIP(
size_t pos) { inst_ptr = pos; }
350 if (
id >= traits.
size()) traits.
resize(
id+1, 0.0);
362 void PushInst(
size_t id,
size_t a0=0,
size_t a1=0,
size_t a2=0) {
363 genome.sequence.emplace_back(
id, a0, a1, a2);
365 void PushInst(
const std::string & name,
size_t a0=0,
size_t a1=0,
size_t a2=0) {
366 size_t id = genome.inst_lib->GetID(name);
367 genome.sequence.emplace_back(
id, a0, a1, a2);
372 size_t id = genome.inst_lib->GetID(
string_pop(info) );
373 size_t arg1 = info.size() ? from_string<size_t>(
string_pop(info)) : 0;
374 size_t arg2 = info.size() ? from_string<size_t>(
string_pop(info)) : 0;
375 size_t arg3 = info.size() ? from_string<size_t>(
string_pop(info)) : 0;
379 for (
size_t i = 0; i < count; i++) {
385 bool Load(std::istream & input);
386 bool Load(
const std::string & filename) { std::ifstream is(filename);
return Load(is); }
397 if (inst_ptr >= genome.sequence.size())
ResetIP();
398 genome.inst_lib->ProcessInst(
ToPtr(
this), genome.sequence[inst_ptr]);
406 void PrintInst(
const inst_t & inst, std::ostream & os=std::cout)
const;
409 void PrintGenome(std::ostream & os=std::cout)
const;
410 void PrintGenome(
const std::string & filename)
const;
416 void PrintState(std::ostream & os=std::cout)
const;
419 void Trace(
size_t num_inst, std::ostream & os=std::cout) {
422 void Trace(
size_t num_inst,
const std::string & filename) {
423 std::ofstream of(filename);
430 template <
typename HARDWARE>
439 template <
typename HARDWARE>
445 template <
typename HARDWARE>
449 for (
size_t i = 0; i < num_args; i++) {
450 os <<
' ' << inst.
args[i];
454 template <
typename HARDWARE>
456 size_t cur_scope = 0;
462 if (new_scope == cur_scope) {
463 for (
size_t i = 0; i < cur_scope; i++) os <<
' ';
466 if (new_scope < cur_scope) {
467 cur_scope = new_scope-1;
471 for (
size_t i = 0; i < cur_scope; i++) os <<
' ';
474 if (new_scope > cur_scope) os <<
" --> ";
475 cur_scope = new_scope;
481 template <
typename HARDWARE>
483 std::ofstream of(filename);
488 template <
typename HARDWARE>
491 size_t new_scope = CPU_SIZE+1;
495 if (inst_scope) new_scope = inst_scope;
520 template <
typename HARDWARE>
525 for (
size_t i = 0; i <
CPU_SIZE; i++) os <<
"[" <<
regs[i] <<
"] ";
528 for (
auto & x :
inputs) os <<
"[" << x.first <<
"," << x.second <<
"] ";
529 os <<
"\n OUTPUTS: ";
531 for (
auto & x :
outputs) os <<
"[" << x.first <<
"," << x.second <<
"] ";
535 if (inst_ptr != next_inst) os <<
"(-> " << next_inst <<
")";
Genome genome_t
Definition: AvidaGP.h:51
Ptr< T > ToPtr(T *_in, bool own=false)
Convert a T* to a Ptr<T>. By default, don't track.
Definition: Ptr.h:816
void PrintGenome(std::ostream &os=std::cout) const
Print out this program.
Definition: AvidaGP.h:455
size_t GetNumTraits() const
Definition: AvidaGP.h:318
inst_t GetRandomInst(Random &rand)
Definition: AvidaGP.h:355
AvidaCPU_Base()
Create a default AvidaCPU (no genome sequence, default instruction set)
Definition: AvidaGP.h:239
void PushInstString(std::string info)
Definition: AvidaGP.h:371
void PushInst(const std::string &name, size_t a0=0, size_t a1=0, size_t a2=0)
Definition: AvidaGP.h:365
void Trace(size_t num_inst, const std::string &filename)
Definition: AvidaGP.h:422
emp::vector< RegBackup > GetRegStack() const
Definition: AvidaGP.h:313
Definition: AvidaCPU_InstLib.h:23
void SetOutputs(const std::unordered_map< int, double > &vals)
Definition: AvidaGP.h:330
virtual ~AvidaCPU_Base()
Destructor.
Definition: AvidaGP.h:252
size_t GetNumErrors() const
Definition: AvidaGP.h:315
void SetOutputs(std::unordered_map< int, double > &&vals)
Definition: AvidaGP.h:331
emp::array< stack_t, CPU_SIZE > stacks
Definition: AvidaGP.h:138
const stack_t & GetStack(size_t id) const
Definition: AvidaGP.h:306
void RandomizeInst(size_t pos, Random &rand)
Definition: AvidaGP.h:360
size_t start_pos
Definition: AvidaGP.h:118
Ptr< const inst_lib_t > inst_lib
Definition: AvidaGP.h:82
virtual void ResetHardware()
Reset just the CPU hardware, but keep the genome and traits.
Definition: AvidaGP.h:266
A specialized version of InstLib to handle AvidaCPU Instructions.
const emp::vector< double > & GetTraits()
Definition: AvidaGP.h:317
A class to maintin files for loading, writing, storing, and easy access to components.
Definition: File.h:32
A versatile and non-patterned pseudo-random-number generator (Mersenne Twister).
Definition: ce_random.h:52
double GetInput(int id) const
Definition: AvidaGP.h:300
void ResetIP()
Reset the instruction pointer to the beginning of the genome AND reset scope.
Definition: AvidaGP.h:283
void SetInputs(const std::unordered_map< int, double > &vals)
Definition: AvidaGP.h:327
Genome(const inst_lib_t &_inst_lib, const sequence_t &_seq=sequence_t(0))
Definition: AvidaGP.h:88
void SetInst(size_t pos, size_t id, size_t a0=0, size_t a1=0, size_t a2=0)
Definition: AvidaGP.h:321
emp::vector< size_t > call_stack
Definition: AvidaGP.h:144
void PushRegInfo(size_t scope_id, size_t reg_id)
Definition: AvidaGP.h:344
void push_back(PB_Ts &&...args)
Definition: vector.h:189
void Trace(size_t num_inst, std::ostream &os=std::cout)
Trace the instructions being exectured, with full CPU details.
Definition: AvidaGP.h:419
void SetInput(int input_id, double value)
Definition: AvidaGP.h:326
void PushStack(size_t id, double value)
Definition: AvidaGP.h:338
AvidaGP(Ptr< const inst_lib_t > inst_lib)
Definition: AvidaGP.h:559
File & Apply(const std::function< void(std::string &)> &fun)
Apply a string manipulation function to all lines in the file.
Definition: File.h:178
int GetFunStart(size_t id) const
Definition: AvidaGP.h:307
void ExitScope()
Definition: AvidaGP.h:152
arg_set_t args
Definition: AvidaGP.h:60
std::unordered_map< int, double > outputs
Definition: AvidaGP.h:137
AvidaGP(const genome_t &in_genome)
Definition: AvidaGP.h:558
void Reset()
Reset the entire CPU to a starting state, without a genome.
Definition: AvidaGP.h:259
emp::vector< double > traits
Definition: AvidaGP.h:149
double GetTrait(size_t id) const
Definition: AvidaGP.h:316
void SetInst(size_t pos, const inst_t &inst)
Definition: AvidaGP.h:320
bool operator<=(const Genome &other) const
Definition: AvidaGP.h:110
size_t InstScope(const inst_t &inst) const
Determine the scope associated with a particular instruction.
Definition: AvidaGP.h:440
size_t size() const
Definition: vector.h:151
ScopeType CurScopeType() const
Definition: AvidaGP.h:311
bool operator==(const Genome &other) const
Definition: AvidaGP.h:107
void emplace_back(ARGS &&...args)
Definition: vector.h:219
ScopeType GetScopeType(size_t id)
Definition: AvidaGP.h:312
void Set(size_t _id, size_t _a0=0, size_t _a1=0, size_t _a2=0)
Definition: AvidaGP.h:73
Instruction & operator=(const Instruction &)=default
constexpr uint32_t GetUInt(const uint32_t max)
Definition: ce_random.h:191
ScopeType type
Definition: AvidaGP.h:117
RegBackup(size_t _s, size_t _r, double _v)
Definition: AvidaGP.h:130
emp::array< double, CPU_SIZE > regs
Definition: AvidaGP.h:135
void push_back(PB_Ts &&...args)
Definition: array.h:169
bool Load(std::istream &input)
Definition: AvidaGP.h:431
void SingleProcess()
Process the NEXT instruction pointed to be the instruction pointer.
Definition: AvidaGP.h:395
bool operator>=(const Genome &other) const
Definition: AvidaGP.h:112
Definition: AvidaGP.h:101
auto Find(const MAP_T &in_map, const KEY_T &key, const typename MAP_T::mapped_type &dval)
Definition: map_utils.h:29
genome_t genome
Definition: AvidaGP.h:134
std::string string_pop(std::string &in_string, const char delim=' ')
Definition: string_utils.h:303
bool Load(const std::string &filename)
Definition: AvidaGP.h:386
double GetOutput(int id) const
Definition: AvidaGP.h:303
static const PrintStr endl("<br>")
Pre-define emp::endl to insert a "<br>" and thus acting like a newline.
T & back()
Definition: array.h:156
void pop_back()
Definition: vector.h:194
void resize(size_t new_size)
Definition: array.h:165
void Process(size_t num_inst)
Process the next SERIES of instructions, directed by the instruction pointer.
Definition: AvidaGP.h:403
void SetTrait(size_t id, double val)
Definition: AvidaGP.h:349
AvidaCPU_Base(const inst_lib_t &inst_lib)
Definition: AvidaGP.h:243
double PopStack(size_t id)
Definition: AvidaGP.h:332
double GetReg(size_t id) const
Definition: AvidaGP.h:299
bool operator!=(const Genome &other) const
Definition: AvidaGP.h:108
AvidaGP(const inst_lib_t &inst_lib)
Definition: AvidaGP.h:560
Genome(Ptr< const inst_lib_t > _inst_lib, const sequence_t &_seq=sequence_t(0))
Definition: AvidaGP.h:86
emp::vector< ScopeInfo > GetScopeStack() const
Definition: AvidaGP.h:309
bool operator<(const this_t &other) const
Definition: AvidaGP.h:254
bool UpdateScope(size_t new_scope, ScopeType type=ScopeType::BASIC)
Definition: AvidaGP.h:169
size_t reg_id
Definition: AvidaGP.h:126
size_t GetNumInputs() const
Definition: AvidaGP.h:302
Instruction(size_t _id=0, size_t a0=0, size_t a1=0, size_t a2=0)
Definition: AvidaGP.h:62
void PushInst(const Instruction &inst)
Definition: AvidaGP.h:369
const std::unordered_map< int, double > & GetOutputs() const
Definition: AvidaGP.h:304
std::unordered_map< int, double > inputs
Definition: AvidaGP.h:136
static constexpr size_t CPU_SIZE
Definition: AvidaGP.h:41
void PushTrait(double val)
Definition: AvidaGP.h:353
void BypassScope(size_t scope)
Definition: AvidaGP.h:208
virtual ~AvidaGP()
Definition: AvidaGP.h:566
Definition: AvidaGP.h:124
size_t scope
Definition: AvidaGP.h:116
~Genome()
Definition: AvidaGP.h:92
void resize(size_t new_size)
Definition: vector.h:161
emp::vector< ScopeInfo > scope_stack
Definition: AvidaGP.h:142
size_t id
Definition: AvidaGP.h:59
size_t Hash() const
Definition: AvidaGP.h:94
bool operator==(const Instruction &in) const
Definition: AvidaGP.h:76
const size_t GetSize() const
Definition: AvidaGP.h:298
File & RemoveComments(const std::string &marker)
A technique to remove all comments in a file.
Definition: File.h:224
void SetIP(size_t pos)
Definition: AvidaGP.h:343
emp::vector< size_t > GetCallStack() const
Definition: AvidaGP.h:314
const genome_t & GetGenome() const
Definition: AvidaGP.h:297
AvidaCPU_Base(const genome_t &in_genome)
Create a new AvidaCPU seeding it with a genome.
Definition: AvidaGP.h:227
void PrintInst(const inst_t &inst, std::ostream &os=std::cout) const
Print out a single instruction, with its arguments.
Definition: AvidaGP.h:446
If we are in emscripten, make sure to include the header.
Definition: array.h:37
void PushInst(Instruction &&inst)
Definition: AvidaGP.h:370
void SetReg(size_t id, double val)
Definition: AvidaGP.h:325
A single instruction in a linear genome.
Definition: LinearCode.h:20
RegBackup()
Definition: AvidaGP.h:129
void SetFunStart(size_t id, int value)
Definition: AvidaGP.h:342
ScopeType
Definition: InstLib.h:27
size_t errors
Definition: AvidaGP.h:146
size_t operator()(const Genome &g) const
Definition: AvidaGP.h:101
#define emp_assert(...)
Definition: assert.h:199
void IncErrors()
Definition: AvidaGP.h:348
void PushRandom(Random &rand, const size_t count=1)
Definition: AvidaGP.h:378
T & back()
Definition: vector.h:183
void PrintState(std::ostream &os=std::cout) const
Print out the state of the virtual CPU.
Definition: AvidaGP.h:521
size_t GetIP() const
Definition: AvidaGP.h:308
static constexpr size_t STACK_CAP
Definition: AvidaGP.h:43
inst_t GetInst(size_t pos) const
Definition: AvidaGP.h:296
size_t inst_ptr
Definition: AvidaGP.h:141
ScopeInfo(size_t _s, ScopeType _t, size_t _p)
Definition: AvidaGP.h:121
sequence_t sequence
Definition: AvidaGP.h:83
ScopeInfo()
Definition: AvidaGP.h:120
void SetOutput(int output_id, double value)
Definition: AvidaGP.h:329
void PushCallInfo(size_t pos)
Definition: AvidaGP.h:347
size_t CurScope() const
Definition: AvidaGP.h:310
size_t scope
Definition: AvidaGP.h:125
void pop_back()
Definition: array.h:170
emp::array< int, CPU_SIZE > fun_starts
Definition: AvidaGP.h:139
double value
Definition: AvidaGP.h:127
size_t GetNumOutputs() const
Definition: AvidaGP.h:305
void ProcessInst(const inst_t &inst)
Process a specified instruction, provided by the caller.
Definition: AvidaGP.h:389
Instruction inst_t
Definition: AvidaGP.h:50
size_t arg_t
Definition: AvidaGP.h:52
void SetInputs(std::unordered_map< int, double > &&vals)
Definition: AvidaGP.h:328
const std::unordered_map< int, double > & GetInputs() const
Definition: AvidaGP.h:301
size_t PredictNextInst() const
Figure out which instruction is going to actually be run next SingleProcess()
Definition: AvidaGP.h:489
Ptr< const inst_lib_t > GetInstLib() const
Definition: AvidaGP.h:295
void SetGenome(const genome_t &g)
Definition: AvidaGP.h:324
File & CompressWhitespace()
Definition: File.h:202
emp::vector< RegBackup > reg_stack
Definition: AvidaGP.h:143
AvidaCPU_Base(Ptr< const inst_lib_t > inst_lib)
Create an AvidaCPU with a specified instruction set (but no genome sequence)
Definition: AvidaGP.h:242
Definition: AvidaGP.h:115
bool operator<(const Instruction &other) const
Definition: AvidaGP.h:69
static constexpr size_t INST_ARGS
Definition: AvidaGP.h:42
Genome genome_t
Definition: AvidaGP.h:51
void PushInst(size_t id, size_t a0=0, size_t a1=0, size_t a2=0)
Definition: AvidaGP.h:362
Definition: AvidaGP.h:552