use crate::engines::soa::interaction::InteractionOrder;
use crate::engines::soa::{Interaction, InteractionError, InteractionId};
use crate::models::laws::{PowerLawDecay, PowerLawError, PowerLawRange};
#[derive(Debug, Clone, PartialEq)]
pub enum PowerLawNetworkError {
Interaction(InteractionError),
Law(PowerLawError),
}
impl From<InteractionError> for PowerLawNetworkError {
fn from(value: InteractionError) -> Self {
Self::Interaction(value)
}
}
impl From<PowerLawError> for PowerLawNetworkError {
fn from(value: PowerLawError) -> Self {
Self::Law(value)
}
}
#[derive(Debug, Clone)]
pub struct PowerLawNetwork {
interactions: Interaction<PowerLawDecay>,
}
impl Default for PowerLawNetwork {
fn default() -> Self {
Self::empty()
}
}
impl PowerLawNetwork {
pub fn empty() -> Self {
Self {
interactions: Interaction::new(0, InteractionOrder::Unordered),
}
}
pub fn len(&self) -> usize {
self.interactions.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn add_power_law(
&mut self,
pair: (usize, usize),
k: f64,
alpha: f64,
range: Option<PowerLawRange>,
) -> Result<InteractionId, PowerLawNetworkError> {
self.add_payload(pair, PowerLawDecay::new(k, alpha, range)?)
}
pub fn add_payload(
&mut self,
pair: (usize, usize),
payload: PowerLawDecay,
) -> Result<InteractionId, PowerLawNetworkError> {
payload.validate()?;
self.ensure_n_objects_for(pair);
Ok(self.interactions.set_pair(pair.0, pair.1, payload)?)
}
pub fn remove_power_law(
&mut self,
pair: (usize, usize),
) -> Result<Option<PowerLawDecay>, PowerLawNetworkError> {
if pair.0.max(pair.1) >= self.interactions.topology().n_objects() {
return Ok(None);
}
Ok(self
.interactions
.remove_pair(pair.0, pair.1)?
.map(|(_, payload)| payload))
}
pub fn get_power_law(
&self,
pair: (usize, usize),
) -> Result<Option<&PowerLawDecay>, PowerLawNetworkError> {
if pair.0.max(pair.1) >= self.interactions.topology().n_objects() {
return Ok(None);
}
Ok(self.interactions.get_pair(pair.0, pair.1)?)
}
pub fn get_power_law_mut(
&mut self,
pair: (usize, usize),
) -> Result<Option<&mut PowerLawDecay>, PowerLawNetworkError> {
if pair.0.max(pair.1) >= self.interactions.topology().n_objects() {
return Ok(None);
}
Ok(self.interactions.get_pair_mut(pair.0, pair.1)?)
}
pub fn clear(&mut self) {
self.interactions.clear();
}
pub fn interaction(&self) -> &Interaction<PowerLawDecay> {
&self.interactions
}
pub fn interaction_mut(&mut self) -> &mut Interaction<PowerLawDecay> {
&mut self.interactions
}
fn ensure_n_objects_for(&mut self, pair: (usize, usize)) {
let needed = pair.0.max(pair.1).saturating_add(1);
if needed > self.interactions.topology().n_objects() {
self.interactions
.set_n_objects(needed)
.expect("growing power-law interaction object bound should not invalidate entries");
}
}
}