From 86c67b66f855719bbebb7d311f5e5da6e94e3e61 Mon Sep 17 00:00:00 2001 From: Morten Rohgalf Date: Wed, 24 Sep 2025 14:15:18 +0200 Subject: [PATCH] add car racing sim and first geno to phenotype mapper experiment. --- .idea/.gitignore | 8 + .../inspectionProfiles/profiles_settings.xml | 6 + .idea/misc.xml | 7 + .idea/modules.xml | 8 + .idea/neuroevolution.iml | 14 + .idea/vcs.xml | 6 + experiments/car_racing_test/run.py | 12 + .../{ => genotype_mapper}/genotype.json | 0 .../{ => genotype_mapper}/genotype_mapper.py | 2 +- .../pehno_geno_map.cpython-312.pyc | Bin 0 -> 20720 bytes .../phenotype_genotype_map/genotype.json | 258 +++++++++++ .../genotype_updated.json | 258 +++++++++++ .../phenotype_genotype_map/pehno_geno_map.py | 410 ++++++++++++++++++ experiments/phenotype_genotype_map/run.py | 19 + experiments/{ => simple_nn}/neuron.py | 0 experiments/{ => simple_nn}/simplest_nn.py | 5 +- requirements.txt | 4 + 17 files changed, 1015 insertions(+), 2 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/neuroevolution.iml create mode 100644 .idea/vcs.xml create mode 100644 experiments/car_racing_test/run.py rename experiments/{ => genotype_mapper}/genotype.json (100%) rename experiments/{ => genotype_mapper}/genotype_mapper.py (95%) create mode 100644 experiments/phenotype_genotype_map/__pycache__/pehno_geno_map.cpython-312.pyc create mode 100644 experiments/phenotype_genotype_map/genotype.json create mode 100644 experiments/phenotype_genotype_map/genotype_updated.json create mode 100644 experiments/phenotype_genotype_map/pehno_geno_map.py create mode 100644 experiments/phenotype_genotype_map/run.py rename experiments/{ => simple_nn}/neuron.py (100%) rename experiments/{ => simple_nn}/simplest_nn.py (96%) create mode 100644 requirements.txt diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..b464c49 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..26747a4 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/neuroevolution.iml b/.idea/neuroevolution.iml new file mode 100644 index 0000000..7f80a0b --- /dev/null +++ b/.idea/neuroevolution.iml @@ -0,0 +1,14 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/experiments/car_racing_test/run.py b/experiments/car_racing_test/run.py new file mode 100644 index 0000000..ecae6bd --- /dev/null +++ b/experiments/car_racing_test/run.py @@ -0,0 +1,12 @@ +import gymnasium as gym + +env = gym.make("CarRacing-v3", render_mode="human") +obs, info = env.reset() + +for _ in range(1000): + action = env.action_space.sample() + _, reward, terminated, truncated, _ = env.step(action) + if terminated or truncated: + obs, info = env.reset() + +env.close() diff --git a/experiments/genotype.json b/experiments/genotype_mapper/genotype.json similarity index 100% rename from experiments/genotype.json rename to experiments/genotype_mapper/genotype.json diff --git a/experiments/genotype_mapper.py b/experiments/genotype_mapper/genotype_mapper.py similarity index 95% rename from experiments/genotype_mapper.py rename to experiments/genotype_mapper/genotype_mapper.py index fcbf0d9..270a9fd 100644 --- a/experiments/genotype_mapper.py +++ b/experiments/genotype_mapper/genotype_mapper.py @@ -6,7 +6,7 @@ from typing import List, Dict, Tuple # ---- Hilfsfunktionen ---- def generate_id(): - """Generiert eine eindeutige ID basierend auf Zufallszahlen.""" + """generate random number as id. TODO: this should be uuidv4 instead of float""" return random.random() diff --git a/experiments/phenotype_genotype_map/__pycache__/pehno_geno_map.cpython-312.pyc b/experiments/phenotype_genotype_map/__pycache__/pehno_geno_map.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0e7fd4c934e5e06483003e98d3c6dc25c4cce991 GIT binary patch literal 20720 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 Lyvq?}v-bZ01$pj{ literal 0 HcmV?d00001 diff --git a/experiments/phenotype_genotype_map/genotype.json b/experiments/phenotype_genotype_map/genotype.json new file mode 100644 index 0000000..f762020 --- /dev/null +++ b/experiments/phenotype_genotype_map/genotype.json @@ -0,0 +1,258 @@ +{ + "cortex": { + "id": 0.38985127736117664, + "sensor_ids": [ + 0.5481697495393968 + ], + "actuator_ids": [ + 0.300862433948894 + ], + "neuron_ids": [ + 0.7892266733003815, + 0.08993126065168999, + 0.7353679413901013, + 0.7986671199471203, + 0.2619274118215478, + 0.1878355172703, + 0.5460586524022121, + 0.0325156080072021 + ] + }, + "sensor": { + "id": 0.5481697495393968, + "name": "rng", + "vector_length": 2, + "cx_id": 0.37250552293263184, + "fanout_ids": [ + 0.7892266733003815, + 0.08993126065168999, + 0.7353679413901013, + 0.7986671199471203 + ] + }, + "actuator": { + "id": 0.300862433948894, + "name": "pts", + "vector_length": 1, + "cx_id": 0.37250552293263184, + "fanin_ids": [ + 0.0325156080072021 + ] + }, + "neurons": [ + { + "id": 0.7892266733003815, + "layer_index": 0, + "cx_id": 0.37250552293263184, + "activation_function": "tanh", + "input_weights": [ + { + "input_id": 0.5481697495393968, + "weights": [ + -0.2010596737648036, + -0.017559575650012982 + ] + } + ], + "output_ids": [ + 0.11787440750922895, + 0.9473188607259506, + 0.9045741659912035 + ] + }, + { + "id": 0.08993126065168999, + "layer_index": 0, + "cx_id": 0.37250552293263184, + "activation_function": "tanh", + "input_weights": [ + { + "input_id": 0.5481697495393968, + "weights": [ + 0.49425647147649876, + 0.09556856915703738 + ] + } + ], + "output_ids": [ + 0.11787440750922895, + 0.9473188607259506, + 0.9045741659912035 + ] + }, + { + "id": 0.7353679413901013, + "layer_index": 0, + "cx_id": 0.37250552293263184, + "activation_function": "tanh", + "input_weights": [ + { + "input_id": 0.5481697495393968, + "weights": [ + -0.3432015569352376, + -0.15663876804924903 + ] + } + ], + "output_ids": [ + 0.11787440750922895, + 0.9473188607259506, + 0.9045741659912035 + ] + }, + { + "id": 0.7986671199471203, + "layer_index": 0, + "cx_id": 0.37250552293263184, + "activation_function": "tanh", + "input_weights": [ + { + "input_id": 0.5481697495393968, + "weights": [ + 0.44235413103542676, + -0.3014661028473905 + ] + } + ], + "output_ids": [ + 0.11787440750922895, + 0.9473188607259506, + 0.9045741659912035 + ] + }, + { + "id": 0.2619274118215478, + "layer_index": 1, + "cx_id": 0.37250552293263184, + "activation_function": "tanh", + "input_weights": [ + { + "input_id": 0.7892266733003815, + "weights": [ + 0.4815260544600901 + ] + }, + { + "input_id": 0.08993126065168999, + "weights": [ + -0.34742595611872107 + ] + }, + { + "input_id": 0.7353679413901013, + "weights": [ + 0.1955465593022997 + ] + }, + { + "input_id": 0.7986671199471203, + "weights": [ + 0.1420046463445398 + ] + } + ], + "output_ids": [ + 0.804289241732289 + ] + }, + { + "id": 0.1878355172703, + "layer_index": 1, + "cx_id": 0.37250552293263184, + "activation_function": "tanh", + "input_weights": [ + { + "input_id": 0.7892266733003815, + "weights": [ + -0.26492297905129614 + ] + }, + { + "input_id": 0.08993126065168999, + "weights": [ + -0.483071194536965 + ] + }, + { + "input_id": 0.7353679413901013, + "weights": [ + 0.0016581996680702371 + ] + }, + { + "input_id": 0.7986671199471203, + "weights": [ + 0.47010344086613354 + ] + } + ], + "output_ids": [ + 0.804289241732289 + ] + }, + { + "id": 0.5460586524022121, + "layer_index": 1, + "cx_id": 0.37250552293263184, + "activation_function": "tanh", + "input_weights": [ + { + "input_id": 0.7892266733003815, + "weights": [ + 0.22583100100162312 + ] + }, + { + "input_id": 0.08993126065168999, + "weights": [ + 0.22079487426614341 + ] + }, + { + "input_id": 0.7353679413901013, + "weights": [ + 0.3514718848950448 + ] + }, + { + "input_id": 0.7986671199471203, + "weights": [ + 0.03653443587296967 + ] + } + ], + "output_ids": [ + 0.804289241732289 + ] + }, + { + "id": 0.0325156080072021, + "layer_index": 2, + "cx_id": 0.37250552293263184, + "activation_function": "tanh", + "input_weights": [ + { + "input_id": 0.2619274118215478, + "weights": [ + 0.4397546856440344 + ] + }, + { + "input_id": 0.1878355172703, + "weights": [ + 0.024524621225712195 + ] + }, + { + "input_id": 0.5460586524022121, + "weights": [ + 0.19908558570374346 + ] + } + ], + "output_ids": [ + 0.300862433948894 + ] + } + ] +} \ No newline at end of file diff --git a/experiments/phenotype_genotype_map/genotype_updated.json b/experiments/phenotype_genotype_map/genotype_updated.json new file mode 100644 index 0000000..719275e --- /dev/null +++ b/experiments/phenotype_genotype_map/genotype_updated.json @@ -0,0 +1,258 @@ +{ + "cortex": { + "id": 0.38985127736117664, + "sensor_ids": [ + 0.5481697495393968 + ], + "actuator_ids": [ + 0.300862433948894 + ], + "neuron_ids": [ + 0.7892266733003815, + 0.08993126065168999, + 0.7353679413901013, + 0.7986671199471203, + 0.2619274118215478, + 0.1878355172703, + 0.5460586524022121, + 0.0325156080072021 + ] + }, + "sensor": { + "id": 0.5481697495393968, + "name": "rng", + "vector_length": 2, + "cx_id": 0.37250552293263184, + "fanout_ids": [ + 0.7892266733003815, + 0.08993126065168999, + 0.7353679413901013, + 0.7986671199471203 + ] + }, + "actuator": { + "id": 0.300862433948894, + "name": "pts", + "vector_length": 1, + "cx_id": 0.37250552293263184, + "fanin_ids": [ + 0.0325156080072021 + ] + }, + "neurons": [ + { + "id": 0.7892266733003815, + "layer_index": 0, + "cx_id": 0.37250552293263184, + "activation_function": "tanh", + "input_weights": [ + { + "input_id": 0.5481697495393968, + "weights": [ + -0.2010596737648036, + -0.017559575650012982 + ] + } + ], + "output_ids": [ + 0.11787440750922895, + 0.9473188607259506, + 0.9045741659912035 + ] + }, + { + "id": 0.08993126065168999, + "layer_index": 0, + "cx_id": 0.37250552293263184, + "activation_function": "tanh", + "input_weights": [ + { + "input_id": 0.5481697495393968, + "weights": [ + 0.49425647147649876, + 0.09556856915703738 + ] + } + ], + "output_ids": [ + 0.11787440750922895, + 0.9473188607259506, + 0.9045741659912035 + ] + }, + { + "id": 0.7353679413901013, + "layer_index": 0, + "cx_id": 0.37250552293263184, + "activation_function": "tanh", + "input_weights": [ + { + "input_id": 0.5481697495393968, + "weights": [ + -0.3432015569352376, + -0.15663876804924903 + ] + } + ], + "output_ids": [ + 0.11787440750922895, + 0.9473188607259506, + 0.9045741659912035 + ] + }, + { + "id": 0.7986671199471203, + "layer_index": 0, + "cx_id": 0.37250552293263184, + "activation_function": "tanh", + "input_weights": [ + { + "input_id": 0.5481697495393968, + "weights": [ + 0.44235413103542676, + -0.3014661028473905 + ] + } + ], + "output_ids": [ + 0.11787440750922895, + 0.9473188607259506, + 0.9045741659912035 + ] + }, + { + "id": 0.2619274118215478, + "layer_index": 1, + "cx_id": 0.37250552293263184, + "activation_function": "tanh", + "input_weights": [ + { + "input_id": 0.7892266733003815, + "weights": [ + 0.4815260544600901 + ] + }, + { + "input_id": 0.08993126065168999, + "weights": [ + -0.34742595611872107 + ] + }, + { + "input_id": 0.7353679413901013, + "weights": [ + 0.1955465593022997 + ] + }, + { + "input_id": 0.7986671199471203, + "weights": [ + 0.1420046463445398 + ] + } + ], + "output_ids": [ + 0.804289241732289 + ] + }, + { + "id": 0.1878355172703, + "layer_index": 1, + "cx_id": 0.37250552293263184, + "activation_function": "tanh", + "input_weights": [ + { + "input_id": 0.7892266733003815, + "weights": [ + -0.26492297905129614 + ] + }, + { + "input_id": 0.08993126065168999, + "weights": [ + -0.483071194536965 + ] + }, + { + "input_id": 0.7353679413901013, + "weights": [ + 0.0016581996680702371 + ] + }, + { + "input_id": 0.7986671199471203, + "weights": [ + 0.47010344086613354 + ] + } + ], + "output_ids": [ + 0.804289241732289 + ] + }, + { + "id": 0.5460586524022121, + "layer_index": 1, + "cx_id": 0.37250552293263184, + "activation_function": "tanh", + "input_weights": [ + { + "input_id": 0.7892266733003815, + "weights": [ + 0.22583100100162312 + ] + }, + { + "input_id": 0.08993126065168999, + "weights": [ + 0.22079487426614341 + ] + }, + { + "input_id": 0.7353679413901013, + "weights": [ + 0.3514718848950448 + ] + }, + { + "input_id": 0.7986671199471203, + "weights": [ + 0.03653443587296967 + ] + } + ], + "output_ids": [ + 0.804289241732289 + ] + }, + { + "id": 0.0325156080072021, + "layer_index": 2, + "cx_id": 0.37250552293263184, + "activation_function": "tanh", + "input_weights": [ + { + "input_id": 0.2619274118215478, + "weights": [ + 0.4397546856440344 + ] + }, + { + "input_id": 0.1878355172703, + "weights": [ + 0.024524621225712195 + ] + }, + { + "input_id": 0.5460586524022121, + "weights": [ + 0.19908558570374346 + ] + } + ], + "output_ids": [ + 0.300862433948894 + ] + } + ] +} \ No newline at end of file diff --git a/experiments/phenotype_genotype_map/pehno_geno_map.py b/experiments/phenotype_genotype_map/pehno_geno_map.py new file mode 100644 index 0000000..80274dc --- /dev/null +++ b/experiments/phenotype_genotype_map/pehno_geno_map.py @@ -0,0 +1,410 @@ +import asyncio +import json +import math +import random +from collections import defaultdict +from typing import Dict, List, Tuple, Any + + +# utils +def tanh(x: float) -> float: + return math.tanh(x) + + +def rng_vector(vl: int) -> List[float]: + # wie sensor:rng(VL) + return [random.random() for _ in range(vl)] + + +# actor base class +class Actor: + """ + base class for all our actors: sensors, actuators, neurons, cortex. + """ + def __init__(self, name: str): + self.name = name + self.inbox: asyncio.Queue = asyncio.Queue() + + async def send(self, msg: Tuple[Any, ...]): + """ + + """ + await self.inbox.put(msg) + + async def run(self): + """ + this needs to be overridden in subclasses. + """ + raise NotImplementedError + + +# sensor +class Sensor(Actor): + def __init__(self, sid: Any, cx_pid: "Actor", name: str, vl: int, fanout_pids: List["Actor"]): + super().__init__(f"Sensor-{sid}") + self.sid = sid + self.cx_pid = cx_pid + self.sname = name + self.vl = vl + self.fanout = fanout_pids + + async def run(self): + while True: + msg = await self.inbox.get() + tag = msg[0] + if tag == "sync": # {Cx, sync} + # if there is a sync command, we sense from the environment + # and put the result in the inbox of the neurons connected to sensor. + print("sensing...") + # choose sensor funtion + if self.sname == "rng": + vec = rng_vector(self.vl) + else: + # place for own sensors (this will be replaced by scapes down the road) + vec = [0.0] * self.vl + # forward an alle Fanouts + for pid in self.fanout: + await pid.send(("forward", self.sid, vec)) + elif tag == "terminate": + # terminate. + return + + +# neuron +class Neuron(Actor): + def __init__(self, nid: Any, cx_pid: "Actor", af_name: str, + input_idps: List[Tuple[Any, List[float]]], # [(input_id, weights)] (+ optional bias am Ende) + output_pids: List["Actor"]): + super().__init__(f"Neuron-{nid}") + self.nid = nid + self.cx_pid = cx_pid + self.af = tanh if af_name == "tanh" else tanh + # input-id → (weights, received_flag, last_value_vector_or_scalar) + self.inputs: Dict[Any, Dict[str, Any]] = {} + self.order: List[Any] = [] # for deterministic order + for entry in input_idps: + self.order.append(entry[0]) + self.inputs[entry[0]] = {"weights": entry[1], "got": False, "val": None} + self.bias: float = 0.0 # optional bias + self.outputs = output_pids + + async def run(self): + while True: + msg = await self.inbox.get() + tag = msg[0] + if tag == "forward": + # ("forward", from_id, value_vec_or_scalar) + _tag, from_id, data = msg + if from_id not in self.inputs: + # unexpected source - we continue and ignore it + continue + # we mark that we have values from this source to keep sequence + self.inputs[from_id]["got"] = True + self.inputs[from_id]["val"] = data + + # when we have a signal from all sources: calculate dot product. + if all(self.inputs[i]["got"] for i in self.order): + acc = 0.0 + for i in self.order: + w = self.inputs[i]["weights"] + v = self.inputs[i]["val"] + # first layer: v is vector -> dotproduct + if isinstance(v, list): + acc += sum(wj * vj for wj, vj in zip(w, v)) + else: + # from layer 1: scalar -> 1 weight + acc += w[0] * float(v) + out = self.af(acc + self.bias) + # an alle Outputs als Vektor (wie Erlang: [Output]) + for pid in self.outputs: + await pid.send(("forward", self.nid, [out])) + # reset "got"-flags so the next cycle can start + for i in self.order: + self.inputs[i]["got"] = False + self.inputs[i]["val"] = None + + elif tag == "get_backup": + # ("get_backup", reply_to) + _tag, reply_to = msg + # we create (nid, [(input_id, weights), ..., ('bias', bias)]) + idps = [(i, self.inputs[i]["weights"]) for i in self.order] + idps.append(("bias", self.bias)) + # send back to cortex + await reply_to.send(("backup_from_neuron", self.nid, idps)) + + elif tag == "terminate": + return + + +# ---------- Actuator ---------- +class Actuator(Actor): + def __init__(self, aid: Any, cx_pid: "Actor", name: str, fanin_ids: List[Any], expect_count: int): + super().__init__(f"Actuator-{aid}") + self.aid = aid + self.cx_pid = cx_pid + self.aname = name + self.fanin_ids = fanin_ids[:] # order matters! + self.expect = expect_count + self.received: Dict[Any, List[float]] = {} + + async def run(self): + while True: + msg = await self.inbox.get() + tag = msg[0] + if tag == "forward": + _tag, from_id, vec = msg + self.received[from_id] = vec + if len(self.received) == self.expect: + # collect in order of fanin_ids + result: List[float] = [] + for fid in self.fanin_ids: + result.extend(self.received[fid]) + # actuator functions (here: pts → print) + if self.aname == "pts": + print(f"actuator:pts(Result): {result}") + # send sync message to cortex + await self.cx_pid.send(("sync_from_actuator", self.aid)) + self.received.clear() + elif tag == "terminate": + return + + +# cortex with report queue +class Cortex(Actor): + def __init__(self, cid: Any, sensor_pids: List["Actor"], actuator_pids: List["Actor"], + neuron_pids: List["Actor"], total_steps: int, report_queue: asyncio.Queue): + super().__init__(f"Cortex-{cid}") + self.cid = cid + self.sensors = sensor_pids + self.actuators = actuator_pids + self.neurons = neuron_pids + self.total_steps = total_steps + self.awaiting_sync: set = set() + self.actuator_ids: List[Any] = [] + self.report_queue = report_queue + + async def run(self): + # start: trigger all sensors + for s in self.sensors: + await s.send(("sync",)) + + while True: + msg = await self.inbox.get() + tag = msg[0] + + if tag == "register_actuators": + _, actuator_ids = msg + self.actuator_ids = list(actuator_ids) + self.awaiting_sync = set(self.actuator_ids) + + elif tag == "sync_from_actuator": + _, aid = msg + if aid in self.awaiting_sync: + self.awaiting_sync.remove(aid) + + if not self.awaiting_sync: + self.total_steps -= 1 + if self.total_steps <= 0: + # collect backup + weights = [] + for n in self.neurons: + await n.send(("get_backup", self)) + remaining = len(self.neurons) + while remaining > 0: + bmsg = await self.inbox.get() + if bmsg[0] == "backup_from_neuron": + _, nid, idps = bmsg + weights.append((nid, idps)) + remaining -= 1 + + # report result to exoself + await self.report_queue.put(("completed_backup", weights)) + + # terminate + for s in self.sensors: + await s.send(("terminate",)) + for a in self.actuators: + await a.send(("terminate",)) + for n in self.neurons: + await n.send(("terminate",)) + return + + # Nächster Zyklus + self.awaiting_sync = set(self.actuator_ids) + for s in self.sensors: + await s.send(("sync",)) + + elif tag == "completed_backup": + # placeholder + pass + + +# exoself +class Exoself: + def __init__(self, genotype: Dict[str, Any], total_steps: int = 10): + self.g = genotype + self.total_steps = total_steps + self.cx_actor: Cortex = None + self.pid_by_id: Dict[Any, Actor] = {} + self.report_queue: asyncio.Queue = asyncio.Queue() + + # --- helpers for arrays of sensors and actuators --- + @staticmethod + def _as_list(maybe_list_or_item): + if maybe_list_or_item is None: + return [] + if isinstance(maybe_list_or_item, list): + return maybe_list_or_item + return [maybe_list_or_item] + + def _get_sensors_json(self) -> List[Dict[str, Any]]: + if "sensors" in self.g and isinstance(self.g["sensors"], list): + return self.g["sensors"] + elif "sensor" in self.g and isinstance(self.g["sensor"], dict): + return [self.g["sensor"]] + else: + return [] + + def _get_actuators_json(self) -> List[Dict[str, Any]]: + if "actuators" in self.g and isinstance(self.g["actuators"], list): + return self.g["actuators"] + elif "actuator" in self.g and isinstance(self.g["actuator"], dict): + return [self.g["actuator"]] + else: + return [] + + def _build_pid_map(self): + cx = self.g["cortex"] + self.cx_actor = Cortex(cx["id"], [], [], [], self.total_steps, self.report_queue) + self.pid_by_id[cx["id"]] = self.cx_actor + + # placeholder for all known ids + for s in self._get_sensors_json(): + self.pid_by_id[s["id"]] = None + for a in self._get_actuators_json(): + self.pid_by_id[a["id"]] = None + for n in self.g["neurons"]: + self.pid_by_id[n["id"]] = None + + def _link_and_spawn(self): + # order neurons by layers + layers = defaultdict(list) + for n in self.g["neurons"]: + layers[n["layer_index"]].append(n) + ordered_layers = [layers[i] for i in sorted(layers)] + if not ordered_layers: + raise ValueError("Keine Neuronen im Genotyp gefunden.") + + # build actuators + actuators_json = self._get_actuators_json() + actuator_pid_by_id: Dict[Any, Actuator] = {} + + # for last layer: we need list of neuron-ids (for matching) + last_layer = ordered_layers[-1] + last_layer_ids = {n["id"] for n in last_layer} + + for a in actuators_json: + fanin_ids = self._as_list(a.get("fanin_ids", [])) + # Safety: if genotype is empty at this place, take neurons of last layer + if not fanin_ids: + fanin_ids = list(last_layer_ids) + actuator = Actuator(a["id"], self.cx_actor, a["name"], fanin_ids, expect_count=len(fanin_ids)) + self.pid_by_id[a["id"]] = actuator + actuator_pid_by_id[a["id"]] = actuator + + actuator_actors = list(actuator_pid_by_id.values()) + + # build the neurons + neuron_pid_by_id: Dict[Any, Neuron] = {} + for layer in ordered_layers: + for n in layer: + input_idps = [(iw["input_id"], iw["weights"]) for iw in n["input_weights"]] + neuron = Neuron(n["id"], self.cx_actor, n["activation_function"], input_idps, []) + neuron_pid_by_id[n["id"]] = neuron + self.pid_by_id[n["id"]] = neuron + + # set next layer as output for non output neurons + for li, layer in enumerate(ordered_layers[:-1]): + next_layer = ordered_layers[li + 1] + next_pids = [neuron_pid_by_id[nx["id"]] for nx in next_layer] + for n in layer: + neuron_pid_by_id[n["id"]].outputs = next_pids + + # outputs for output layer: actuators + for n in ordered_layers[-1]: + outs: List[Actor] = [] + nid = n["id"] + for a in actuators_json: + fanin_ids = set(self._as_list(a.get("fanin_ids", []))) + # default: if fanin empty, all last layer feed this actuator + if not fanin_ids or nid in fanin_ids: + outs.append(actuator_pid_by_id[a["id"]]) + neuron_pid_by_id[nid].outputs = outs + + # build sensors + sensors_json = self._get_sensors_json() + sensor_actors: List[Sensor] = [] + first_layer = ordered_layers[0] + first_layer_pid_by_id = {n["id"]: neuron_pid_by_id[n["id"]] for n in first_layer} + + for s in sensors_json: + # if the genotype contains fanout_ids we use exactly these + fanout_ids = self._as_list(s.get("fanout_ids", [])) + if fanout_ids: + fanout_pids = [first_layer_pid_by_id[fid] for fid in fanout_ids if fid in first_layer_pid_by_id] + # if fanout_ids point to non-first-layer (unclean genotype), fallback: + if not fanout_pids: + fanout_pids = list(first_layer_pid_by_id.values()) + else: + # default: all neurons in first layer + fanout_pids = list(first_layer_pid_by_id.values()) + + sensor = Sensor(s["id"], self.cx_actor, s["name"], s["vector_length"], fanout_pids) + self.pid_by_id[s["id"]] = sensor + sensor_actors.append(sensor) + + # fill cortex + self.cx_actor.sensors = sensor_actors + self.cx_actor.actuators = actuator_actors + self.cx_actor.neurons = [neuron_pid_by_id[n["id"]] for n in self.g["neurons"]] + + async def run(self) -> List[Tuple[Any, List[Tuple[Any, List[float]]]]]: + self._build_pid_map() + self._link_and_spawn() + + # start tasks + tasks = [asyncio.create_task(self.cx_actor.run())] + for v in self.pid_by_id.values(): + if isinstance(v, Actor) and v is not self.cx_actor: + tasks.append(asyncio.create_task(v.run())) + + # register all actuator ids + actuator_ids = [a["id"] for a in self._get_actuators_json()] + await self.cx_actor.send(("register_actuators", actuator_ids)) + + # wait for result in report queue + tag, weights = await self.report_queue.get() + assert tag == "completed_backup" + + # cleanup + for t in tasks: + if not t.done(): + t.cancel() + return weights + + @staticmethod + def update_genotype_with_backup(geno: Dict[str, Any], + backup: List[Tuple[Any, List[Tuple[Any, List[float]]]]]) -> Dict[str, Any]: + by_id = {n["id"]: n for n in geno["neurons"]} + for nid, idps in backup: + if nid not in by_id: + continue + new_iw = [] + for item in idps: + if isinstance(item[0], str) and item[0] == "bias": + continue + input_id, weights = item + new_iw.append({"input_id": input_id, "weights": weights}) + by_id[nid]["input_weights"] = new_iw + return geno + diff --git a/experiments/phenotype_genotype_map/run.py b/experiments/phenotype_genotype_map/run.py new file mode 100644 index 0000000..74ca059 --- /dev/null +++ b/experiments/phenotype_genotype_map/run.py @@ -0,0 +1,19 @@ +import asyncio +import json +from pehno_geno_map import Exoself + +# load genotype from json +with open("genotype.json") as f: + geno = json.load(f) + +# map phenotype and run for 5 cycles +ex = Exoself(geno, total_steps=5) +# get backup +backup = asyncio.run(ex.run()) + +print("Backup erhalten (gekürzt):", [(nid, len(idps)) for nid, idps in backup]) + +# update genotype and safe +u_geno = Exoself.update_genotype_with_backup(geno, backup) +with open("genotype_updated.json", "w") as f: + json.dump(u_geno, f, indent=2) diff --git a/experiments/neuron.py b/experiments/simple_nn/neuron.py similarity index 100% rename from experiments/neuron.py rename to experiments/simple_nn/neuron.py diff --git a/experiments/simplest_nn.py b/experiments/simple_nn/simplest_nn.py similarity index 96% rename from experiments/simplest_nn.py rename to experiments/simple_nn/simplest_nn.py index a7f0216..281e487 100644 --- a/experiments/simplest_nn.py +++ b/experiments/simple_nn/simplest_nn.py @@ -58,6 +58,7 @@ class Sensor(threading.Thread): except queue.Empty: continue + class Actuator(threading.Thread): def __init__(self, actuator_queue): super().__init__() @@ -80,6 +81,7 @@ class Actuator(threading.Thread): except queue.Empty: continue + class Cortex(threading.Thread): def __init__(self, sensor_queue, neuron_queue, actuator_queue): super().__init__() @@ -102,6 +104,7 @@ class Cortex(threading.Thread): print("Unknown command. Please use 'sense_think_act' or 'terminate'.") print("Cortex terminated.") + if __name__ == "__main__": sensor_queue = queue.Queue() neuron_queue = queue.Queue() @@ -127,4 +130,4 @@ if __name__ == "__main__": neuron.join() actuator.join() - print("System terminated.") \ No newline at end of file + print("System terminated.") diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..b2707d9 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +gymnasium==1.2.1 +numpy>=1.23 +Box2D +pygame \ No newline at end of file