# actors/scape.py from actor import Actor import math class XorScape(Actor): def __init__(self): super().__init__("XorScape") self.data = [ ([-1, -1], [-1]), ([1, -1], [1]), ([-1, 1], [1]), ([1, 1], [-1]) ] self.index = 0 self.error_acc = 0.0 self.last_actuator = None # <-- wer uns zuletzt "action" geschickt hat async def run(self): while True: msg = await self.inbox.get() tag = msg[0] if tag == "sense": print("SCAPE: got sensed by sensor...") # Sensor fragt nach Input _, sid, from_pid = msg self.last_actuator = from_pid # merken, wer beteiligt ist inputs, correct = self.data[self.index] print("SENSOR input /correct: ", inputs, correct) await from_pid.send(("percept", inputs)) elif tag == "action": _, output, from_pid = msg _, correct = self.data[self.index] # Calculate RMSE like the Erlang version step_error = sum((o - c) ** 2 for o, c in zip(output, correct)) step_rmse = math.sqrt(step_error) # This is the key change! print(f"XOR PATTERN: Input={self.data[self.index][0]} → Network={output} → Expected={correct}") self.index += 1 if self.index >= len(self.data): # Episode finished - calculate final fitness total_rmse = math.sqrt(self.error_acc + step_rmse) # Not step_error! fitness = 1.0 / (total_rmse + 1e-5) await from_pid.send(("result", fitness, 1)) self.index = 0 self.error_acc = 0.0 else: # Continue episode self.error_acc += step_rmse # Add RMSE, not raw error await from_pid.send(("result", 0.0, 0)) elif tag == "terminate": return