belief_spread/
agent.rs

1use std::{cell::RefCell, collections::HashMap, rc::Rc};
2
3use anyhow::Result;
4use by_address::ByAddress;
5use uuid::Uuid;
6
7use crate::{
8    errors::{OutOfRangeError, UpdateActivationError},
9    BehaviourPtr, BeliefPtr, SimTime, UUIDd,
10};
11
12/// A [Rc] [RefCell] pointer to an [Agent] compared by its address.
13pub type AgentPtr = ByAddress<Rc<RefCell<dyn Agent>>>;
14
15impl From<BasicAgent> for AgentPtr {
16    /// Convert from a [BasicAgent] into a [AgentPtr].
17    ///
18    /// This consumes the [BasicAgent].
19    ///
20    /// # Arguments
21    /// - `a`: The [BasicAgent] to convert.
22    ///
23    /// # Returns
24    /// The [AgentPtr].
25    ///
26    /// # Examples
27    /// ```
28    /// use belief_spread::{BasicAgent, AgentPtr};
29    ///
30    /// let a = BasicAgent::new();
31    /// let a_ptr = AgentPtr::from(a);
32    /// ```
33    ///
34    /// ```
35    /// use belief_spread::{BasicAgent, AgentPtr};
36    ///
37    /// let a = BasicAgent::new();
38    /// let a_ptr: AgentPtr = a.into();
39    /// ```
40    fn from(a: BasicAgent) -> Self {
41        ByAddress(Rc::new(RefCell::new(a)))
42    }
43}
44
45/// An [Agent] which may exist in the model.
46pub trait Agent: UUIDd {
47    /// Gets the activation of an [Agent] towards a [BeliefPtr] at a given [SimTime].
48    ///
49    /// This is always between -1 and +1.
50    ///
51    /// # Arguments
52    /// - `time`: The [SimTime].
53    /// - `belief`: The [BeliefPtr].
54    ///
55    /// # Returns
56    /// The activation, if found.
57    fn get_activation(&self, time: SimTime, belief: &BeliefPtr) -> Option<f64>;
58
59    /// Gets the activations of an [Agent] towards all [BeliefPtr]s at all [SimTime]s.
60    ///
61    /// This is always between -1 and +1.
62    ///
63    /// [BeliefPtr]s are referenced by their [Uuid]s.
64    ///
65    /// # Return
66    /// A map from simulation time to a new map from [BeliefPtr] to the
67    /// activation.
68    fn get_activations(&self) -> &HashMap<SimTime, HashMap<BeliefPtr, f64>>;
69
70    /// Sets the activation of an [Agent] towards a [BeliefPtr] at a given [SimTime].
71    ///
72    /// If the activation is [None], then the activation is deleted.
73    ///
74    /// This is a value between -1 and +1.
75    ///
76    /// # Arguments
77    /// - `time`: The [SimTime] to update.
78    /// - `belief`: The [BeliefPtr] to update.
79    /// - `activation`: The new activation.
80    ///
81    /// # Returns
82    /// A [Result], [Ok] if nothing went wrong, or an [Err] with an
83    /// [OutOfRangeError], if the activation is not in the range [-1, +1].
84    fn set_activation(
85        &mut self,
86        time: SimTime,
87        belief: BeliefPtr,
88        activation: Option<f64>,
89    ) -> Result<(), OutOfRangeError>;
90
91    /// Gets the friends of the [Agent].
92    ///
93    /// This gets the friends of the [Agent] (identified by their [Uuid]) with
94    /// their weight of connection.
95    ///
96    /// All weights are in the range [0, 1].
97    ///
98    /// # Returns
99    /// The friends with their weight of connection.
100    fn get_friends(&self) -> &HashMap<AgentPtr, f64>;
101
102    /// Gets the weight of a friend of the [Agent].
103    ///
104    /// The weight will be in the range [0, 1];
105    ///
106    /// If they are not friends, returns [None].
107    ///
108    /// # Arguments
109    /// - `friend`: The friend.
110    ///
111    /// # Returns
112    /// The weight, or [None] if they are not friends.
113    fn get_friend_weight(&self, friend: &AgentPtr) -> Option<f64>;
114
115    /// Set the weight of a friend of the [Agent].
116    ///
117    /// If they are not friends, this adds another [Agent] as a `friend` with
118    /// a supplied weight.
119    ///
120    /// `weight` must be in the range [0, 1].
121    ///
122    /// If `friend` already exists, the `weight` is overwritten.
123    ///
124    /// If the `weight` is [None], the `friend` is removed if they were friends.
125    ///
126    /// # Arguments
127    /// - `friend`: The friend.
128    /// - `weight`: The weight
129    ///
130    /// # Returns
131    /// A [Result], [Ok] if nothing went wrong, or an [Err] with an
132    /// [OutOfRangeError], if the weight is not in the range [0, +1].
133    fn set_friend_weight(
134        &mut self,
135        friend: AgentPtr,
136        weight: Option<f64>,
137    ) -> Result<(), OutOfRangeError>;
138
139    /// Gets the [BehaviourPtr] the [Agent] performed at a given [SimTime].
140    ///
141    /// Returns the [BehaviourPtr].
142    ///
143    /// # Arguments
144    /// - `time`: The [SimTime].
145    ///
146    /// # Returns
147    /// The [BehaviourPtr], if one was performed at `time`.
148    fn get_action(&self, time: SimTime) -> Option<&BehaviourPtr>;
149
150    /// Gets all of the [BehaviourPtr]s that the [Agent] has performed.
151    ///
152    /// # Returns
153    /// A [HashMap] from [SimTime] to [BehaviourPtr].
154    fn get_actions(&self) -> &HashMap<SimTime, BehaviourPtr>;
155
156    /// Sets the [BehaviourPtr] the [Agent] performed at a given time.
157    ///
158    /// If [None], it unsets the [BehaviourPtr].
159    ///
160    /// # Arguments
161    /// - `time`: The [SimTime].
162    /// - `behaviour`: The new [BehaviourPtr] that was performed at `time`.
163    fn set_action(&mut self, time: SimTime, behaviour: Option<BehaviourPtr>);
164
165    /// Gets the delta for a given [BeliefPtr].
166    ///
167    /// This is the value that the activation for the [BeliefPtr] changed by
168    /// (multiplicatively) at every time step.
169    ///
170    /// This is a strictly positive value (i.e., > 0).
171    ///
172    /// # Arguments
173    /// - `belief`: The [BeliefPtr].
174    ///
175    /// # Returns
176    /// The delta for the [BeliefPtr] and this [Agent], if found.
177    fn get_delta(&self, belief: &BeliefPtr) -> Option<f64>;
178
179    /// Gets all the deltas for the [Agent].
180    ///
181    /// This is the value that the activation for the [BeliefPtr] changed by
182    /// (multiplicatively) at every time step.
183    ///
184    /// This is a strictly positive value (i.e., > 0).
185    ///
186    /// # Returns
187    /// A map from [BeliefPtr] to delta.
188    fn get_deltas(&self) -> &HashMap<BeliefPtr, f64>;
189
190    /// Sets the delta for a given [BeliefPtr].
191    ///
192    /// This is the value that the activation for the [BeliefPtr] changed by
193    /// (multiplicatively) at every time step.
194    ///
195    /// This is a strictly positive value (i.e., > 0).
196    ///
197    /// If `delta` is [None], then this function removes the delta.
198    ///
199    /// # Arguments
200    /// - `belief`: The [BeliefPtr].
201    /// - `delta`: The new delta.
202    ///
203    /// # Returns
204    /// A [Result], [Ok] if nothing is wrong, or an [Err] with a
205    /// [OutOfRangeError], if the delta is not strictly positive.
206    fn set_delta(&mut self, belief: BeliefPtr, delta: Option<f64>) -> Result<(), OutOfRangeError>;
207
208    /// Gets the weighted relationship between [BeliefPtr]s `b1` and `b2`.
209    ///
210    /// This is the compatibility for holding `b2`, given that the [Agent]
211    /// already holds `b1`.
212    ///
213    /// This is equal to the activation of `b1`
214    /// ([`Agent::get_activation`]), multiplied by the
215    /// relationship between `b1` and `b2`
216    /// ([`crate::Belief::get_relationship`]).
217    ///
218    /// Returns [None] if either activation of `b1` at time `t` is [None], or
219    /// the relationship between `b1` and `b2` is [None].
220    ///
221    /// # Arguments
222    /// - `t`: The simulation time ([SimTime]).
223    /// - `b1`: The first [BeliefPtr].
224    /// - `b2`: The second [BeliefPtr].
225    ///
226    /// # Returns
227    /// The weighted relationship.
228    fn weighted_relationship(&self, t: SimTime, b1: &BeliefPtr, b2: &BeliefPtr) -> Option<f64>;
229
230    /// Gets the context for holding the [BeliefPtr] `b`.
231    ///
232    /// This is the compatibility for holding `b`, given all the beliefs the
233    /// agent holds.
234    ///
235    /// This is the average of [`Agent::weighted_relationship`] for every
236    /// [BeliefPtr] (as given in `beliefs).
237    ///
238    /// # Arguments
239    /// - `time`: The simulation time ([SimTime]).
240    /// - `b`: The [BeliefPtr].
241    /// - `beliefs`: All the [BeliefPtr]s in existence.
242    ///
243    /// # Returns
244    /// The context.
245    fn contextualise(&self, t: SimTime, b: &BeliefPtr, beliefs: &[BeliefPtr]) -> f64;
246
247    /// Gets the pressure the [Agent] feels to adopt a [BeliefPtr] given the
248    /// actions of their friends.
249    ///
250    /// This does not take into account the beliefs that the [Agent] already
251    /// holds.
252    ///
253    /// # Arguments
254    /// - `time`: The time as [SimTime].
255    /// - `belief`: The [BeliefPtr].
256    ///
257    /// # Returns
258    /// The pressure
259    fn pressure(&self, time: SimTime, belief: &BeliefPtr) -> f64;
260
261    /// Gets the change in activation for the [Agent] as a result of the
262    /// [BehaviourPtr]s observed.
263    ///
264    /// This takes into account the beliefs that the agent already holds
265    ///
266    /// # Arguments
267    /// - `time`: The time as [SimTime].
268    /// - `belief`: The [BeliefPtr].
269    /// - `beliefs`: All the [BeliefPtr]s in existence.
270    ///
271    /// # Return
272    /// - The change in activation
273    fn activation_change(&self, time: SimTime, belief: &BeliefPtr, beliefs: &[BeliefPtr]) -> f64;
274}
275
276/// A [BasicAgent] is an implementation of [Agent].
277pub struct BasicAgent {
278    uuid: Uuid,
279    activations: HashMap<SimTime, HashMap<BeliefPtr, f64>>,
280    friends: HashMap<AgentPtr, f64>,
281    actions: HashMap<SimTime, BehaviourPtr>,
282    deltas: HashMap<BeliefPtr, f64>,
283}
284
285impl BasicAgent {
286    /// Create a new [BasicAgent] with a random [Uuid]
287    ///
288    /// # Returns
289    /// The new [BasicAgent] with a [Uuid] generated using
290    /// [`uuid::Uuid::new_v4`].
291    ///
292    /// # Examples
293    ///
294    /// ```
295    /// use belief_spread::BasicAgent;
296    ///
297    /// let a = BasicAgent::new();
298    /// ```
299    pub fn new() -> Self {
300        Self::new_with_uuid(Uuid::new_v4())
301    }
302
303    /// Create a new [BasicAgent] with a specified [Uuid]
304    ///
305    /// # Arguments
306    /// - `uuid`: The [Uuid] of the [BasicAgent].
307    ///
308    /// # Returns
309    /// The new [BasicAgent] with a specified [Uuid].
310    ///
311    /// # Examples
312    ///
313    /// ```
314    /// use belief_spread::BasicAgent;
315    /// use uuid::Uuid;
316    ///
317    /// let u = Uuid::new_v4();
318    /// let a = BasicAgent::new_with_uuid(u);
319    /// ```
320    pub fn new_with_uuid(u: Uuid) -> Self {
321        BasicAgent {
322            uuid: u,
323            activations: HashMap::new(),
324            friends: HashMap::new(),
325            actions: HashMap::new(),
326            deltas: HashMap::new(),
327        }
328    }
329}
330
331impl Agent for BasicAgent {
332    /// Gets the activation of an [Agent] towards a [BeliefPtr] at a given [SimTime].
333    ///
334    /// This is always between -1 and +1.
335    ///
336    /// # Arguments
337    /// - `time`: The [SimTime].
338    /// - `belief`: The [BeliefPtr].
339    ///
340    /// # Returns
341    /// The activation, if found.
342    ///
343    /// # Examples
344    ///
345    /// ```
346    /// use belief_spread::{BasicAgent, Agent, BasicBelief, BeliefPtr};
347    ///
348    /// let mut a = BasicAgent::new();
349    /// let b = BasicBelief::new("b1".to_string());
350    /// let b_ptr: BeliefPtr = b.into();
351    /// a.set_activation(3, b_ptr.clone(), Some(0.1));
352    /// assert_eq!(a.get_activation(3, &b_ptr).unwrap(), 0.1);
353    /// ```
354    fn get_activation(&self, time: SimTime, belief: &BeliefPtr) -> Option<f64> {
355        match self.activations.get(&time) {
356            Some(x) => x.get(belief).cloned(),
357            None => None,
358        }
359    }
360
361    /// Gets the activations of an [Agent] towards all [BeliefPtr]s at all [SimTime]s.
362    ///
363    /// This is always between -1 and +1.
364    ///
365    /// [BeliefPtr]s are referenced by their [Uuid]s.
366    ///
367    /// # Return
368    /// A map from simulation time to a new map from [BeliefPtr] to the
369    /// activation.
370    ///
371    /// # Examples
372    ///
373    /// ```
374    /// use belief_spread::{BasicAgent, Agent, BasicBelief, BeliefPtr, UUIDd};
375    ///
376    /// let mut a = BasicAgent::new();
377    /// let b = BasicBelief::new("b1".to_string());
378    /// let b_ptr: BeliefPtr = b.into();
379    /// a.set_activation(3, b_ptr.clone(), Some(0.1));
380    /// let activations = a.get_activations();
381    /// assert_eq!(activations.len(), 1);
382    /// assert_eq!(activations.get(&3).unwrap().len(), 1);
383    /// assert_eq!(*activations.get(&3).unwrap().get(&b_ptr).unwrap(), 0.1);
384    /// ```
385    fn get_activations(&self) -> &HashMap<SimTime, HashMap<BeliefPtr, f64>> {
386        &self.activations
387    }
388
389    /// Sets the activation of an [Agent] towards a [BeliefPtr] at a given [SimTime].
390    ///
391    /// If the activation is [None], then the activation is deleted.
392    ///
393    /// This is a value between -1 and +1.
394    ///
395    /// # Arguments
396    /// - `time`: The [SimTime] to update.
397    /// - `belief`: The [BeliefPtr] to update.
398    /// - `activation`: The new activation.
399    ///
400    /// # Returns
401    /// A [Result], [Ok] if nothing went wrong, or an [Err] with an
402    /// [OutOfRangeError], if the activation is not in the range [-1, +1].
403    ///
404    /// # Examples
405    ///
406    /// ## Updating activation
407    ///
408    /// ```
409    /// use belief_spread::{BasicAgent, Agent, BasicBelief, BeliefPtr};
410    ///
411    /// let mut a = BasicAgent::new();
412    /// let b = BasicBelief::new("b1".to_string());
413    /// let b_ptr: BeliefPtr = b.into();
414    /// a.set_activation(3, b_ptr.clone(), Some(0.1));
415    /// assert_eq!(a.get_activation(3, &b_ptr).unwrap(), 0.1);
416    /// a.set_activation(3, b_ptr.clone(), Some(-0.1));
417    /// assert_eq!(a.get_activation(3, &b_ptr).unwrap(), -0.1);
418    /// ```
419    ///
420    /// ## Deleting activation
421    ///
422    /// ```
423    /// use belief_spread::{BasicAgent, Agent, BasicBelief, BeliefPtr};
424    ///
425    /// let mut a = BasicAgent::new();
426    /// let b = BasicBelief::new("b1".to_string());
427    /// let b_ptr: BeliefPtr = b.into();
428    /// a.set_activation(3, b_ptr.clone(), Some(0.1));
429    /// assert_eq!(a.get_activation(3, &b_ptr).unwrap(), 0.1);
430    /// a.set_activation(3, b_ptr.clone(), None);
431    /// assert_eq!(a.get_activation(3, &b_ptr), None);
432    /// ```
433    fn set_activation(
434        &mut self,
435        time: SimTime,
436        belief: BeliefPtr,
437        activation: Option<f64>,
438    ) -> Result<(), OutOfRangeError> {
439        match activation {
440            Some(x) if x > 1.0 => Err(OutOfRangeError::TooHigh {
441                found: x,
442                min: -1.0,
443                max: 1.0,
444            }),
445            Some(x) if x < -1.0 => Err(OutOfRangeError::TooLow {
446                found: x,
447                min: -1.0,
448                max: 1.0,
449            }),
450            Some(x) => {
451                if !self.activations.contains_key(&time) {
452                    self.activations.insert(time, HashMap::new());
453                }
454                self.activations.get_mut(&time).unwrap().insert(belief, x);
455                Ok(())
456            }
457            None => {
458                match self.activations.get_mut(&time) {
459                    Some(x) => x.remove(&belief),
460                    None => None,
461                };
462                Ok(())
463            }
464        }
465    }
466
467    /// Gets the friends of the [Agent].
468    ///
469    /// This gets the friends of the [Agent] (identified by their [Uuid]) with
470    /// their weight of connection.
471    ///
472    /// All weights are in the range [0, 1].
473    ///
474    /// # Returns
475    /// The friends (identified by their Uuid) with their weight of connection.
476    ///
477    /// # Examples
478    /// ```
479    /// use belief_spread::{BasicAgent, Agent, AgentPtr, UUIDd};
480    ///
481    /// let mut a1 = BasicAgent::new();
482    /// let a2 = BasicAgent::new();
483    /// let a2_ptr: AgentPtr = a2.into();
484    /// a1.set_friend_weight(a2_ptr.clone(), Some(0.1)).unwrap();
485    /// let friends = a1.get_friends();
486    /// assert_eq!(friends.len(), 1);
487    /// assert_eq!(*friends.get(&a2_ptr).unwrap(), 0.1);
488    /// ```
489    fn get_friends(&self) -> &HashMap<AgentPtr, f64> {
490        &self.friends
491    }
492
493    /// Gets the weight of a friend of the [Agent].
494    ///
495    /// The weight will be in the range [0, 1];
496    ///
497    /// If they are not friends, returns [None].
498    ///
499    /// # Arguments
500    /// - `friend`: The friend.
501    ///
502    /// # Returns
503    /// The weight, or [None] if they are not friends.
504    ///
505    /// # Examples
506    /// ```
507    /// use belief_spread::{BasicAgent, Agent, UUIDd, AgentPtr};
508    ///
509    /// let mut a1 = BasicAgent::new();
510    /// let a2 = BasicAgent::new();
511    /// let a2_ptr: AgentPtr = a2.into();
512    /// a1.set_friend_weight(a2_ptr.clone(), Some(0.1)).unwrap();
513    /// assert_eq!(a1.get_friend_weight(&a2_ptr).unwrap(), 0.1)
514    /// ```
515    fn get_friend_weight(&self, friend: &AgentPtr) -> Option<f64> {
516        self.friends.get(friend).cloned()
517    }
518
519    /// Set the weight of a friend of the [Agent].
520    ///
521    /// If they are not friends, this adds another [Agent] as a `friend` with
522    /// a supplied weight.
523    ///
524    /// `weight` must be in the range [0, 1].
525    ///
526    /// If `friend` already exists, the `weight` is overwritten.
527    ///
528    /// If the `weight` is [None], the `friend` is removed if they were friends.
529    ///
530    /// # Arguments
531    /// - `friend`: The friend.
532    /// - `weight`: The weight
533    ///
534    /// # Returns
535    /// A [Result], [Ok] if nothing went wrong, or an [Err] with an
536    /// [OutOfRangeError], if the weight is not in the range [0, +1].
537    ///
538    /// # Examples
539    /// ```
540    /// use belief_spread::{BasicAgent, Agent, UUIDd, AgentPtr};
541    ///
542    /// let mut a1 = BasicAgent::new();
543    /// let a2 = BasicAgent::new();
544    /// let a2_ptr: AgentPtr = a2.into();
545    /// a1.set_friend_weight(a2_ptr.clone(), Some(0.1)).unwrap();
546    /// assert_eq!(a1.get_friend_weight(&a2_ptr).unwrap(), 0.1)
547    /// ```
548    fn set_friend_weight(
549        &mut self,
550        friend: AgentPtr,
551        weight: Option<f64>,
552    ) -> Result<(), OutOfRangeError> {
553        match weight {
554            Some(x) if x > 1.0 => Err(OutOfRangeError::TooHigh {
555                found: x,
556                min: 0.0,
557                max: 1.0,
558            }),
559            Some(x) if x < 0.0 => Err(OutOfRangeError::TooLow {
560                found: x,
561                min: 0.0,
562                max: 1.0,
563            }),
564            Some(x) => {
565                self.friends.insert(friend, x);
566                Ok(())
567            }
568            None => {
569                self.friends.remove(&friend);
570                Ok(())
571            }
572        }
573    }
574
575    /// Gets the [BehaviourPtr] the [Agent] performed at a given [SimTime].
576    ///
577    /// Returns the [BehaviourPtr].
578    ///
579    /// # Arguments
580    /// - `time`: The [SimTime].
581    ///
582    /// # Returns
583    /// The [BehaviourPtr], if one was performed at `time`.
584    ///
585    /// # Examples
586    /// ```
587    /// use belief_spread::{BasicAgent, Agent, BasicBehaviour, BehaviourPtr, UUIDd};
588    ///
589    /// let mut a1 = BasicAgent::new();
590    /// let b = BasicBehaviour::new("b1".to_string());
591    /// let b_ptr: BehaviourPtr = b.into();
592    ///
593    /// a1.set_action(2, Some(b_ptr.clone()));
594    /// assert_eq!(a1.get_action(2).unwrap(), &b_ptr);
595    /// ```
596    fn get_action(&self, time: SimTime) -> Option<&BehaviourPtr> {
597        self.actions.get(&time)
598    }
599
600    /// Gets all of the [BehaviourPtr]s that the [Agent] has performed.
601    ///
602    /// # Returns
603    /// A [HashMap] from [SimTime] to [BehaviourPtr].
604    ///
605    /// # Examples
606    /// ```
607    /// use belief_spread::{BasicAgent, Agent, BasicBehaviour, BehaviourPtr, UUIDd};
608    ///
609    /// let mut a1 = BasicAgent::new();
610    /// let b = BasicBehaviour::new("b1".to_string());
611    /// let b_ptr: BehaviourPtr = b.into();
612    ///
613    /// a1.set_action(2, Some(b_ptr.clone()));
614    /// let actions = a1.get_actions();
615    /// assert_eq!(actions.len(), 1);
616    /// assert_eq!(actions.get(&2).unwrap(), &b_ptr);
617    /// ```
618    fn get_actions(&self) -> &HashMap<SimTime, BehaviourPtr> {
619        &self.actions
620    }
621
622    /// Sets the [BehaviourPtr] the [Agent] performed at a given time.
623    ///
624    /// If [None], it unsets the [BehaviourPtr].
625    ///
626    /// # Arguments
627    /// - `time`: The [SimTime].
628    /// - `behaviour`: The new [BehaviourPtr] that was performed at `time`.
629    ///
630    /// # Examples
631    /// ```
632    /// use belief_spread::{BasicAgent, Agent, BasicBehaviour, BehaviourPtr, UUIDd};
633    ///
634    /// let mut a1 = BasicAgent::new();
635    /// let b = BasicBehaviour::new("b1".to_string());
636    /// let b_ptr: BehaviourPtr = b.into();
637    ///
638    /// a1.set_action(2, Some(b_ptr.clone()));
639    /// assert_eq!(a1.get_action(2).unwrap(), &b_ptr);
640    /// ```
641    fn set_action(&mut self, time: SimTime, behaviour: Option<BehaviourPtr>) {
642        match behaviour {
643            Some(x) => self.actions.insert(time, x),
644            None => self.actions.remove(&time),
645        };
646    }
647
648    /// Gets the delta for a given [BeliefPtr].
649    ///
650    /// This is the value that the activation for the [BeliefPtr] changed by
651    /// (multiplicatively) at every time step.
652    ///
653    /// This is a strictly positive value (i.e., > 0).
654    ///
655    /// # Arguments
656    /// - `belief`: The [BeliefPtr].
657    ///
658    /// # Returns
659    /// The delta for the [BeliefPtr] and this [Agent], if found.
660    ///
661    /// # Examples
662    ///
663    /// ```
664    /// use belief_spread::{BasicAgent, Agent, BasicBelief, BeliefPtr, UUIDd};
665    ///
666    /// let mut a = BasicAgent::new();
667    /// let b = BasicBelief::new("b1".to_string());
668    /// let b_ptr: BeliefPtr = b.into();
669    /// a.set_delta(b_ptr.clone(), Some(0.1)).unwrap();
670    /// assert_eq!(a.get_delta(&b_ptr).unwrap(), 0.1);
671    /// ```
672    fn get_delta(&self, belief: &BeliefPtr) -> Option<f64> {
673        self.deltas.get(belief).cloned()
674    }
675
676    /// Gets all the deltas for the [Agent].
677    ///
678    /// This is the value that the activation for the [BeliefPtr] changed by
679    /// (multiplicatively) at every time step.
680    ///
681    /// This is a strictly positive value (i.e., > 0).
682    ///
683    /// # Returns
684    /// A map from [BeliefPtr] to delta.
685    ///
686    /// # Examples
687    ///
688    /// ```
689    /// use belief_spread::{BasicAgent, Agent, BasicBelief, BeliefPtr, UUIDd};
690    ///
691    /// let mut a = BasicAgent::new();
692    /// let b = BasicBelief::new("b1".to_string());
693    /// let b_ptr: BeliefPtr = b.into();
694    /// a.set_delta(b_ptr.clone(), Some(0.1)).unwrap();
695    /// let deltas = a.get_deltas();
696    /// assert_eq!(deltas.len(), 1);
697    /// assert_eq!(*deltas.get(&b_ptr).unwrap(), 0.1);
698    ///
699    /// ```
700    fn get_deltas(&self) -> &HashMap<BeliefPtr, f64> {
701        &self.deltas
702    }
703
704    /// Sets the delta for a given [BeliefPtr].
705    ///
706    /// This is the value that the activation for the [BeliefPtr] changed by
707    /// (multiplicatively) at every time step.
708    ///
709    /// This is a strictly positive value (i.e., > 0).
710    ///
711    /// If `delta` is [None], then this function removes the delta.
712    ///
713    /// # Arguments
714    /// - `belief`: The [BeliefPtr].
715    /// - `delta`: The new delta.
716    ///
717    /// # Returns
718    /// A [Result], [Ok] if nothing is wrong, or an [Err] with a
719    /// [OutOfRangeError], if the delta is not strictly positive.
720    ///
721    /// # Examples
722    ///
723    /// ```
724    /// use belief_spread::{BasicAgent, Agent, BasicBelief, BeliefPtr, UUIDd};
725    ///
726    /// let mut a = BasicAgent::new();
727    /// let b = BasicBelief::new("b1".to_string());
728    /// let b_ptr: BeliefPtr = b.into();
729    /// a.set_delta(b_ptr.clone(), Some(0.1)).unwrap();
730    /// assert_eq!(a.get_delta(&b_ptr).unwrap(), 0.1);
731    /// ```
732    fn set_delta(&mut self, belief: BeliefPtr, delta: Option<f64>) -> Result<(), OutOfRangeError> {
733        match delta {
734            None => {
735                self.deltas.remove(&belief);
736                Ok(())
737            }
738            Some(d) if d <= 0.0 => Err(OutOfRangeError::TooLow {
739                found: d,
740                min: 0.0 + f64::EPSILON,
741                max: f64::INFINITY,
742            }),
743            Some(d) => {
744                self.deltas.insert(belief, d);
745                Ok(())
746            }
747        }
748    }
749
750    /// Gets the weighted relationship between [BeliefPtr]s `b1` and `b2`.
751    ///
752    /// This is the compatibility for holding `b2`, given that the [Agent]
753    /// already holds `b1`.
754    ///
755    /// This is equal to the activation of `b1`
756    /// ([`Agent::get_activation`]), multiplied by the
757    /// relationship between `b1` and `b2`
758    /// ([`crate::Belief::get_relationship`]).
759    ///
760    /// Returns [None] if either activation of `b1` at time `t` is [None], or
761    /// the relationship between `b1` and `b2` is [None].
762    ///
763    /// # Arguments
764    /// - `t`: The simulation time ([SimTime]).
765    /// - `b1`: The first [BeliefPtr].
766    /// - `b2`: The second [BeliefPtr].
767    ///
768    /// # Returns
769    /// The weighted relationship.
770    ///
771    /// # Examples
772    ///
773    /// ```
774    /// use belief_spread::{Agent, BasicAgent, BeliefPtr, BasicBelief};
775    ///
776    /// let mut a = BasicAgent::new();
777    /// let b1 = BasicBelief::new("b1".to_string());
778    /// let b1_ptr: BeliefPtr = b1.into();
779    /// let b2 = BasicBelief::new("b2".to_string());
780    /// let b2_ptr: BeliefPtr = b2.into();
781    /// b1_ptr.borrow_mut().set_relationship(b2_ptr.clone(), Some(0.5));
782    /// a.set_activation(2, b1_ptr.clone(), Some(0.5));
783    ///
784    /// assert_eq!(a.weighted_relationship(2, &b1_ptr, &b2_ptr).unwrap(), 0.25);
785    /// ```
786    fn weighted_relationship(&self, t: SimTime, b1: &BeliefPtr, b2: &BeliefPtr) -> Option<f64> {
787        match self.get_activation(t, b1) {
788            Some(x) => match b1.borrow().get_relationship(b2) {
789                Some(y) => Some(x * y),
790                None => None,
791            },
792            None => None,
793        }
794    }
795
796    /// Gets the context for holding the [BeliefPtr] `b`.
797    ///
798    /// This is the compatibility for holding `b`, given all the beliefs the
799    /// agent holds.
800    ///
801    /// This is the average of [`Agent::weighted_relationship`] for every
802    /// [BeliefPtr] (as given in `beliefs).
803    ///
804    /// # Arguments
805    /// - `time`: The simulation time ([SimTime]).
806    /// - `b`: The [BeliefPtr].
807    /// - `beliefs`: All the [BeliefPtr]s in existence.
808    ///
809    /// # Returns
810    /// The context.
811    ///
812    /// # Examples
813    /// ```
814    /// use belief_spread::{Agent, BasicAgent, BeliefPtr, BasicBelief, UUIDd};
815    ///
816    /// let mut a = BasicAgent::new();
817    /// let b1 = BasicBelief::new("b1".to_string());
818    /// let b1_ptr: BeliefPtr = b1.into();
819    /// let b2 = BasicBelief::new("b2".to_string());
820    /// let b2_ptr: BeliefPtr = b2.into();
821    ///
822    /// a.set_activation(2, b1_ptr.clone(), Some(1.0)).unwrap();
823    /// a.set_activation(2, b2_ptr.clone(), Some(1.0)).unwrap();
824    ///
825    /// b1_ptr.borrow_mut().set_relationship(
826    ///     b1_ptr.clone(),
827    ///     Some(0.5),
828    /// )
829    /// .unwrap();
830    /// b1_ptr.borrow_mut().set_relationship(b2_ptr.clone(), Some(-0.75)).unwrap();
831    ///
832    /// let mut beliefs: Vec<BeliefPtr> = Vec::new();
833    /// beliefs.push(b1_ptr.clone());
834    /// beliefs.push(b2_ptr.clone());
835    ///
836    /// assert_eq!(
837    ///     a.contextualise(2, &b1_ptr, &beliefs),
838    ///     -0.125
839    /// );
840    /// ```
841    fn contextualise(&self, t: SimTime, b: &BeliefPtr, beliefs: &[BeliefPtr]) -> f64 {
842        match beliefs.len() {
843            0 => 0.0,
844            size => {
845                beliefs
846                    .iter()
847                    .map(|b2| self.weighted_relationship(t, b, b2))
848                    .flatten()
849                    .fold(0.0, |acc, v| acc + v)
850                    / (size as f64)
851            }
852        }
853    }
854
855    /// Gets the pressure the [Agent] feels to adopt a [BeliefPtr] given the
856    /// actions of their friends.
857    ///
858    /// This does not take into account the beliefs that the [Agent] already
859    /// holds.
860    ///
861    /// # Arguments
862    /// - `time`: The time as [SimTime].
863    /// - `belief`: The [BeliefPtr].
864    ///
865    /// # Returns
866    /// The pressure
867    ///
868    /// # Examples
869    /// ```
870    /// use belief_spread::{BasicAgent, Agent, BasicBehaviour, BehaviourPtr, BasicBelief, BeliefPtr};
871    /// use std::collections::HashMap;
872    ///
873    /// let mut agent = BasicAgent::new();
874    /// let mut f1 = BasicAgent::new();
875    /// let mut f2 = BasicAgent::new();
876    /// let b1 = BasicBehaviour::new("b1".to_string());
877    /// let b1_ptr: BehaviourPtr = b1.into();
878    /// let b2 = BasicBehaviour::new("b2".to_string());
879    /// let b2_ptr: BehaviourPtr = b2.into();
880    ///
881    /// f1.set_action(2, Some(b1_ptr.clone()));
882    /// f2.set_action(2, Some(b2_ptr.clone()));
883    ///
884    /// let mut belief = BasicBelief::new("b1".to_string());
885    /// let belief_ptr: BeliefPtr = belief.into();
886    /// belief_ptr.borrow_mut().set_perception(b1_ptr.clone(), Some(0.2)).unwrap();
887    /// belief_ptr.borrow_mut().set_perception(b2_ptr.clone(), Some(0.3)).unwrap();
888    ///
889    /// agent.set_friend_weight(f1.into(), Some(0.5));
890    /// agent.set_friend_weight(f2.into(), Some(1.0));
891    ///
892    /// assert_eq!(agent.pressure(2, &belief_ptr), 0.2);
893    /// ```
894    fn pressure(&self, time: SimTime, belief: &BeliefPtr) -> f64 {
895        match self.friends.len() {
896            0 => 0.0,
897            n => {
898                self.friends
899                    .iter()
900                    .map(|(a, w)| {
901                        a.borrow()
902                            .get_action(time)
903                            .map(|behaviour| {
904                                belief
905                                    .borrow()
906                                    .get_perception(behaviour)
907                                    .unwrap_or_else(|| 0.0)
908                            })
909                            .map(|v| v * w)
910                    })
911                    .flatten()
912                    .sum::<f64>()
913                    / (n as f64)
914            }
915        }
916    }
917
918    /// Gets the change in activation for the [Agent] as a result of the
919    /// [BehaviourPtr]s observed.
920    ///
921    /// This takes into account the beliefs that the agent already holds
922    ///
923    /// # Arguments
924    /// - `time`: The time as [SimTime].
925    /// - `belief`: The [BeliefPtr].
926    /// - `beliefs`: All the [BeliefPtr]s in existence.
927    ///
928    /// # Return
929    /// - The change in activation
930    ///
931    /// # Examples
932    ///
933    /// ```
934    /// use belief_spread::{BasicAgent, Agent, BasicBehaviour, BehaviourPtr, BasicBelief, BeliefPtr};
935    /// use float_cmp::approx_eq;
936    ///
937    /// let mut agent = BasicAgent::new();
938    /// let mut f1 = BasicAgent::new();
939    /// let mut f2 = BasicAgent::new();
940    /// let b1 = BasicBehaviour::new("b1".to_string());
941    /// let b1_ptr: BehaviourPtr = b1.into();
942    /// let b2 = BasicBehaviour::new("b2".to_string());
943    /// let b2_ptr: BehaviourPtr = b2.into();
944    ///
945    /// f1.set_action(2, Some(b1_ptr.clone()));
946    /// f2.set_action(2, Some(b2_ptr.clone()));
947    ///
948    /// let belief = BasicBelief::new("b1".to_string());
949    /// let belief_ptr: BeliefPtr = belief.into();
950    /// belief_ptr.borrow_mut().set_perception(b1_ptr.clone(), Some(0.2)).unwrap();
951    /// belief_ptr.borrow_mut().set_perception(b2_ptr.clone(), Some(0.3)).unwrap();
952    ///
953    /// agent.set_friend_weight(f1.into(), Some(0.5));
954    /// agent.set_friend_weight(f2.into(), Some(1.0));
955    /// // Pressure is 0.2
956    ///
957    /// let belief2 = BasicBelief::new("b2".to_string());
958    /// let belief2_ptr: BeliefPtr = belief2.into();
959    /// let mut beliefs = Vec::<BeliefPtr>::new();
960    /// beliefs.push(belief_ptr.clone());
961    /// beliefs.push(belief2_ptr.clone());
962    ///
963    /// agent.set_activation(2, belief_ptr.clone(), Some(1.0)).unwrap();
964    /// agent.set_activation(2, belief2_ptr.clone(), Some(1.0)).unwrap();
965    /// belief_ptr.borrow_mut().set_relationship(belief_ptr.clone(), Some(0.5)).unwrap();
966    /// belief_ptr.borrow_mut().set_relationship(belief2_ptr.clone(), Some(-0.75)).unwrap();
967    /// // Contextualise is -0.125
968    ///
969    /// assert!(approx_eq!(
970    ///     f64,
971    ///     agent.activation_change(2, &belief_ptr, &beliefs),
972    ///     0.0875,
973    ///     ulps = 2
974    /// ))
975    fn activation_change(&self, time: SimTime, belief: &BeliefPtr, beliefs: &[BeliefPtr]) -> f64 {
976        match self.pressure(time, belief) {
977            p if p > 0.0 => (1.0 + self.contextualise(time, belief, beliefs)) / 2.0 * p,
978            p => (1.0 - self.contextualise(time, belief, beliefs)) / 2.0 * p,
979        }
980    }
981}
982
983/// Updates the activation for a given [Agent] `time` and [BeliefPtr].
984///
985/// # Arguments
986/// - `time`: The time as [SimTime].
987/// - `belief`: The [BeliefPtr].
988/// - `beliefs`: All the [BeliefPtr]s in existence.
989///
990/// # Return
991/// A [Result] with nothing if [Ok], or an [Err] containing
992/// [UpdateActivationError] if activation is [None] or delta is [None].
993///
994/// # Examples
995/// ```
996/// use belief_spread::{BasicAgent, Agent, BasicBehaviour, AgentPtr,
997///     BehaviourPtr, BasicBelief, BeliefPtr, update_activation_for_agent};
998/// use float_cmp::approx_eq;
999///
1000/// let mut agent = BasicAgent::new();
1001/// let f1 = BasicAgent::new();
1002/// let f1_ptr: AgentPtr = f1.into();
1003/// let f2 = BasicAgent::new();
1004/// let f2_ptr: AgentPtr = f2.into();
1005/// let b1 = BasicBehaviour::new("b1".to_string());
1006/// let b1_ptr: BehaviourPtr = b1.into();
1007/// let b2 = BasicBehaviour::new("b2".to_string());
1008/// let b2_ptr: BehaviourPtr = b2.into();
1009///
1010/// f1_ptr.borrow_mut().set_action(2, Some(b1_ptr.clone()));
1011/// f2_ptr.borrow_mut().set_action(2, Some(b2_ptr.clone()));
1012///
1013/// let belief = BasicBelief::new("b1".to_string());
1014/// let belief_ptr: BeliefPtr = belief.into();
1015/// belief_ptr
1016///     .borrow_mut()
1017///     .set_perception(b1_ptr.clone(), Some(0.2))
1018///     .unwrap();
1019/// belief_ptr
1020///     .borrow_mut()
1021///     .set_perception(b2_ptr.clone(), Some(0.3))
1022///     .unwrap();
1023///
1024/// agent.set_friend_weight(f1_ptr.clone(), Some(0.5));
1025/// agent.set_friend_weight(f2_ptr.clone(), Some(1.0));
1026///
1027/// // Pressure is 0.2
1028///
1029/// let belief2 = BasicBelief::new("b2".to_string());
1030/// let belief2_ptr: BeliefPtr = belief2.into();
1031/// let mut beliefs = Vec::<BeliefPtr>::new();
1032/// beliefs.push(belief_ptr.clone());
1033/// beliefs.push(belief2_ptr.clone());
1034///
1035/// agent
1036///     .set_activation(2, belief_ptr.clone(), Some(0.5))
1037///     .unwrap();
1038/// agent
1039///     .set_activation(2, belief2_ptr.clone(), Some(1.0))
1040///     .unwrap();
1041/// belief_ptr
1042///     .borrow_mut()
1043///     .set_relationship(belief_ptr.clone(), Some(1.0))
1044///     .unwrap();
1045/// belief_ptr
1046///     .borrow_mut()
1047///     .set_relationship(belief2_ptr.clone(), Some(-0.75))
1048///     .unwrap();
1049/// // Contextualise is -0.0625
1050///
1051/// // activation_change is 0.10625
1052/// agent.set_delta(belief_ptr.clone(), Some(1.1));
1053///
1054/// let agent_ptr: AgentPtr = agent.into();
1055///
1056/// update_activation_for_agent(&agent_ptr, 3, &belief_ptr, &beliefs).unwrap();
1057///
1058/// assert!(approx_eq!(
1059///     f64,
1060///     *agent_ptr
1061///         .borrow()
1062///         .get_activations()
1063///         .get(&3)
1064///         .unwrap()
1065///         .get(&belief_ptr)
1066///         .unwrap(),
1067///     0.65625,
1068///     ulps = 4
1069/// ))
1070/// ```
1071pub fn update_activation_for_agent(
1072    agent: &AgentPtr,
1073    time: SimTime,
1074    belief: &BeliefPtr,
1075    beliefs: &[BeliefPtr],
1076) -> Result<(), UpdateActivationError> {
1077    let delta = agent.borrow().get_delta(belief);
1078    match delta {
1079        None => Err(UpdateActivationError::GetDeltaNone {
1080            belief: belief.borrow().uuid().clone(),
1081        }),
1082        Some(d) => {
1083            let activation = agent.borrow().get_activation(time - 1, belief);
1084            match activation {
1085                None => Err(UpdateActivationError::GetActivationNone {
1086                    time: time - 1,
1087                    belief: belief.borrow().uuid().clone(),
1088                }),
1089                Some(a) => {
1090                    let activation_change =
1091                        { agent.borrow().activation_change(time - 1, belief, beliefs) };
1092                    let new_activation = (-1.0_f64).max((1.0_f64).min(d * a + activation_change));
1093                    agent
1094                        .borrow_mut()
1095                        .set_activation(time, belief.clone(), Some(new_activation))
1096                        .unwrap();
1097                    Ok(())
1098                }
1099            }
1100        }
1101    }
1102}
1103
1104impl UUIDd for BasicAgent {
1105    /// Get the UUID of the [BasicAgent].
1106    fn uuid(&self) -> &Uuid {
1107        &self.uuid
1108    }
1109
1110    /// Set the UUID of the [BasicAgent].
1111    fn set_uuid(&mut self, u: Uuid) {
1112        self.uuid = u;
1113    }
1114}
1115
1116#[cfg(test)]
1117mod tests {
1118    use float_cmp::approx_eq;
1119
1120    use crate::{BasicBehaviour, BasicBelief};
1121
1122    use super::*;
1123
1124    #[test]
1125    fn new_assigns_random_uuid() {
1126        let a1 = BasicAgent::new();
1127        let a2 = BasicAgent::new();
1128        assert_ne!(a1.uuid, a2.uuid);
1129    }
1130
1131    #[test]
1132    fn new_with_uuid_assigns_uuid() {
1133        let u = Uuid::new_v4();
1134        let a = BasicAgent::new_with_uuid(u.clone());
1135        assert_eq!(a.uuid, u)
1136    }
1137
1138    #[test]
1139    fn uuid_returns_uuid() {
1140        let u = Uuid::new_v4();
1141        let a = BasicAgent::new_with_uuid(u.clone());
1142        assert_eq!(a.uuid(), &u)
1143    }
1144
1145    #[test]
1146    fn set_uuid_sets_uuid() {
1147        let mut a = BasicAgent::new();
1148        let u = Uuid::new_v4();
1149        a.set_uuid(u.clone());
1150        assert_eq!(a.uuid, u)
1151    }
1152
1153    #[test]
1154    fn activation_is_initialized_empty() {
1155        let a = BasicAgent::new();
1156        assert!(a.activations.is_empty());
1157    }
1158
1159    #[test]
1160    fn get_activation_when_exists() {
1161        let mut a = BasicAgent::new();
1162        let b = BasicBelief::new("b".to_string());
1163        let b_ptr: BeliefPtr = b.into();
1164        let mut act: HashMap<SimTime, HashMap<BeliefPtr, f64>> = HashMap::new();
1165        let mut act_at_2: HashMap<BeliefPtr, f64> = HashMap::new();
1166        act_at_2.insert(b_ptr.clone(), 0.5);
1167        act.insert(2, act_at_2);
1168        a.activations = act;
1169        assert_eq!(a.get_activation(2, &b_ptr).unwrap(), 0.5);
1170    }
1171
1172    #[test]
1173    fn get_activation_when_time_exists_but_belief_doesnt() {
1174        let mut a = BasicAgent::new();
1175        let b = BasicBelief::new("b".to_string());
1176        let b_ptr: BeliefPtr = b.into();
1177        let mut act: HashMap<SimTime, HashMap<BeliefPtr, f64>> = HashMap::new();
1178        let act_at_2: HashMap<BeliefPtr, f64> = HashMap::new();
1179        act.insert(2, act_at_2);
1180        a.activations = act;
1181        assert_eq!(a.get_activation(2, &b_ptr), None);
1182    }
1183
1184    #[test]
1185    fn get_activation_when_not_exists() {
1186        let mut a = BasicAgent::new();
1187        let b = BasicBelief::new("b".to_string());
1188        let b_ptr: BeliefPtr = b.into();
1189        let act: HashMap<SimTime, HashMap<BeliefPtr, f64>> = HashMap::new();
1190        a.activations = act;
1191        assert_eq!(a.get_activation(2, &b_ptr), None);
1192    }
1193
1194    #[test]
1195    fn get_activations_when_exists() {
1196        let mut a = BasicAgent::new();
1197        let b = BasicBelief::new("b".to_string());
1198        let b_ptr: BeliefPtr = b.into();
1199        let mut act: HashMap<SimTime, HashMap<BeliefPtr, f64>> = HashMap::new();
1200        let mut act_at_2: HashMap<BeliefPtr, f64> = HashMap::new();
1201        act_at_2.insert(b_ptr.clone(), 0.5);
1202        act.insert(2, act_at_2);
1203        a.activations = act;
1204        let activations = a.get_activations();
1205        assert_eq!(activations.len(), 1);
1206        assert_eq!(activations.get(&2).unwrap().len(), 1);
1207        assert_eq!(*activations.get(&2).unwrap().get(&b_ptr).unwrap(), 0.5);
1208    }
1209
1210    #[test]
1211    fn get_activations_when_time_exists_but_belief_doesnt() {
1212        let mut a = BasicAgent::new();
1213        let mut act: HashMap<SimTime, HashMap<BeliefPtr, f64>> = HashMap::new();
1214        let act_at_2: HashMap<BeliefPtr, f64> = HashMap::new();
1215        act.insert(2, act_at_2);
1216        a.activations = act;
1217        let activations = a.get_activations();
1218        assert_eq!(activations.len(), 1);
1219        assert!(activations.get(&2).unwrap().is_empty());
1220    }
1221
1222    #[test]
1223    fn get_activations_when_not_exists() {
1224        let mut a = BasicAgent::new();
1225        let act: HashMap<SimTime, HashMap<BeliefPtr, f64>> = HashMap::new();
1226        a.activations = act;
1227        let activations = a.get_activations();
1228        assert!(activations.is_empty());
1229    }
1230
1231    #[test]
1232    fn set_activation_delete_when_exists() {
1233        let mut a = BasicAgent::new();
1234        let b = BasicBelief::new("b".to_string());
1235        let b_ptr: BeliefPtr = b.into();
1236        let mut act: HashMap<SimTime, HashMap<BeliefPtr, f64>> = HashMap::new();
1237        let mut act_at_2: HashMap<BeliefPtr, f64> = HashMap::new();
1238        act_at_2.insert(b_ptr.clone(), 0.5);
1239        act.insert(2, act_at_2);
1240        a.activations = act;
1241        a.set_activation(2, b_ptr.clone(), None).unwrap();
1242        assert_eq!(a.activations.get(&2).unwrap().get(&b_ptr), None);
1243    }
1244
1245    #[test]
1246    fn set_activation_delete_when_time_exists_but_belief_doesnt() {
1247        let mut a = BasicAgent::new();
1248        let b = BasicBelief::new("b".to_string());
1249        let b_ptr: BeliefPtr = b.into();
1250        let mut act: HashMap<SimTime, HashMap<BeliefPtr, f64>> = HashMap::new();
1251        let act_at_2: HashMap<BeliefPtr, f64> = HashMap::new();
1252        act.insert(2, act_at_2);
1253        a.activations = act;
1254        a.set_activation(2, b_ptr.clone(), None).unwrap();
1255        assert_eq!(a.activations.get(&2).unwrap().get(&b_ptr), None);
1256    }
1257
1258    #[test]
1259    fn set_activation_delete_when_not_exists() {
1260        let mut a = BasicAgent::new();
1261        let b = BasicBelief::new("b".to_string());
1262        let b_ptr: BeliefPtr = b.into();
1263        let act: HashMap<SimTime, HashMap<BeliefPtr, f64>> = HashMap::new();
1264        a.activations = act;
1265        a.set_activation(2, b_ptr.clone(), None).unwrap();
1266        assert!(a.activations.get(&2).is_none());
1267    }
1268
1269    #[test]
1270    fn set_activation_errors_when_too_low() {
1271        let mut a = BasicAgent::new();
1272        let b = BasicBelief::new("b1".to_string());
1273        let b_ptr: BeliefPtr = b.into();
1274        let expected_error = OutOfRangeError::TooLow {
1275            found: -1.1,
1276            min: -1.0,
1277            max: 1.0,
1278        };
1279        assert_eq!(
1280            a.set_activation(2, b_ptr.clone(), Some(-1.1)).unwrap_err(),
1281            expected_error
1282        );
1283    }
1284
1285    #[test]
1286    fn set_activation_errors_when_too_high() {
1287        let mut a = BasicAgent::new();
1288        let b = BasicBelief::new("b1".to_string());
1289        let b_ptr: BeliefPtr = b.into();
1290        let expected_error = OutOfRangeError::TooHigh {
1291            found: 1.1,
1292            min: -1.0,
1293            max: 1.0,
1294        };
1295        assert_eq!(
1296            a.set_activation(2, b_ptr.clone(), Some(1.1)).unwrap_err(),
1297            expected_error
1298        );
1299    }
1300
1301    #[test]
1302    fn set_activation_when_exists() {
1303        let mut a = BasicAgent::new();
1304        let b = BasicBelief::new("b".to_string());
1305        let b_ptr: BeliefPtr = b.into();
1306        let mut act: HashMap<SimTime, HashMap<BeliefPtr, f64>> = HashMap::new();
1307        let mut act_at_2: HashMap<BeliefPtr, f64> = HashMap::new();
1308        act_at_2.insert(b_ptr.clone(), 0.5);
1309        act.insert(2, act_at_2);
1310        a.activations = act;
1311        a.set_activation(2, b_ptr.clone(), Some(0.2)).unwrap();
1312        assert_eq!(*a.activations.get(&2).unwrap().get(&b_ptr).unwrap(), 0.2);
1313    }
1314
1315    #[test]
1316    fn set_activation_when_time_exists_but_belief_doesnt() {
1317        let mut a = BasicAgent::new();
1318        let b = BasicBelief::new("b".to_string());
1319        let b_ptr: BeliefPtr = b.into();
1320        let mut act: HashMap<SimTime, HashMap<BeliefPtr, f64>> = HashMap::new();
1321        let act_at_2: HashMap<BeliefPtr, f64> = HashMap::new();
1322        act.insert(2, act_at_2);
1323        a.activations = act;
1324        a.set_activation(2, b_ptr.clone(), Some(0.2)).unwrap();
1325        assert_eq!(*a.activations.get(&2).unwrap().get(&b_ptr).unwrap(), 0.2);
1326    }
1327
1328    #[test]
1329    fn set_activation_when_not_exists() {
1330        let mut a = BasicAgent::new();
1331        let b = BasicBelief::new("b".to_string());
1332        let b_ptr: BeliefPtr = b.into();
1333        let act: HashMap<SimTime, HashMap<BeliefPtr, f64>> = HashMap::new();
1334        a.activations = act;
1335        a.set_activation(2, b_ptr.clone(), Some(0.2)).unwrap();
1336        assert_eq!(*a.activations.get(&2).unwrap().get(&b_ptr).unwrap(), 0.2);
1337    }
1338
1339    #[test]
1340    fn friends_is_initialized_empty() {
1341        let a = BasicAgent::new();
1342        assert!(a.friends.is_empty())
1343    }
1344
1345    #[test]
1346    fn get_friends_when_empty() {
1347        let mut a = BasicAgent::new();
1348        let friends: HashMap<AgentPtr, f64> = HashMap::new();
1349        a.friends = friends;
1350        assert!(a.get_friends().is_empty())
1351    }
1352
1353    #[test]
1354    fn get_friends_when_not_empty() {
1355        let mut a = BasicAgent::new();
1356        let a2 = BasicAgent::new();
1357        let a2_ptr: AgentPtr = a2.into();
1358        let mut friends: HashMap<AgentPtr, f64> = HashMap::new();
1359        friends.insert(a2_ptr.clone(), 0.3);
1360        a.friends = friends;
1361        assert_eq!(a.get_friends().len(), 1);
1362        assert_eq!(*a.get_friends().get(&a2_ptr).unwrap(), 0.3);
1363    }
1364
1365    #[test]
1366    fn get_friend_weight_when_exists() {
1367        let mut a = BasicAgent::new();
1368        let a2 = BasicAgent::new();
1369        let a2_ptr: AgentPtr = a2.into();
1370        let mut friends: HashMap<AgentPtr, f64> = HashMap::new();
1371        friends.insert(a2_ptr.clone(), 0.3);
1372        a.friends = friends;
1373        assert_eq!(a.get_friend_weight(&a2_ptr).unwrap(), 0.3);
1374    }
1375
1376    #[test]
1377    fn get_friend_weight_when_not_exists() {
1378        let mut a = BasicAgent::new();
1379        let a2 = BasicAgent::new();
1380        let a2_ptr: AgentPtr = a2.into();
1381        let friends: HashMap<AgentPtr, f64> = HashMap::new();
1382        a.friends = friends;
1383        assert_eq!(a.get_friend_weight(&a2_ptr), None);
1384    }
1385
1386    #[test]
1387    fn set_friend_weight_when_not_exists_and_valid() {
1388        let mut a = BasicAgent::new();
1389        let friends: HashMap<AgentPtr, f64> = HashMap::new();
1390        a.friends = friends;
1391
1392        let a2 = BasicAgent::new();
1393        let a2_ptr: AgentPtr = a2.into();
1394        a.set_friend_weight(a2_ptr.clone(), Some(0.5)).unwrap();
1395        assert_eq!(*a.friends.get(&a2_ptr).unwrap(), 0.5);
1396    }
1397
1398    #[test]
1399    fn set_friend_weight_when_exists_and_valid() {
1400        let mut a = BasicAgent::new();
1401        let mut friends: HashMap<AgentPtr, f64> = HashMap::new();
1402        let a2 = BasicAgent::new();
1403        let a2_ptr: AgentPtr = a2.into();
1404        friends.insert(a2_ptr.clone(), 0.2);
1405        a.friends = friends;
1406
1407        a.set_friend_weight(a2_ptr.clone(), Some(0.5)).unwrap();
1408        assert_eq!(*a.friends.get(&a2_ptr).unwrap(), 0.5);
1409    }
1410
1411    #[test]
1412    fn set_friend_weight_when_exists_and_valid_delete() {
1413        let mut a = BasicAgent::new();
1414        let mut friends: HashMap<AgentPtr, f64> = HashMap::new();
1415        let a2 = BasicAgent::new();
1416        let a2_ptr: AgentPtr = a2.into();
1417        friends.insert(a2_ptr.clone(), 0.2);
1418        a.friends = friends;
1419
1420        a.set_friend_weight(a2_ptr.clone(), None).unwrap();
1421        assert_eq!(a.friends.get(&a2_ptr), None);
1422    }
1423
1424    #[test]
1425    fn set_friend_weight_when_not_exists_and_valid_delete() {
1426        let mut a = BasicAgent::new();
1427        let friends: HashMap<AgentPtr, f64> = HashMap::new();
1428        a.friends = friends;
1429
1430        let a2 = BasicAgent::new();
1431        let a2_ptr: AgentPtr = a2.into();
1432        a.set_friend_weight(a2_ptr.clone(), None).unwrap();
1433        assert_eq!(a.friends.get(&a2_ptr), None);
1434    }
1435
1436    #[test]
1437    fn set_friend_weight_when_exists_and_too_low() {
1438        let mut a = BasicAgent::new();
1439        let mut friends: HashMap<AgentPtr, f64> = HashMap::new();
1440        let a2 = BasicAgent::new();
1441        let a2_ptr: AgentPtr = a2.into();
1442        friends.insert(a2_ptr.clone(), 0.2);
1443        a.friends = friends;
1444
1445        let result = a.set_friend_weight(a2_ptr.clone(), Some(-0.1));
1446
1447        let expected_error = OutOfRangeError::TooLow {
1448            found: -0.1,
1449            min: 0.0,
1450            max: 1.0,
1451        };
1452
1453        assert_eq!(result.unwrap_err(), expected_error);
1454
1455        assert_eq!(*a.friends.get(&a2_ptr).unwrap(), 0.2);
1456    }
1457
1458    #[test]
1459    fn set_friend_weight_when_not_exists_and_too_low() {
1460        let mut a = BasicAgent::new();
1461        let friends: HashMap<AgentPtr, f64> = HashMap::new();
1462        let a2 = BasicAgent::new();
1463        let a2_ptr: AgentPtr = a2.into();
1464        a.friends = friends;
1465
1466        let result = a.set_friend_weight(a2_ptr.clone(), Some(-0.1));
1467
1468        let expected_error = OutOfRangeError::TooLow {
1469            found: -0.1,
1470            min: 0.0,
1471            max: 1.0,
1472        };
1473
1474        assert_eq!(result.unwrap_err(), expected_error);
1475
1476        assert_eq!(a.friends.get(&a2_ptr), None);
1477    }
1478
1479    #[test]
1480    fn set_friend_weight_when_exists_and_too_high() {
1481        let mut a = BasicAgent::new();
1482        let mut friends: HashMap<AgentPtr, f64> = HashMap::new();
1483        let a2 = BasicAgent::new();
1484        let a2_ptr: AgentPtr = a2.into();
1485        friends.insert(a2_ptr.clone(), 0.2);
1486        a.friends = friends;
1487
1488        let result = a.set_friend_weight(a2_ptr.clone(), Some(1.1));
1489
1490        let expected_error = OutOfRangeError::TooHigh {
1491            found: 1.1,
1492            min: 0.0,
1493            max: 1.0,
1494        };
1495
1496        assert_eq!(result.unwrap_err(), expected_error);
1497
1498        assert_eq!(*a.friends.get(&a2_ptr).unwrap(), 0.2);
1499    }
1500
1501    #[test]
1502    fn set_friend_weight_when_not_exists_and_too_high() {
1503        let mut a = BasicAgent::new();
1504        let friends: HashMap<AgentPtr, f64> = HashMap::new();
1505        let a2 = BasicAgent::new();
1506        let a2_ptr: AgentPtr = a2.into();
1507        a.friends = friends;
1508
1509        let result = a.set_friend_weight(a2_ptr.clone(), Some(1.1));
1510
1511        let expected_error = OutOfRangeError::TooHigh {
1512            found: 1.1,
1513            min: 0.0,
1514            max: 1.0,
1515        };
1516
1517        assert_eq!(result.unwrap_err(), expected_error);
1518
1519        assert_eq!(a.friends.get(&a2_ptr), None);
1520    }
1521
1522    #[test]
1523    fn actions_is_initialized_empty() {
1524        let a = BasicAgent::new();
1525        assert!(a.actions.is_empty());
1526    }
1527
1528    #[test]
1529    fn get_action_when_exists() {
1530        let mut a = BasicAgent::new();
1531        let mut actions: HashMap<SimTime, BehaviourPtr> = HashMap::new();
1532        let b = BasicBehaviour::new("b".to_string());
1533        let b_ptr: BehaviourPtr = b.into();
1534        actions.insert(2, b_ptr.clone());
1535        a.actions = actions;
1536
1537        assert_eq!(a.get_action(2).unwrap(), &b_ptr);
1538    }
1539
1540    #[test]
1541    fn get_action_when_not_exists() {
1542        let mut a = BasicAgent::new();
1543        let actions: HashMap<SimTime, BehaviourPtr> = HashMap::new();
1544        a.actions = actions;
1545
1546        assert_eq!(a.get_action(2), None);
1547    }
1548
1549    #[test]
1550    fn get_actions_when_exists() {
1551        let mut a = BasicAgent::new();
1552        let mut actions: HashMap<SimTime, BehaviourPtr> = HashMap::new();
1553        let b = BasicBehaviour::new("b".to_string());
1554        let b_ptr: BehaviourPtr = b.into();
1555        actions.insert(2, b_ptr.clone());
1556        a.actions = actions;
1557
1558        let actions_obs = a.get_actions();
1559
1560        assert_eq!(actions_obs.len(), 1);
1561        assert_eq!(actions_obs.get(&2).unwrap(), &b_ptr);
1562    }
1563
1564    #[test]
1565    fn get_actions_when_not_exists() {
1566        let mut a = BasicAgent::new();
1567        let actions: HashMap<SimTime, BehaviourPtr> = HashMap::new();
1568        a.actions = actions;
1569
1570        let actions_obs = a.get_actions();
1571
1572        assert!(actions_obs.is_empty());
1573    }
1574
1575    #[test]
1576    fn set_action_when_exists() {
1577        let mut a = BasicAgent::new();
1578        let mut actions: HashMap<SimTime, BehaviourPtr> = HashMap::new();
1579        let b = BasicBehaviour::new("b".to_string());
1580        let b_ptr: BehaviourPtr = b.into();
1581        actions.insert(2, b_ptr.clone());
1582        a.actions = actions;
1583
1584        let b2 = BasicBehaviour::new("b2".to_string());
1585        let b2_ptr: BehaviourPtr = b2.into();
1586
1587        a.set_action(2, Some(b2_ptr.clone()));
1588        assert_eq!(a.actions.get(&2).unwrap(), &b2_ptr);
1589    }
1590
1591    #[test]
1592    fn set_action_when_exists_delete() {
1593        let mut a = BasicAgent::new();
1594        let mut actions: HashMap<SimTime, BehaviourPtr> = HashMap::new();
1595        let b = BasicBehaviour::new("b".to_string());
1596        let b_ptr: BehaviourPtr = b.into();
1597        actions.insert(2, b_ptr.clone());
1598        a.actions = actions;
1599
1600        a.set_action(2, None);
1601        assert_eq!(a.actions.get(&2), None);
1602    }
1603
1604    #[test]
1605    fn set_action_when_not_exists() {
1606        let mut a = BasicAgent::new();
1607        let actions: HashMap<SimTime, BehaviourPtr> = HashMap::new();
1608        a.actions = actions;
1609
1610        let b2 = BasicBehaviour::new("b2".to_string());
1611        let b2_ptr: BehaviourPtr = b2.into();
1612
1613        a.set_action(2, Some(b2_ptr.clone()));
1614        assert_eq!(a.actions.get(&2).unwrap(), &b2_ptr);
1615    }
1616
1617    #[test]
1618    fn set_action_when_not_exists_delete() {
1619        let mut a = BasicAgent::new();
1620        let actions: HashMap<SimTime, BehaviourPtr> = HashMap::new();
1621        a.actions = actions;
1622
1623        a.set_action(2, None);
1624        assert_eq!(a.actions.get(&2), None);
1625    }
1626
1627    #[test]
1628    fn deltas_initialized_empty() {
1629        let a = BasicAgent::new();
1630        assert!(a.deltas.is_empty());
1631    }
1632
1633    #[test]
1634    fn get_delta_when_exists() {
1635        let mut a = BasicAgent::new();
1636        let b = BasicBelief::new("b1".to_string());
1637        let b_ptr: BeliefPtr = b.into();
1638        let mut deltas: HashMap<BeliefPtr, f64> = HashMap::new();
1639        deltas.insert(b_ptr.clone(), 0.2);
1640        a.deltas = deltas;
1641
1642        assert_eq!(a.get_delta(&b_ptr).unwrap(), 0.2);
1643    }
1644
1645    #[test]
1646    fn get_delta_when_not_exists() {
1647        let mut a = BasicAgent::new();
1648        let b = BasicBelief::new("b1".to_string());
1649        let b_ptr: BeliefPtr = b.into();
1650        let deltas: HashMap<BeliefPtr, f64> = HashMap::new();
1651        a.deltas = deltas;
1652
1653        assert_eq!(a.get_delta(&b_ptr), None);
1654    }
1655
1656    #[test]
1657    fn get_deltas_when_exists() {
1658        let mut a = BasicAgent::new();
1659        let b = BasicBelief::new("b1".to_string());
1660        let b_ptr: BeliefPtr = b.into();
1661        let mut deltas: HashMap<BeliefPtr, f64> = HashMap::new();
1662        deltas.insert(b_ptr.clone(), 0.2);
1663        a.deltas = deltas;
1664
1665        let deltas_obs = a.get_deltas();
1666
1667        assert_eq!(deltas_obs.len(), 1);
1668        assert_eq!(*deltas_obs.get(&b_ptr).unwrap(), 0.2);
1669    }
1670
1671    #[test]
1672    fn get_deltas_when_not_exists() {
1673        let mut a = BasicAgent::new();
1674        let deltas: HashMap<BeliefPtr, f64> = HashMap::new();
1675        a.deltas = deltas;
1676
1677        let deltas_obs = a.get_deltas();
1678
1679        assert!(deltas_obs.is_empty());
1680    }
1681
1682    #[test]
1683    fn set_delta_when_exists() {
1684        let mut a = BasicAgent::new();
1685        let b = BasicBelief::new("b1".to_string());
1686        let b_ptr: BeliefPtr = b.into();
1687        let mut deltas: HashMap<BeliefPtr, f64> = HashMap::new();
1688        deltas.insert(b_ptr.clone(), 0.2);
1689        a.deltas = deltas;
1690
1691        a.set_delta(b_ptr.clone(), Some(0.9)).unwrap();
1692        assert_eq!(*a.deltas.get(&b_ptr).unwrap(), 0.9);
1693    }
1694
1695    #[test]
1696    fn set_delta_when_exists_delete() {
1697        let mut a = BasicAgent::new();
1698        let b = BasicBelief::new("b1".to_string());
1699        let b_ptr: BeliefPtr = b.into();
1700        let mut deltas: HashMap<BeliefPtr, f64> = HashMap::new();
1701        deltas.insert(b_ptr.clone(), 0.2);
1702        a.deltas = deltas;
1703
1704        a.set_delta(b_ptr.clone(), None).unwrap();
1705        assert_eq!(a.deltas.get(&b_ptr), None);
1706    }
1707
1708    #[test]
1709    fn set_delta_when_not_exists() {
1710        let mut a = BasicAgent::new();
1711        let b = BasicBelief::new("b1".to_string());
1712        let b_ptr: BeliefPtr = b.into();
1713        let deltas: HashMap<BeliefPtr, f64> = HashMap::new();
1714        a.deltas = deltas;
1715
1716        a.set_delta(b_ptr.clone(), Some(0.9)).unwrap();
1717        assert_eq!(*a.deltas.get(&b_ptr).unwrap(), 0.9);
1718    }
1719
1720    #[test]
1721    fn set_delta_when_not_exists_delete() {
1722        let mut a = BasicAgent::new();
1723        let b = BasicBelief::new("b1".to_string());
1724        let b_ptr: BeliefPtr = b.into();
1725        let deltas: HashMap<BeliefPtr, f64> = HashMap::new();
1726        a.deltas = deltas;
1727
1728        a.set_delta(b_ptr.clone(), None).unwrap();
1729        assert_eq!(a.deltas.get(&b_ptr), None);
1730    }
1731
1732    #[test]
1733    fn set_delta_when_exists_too_low() {
1734        let mut a = BasicAgent::new();
1735        let b = BasicBelief::new("b1".to_string());
1736        let b_ptr: BeliefPtr = b.into();
1737        let mut deltas: HashMap<BeliefPtr, f64> = HashMap::new();
1738        deltas.insert(b_ptr.clone(), 0.2);
1739        a.deltas = deltas;
1740
1741        let result = a.set_delta(b_ptr.clone(), Some(-0.1));
1742
1743        let expected_error = OutOfRangeError::TooLow {
1744            found: -0.1,
1745            min: 0.0 + f64::EPSILON,
1746            max: f64::INFINITY,
1747        };
1748
1749        assert_eq!(result.unwrap_err(), expected_error);
1750
1751        assert_eq!(*a.deltas.get(&b_ptr).unwrap(), 0.2);
1752    }
1753
1754    #[test]
1755    fn set_delta_when_not_exists_too_low() {
1756        let mut a = BasicAgent::new();
1757        let b = BasicBelief::new("b1".to_string());
1758        let b_ptr: BeliefPtr = b.into();
1759        let deltas: HashMap<BeliefPtr, f64> = HashMap::new();
1760        a.deltas = deltas;
1761
1762        let result = a.set_delta(b_ptr.clone(), Some(-0.1));
1763
1764        let expected_error = OutOfRangeError::TooLow {
1765            found: -0.1,
1766            min: 0.0 + f64::EPSILON,
1767            max: f64::INFINITY,
1768        };
1769
1770        assert_eq!(result.unwrap_err(), expected_error);
1771
1772        assert_eq!(a.deltas.get(&b_ptr), None);
1773    }
1774
1775    #[test]
1776    fn weighted_relationship_when_exists() {
1777        let mut a = BasicAgent::new();
1778        let b1 = BasicBelief::new("b1".to_string());
1779        let b1_ptr: BeliefPtr = b1.into();
1780        let b2 = BasicBelief::new("b2".to_string());
1781        let b2_ptr: BeliefPtr = b2.into();
1782
1783        a.set_activation(2, b1_ptr.clone(), Some(0.5)).unwrap();
1784        b1_ptr
1785            .borrow_mut()
1786            .set_relationship(b2_ptr.clone(), Some(0.1))
1787            .unwrap();
1788
1789        assert_eq!(a.weighted_relationship(2, &b1_ptr, &b2_ptr).unwrap(), 0.05);
1790    }
1791
1792    #[test]
1793    fn weighted_relationship_when_activation_not_exists() {
1794        let a = BasicAgent::new();
1795        let b1 = BasicBelief::new("b1".to_string());
1796        let b1_ptr: BeliefPtr = b1.into();
1797        let b2 = BasicBelief::new("b2".to_string());
1798        let b2_ptr: BeliefPtr = b2.into();
1799
1800        b1_ptr
1801            .borrow_mut()
1802            .set_relationship(b2_ptr.clone(), Some(0.1))
1803            .unwrap();
1804
1805        assert_eq!(a.weighted_relationship(2, &b1_ptr, &b2_ptr), None);
1806    }
1807
1808    #[test]
1809    fn weighted_relationship_when_relationship_not_exists() {
1810        let mut a = BasicAgent::new();
1811        let b1 = BasicBelief::new("b1".to_string());
1812        let b1_ptr: BeliefPtr = b1.into();
1813        let b2 = BasicBelief::new("b2".to_string());
1814        let b2_ptr: BeliefPtr = b2.into();
1815
1816        a.set_activation(2, b1_ptr.clone(), Some(0.5)).unwrap();
1817
1818        assert_eq!(a.weighted_relationship(2, &b1_ptr, &b2_ptr), None);
1819    }
1820
1821    #[test]
1822    fn weighted_relationship_when_not_exists() {
1823        let a = BasicAgent::new();
1824        let b1 = BasicBelief::new("b1".to_string());
1825        let b1_ptr: BeliefPtr = b1.into();
1826        let b2 = BasicBelief::new("b2".to_string());
1827        let b2_ptr: BeliefPtr = b2.into();
1828
1829        assert_eq!(a.weighted_relationship(2, &b1_ptr, &b2_ptr), None);
1830    }
1831
1832    #[test]
1833    fn contextualise_when_beliefs_empty_returns_0() {
1834        let b = BasicBelief::new("b".to_string());
1835        let b_ptr: BeliefPtr = b.into();
1836        let a = BasicAgent::new();
1837        let beliefs: Vec<BeliefPtr> = Vec::new();
1838
1839        assert_eq!(a.contextualise(2, &b_ptr, &beliefs), 0.0);
1840    }
1841
1842    #[test]
1843    fn contextualise_when_beliefs_non_empty_and_all_weighted_relationships_not_none() {
1844        let mut a = BasicAgent::new();
1845        let b1 = BasicBelief::new("b1".to_string());
1846        let b1_ptr: BeliefPtr = b1.into();
1847        let b2 = BasicBelief::new("b2".to_string());
1848        let b2_ptr: BeliefPtr = b2.into();
1849
1850        a.set_activation(2, b1_ptr.clone(), Some(1.0)).unwrap();
1851        a.set_activation(2, b2_ptr.clone(), Some(1.0)).unwrap();
1852
1853        b1_ptr
1854            .borrow_mut()
1855            .set_relationship(b1_ptr.clone(), Some(0.5))
1856            .unwrap();
1857        b1_ptr
1858            .borrow_mut()
1859            .set_relationship(b2_ptr.clone(), Some(-0.75))
1860            .unwrap();
1861
1862        let mut beliefs: Vec<BeliefPtr> = Vec::new();
1863        beliefs.push(b1_ptr.clone());
1864        beliefs.push(b2_ptr.clone());
1865
1866        assert_eq!(a.contextualise(2, &b1_ptr, &beliefs), -0.125);
1867    }
1868
1869    #[test]
1870    fn contextualise_when_beliefs_non_empty_and_not_all_weighted_relationships_not_none() {
1871        let mut a = BasicAgent::new();
1872        let b1 = BasicBelief::new("b1".to_string());
1873        let b1_ptr: BeliefPtr = b1.into();
1874        let b2 = BasicBelief::new("b2".to_string());
1875        let b2_ptr: BeliefPtr = b2.into();
1876
1877        a.set_activation(2, b1_ptr.clone(), Some(0.5)).unwrap();
1878        a.set_activation(2, b2_ptr.clone(), Some(1.0)).unwrap();
1879
1880        b1_ptr
1881            .borrow_mut()
1882            .set_relationship(b1_ptr.clone(), Some(1.0))
1883            .unwrap();
1884
1885        let mut beliefs: Vec<BeliefPtr> = Vec::new();
1886        beliefs.push(b1_ptr.clone());
1887        beliefs.push(b2_ptr.clone());
1888
1889        assert_eq!(a.contextualise(2, &b1_ptr, &beliefs), 0.25);
1890    }
1891
1892    #[test]
1893    fn contextualise_when_beliefs_non_empty_and_all_weighted_relationships_none() {
1894        let mut a = BasicAgent::new();
1895        let b1 = BasicBelief::new("b1".to_string());
1896        let b1_ptr: BeliefPtr = b1.into();
1897        let b2 = BasicBelief::new("b2".to_string());
1898        let b2_ptr: BeliefPtr = b2.into();
1899
1900        a.set_activation(2, b1_ptr.clone(), Some(0.5)).unwrap();
1901        a.set_activation(2, b2_ptr.clone(), Some(1.0)).unwrap();
1902
1903        let mut beliefs: Vec<BeliefPtr> = Vec::new();
1904        beliefs.push(b1_ptr.clone());
1905        beliefs.push(b2_ptr.clone());
1906
1907        assert_eq!(a.contextualise(2, &b1_ptr, &beliefs), 0.0);
1908    }
1909
1910    #[test]
1911    fn pressure_when_no_friends() {
1912        let mut agent = BasicAgent::new();
1913        let belief = BasicBelief::new("b1".to_string());
1914        let belief_ptr: BeliefPtr = belief.into();
1915        let friends: HashMap<AgentPtr, f64> = HashMap::new();
1916        agent.friends = friends;
1917        assert_eq!(agent.pressure(2, &belief_ptr), 0.0);
1918    }
1919
1920    #[test]
1921    fn pressure_when_friends_did_nothing() {
1922        let agent = BasicAgent::new();
1923        let agent_ptr: AgentPtr = agent.into();
1924        let f1 = BasicAgent::new();
1925        let f1_ptr: AgentPtr = f1.into();
1926        let f2 = BasicAgent::new();
1927        let f2_ptr: AgentPtr = f2.into();
1928
1929        let belief = BasicBelief::new("b1".to_string());
1930        let belief_ptr: BeliefPtr = belief.into();
1931
1932        {
1933            let mut mut_agent = agent_ptr.borrow_mut();
1934            mut_agent
1935                .set_friend_weight(agent_ptr.clone(), Some(0.2))
1936                .unwrap();
1937            mut_agent
1938                .set_friend_weight(f1_ptr.clone(), Some(0.5))
1939                .unwrap();
1940            mut_agent
1941                .set_friend_weight(f2_ptr.clone(), Some(1.0))
1942                .unwrap();
1943        }
1944
1945        assert_eq!(agent_ptr.borrow().pressure(2, &belief_ptr), 0.0);
1946    }
1947
1948    #[test]
1949    fn pressure_when_friends_did_something_but_perception_null() {
1950        let agent = BasicAgent::new();
1951        let agent_ptr: AgentPtr = agent.into();
1952        let f1 = BasicAgent::new();
1953        let f1_ptr: AgentPtr = f1.into();
1954        let f2 = BasicAgent::new();
1955        let f2_ptr: AgentPtr = f2.into();
1956        let b1 = BasicBehaviour::new("b1".to_string());
1957        let b1_ptr: BehaviourPtr = b1.into();
1958        let b2 = BasicBehaviour::new("b2".to_string());
1959        let b2_ptr: BehaviourPtr = b2.into();
1960
1961        f1_ptr.borrow_mut().set_action(2, Some(b1_ptr.clone()));
1962        f2_ptr.borrow_mut().set_action(2, Some(b2_ptr.clone()));
1963
1964        let belief = BasicBelief::new("b1".to_string());
1965        let belief_ptr: BeliefPtr = belief.into();
1966
1967        {
1968            let mut mut_agent = agent_ptr.borrow_mut();
1969            mut_agent
1970                .set_friend_weight(agent_ptr.clone(), Some(0.2))
1971                .unwrap();
1972            mut_agent
1973                .set_friend_weight(f1_ptr.clone(), Some(0.5))
1974                .unwrap();
1975            mut_agent
1976                .set_friend_weight(f2_ptr.clone(), Some(1.0))
1977                .unwrap();
1978        }
1979
1980        assert_eq!(agent_ptr.borrow().pressure(2, &belief_ptr), 0.0);
1981    }
1982
1983    #[test]
1984    fn pressure_when_friends_did_something() {
1985        let agent = BasicAgent::new();
1986        let agent_ptr: AgentPtr = agent.into();
1987        let f1 = BasicAgent::new();
1988        let f1_ptr: AgentPtr = f1.into();
1989        let f2 = BasicAgent::new();
1990        let f2_ptr: AgentPtr = f2.into();
1991
1992        let b1 = BasicBehaviour::new("b1".to_string());
1993        let b1_ptr: BehaviourPtr = b1.into();
1994        let b2 = BasicBehaviour::new("b2".to_string());
1995        let b2_ptr: BehaviourPtr = b2.into();
1996
1997        f1_ptr.borrow_mut().set_action(2, Some(b1_ptr.clone()));
1998        f2_ptr.borrow_mut().set_action(2, Some(b2_ptr.clone()));
1999
2000        let belief = BasicBelief::new("b1".to_string());
2001        let belief_ptr: BeliefPtr = belief.into();
2002        belief_ptr
2003            .borrow_mut()
2004            .set_perception(b1_ptr.clone(), Some(0.2))
2005            .unwrap();
2006        belief_ptr
2007            .borrow_mut()
2008            .set_perception(b2_ptr.clone(), Some(0.3))
2009            .unwrap();
2010
2011        {
2012            let mut mut_agent = agent_ptr.borrow_mut();
2013            mut_agent
2014                .set_friend_weight(f1_ptr.clone(), Some(0.5))
2015                .unwrap();
2016            mut_agent
2017                .set_friend_weight(f2_ptr.clone(), Some(1.0))
2018                .unwrap();
2019        }
2020
2021        assert_eq!(agent_ptr.borrow().pressure(2, &belief_ptr), 0.2);
2022    }
2023
2024    #[test]
2025    fn activation_change_when_pressure_positive() {
2026        let agent = BasicAgent::new();
2027        let agent_ptr: AgentPtr = agent.into();
2028        let f1 = BasicAgent::new();
2029        let f1_ptr: AgentPtr = f1.into();
2030        let f2 = BasicAgent::new();
2031        let f2_ptr: AgentPtr = f2.into();
2032
2033        let b1 = BasicBehaviour::new("b1".to_string());
2034        let b1_ptr: BehaviourPtr = b1.into();
2035        let b2 = BasicBehaviour::new("b2".to_string());
2036        let b2_ptr: BehaviourPtr = b2.into();
2037
2038        f1_ptr.borrow_mut().set_action(2, Some(b1_ptr.clone()));
2039        f2_ptr.borrow_mut().set_action(2, Some(b2_ptr.clone()));
2040
2041        let belief = BasicBelief::new("b1".to_string());
2042        let belief_ptr: BeliefPtr = belief.into();
2043        belief_ptr
2044            .borrow_mut()
2045            .set_perception(b1_ptr.clone(), Some(0.2))
2046            .unwrap();
2047        belief_ptr
2048            .borrow_mut()
2049            .set_perception(b2_ptr.clone(), Some(0.3))
2050            .unwrap();
2051
2052        {
2053            let mut mut_agent = agent_ptr.borrow_mut();
2054            mut_agent
2055                .set_friend_weight(f1_ptr.clone(), Some(0.5))
2056                .unwrap();
2057            mut_agent
2058                .set_friend_weight(f2_ptr.clone(), Some(1.0))
2059                .unwrap();
2060        }
2061        // Pressure is 0.2
2062
2063        let belief2 = BasicBelief::new("b2".to_string());
2064        let belief2_ptr: BeliefPtr = belief2.into();
2065        let mut beliefs = Vec::<BeliefPtr>::new();
2066        beliefs.push(belief_ptr.clone());
2067        beliefs.push(belief2_ptr.clone());
2068
2069        agent_ptr
2070            .borrow_mut()
2071            .set_activation(2, belief_ptr.clone(), Some(1.0))
2072            .unwrap();
2073        agent_ptr
2074            .borrow_mut()
2075            .set_activation(2, belief2_ptr.clone(), Some(1.0))
2076            .unwrap();
2077        belief_ptr
2078            .borrow_mut()
2079            .set_relationship(belief_ptr.clone(), Some(0.5))
2080            .unwrap();
2081        belief_ptr
2082            .borrow_mut()
2083            .set_relationship(belief2_ptr.clone(), Some(-0.75))
2084            .unwrap();
2085        // Contextualise is -0.125
2086
2087        assert!(approx_eq!(
2088            f64,
2089            agent_ptr
2090                .borrow()
2091                .activation_change(2, &belief_ptr, &beliefs),
2092            0.0875,
2093            ulps = 2
2094        ))
2095    }
2096
2097    #[test]
2098    fn activation_change_when_pressure_negative() {
2099        let agent = BasicAgent::new();
2100        let agent_ptr: AgentPtr = agent.into();
2101        let f1 = BasicAgent::new();
2102        let f1_ptr: AgentPtr = f1.into();
2103        let f2 = BasicAgent::new();
2104        let f2_ptr: AgentPtr = f2.into();
2105
2106        let b1 = BasicBehaviour::new("b1".to_string());
2107        let b1_ptr: BehaviourPtr = b1.into();
2108        let b2 = BasicBehaviour::new("b2".to_string());
2109        let b2_ptr: BehaviourPtr = b2.into();
2110
2111        f1_ptr.borrow_mut().set_action(2, Some(b1_ptr.clone()));
2112        f2_ptr.borrow_mut().set_action(2, Some(b2_ptr.clone()));
2113
2114        let belief = BasicBelief::new("b1".to_string());
2115        let belief_ptr: BeliefPtr = belief.into();
2116        belief_ptr
2117            .borrow_mut()
2118            .set_perception(b1_ptr.clone(), Some(-0.2))
2119            .unwrap();
2120        belief_ptr
2121            .borrow_mut()
2122            .set_perception(b2_ptr.clone(), Some(-0.3))
2123            .unwrap();
2124
2125        {
2126            let mut mut_agent = agent_ptr.borrow_mut();
2127            mut_agent
2128                .set_friend_weight(f1_ptr.clone(), Some(0.5))
2129                .unwrap();
2130            mut_agent
2131                .set_friend_weight(f2_ptr.clone(), Some(1.0))
2132                .unwrap();
2133        }
2134        // Pressure is -0.2
2135
2136        let belief2 = BasicBelief::new("b2".to_string());
2137        let belief2_ptr: BeliefPtr = belief2.into();
2138        let mut beliefs = Vec::<BeliefPtr>::new();
2139        beliefs.push(belief_ptr.clone());
2140        beliefs.push(belief2_ptr.clone());
2141
2142        agent_ptr
2143            .borrow_mut()
2144            .set_activation(2, belief_ptr.clone(), Some(1.0))
2145            .unwrap();
2146        agent_ptr
2147            .borrow_mut()
2148            .set_activation(2, belief2_ptr.clone(), Some(1.0))
2149            .unwrap();
2150        belief_ptr
2151            .borrow_mut()
2152            .set_relationship(belief_ptr.clone(), Some(0.5))
2153            .unwrap();
2154        belief_ptr
2155            .borrow_mut()
2156            .set_relationship(belief2_ptr.clone(), Some(-0.75))
2157            .unwrap();
2158        // Contextualise is -0.125
2159
2160        assert!(approx_eq!(
2161            f64,
2162            agent_ptr
2163                .borrow()
2164                .activation_change(2, &belief_ptr, &beliefs),
2165            -0.1125,
2166            ulps = 2
2167        ))
2168    }
2169
2170    #[test]
2171    fn update_activation_when_previous_activation_none() {
2172        let mut agent = BasicAgent::new();
2173        let belief = BasicBelief::new("b1".to_string());
2174        let belief_ptr: BeliefPtr = belief.into();
2175        let beliefs: Vec<BeliefPtr> = Vec::new();
2176
2177        let mut deltas: HashMap<BeliefPtr, f64> = HashMap::new();
2178        deltas.insert(belief_ptr.clone(), 1.1);
2179
2180        agent.deltas = deltas;
2181
2182        let agent_ptr: AgentPtr = agent.into();
2183
2184        let expected_error = UpdateActivationError::GetActivationNone {
2185            time: 2,
2186            belief: belief_ptr.borrow().uuid().clone(),
2187        };
2188
2189        assert_eq!(
2190            update_activation_for_agent(&agent_ptr, 3, &belief_ptr, &beliefs).unwrap_err(),
2191            expected_error
2192        );
2193    }
2194
2195    #[test]
2196    fn update_activation_when_delta_none() {
2197        let agent = BasicAgent::new();
2198        let belief = BasicBelief::new("b1".to_string());
2199        let belief_ptr: BeliefPtr = belief.into();
2200        let beliefs: Vec<BeliefPtr> = Vec::new();
2201
2202        let expected_error = UpdateActivationError::GetDeltaNone {
2203            belief: belief_ptr.borrow().uuid().clone(),
2204        };
2205
2206        let agent_ptr: AgentPtr = agent.into();
2207        assert_eq!(
2208            update_activation_for_agent(&agent_ptr, 2, &belief_ptr, &beliefs).unwrap_err(),
2209            expected_error
2210        );
2211    }
2212
2213    #[test]
2214    fn update_activation_when_new_value_in_range() {
2215        let mut agent = BasicAgent::new();
2216        let f1 = BasicAgent::new();
2217        let f1_ptr: AgentPtr = f1.into();
2218        let f2 = BasicAgent::new();
2219        let f2_ptr: AgentPtr = f2.into();
2220        let b1 = BasicBehaviour::new("b1".to_string());
2221        let b1_ptr: BehaviourPtr = b1.into();
2222        let b2 = BasicBehaviour::new("b2".to_string());
2223        let b2_ptr: BehaviourPtr = b2.into();
2224
2225        f1_ptr.borrow_mut().set_action(2, Some(b1_ptr.clone()));
2226        f2_ptr.borrow_mut().set_action(2, Some(b2_ptr.clone()));
2227
2228        let belief = BasicBelief::new("b1".to_string());
2229        let belief_ptr: BeliefPtr = belief.into();
2230        belief_ptr
2231            .borrow_mut()
2232            .set_perception(b1_ptr.clone(), Some(0.2))
2233            .unwrap();
2234        belief_ptr
2235            .borrow_mut()
2236            .set_perception(b2_ptr.clone(), Some(0.3))
2237            .unwrap();
2238
2239        let mut friends: HashMap<AgentPtr, f64> = HashMap::new();
2240
2241        friends.insert(f1_ptr.clone(), 0.5);
2242        friends.insert(f2_ptr.clone(), 1.0);
2243
2244        agent.friends = friends;
2245        // Pressure is 0.2
2246
2247        let belief2 = BasicBelief::new("b2".to_string());
2248        let belief2_ptr: BeliefPtr = belief2.into();
2249        let mut beliefs = Vec::<BeliefPtr>::new();
2250        beliefs.push(belief_ptr.clone());
2251        beliefs.push(belief2_ptr.clone());
2252
2253        agent
2254            .set_activation(2, belief_ptr.clone(), Some(0.5))
2255            .unwrap();
2256        agent
2257            .set_activation(2, belief2_ptr.clone(), Some(1.0))
2258            .unwrap();
2259        belief_ptr
2260            .borrow_mut()
2261            .set_relationship(belief_ptr.clone(), Some(1.0))
2262            .unwrap();
2263        belief_ptr
2264            .borrow_mut()
2265            .set_relationship(belief2_ptr.clone(), Some(-0.75))
2266            .unwrap();
2267        // Contextualise is -0.0625
2268
2269        // activation_change is 0.10625
2270        let mut delta: HashMap<BeliefPtr, f64> = HashMap::new();
2271        delta.insert(belief_ptr.clone(), 1.1);
2272        agent.deltas = delta;
2273
2274        let agent_ptr: AgentPtr = agent.into();
2275
2276        update_activation_for_agent(&agent_ptr, 3, &belief_ptr, &beliefs).unwrap();
2277
2278        assert!(approx_eq!(
2279            f64,
2280            *agent_ptr
2281                .borrow()
2282                .get_activations()
2283                .get(&3)
2284                .unwrap()
2285                .get(&belief_ptr)
2286                .unwrap(),
2287            0.65625,
2288            ulps = 4
2289        ))
2290    }
2291
2292    #[test]
2293    fn update_activation_when_new_value_too_high() {
2294        let mut agent = BasicAgent::new();
2295        let f1 = BasicAgent::new();
2296        let f1_ptr: AgentPtr = f1.into();
2297        let f2 = BasicAgent::new();
2298        let f2_ptr: AgentPtr = f2.into();
2299        let b1 = BasicBehaviour::new("b1".to_string());
2300        let b1_ptr: BehaviourPtr = b1.into();
2301        let b2 = BasicBehaviour::new("b2".to_string());
2302        let b2_ptr: BehaviourPtr = b2.into();
2303
2304        f1_ptr.borrow_mut().set_action(2, Some(b1_ptr.clone()));
2305        f2_ptr.borrow_mut().set_action(2, Some(b2_ptr.clone()));
2306
2307        let belief = BasicBelief::new("b1".to_string());
2308        let belief_ptr: BeliefPtr = belief.into();
2309        belief_ptr
2310            .borrow_mut()
2311            .set_perception(b1_ptr.clone(), Some(0.2))
2312            .unwrap();
2313        belief_ptr
2314            .borrow_mut()
2315            .set_perception(b2_ptr.clone(), Some(0.3))
2316            .unwrap();
2317
2318        let mut friends: HashMap<AgentPtr, f64> = HashMap::new();
2319
2320        friends.insert(f1_ptr.clone(), 0.5);
2321        friends.insert(f2_ptr.clone(), 1.0);
2322
2323        agent.friends = friends;
2324        // Pressure is 0.2
2325
2326        let belief2 = BasicBelief::new("b2".to_string());
2327        let belief2_ptr: BeliefPtr = belief2.into();
2328        let mut beliefs = Vec::<BeliefPtr>::new();
2329        beliefs.push(belief_ptr.clone());
2330        beliefs.push(belief2_ptr.clone());
2331
2332        agent
2333            .set_activation(2, belief_ptr.clone(), Some(0.5))
2334            .unwrap();
2335        agent
2336            .set_activation(2, belief2_ptr.clone(), Some(1.0))
2337            .unwrap();
2338        belief_ptr
2339            .borrow_mut()
2340            .set_relationship(belief_ptr.clone(), Some(1.0))
2341            .unwrap();
2342        belief_ptr
2343            .borrow_mut()
2344            .set_relationship(belief2_ptr.clone(), Some(-0.75))
2345            .unwrap();
2346        // Contextualise is -0.0625
2347
2348        // activation_change is 0.10625
2349        let mut delta: HashMap<BeliefPtr, f64> = HashMap::new();
2350        delta.insert(belief_ptr.clone(), 100000.0);
2351        agent.deltas = delta;
2352
2353        let agent_ptr: AgentPtr = agent.into();
2354        update_activation_for_agent(&agent_ptr, 3, &belief_ptr, &beliefs).unwrap();
2355
2356        assert!(approx_eq!(
2357            f64,
2358            *agent_ptr
2359                .borrow()
2360                .get_activations()
2361                .get(&3)
2362                .unwrap()
2363                .get(&belief_ptr)
2364                .unwrap(),
2365            1.0,
2366            ulps = 4
2367        ))
2368    }
2369
2370    #[test]
2371    fn update_activation_when_new_value_too_low() {
2372        let mut agent = BasicAgent::new();
2373        let f1 = BasicAgent::new();
2374        let f1_ptr: AgentPtr = f1.into();
2375        let f2 = BasicAgent::new();
2376        let f2_ptr: AgentPtr = f2.into();
2377        let b1 = BasicBehaviour::new("b1".to_string());
2378        let b1_ptr: BehaviourPtr = b1.into();
2379        let b2 = BasicBehaviour::new("b2".to_string());
2380        let b2_ptr: BehaviourPtr = b2.into();
2381
2382        f1_ptr.borrow_mut().set_action(2, Some(b1_ptr.clone()));
2383        f2_ptr.borrow_mut().set_action(2, Some(b2_ptr.clone()));
2384
2385        let belief = BasicBelief::new("b1".to_string());
2386        let belief_ptr: BeliefPtr = belief.into();
2387        belief_ptr
2388            .borrow_mut()
2389            .set_perception(b1_ptr.clone(), Some(0.2))
2390            .unwrap();
2391        belief_ptr
2392            .borrow_mut()
2393            .set_perception(b2_ptr.clone(), Some(0.3))
2394            .unwrap();
2395
2396        let mut friends: HashMap<AgentPtr, f64> = HashMap::new();
2397
2398        friends.insert(f1_ptr.clone(), 0.5);
2399        friends.insert(f2_ptr.clone(), 1.0);
2400
2401        agent.friends = friends;
2402        // Pressure is 0.2
2403
2404        let belief2 = BasicBelief::new("b2".to_string());
2405        let belief2_ptr: BeliefPtr = belief2.into();
2406        let mut beliefs = Vec::<BeliefPtr>::new();
2407        beliefs.push(belief_ptr.clone());
2408        beliefs.push(belief2_ptr.clone());
2409
2410        agent
2411            .set_activation(2, belief_ptr.clone(), Some(0.5))
2412            .unwrap();
2413        agent
2414            .set_activation(2, belief2_ptr.clone(), Some(1.0))
2415            .unwrap();
2416
2417        belief_ptr
2418            .borrow_mut()
2419            .set_relationship(belief_ptr.clone(), Some(1.0))
2420            .unwrap();
2421        belief_ptr
2422            .borrow_mut()
2423            .set_relationship(belief2_ptr.clone(), Some(-0.75))
2424            .unwrap();
2425        // Contextualise is -0.0625
2426
2427        // activation_change is 0.10625
2428        let mut delta: HashMap<BeliefPtr, f64> = HashMap::new();
2429
2430        // This is a total cheat to force activation really low, officially
2431        // delta cannot be less than 0, but it doesn't matter.
2432
2433        delta.insert(belief_ptr.clone(), -100000.0);
2434        agent.deltas = delta;
2435
2436        let agent_ptr: AgentPtr = agent.into();
2437        update_activation_for_agent(&agent_ptr, 3, &belief_ptr, &beliefs).unwrap();
2438
2439        assert!(approx_eq!(
2440            f64,
2441            *agent_ptr
2442                .borrow()
2443                .get_activations()
2444                .get(&3)
2445                .unwrap()
2446                .get(&belief_ptr)
2447                .unwrap(),
2448            -1.0,
2449            ulps = 4
2450        ))
2451    }
2452
2453    #[test]
2454    fn test_from() {
2455        let a = BasicAgent::new();
2456        let uuid = a.uuid().clone();
2457        let a_ptr: AgentPtr = AgentPtr::from(a);
2458        assert_eq!(a_ptr.borrow().uuid().clone(), uuid);
2459    }
2460
2461    #[test]
2462    fn test_into() {
2463        let a = BasicAgent::new();
2464        let uuid = a.uuid().clone();
2465        let a_ptr: AgentPtr = a.into();
2466        assert_eq!(a_ptr.borrow().uuid().clone(), uuid);
2467    }
2468}