Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
45b474c
Added Steal and Donate Health host with config
EliasH-E Jul 1, 2025
7d355b9
Made fixes and improvements to donate and steal
EliasH-E Jul 1, 2025
9287092
Made fixes to tests and folded ONLYNOT test into SGPWorld.test.cc sin…
EliasH-E Jul 2, 2025
ffca7fe
Added functionality for instructions for stealing and donating to Hea…
EliasH-E Jul 7, 2025
f0e9611
Added Tests for steal/donate instructions
EliasH-E Jul 7, 2025
875f175
Added variable starting steal count, tied for now to CPU_TRANSFER_AMOUNT
EliasH-E Jul 8, 2025
25d5ab6
Made changes based on feedback, removed trash lines and cleaned up co…
EliasH-E Jul 9, 2025
d396fe5
Merged self
EliasH-E Jul 10, 2025
a75fbd7
Finished merge
EliasH-E Jul 10, 2025
0207c43
Really finished merge
EliasH-E Jul 10, 2025
b9ce91a
final merge fix
EliasH-E Jul 10, 2025
5866e06
Merged
EliasH-E Jul 10, 2025
2d3016c
merged
EliasH-E Jul 10, 2025
ac4d00f
Merge branch 'complex-syms-clean' of https://github.com/EliasH-E/Symb…
EliasH-E Jul 10, 2025
0d88a66
Fixed merge again
EliasH-E Jul 10, 2025
3512963
Merge branch 'anyaevostinar:complex-syms-clean' into complex-syms-clean
EliasH-E Jul 10, 2025
0860e0c
Merge branch 'complex-syms-clean' into steal_instructions
EliasH-E Jul 10, 2025
15894f6
Merge branch 'complex-syms-clean' into steal_instructions
anyaevostinar Jul 10, 2025
32c9f06
Fixed last merge problems
EliasH-E Jul 10, 2025
7ab4e6a
Merge branch 'steal_instructions' of https://github.com/EliasH-E/Symb…
EliasH-E Jul 10, 2025
e66d0a8
Made fix to CreateStartProgram and added some documentation
EliasH-E Jul 10, 2025
d3c2e8d
Made fixes to no longer crash on test build
EliasH-E Jul 10, 2025
1378b45
fixed merge tests
EliasH-E Jul 10, 2025
11a136b
Made changes based on feedback and removed new test prints
EliasH-E Jul 10, 2025
f20940d
Added free bonus updates to syms, moved where steal success is decide…
EliasH-E Jul 11, 2025
7917475
Fixed errors in sgp mode test
EliasH-E Jul 14, 2025
85a08e2
Edited steal Health to better match original
EliasH-E Jul 14, 2025
dde32b3
Merge branch 'complex-syms-clean' into steal_instructions
anyaevostinar Jul 15, 2025
3f34c3e
Added spread out steals, fixed tests and more
EliasH-E Jul 15, 2025
939728e
Merge branch 'steal_instructions' of https://github.com/EliasH-E/Symb…
EliasH-E Jul 15, 2025
89e40ec
merged
EliasH-E Jul 16, 2025
fc77eb4
Fixed Memory Leak
EliasH-E Jul 16, 2025
cd8341a
Merge branch 'anyaevostinar:complex-syms-clean' into complex-syms-clean
EliasH-E Jul 16, 2025
4fb08ed
Fixed donate tracking
EliasH-E Jul 17, 2025
b776b68
merged
EliasH-E Jul 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion source/Organism.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,14 @@ class Organism {
virtual void ClearReproSyms() {
std::cout << "ClearReproSyms called from Organism" << std::endl;
throw "Organism method called!";}

virtual void CycleTransfer(int _in){
std::cout << "CycleTransfer called from Organism" << std::endl;
throw "Organism method called!";
}
virtual int GetCyclesGiven(){
std::cout << "GetCyclesGiven called from Organism" << std::endl;
throw "Organism method called!";
}
//Bacterium functions
virtual double ProcessLysogenResources(double phage_inc_val){
std::cout << "ProcessLysogenResources called from Organism" << std::endl;
Expand Down
58 changes: 55 additions & 3 deletions source/sgp_mode/GenomeLibrary.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ using Library = sgpl::OpLibrary<
//inst::Infect,
// if-label doesn't make sense for SGP, same with *-head
// and set-flow but this is required
sgpl::global::Anchor
//inst::Steal
sgpl::global::Anchor,
inst::Steal,
inst::Donate
>;

using Spec = sgpl::Spec<Library, CPUState>;
Expand Down Expand Up @@ -263,6 +264,24 @@ class ProgramBuilder : emp::vector<sgpl::Instruction<Spec>> {
Add("Nand", 0, 0, 0);
Add("SharedIO");
}

void AddSteal(int steal_count){

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This name should make it clear what the overall phenotype is since it's more than just adding a single steal instruction. And what is it actually doing since it has steal and donate?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I kind of actually forgot that this would be added to the pull request automatically on pushing. This was my current rusty implementation of placing steals throughout the genome. For some reason it was not letting me add nop inbetween, I was planning on asking about that in the slack today but it slipped my mind. I used donate because currently in my tests unless ALLOW_TRANSITION is on donate will do nothing.


for (int i = 0; i < steal_count; i++){
Add("Steal");
Comment thread
EliasH-E marked this conversation as resolved.
Outdated

Add("Donate");
Add("Donate");
Add("Donate");

}
Add("Steal");
//std::cout << "Adding Steal" << std::endl;
Comment thread
EliasH-E marked this conversation as resolved.
Outdated
}

void AddDonate(){
Add("Donate");
}
};

sgpl::Program<Spec> CreateRandomProgram(size_t length) {
Expand All @@ -280,6 +299,27 @@ sgpl::Program<Spec> CreateNotProgram(size_t length) {
return program.Build(length);
}

sgpl::Program<Spec> CreateParasiteNotProgram(size_t length, int steal_count) {
ProgramBuilder program;
program.AddSteal(steal_count);
program.AddNot();

return program.Build(length);
}

sgpl::Program<Spec> CreateMutualistNotProgram(size_t length) {
ProgramBuilder program;
program.AddNot();
program.AddDonate();
Comment thread
EliasH-E marked this conversation as resolved.
Outdated
return program.Build(length);
}

sgpl::Program<Spec> CreateEquProgram(size_t length) {
ProgramBuilder program;
program.AddEqu();
return program.Build(length);
}


sgpl::Program<Spec> CreatePrivateNotProgram(size_t length) {
ProgramBuilder program;
Expand Down Expand Up @@ -308,7 +348,19 @@ sgpl::Program<Spec> CreateStartProgram(emp::Ptr<SymConfigSGP> config) {
if (config->RANDOM_ANCESTOR()) {
return CreateRandomProgram(PROGRAM_LENGTH);
} else if (config->TASK_TYPE() == 1) {
return CreateNotProgram(PROGRAM_LENGTH);
if(config->DONATION_STEAL_INST() == 1){
if(config->STRESS_TYPE() == 1){
std::cout << "eyyy its parasite time" << std::endl;
Comment thread
EliasH-E marked this conversation as resolved.
Outdated
return CreateParasiteNotProgram(PROGRAM_LENGTH, config->CPU_TRANSFER_AMOUNT());
}
else if(config->STRESS_TYPE() == 0){
return CreateMutualistNotProgram(PROGRAM_LENGTH);
}
}
else{
std::cout << "U said I cant steal.." << std::endl;
Comment thread
EliasH-E marked this conversation as resolved.
Outdated
return CreateNotProgram(PROGRAM_LENGTH);
}
} else {
Comment thread
EliasH-E marked this conversation as resolved.
Outdated
return CreateReproProgram(PROGRAM_LENGTH);
}
Expand Down
52 changes: 50 additions & 2 deletions source/sgp_mode/HealthHost.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ class HealthHost : public SGPHost {

public:

int cycles_given = 0;
Comment thread
EliasH-E marked this conversation as resolved.
Outdated

/**
* Constructs a new SGPHost as an ancestor organism, with either a random
* genome or a blank genome that knows how to do a simple task depending on
Expand Down Expand Up @@ -62,9 +64,32 @@ class HealthHost : public SGPHost {
int host_cycle = 1;
int sym_cycle = 0;
if (HasSym()) {
if (sgp_config->STRESS_TYPE() == MUTUALIST) {

if(sgp_config->DONATION_STEAL_INST()){
sym_cycle = 1;

if(cycles_given >= 1){
if(random->P(sgp_config->CPU_TRANSFER_CHANCE())){
host_cycle += 1;
sym_cycle -= 1;
//std::cout << "here a donation" << std::endl;
Comment thread
EliasH-E marked this conversation as resolved.
Outdated
}
cycles_given = 0;

}
else if(cycles_given <= -1){
if(random->P(sgp_config->CPU_TRANSFER_CHANCE())){
host_cycle -= 1;
sym_cycle += 1;
//std::cout << "here a steal >:)" << std::endl;
}
cycles_given = 0;

}
}
Comment thread
EliasH-E marked this conversation as resolved.
else{
if (sgp_config->STRESS_TYPE() == MUTUALIST) {
//Host with mutualist gains 50% of CPU from mutualist

if (random->P(sgp_config->CPU_TRANSFER_CHANCE())) {
host_cycle = 2;
sym_cycle = 0;
Expand All @@ -83,6 +108,7 @@ class HealthHost : public SGPHost {
sym_cycle = 0;
}
}
}
}

//Loops running CPU steps
Expand Down Expand Up @@ -116,5 +142,27 @@ class HealthHost : public SGPHost {
}
GrowOlder();
}

void CycleTransfer(int amount) override {
Comment thread
EliasH-E marked this conversation as resolved.
Outdated
// for (int i = 0; i < abs(amount/4); i++){
Comment thread
EliasH-E marked this conversation as resolved.
Outdated
// if(random->P(sgp_config->CPU_TRANSFER_CHANCE())){
// cycles_given += amount/(abs(amount)) * 4;
// }
// else{
// break;
// }
// }
cycles_given += amount;
}

int GetCyclesGiven(){
return cycles_given;
}

std::string const GetName() override{
return "HealthHost";
}
};

Comment thread
EliasH-E marked this conversation as resolved.

#endif // HEALTHHOST_H
51 changes: 24 additions & 27 deletions source/sgp_mode/Instructions.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#ifndef INSTRUCTIONS_H
#define INSTRUCTIONS_H


#include "CPUState.h"
#include "SGPWorld.h"
#include "Tasks.h"


#include "sgpl/hardware/Cpu.hpp"
#include "sgpl/operations/flow_global/Anchor.hpp"
#include "sgpl/program/Program.hpp"
Expand Down Expand Up @@ -135,43 +138,37 @@ INST(SharedIO, {
state.input_buf.push(next);
});
INST(Donate, {
if (state.world->GetConfig()->DONATION_STEAL_INST()) {
if (state.organism->IsHost() || state.organism->GetHost() == nullptr)
if (state.world->GetConfig()->DONATION_STEAL_INST() && (state.world->GetConfig()->STRESS_TYPE() == 0 || state.world->GetConfig()->ALLOW_TRANSITION_EVOLUTION() == 1)) {
if (state.organism->IsHost() || state.organism->GetHost() == nullptr){
Comment thread
EliasH-E marked this conversation as resolved.
Outdated

return;
}
if (emp::Ptr<Organism> host = state.organism->GetHost()) {
Comment thread
EliasH-E marked this conversation as resolved.
Outdated
// Donate 20% of the total points of the symbiont-host system
// This way, a sym can donate e.g. 40 or 60 percent of their points in a
// couple of instructions
double to_donate =
fmin(state.organism->GetPoints(),
(state.organism->GetPoints() + host->GetPoints()) * 0.20);
state.world->GetSymDonatedDataNode().WithMonitor(
[=](auto &m) { m.AddDatum(to_donate); });
host->AddPoints(to_donate *
(1.0 - state.world->GetConfig()->DONATE_PENALTY()));
state.organism->AddPoints(-to_donate);

//New Donate implementation:
if(host->GetCyclesGiven() <= 0){
host->CycleTransfer(1);
}
}
}
else{
}
});
INST(Steal, {
if (state.world->GetConfig()->DONATION_STEAL_INST()) {
if (state.organism->IsHost() || state.organism->GetHost() == nullptr)
if (state.world->GetConfig()->DONATION_STEAL_INST() && (state.world->GetConfig()->STRESS_TYPE() == 1 || state.world->GetConfig()->ALLOW_TRANSITION_EVOLUTION() == 1)) {
if (state.organism->IsHost() || state.organism->GetHost() == nullptr){
return;
}
if (emp::Ptr<Organism> host = state.organism->GetHost()) {
// Steal 20% of the total points of the symbiont-host system
// This way, a sym can steal e.g. 40 or 60 percent of the host's points in
// a couple of instructions
double to_steal =
fmin(host->GetPoints(),
(state.organism->GetPoints() + host->GetPoints()) * 0.20);
state.world->GetSymStolenDataNode().WithMonitor(
[=](auto &m) { m.AddDatum(to_steal); });
host->AddPoints(-to_steal);
// 10% of the stolen resources are lost
state.organism->AddPoints(
to_steal * (1.0 - state.world->GetConfig()->STEAL_PENALTY()));

//New Steal Implementation
if(host->GetCyclesGiven() >= 0){
host->CycleTransfer(-1);
}
}
}
else{
}
});

INST(Reuptake, {
Expand Down
5 changes: 3 additions & 2 deletions source/sgp_mode/SGPConfigSetup.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ EMP_EXTEND_CONFIG(SymConfigSGP, SymConfigBase,
VALUE(MUTUALIST_DEATH_CHANCE, double, 0.125, "What death chance does a mutualist confer?"),
VALUE(BASE_DEATH_CHANCE, double, 0.25, "What death chance does a host have in the absence of symbionts?"),
VALUE(CPU_TRANSFER_CHANCE, double, 0.5, "What is the chance for cycles to be stolen/donated?"),
VALUE(ONLY_FIRST_TASK_CREDIT, int, 0, "Should symbionts only get credit for their first task")

VALUE(CPU_TRANSFER_AMOUNT, double, 1, "How many updates should be stolen/donated by instruction based symbionts"),
VALUE(ONLY_FIRST_TASK_CREDIT, int, 0, "Should symbionts only get credit for their first task"),
Comment thread
EliasH-E marked this conversation as resolved.
Outdated
VALUE(ALLOW_TRANSITION_EVOLUTION, int, 0, "Should symbionts be allowed to evolve from mutalists to parasties and vice versa")
Comment thread
EliasH-E marked this conversation as resolved.
Outdated
)

#endif
106 changes: 106 additions & 0 deletions source/test/sgp_mode_test/HealthHost.test.cc
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include "../../sgp_mode/GenomeLibrary.h"
#include "../../sgp_mode/CPU.h"
#include "../../sgp_mode/HealthHost.h"
#include "../../sgp_mode/SGPWorld.h"
#include "../../sgp_mode/SGPWorldSetup.cc"
Expand Down Expand Up @@ -146,3 +148,107 @@ TEST_CASE("Health hosts evolve", "[sgp-integration]") {
}
}
}

TEST_CASE("When DONATION_STEAL_INST is 1 then Symbiont with 'Steal' instruction properly takes CPU cycles from HealthHost", "[sgp]"){

emp::Random random(1);
SymConfigSGP config;
config.RANDOM_ANCESTOR(false);
config.SEED(0);
config.ORGANISM_TYPE(HEALTH);
config.STRESS_TYPE(1);
config.MUTATION_RATE(0.0);
config.MUTATION_SIZE(0.00);
config.TRACK_PARENT_TASKS(1);
config.VT_TASK_MATCH(1);
config.ONLY_FIRST_TASK_CREDIT(1);
config.HOST_REPRO_RES(10000);
config.DONATION_STEAL_INST(1);
config.CPU_TRANSFER_CHANCE(1);


SGPWorld world(random, &config, LogicTasks);

//Builds program that does both NOT and NAND operations

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are places where you could use the "GIVEN" catch command



//Creates a host that only does NOT operations
emp::Ptr<HealthHost> host = emp::NewPtr<HealthHost>(&random, &world, &config, CreateNotProgram(100));
//Creates a symbiont that does both Not and Nand operations
emp::Ptr<SGPSymbiont> sym = emp::NewPtr<SGPSymbiont>(&random, &world, &config, CreateParasiteNotProgram(100));

//Adds host to world and sym to host.
world.AddOrgAt(host, 0);
host->AddSymbiont(sym);

WHEN("A symbiont performs a Steal instruction"){
sym->GetCPU().RunCPUStep(0, 100);
(*(sym->GetCPU().state.tasks_performed))[0] = 0;
THEN("The host should be set to lose 4 cycles to the symbiont"){
REQUIRE(host->GetCyclesGiven() == -4);
}
for (size_t i = 0; i < 24; i++) {
world.Update();
}
THEN("The symbiont should complete its task one update early"){
REQUIRE(sym->GetCPU().state.tasks_performed->Get(0) == true);
}
world.Update();
THEN("The host should be unable to complete its task in 25 updates"){
REQUIRE(host->GetCPU().state.tasks_performed->Get(0) == false);
}
}

}

TEST_CASE("When DONATION_STEAL_INST is 1 then Symbiont with 'Donate' instruction properly gives CPU cycles to HealthHost", "[sgp]"){

emp::Random random(1);
SymConfigSGP config;
config.RANDOM_ANCESTOR(false);
config.SEED(0);
config.ORGANISM_TYPE(HEALTH);
config.STRESS_TYPE(0);
config.MUTATION_RATE(0.0);
config.MUTATION_SIZE(0.00);
config.TRACK_PARENT_TASKS(1);
config.VT_TASK_MATCH(1);
config.ONLY_FIRST_TASK_CREDIT(1);
config.DONATION_STEAL_INST(1);
config.CPU_TRANSFER_CHANCE(1);

config.HOST_REPRO_RES(10000);

SGPWorld world(random, &config, LogicTasks);

//Builds program that does both NOT and NAND operations


//Creates a host that only does NOT operations
emp::Ptr<HealthHost> host = emp::NewPtr<HealthHost>(&random, &world, &config, CreateNotProgram(100));
//Creates a symbiont that does both Not and Nand operations
emp::Ptr<SGPSymbiont> sym = emp::NewPtr<SGPSymbiont>(&random, &world, &config, CreateMutualistNotProgram(100));

//Adds host to world and sym to host.
world.AddOrgAt(host, 0);
host->AddSymbiont(sym);

WHEN("A symbiont performs a Donate instruction"){
sym->GetCPU().RunCPUStep(0, 100);
(*(sym->GetCPU().state.tasks_performed))[0] = 0;
THEN("The host should be set to gain 4 cycles from the symbiont"){
REQUIRE(host->GetCyclesGiven() == 4);
}
for (size_t i = 0; i < 24; i++) {
world.Update();
}
THEN("The host should complete its task one update early"){
REQUIRE(host->GetCPU().state.tasks_performed->Get(0) == true);
}
world.Update();
THEN("The symbiont should be unable to complete its task in 25 updates"){
REQUIRE(sym->GetCPU().state.tasks_performed->Get(0) == false);
}

}
}
Loading