use crate::types::{RootVector, RootSpace};
use alloc::vec::Vec;
use alloc::boxed::Box;
use core::fmt;
pub trait MicroNet {
fn id(&self) -> u32;
fn state(&self) -> &AgentState;
fn update_state(&mut self, new_state: RootVector);
fn forward(&mut self, input: &RootVector) -> RootVector;
fn is_routing_head(&self) -> bool;
fn agent_type(&self) -> AgentType;
fn net_type(&self) -> AgentType {
self.agent_type()
}
fn compatibility(&self, other: &dyn MicroNet) -> f32 {
let self_state = self.state().root_vector;
let other_state = other.state().root_vector;
let dot = self_state.dot(&other_state);
let self_mag = self_state.magnitude();
let other_mag = other_state.magnitude();
if self_mag > 0.0 && other_mag > 0.0 {
(dot / (self_mag * other_mag) + 1.0) / 2.0
} else {
0.5 }
}
}
#[derive(Clone, Debug)]
pub struct AgentState {
pub root_vector: RootVector,
pub activation: f32,
pub confidence: f32,
pub update_count: u32,
}
impl AgentState {
pub fn new() -> Self {
Self {
root_vector: RootVector::zero(),
activation: 0.0,
confidence: 0.0,
update_count: 0,
}
}
pub fn with_vector(root_vector: RootVector) -> Self {
Self {
root_vector,
activation: 1.0,
confidence: 1.0,
update_count: 0,
}
}
pub fn update(&mut self, new_vector: RootVector, learning_rate: f32) {
for i in 0..32 {
self.root_vector.data[i] =
(1.0 - learning_rate) * self.root_vector.data[i] +
learning_rate * new_vector.data[i];
}
self.update_count += 1;
let similarity = self.root_vector.dot(&new_vector) /
(self.root_vector.magnitude() * new_vector.magnitude());
self.confidence = 0.9 * self.confidence + 0.1 * similarity.abs();
}
}
impl Default for AgentState {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum AgentType {
Reasoning,
Routing,
Feature,
Embedding,
Expert,
}
impl fmt::Display for AgentType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AgentType::Reasoning => write!(f, "Reasoning"),
AgentType::Routing => write!(f, "Routing"),
AgentType::Feature => write!(f, "Feature"),
AgentType::Embedding => write!(f, "Embedding"),
AgentType::Expert => write!(f, "Expert"),
}
}
}
pub struct BasicAgent {
id: u32,
state: AgentState,
agent_type: AgentType,
weights: RootVector,
bias: f32,
is_rank_one: bool,
}
impl BasicAgent {
pub fn new(id: u32, agent_type: AgentType) -> Self {
Self {
id,
state: AgentState::new(),
agent_type,
weights: RootVector::zero(),
bias: 0.0,
is_rank_one: agent_type == AgentType::Routing,
}
}
pub fn new_routing(id: u32) -> Self {
Self::new(id, AgentType::Routing)
}
pub fn new_reasoning(id: u32) -> Self {
Self::new(id, AgentType::Reasoning)
}
pub fn with_weights(mut self, weights: RootVector) -> Self {
self.weights = weights;
self.weights.normalize();
self
}
}
impl MicroNet for BasicAgent {
fn id(&self) -> u32 {
self.id
}
fn state(&self) -> &AgentState {
&self.state
}
fn update_state(&mut self, new_state: RootVector) {
self.state.update(new_state, 0.1); }
fn forward(&mut self, input: &RootVector) -> RootVector {
let mut output = RootVector::zero();
if self.is_rank_one {
let projection = input.dot(&self.weights);
for i in 0..32 {
output.data[i] = projection * self.weights.data[i] + self.bias;
}
} else {
for i in 0..32 {
output.data[i] = input.data[i] * self.weights.data[i] + self.bias;
}
}
self.state.root_vector = output;
self.state.activation = output.magnitude().min(1.0);
output
}
fn is_routing_head(&self) -> bool {
self.is_rank_one
}
fn agent_type(&self) -> AgentType {
self.agent_type
}
}
pub struct AgentSwarm {
agents: Vec<Box<dyn MicroNet>>,
root_space: RootSpace,
}
impl AgentSwarm {
pub fn new(root_space: RootSpace) -> Self {
Self {
agents: Vec::new(),
root_space,
}
}
pub fn add_agent(&mut self, agent: Box<dyn MicroNet>) {
self.agents.push(agent);
}
pub fn agents_by_type(&self, agent_type: AgentType) -> Vec<&dyn MicroNet> {
self.agents
.iter()
.filter(|a| a.agent_type() == agent_type)
.map(|a| a.as_ref())
.collect()
}
pub fn find_compatible(&self, agent: &dyn MicroNet, threshold: f32) -> Vec<&dyn MicroNet> {
self.agents
.iter()
.filter(|a| {
let compat = agent.compatibility(a.as_ref());
compat >= threshold && a.id() != agent.id()
})
.map(|a| a.as_ref())
.collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_agent_creation() {
let agent = BasicAgent::new(1, AgentType::Reasoning);
assert_eq!(agent.id(), 1);
assert_eq!(agent.agent_type(), AgentType::Reasoning);
assert!(!agent.is_routing_head());
}
#[test]
fn test_routing_agent() {
let agent = BasicAgent::new_routing(2);
assert_eq!(agent.agent_type(), AgentType::Routing);
assert!(agent.is_routing_head());
}
#[test]
fn test_agent_compatibility() {
let mut agent1 = BasicAgent::new(1, AgentType::Reasoning);
let mut agent2 = BasicAgent::new(2, AgentType::Reasoning);
let state = RootVector::from_array([1.0; 32]);
agent1.update_state(state);
agent2.update_state(state);
let compat = agent1.compatibility(&agent2);
assert!(compat > 0.9); }
}