last changes
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -2,6 +2,9 @@ import asyncio
|
||||
|
||||
|
||||
class Actor:
|
||||
"""
|
||||
actor base class.
|
||||
"""
|
||||
def __init__(self, name: str):
|
||||
self.name = name
|
||||
self.inbox = asyncio.Queue()
|
||||
|
||||
@@ -7,6 +7,33 @@ log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Actuator(Actor):
|
||||
"""
|
||||
Actuator actor responsible for collecting outputs from upstream neurons
|
||||
(fanin), assembling them into an action/output vector, interacting with
|
||||
a scape (environment), and synchronizing the result back to the cortex.
|
||||
|
||||
Conceptually, an Actuator represents the *output layer* of a cortex/agent:
|
||||
- It waits for `forward` messages from all expected fanin sources.
|
||||
- Once all signals are received, they are concatenated in the order
|
||||
defined by `fanin_ids` into a flat output vector.
|
||||
- Depending on `aname`, the output is:
|
||||
* used for debugging/testing ("pts"),
|
||||
* sent directly as an action to a scape ("xor_SendOutput"),
|
||||
* mapped to a car control action and sent to a CarRacing scape
|
||||
("car_ApplyAction"),
|
||||
* or ignored with a default fitness.
|
||||
- After the interaction, the actuator reports the resulting fitness
|
||||
and halt flag back to the cortex via a `"sync"` message.
|
||||
|
||||
Inbox message protocol:
|
||||
- ("forward", from_id, vec):
|
||||
`from_id` is the ID of the sending fanin neuron,
|
||||
`vec` is its output vector.
|
||||
- ("result", fitness, halt_flag):
|
||||
Response from the scape after an action was applied.
|
||||
- ("terminate",):
|
||||
Terminates the actor.
|
||||
"""
|
||||
def __init__(self, aid, cx_pid, name, fanin_ids, expect_count, scape=None):
|
||||
super().__init__(f"Actuator-{aid}")
|
||||
self.aid = aid
|
||||
|
||||
@@ -6,6 +6,41 @@ log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Cortex(Actor):
|
||||
"""
|
||||
Cortex actor coordinating a network of Sensors, Neurons, and Actuators.
|
||||
|
||||
The Cortex is responsible for driving the network forward in discrete
|
||||
computation cycles, collecting fitness feedback from all actuators, and
|
||||
reporting evaluation results to an Exoself (supervisor) actor.
|
||||
|
||||
High-level behavior:
|
||||
- At the start of an episode, the cortex triggers a new cycle:
|
||||
1) It tells all neurons to prepare recurrent state for the new cycle
|
||||
via ("cycle_start",).
|
||||
2) It optionally triggers neurons via ("tick",) (scheduler hook).
|
||||
3) It tells all sensors to produce outputs via ("sync",).
|
||||
- Actuators eventually send back ("sync", aid, fitness, halt_flag).
|
||||
- Once all actuators have synchronized for the current cycle, the cortex
|
||||
either:
|
||||
* ends the evaluation if any actuator requested a halt (halt_flag > 0),
|
||||
and reports ("evaluation_completed", total_fitness, cycles, elapsed)
|
||||
to the exoself, or
|
||||
* starts the next cycle.
|
||||
|
||||
Message protocol (inbox):
|
||||
- ("register_actuators", aids):
|
||||
Provide/replace the set of actuator IDs that must sync each cycle.
|
||||
Used when actuators are created dynamically or not known at init.
|
||||
- ("sync", aid, fitness, halt_flag):
|
||||
Fitness feedback from an actuator for the current cycle.
|
||||
The cortex accumulates fitness and checks halt conditions.
|
||||
- ("reactivate",):
|
||||
Restart a new evaluation episode (reset counters and kick sensors).
|
||||
- ("terminate",):
|
||||
Terminate the cortex and cascade termination to sensors/neurons/actuators.
|
||||
- ("backup_from_neuron", nid, idps...):
|
||||
Forward neuron backup data upstream to the exoself.
|
||||
"""
|
||||
def __init__(self, cid, exoself_pid, sensor_pids, neuron_pids, actuator_pids):
|
||||
super().__init__(f"Cortex-{cid}")
|
||||
self.cid = cid
|
||||
|
||||
@@ -12,6 +12,24 @@ def tanh(x): return math.tanh(x)
|
||||
|
||||
|
||||
class Neuron(Actor):
|
||||
"""
|
||||
Neuron actor implementing a weighted-sum neuron with an activation function
|
||||
and optional recurrent inputs.
|
||||
|
||||
The Neuron receives input vectors from upstream neurons, accumulates them
|
||||
according to its weight configuration, applies an activation function,
|
||||
and forwards the resulting output to downstream actors.
|
||||
|
||||
It supports:
|
||||
- feed-forward and recurrent connections
|
||||
- bias handling
|
||||
- asynchronous message-based execution
|
||||
- weight backup, restoration, and stochastic perturbation (mutation)
|
||||
- cycle-based updates for recurrent networks
|
||||
|
||||
This actor is designed to be used inside a cortex/agent actor network,
|
||||
where synchronization and evolution are coordinated externally.
|
||||
"""
|
||||
def __init__(self, nid, cx_pid, af_name, input_idps, output_pids, bias: Optional[float] = None):
|
||||
super().__init__(f"Neuron-{nid}")
|
||||
self.nid = nid
|
||||
|
||||
@@ -6,6 +6,42 @@ log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Sensor(Actor):
|
||||
"""
|
||||
Sensor actor that produces an input vector for the network and forwards it
|
||||
to downstream actors (fanout).
|
||||
|
||||
A Sensor is an *input node* in the actor-based neural architecture. It does
|
||||
not compute from other neurons; instead, it generates observations either
|
||||
from:
|
||||
- a local source (e.g., random numbers), or
|
||||
- an external scape/environment actor.
|
||||
|
||||
When the cortex triggers a sensor with a ("sync",) message, the sensor:
|
||||
1) calls `_sense()` to obtain a vector,
|
||||
2) broadcasts that vector to all downstream targets in `fanout` via
|
||||
("forward", sid, vec).
|
||||
|
||||
Supported sensor types (controlled by `sname`):
|
||||
- "rng":
|
||||
Produces `vl` random floats in [0, 1).
|
||||
- "xor_GetInput" (requires `scape`):
|
||||
Requests an input vector from the scape and expects a ("percept", vec)
|
||||
reply on its own inbox.
|
||||
- "car_GetFeatures" (requires `scape`):
|
||||
Requests a feature vector from the scape and normalizes it:
|
||||
* clamps values to [-1, 1],
|
||||
* pads with zeros or truncates to exactly `vl` elements.
|
||||
- default:
|
||||
Returns a zero vector of length `vl`.
|
||||
|
||||
Inbox message protocol:
|
||||
- ("sync",):
|
||||
Trigger sensing and forwarding to fanout.
|
||||
- ("percept", vec):
|
||||
Scape reply to a previous ("sense", sid, self) request (handled inside `_sense()`).
|
||||
- ("terminate",):
|
||||
Stop the actor.
|
||||
"""
|
||||
def __init__(self, sid, cx_pid, name, vector_length, fanout_pids, scape=None):
|
||||
super().__init__(f"Sensor-{sid}")
|
||||
self.sid = sid
|
||||
|
||||
Reference in New Issue
Block a user