machine_check_common/iir/
property.rs

1use std::collections::BTreeSet;
2
3use super::func::IFn;
4
5use serde::{Deserialize, Serialize};
6
7#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
8pub struct ISubpropertyFunc {
9    pub parent: Option<usize>,
10    pub func: IFn,
11    pub children: Vec<usize>,
12    pub dependencies: BTreeSet<usize>,
13    pub display: Option<String>,
14}
15
16#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
17pub struct ISubpropertyNext {
18    pub parent: Option<usize>,
19    pub universal: bool,
20    pub inner: usize,
21    pub display: Option<String>,
22}
23
24#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
25pub struct ISubpropertyFixedPoint {
26    pub parent: Option<usize>,
27    pub universal: bool,
28    pub inner: usize,
29    pub dependents: Vec<usize>,
30    pub display: Option<String>,
31}
32
33#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
34pub enum ISubproperty {
35    Func(ISubpropertyFunc),
36    Next(ISubpropertyNext),
37    FixedPoint(ISubpropertyFixedPoint),
38}
39
40impl ISubproperty {
41    pub fn parent(&self) -> Option<usize> {
42        match self {
43            ISubproperty::Func(subproperty) => subproperty.parent,
44            ISubproperty::Next(subproperty) => subproperty.parent,
45            ISubproperty::FixedPoint(subproperty) => subproperty.parent,
46        }
47    }
48
49    pub fn children(&self) -> &[usize] {
50        match self {
51            ISubproperty::Func(subproperty) => &subproperty.children,
52            ISubproperty::Next(subproperty) => std::slice::from_ref(&subproperty.inner),
53            ISubproperty::FixedPoint(subproperty) => std::slice::from_ref(&subproperty.inner),
54        }
55    }
56
57    pub fn display_str(&self) -> Option<&str> {
58        match self {
59            ISubproperty::Func(subproperty) => subproperty.display.as_ref(),
60            ISubproperty::Next(subproperty) => subproperty.display.as_ref(),
61            ISubproperty::FixedPoint(subproperty) => subproperty.display.as_ref(),
62        }
63        .map(|v| v.as_str())
64    }
65}
66
67#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
68pub struct IProperty {
69    pub subproperties: Vec<ISubproperty>,
70}
71
72impl IProperty {
73    pub fn num_subproperties(&self) -> usize {
74        self.subproperties.len()
75    }
76
77    pub fn subproperty_entry(&self, index: usize) -> &ISubproperty {
78        &self.subproperties[index]
79    }
80
81    pub fn transition_depth(&self) -> usize {
82        let (open_number, max_closed_number) = self.subproperty_transition_depth(0);
83
84        open_number.max(max_closed_number)
85    }
86
87    fn subproperty_transition_depth(&self, subproperty_index: usize) -> (usize, usize) {
88        let subproperty = &self.subproperties[subproperty_index];
89        match subproperty {
90            ISubproperty::Func(subproperty) => {
91                // maximum of children
92                let mut open_number = 0;
93                let mut max_closed_number = 0;
94
95                for child_index in subproperty.children.iter().cloned() {
96                    let (candidate_open_number, candidate_max_closed_number) =
97                        self.subproperty_transition_depth(child_index);
98
99                    open_number = open_number.max(candidate_open_number);
100                    max_closed_number = max_closed_number.max(candidate_max_closed_number);
101                }
102
103                (open_number, max_closed_number)
104            }
105            ISubproperty::Next(subproperty) => {
106                // increment open number
107                let (mut open_number, max_closed_number) =
108                    self.subproperty_transition_depth(subproperty.inner);
109                open_number += 1;
110                (open_number, max_closed_number)
111            }
112            ISubproperty::FixedPoint(subproperty) => {
113                // close the opening
114                let (open_number, max_closed_number) =
115                    self.subproperty_transition_depth(subproperty.inner);
116                let max_closed_number = max_closed_number.max(open_number);
117                (0, max_closed_number)
118            }
119        }
120    }
121
122    pub fn is_subproperty_closed_form(&self, subproperty_index: usize) -> bool {
123        let mut self_descendants = BTreeSet::new();
124        let mut dependencies = BTreeSet::new();
125
126        self.compute_self_descendants_and_dependencies(
127            subproperty_index,
128            &mut self_descendants,
129            &mut dependencies,
130        );
131        self_descendants == dependencies
132    }
133
134    fn compute_self_descendants_and_dependencies(
135        &self,
136        subproperty_index: usize,
137        self_descendants: &mut BTreeSet<usize>,
138        dependencies: &mut BTreeSet<usize>,
139    ) {
140        self_descendants.insert(subproperty_index);
141        dependencies.insert(subproperty_index);
142        let subproperty = &self.subproperties[subproperty_index];
143        match subproperty {
144            ISubproperty::Func(subproperty) => {
145                dependencies.extend(subproperty.dependencies.iter().cloned());
146                for child_index in subproperty.children.iter().cloned() {
147                    self.compute_self_descendants_and_dependencies(
148                        child_index,
149                        self_descendants,
150                        dependencies,
151                    );
152                }
153            }
154            ISubproperty::Next(subproperty) => {
155                self.compute_self_descendants_and_dependencies(
156                    subproperty.inner,
157                    self_descendants,
158                    dependencies,
159                );
160            }
161            ISubproperty::FixedPoint(subproperty) => {
162                self.compute_self_descendants_and_dependencies(
163                    subproperty.inner,
164                    self_descendants,
165                    dependencies,
166                );
167            }
168        };
169    }
170}