catlog/stdlib/analyses/ode/
signed_coefficients.rs1use indexmap::IndexMap;
4use nalgebra::DMatrix;
5use num_traits::zero;
6
7use super::Parameter;
8use crate::{
9 dbl::model::FpDblModel,
10 zero::{QualifiedName, rig::Monomial},
11};
12
13pub struct SignedCoefficientBuilder<ObType, MorType> {
18 var_ob_type: ObType,
19 positive_mor_types: Vec<MorType>,
20 negative_mor_types: Vec<MorType>,
21}
22
23impl<ObType, MorType> SignedCoefficientBuilder<ObType, MorType> {
24 pub fn new(var_ob_type: ObType) -> Self {
26 Self {
27 var_ob_type,
28 positive_mor_types: Vec::new(),
29 negative_mor_types: Vec::new(),
30 }
31 }
32
33 pub fn add_positive(mut self, mor_type: MorType) -> Self {
35 self.positive_mor_types.push(mor_type);
36 self
37 }
38
39 pub fn add_negative(mut self, mor_type: MorType) -> Self {
41 self.negative_mor_types.push(mor_type);
42 self
43 }
44
45 pub fn build_matrix(
50 &self,
51 model: &impl FpDblModel<
52 ObType = ObType,
53 MorType = MorType,
54 Ob = QualifiedName,
55 ObGen = QualifiedName,
56 MorGen = QualifiedName,
57 >,
58 ) -> (DMatrix<Parameter<QualifiedName>>, IndexMap<QualifiedName, usize>) {
59 let ob_index: IndexMap<_, _> = model
60 .ob_generators_with_type(&self.var_ob_type)
61 .enumerate()
62 .map(|(i, x)| (x, i))
63 .collect();
64
65 let n = ob_index.len();
66 let mut mat = DMatrix::from_element(n, n, zero());
67 for mor_type in self.positive_mor_types.iter() {
68 for mor in model.mor_generators_with_type(mor_type) {
69 let i = *ob_index.get(&model.mor_generator_dom(&mor)).unwrap();
70 let j = *ob_index.get(&model.mor_generator_cod(&mor)).unwrap();
71 mat[(j, i)] += (1.0, Monomial::generator(mor));
72 }
73 }
74 for mor_type in self.negative_mor_types.iter() {
75 for mor in model.mor_generators_with_type(mor_type) {
76 let i = *ob_index.get(&model.mor_generator_dom(&mor)).unwrap();
77 let j = *ob_index.get(&model.mor_generator_cod(&mor)).unwrap();
78 mat[(j, i)] += (-1.0, Monomial::generator(mor));
79 }
80 }
81
82 (mat, ob_index)
83 }
84}