distributed_control/
mas.rs1use ndarray::LinalgScalar;
5
6use crate::dynamics::{compact_dynamics, compact_output, Dynamics, MasDynamics};
7
8pub struct HomMas<'a, T: LinalgScalar> {
10 hom_dynamics: &'a dyn Dynamics<T>,
11 n_agents: usize,
12}
13
14impl<'a, T: LinalgScalar> HomMas<'a, T> {
15 pub fn new(hom_dynamics: &dyn Dynamics<T>, n_agents: usize) -> HomMas<T> {
17 HomMas {
18 hom_dynamics,
19 n_agents,
20 }
21 }
22}
23
24impl<'a, T: LinalgScalar> MasDynamics<T> for HomMas<'a, T> {
25 fn mas_dynamics(&self, i: usize) -> Result<&dyn Dynamics<T>, &str> {
26 if i < self.n_agents {
27 Ok(self.hom_dynamics)
28 } else {
29 Err("The agent index exceeds the number of agents.")
30 }
31 }
32 fn n_agents(&self) -> usize {
33 self.n_agents
34 }
35}
36
37impl<'a, T: LinalgScalar> Dynamics<T> for HomMas<'a, T> {
38 fn dynamics(
39 &self,
40 t: T,
41 x: &ndarray::prelude::Array1<T>,
42 u: &ndarray::prelude::Array1<T>,
43 ) -> ndarray::prelude::Array1<T> {
44 compact_dynamics(self, t, x, u)
45 }
46
47 fn output(
48 &self,
49 t: T,
50 x: &ndarray::prelude::Array1<T>,
51 u: &ndarray::prelude::Array1<T>,
52 ) -> ndarray::prelude::Array1<T> {
53 compact_output(self, t, x, u)
54 }
55
56 fn n_input(&self) -> usize {
57 (0..self.n_agents())
58 .map(|i| self.mas_dynamics(i).unwrap().n_input())
59 .sum()
60 }
61
62 fn n_state(&self) -> usize {
63 (0..self.n_agents())
64 .map(|i| self.mas_dynamics(i).unwrap().n_state())
65 .sum()
66 }
67
68 fn n_output(&self) -> usize {
69 (0..self.n_agents())
70 .map(|i| self.mas_dynamics(i).unwrap().n_output())
71 .sum()
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use ndarray::array;
78
79 use super::*;
80 use crate::dynamics;
81
82 #[test]
83 fn test_hom_mas() {
84 let lin_dyn = dynamics::LtiDynamics::new(array![[0.]], array![[1.]]);
85 let mas = HomMas::new(&lin_dyn, 3);
86 assert_eq!(mas.n_agents(), 3);
87 assert_eq!(
88 mas.mas_dynamics(1)
89 .unwrap()
90 .dynamics(0., &array![1.,], &array![2.]),
91 array![2.]
92 );
93 assert_eq!(
94 mas.dynamics(0., &array![1., 2., 3.], &array![1., 1., 1.]),
95 array![1., 1., 1.]
96 );
97 }
98
99 #[test]
100 #[should_panic(expected = "agent index exceeds")]
101 fn test_hom_mas_out_of_index() {
102 let lin_dyn = dynamics::LtiDynamics::new(array![[0.]], array![[1.]]);
103 let mas = HomMas::new(&lin_dyn, 3);
104 mas.mas_dynamics(3).unwrap();
105 }
106}