yui_link/link/
node.rs

1use std::fmt::Display;
2
3use yui_core::bitseq::Bit;
4use yui_core::CloneAnd;
5
6use crate::Path;
7use super::Edge;
8
9use NodeType::{X, Xm, V, H};
10
11#[derive(Clone, Copy, PartialEq, Eq, Hash, derive_more::Display, Debug)]
12pub enum NodeType { 
13    X, Xm, V, H 
14}
15
16impl NodeType { 
17    pub fn cc(&mut self) {
18        match self { 
19            Xm => *self = X,
20            X  => *self = Xm,
21            _ => ()
22        }
23    }
24}
25
26#[derive(Debug, Clone, PartialEq, Eq, Hash)]
27pub struct Node { 
28    ntype: NodeType,
29    edges: [Edge; 4]
30}
31
32impl Node {
33    pub fn new(ntype: NodeType, edges: [Edge; 4]) -> Self { 
34        Node { ntype, edges }
35    }
36
37    pub fn from_pd_code(edges: [Edge; 4]) -> Self { 
38        Node::new(NodeType::X, edges)
39    }
40
41    pub fn ntype(&self) -> NodeType { 
42        self.ntype
43    }
44
45    pub fn edge(&self, i: usize) -> Edge { 
46        assert!(i < 4);
47        self.edges[i]
48    }
49
50    pub fn edges(&self) -> &[Edge; 4] { 
51        &self.edges
52    }
53
54    pub fn min_edge(&self) -> Edge { 
55        self.edges.iter().min().unwrap().clone()
56    }
57
58    pub fn is_crossing(&self) -> bool { 
59        matches!(self.ntype, X | Xm)
60    }
61
62    pub fn is_resolved(&self) -> bool { 
63        matches!(self.ntype, V | H)
64    }
65
66    pub fn resolve(&mut self, r: Bit) {
67        use Bit::{Bit0, Bit1};
68
69        match (self.ntype, r) {
70            (X, Bit0) | (Xm, Bit1) => self.ntype = H,
71            (X, Bit1) | (Xm, Bit0) => self.ntype = V,
72            _ => panic!()
73        }
74    }
75
76    pub fn resolved(&self, r: Bit) -> Self { 
77        self.clone_and(|x|
78            x.resolve(r)
79        )
80    }
81
82    pub fn cc(&mut self) { 
83        self.ntype.cc()
84    }
85
86    pub fn is_adj_to(&self, x: &Node) -> bool { 
87        self.edges.iter().any(|e| x.edges.contains(e))
88    }
89
90    pub fn arcs(&self) -> (Path, Path) {
91        let comp = |i: usize, j: usize| {
92            let (ei, ej) = (self.edges[i], self.edges[j]);
93            if ei == ej { 
94                Path::new(vec![ei], true)
95            } else { 
96                Path::new(vec![ei, ej], false)
97            }
98        };
99        match self.ntype { 
100            X | 
101            Xm => (comp(0, 2), comp(1, 3)),
102            V  => (comp(0, 3), comp(1, 2)),
103            H  => (comp(0, 1), comp(2, 3))
104        }
105    }
106
107    pub fn convert_edges<F>(&self, f: F) -> Self
108    where F: Fn(Edge) -> Edge { 
109        Self { 
110            ntype: self.ntype, 
111            edges: self.edges.map(|e| f(e)) 
112        }
113    }
114
115    pub(crate) fn traverse_inner(&self, index:usize) -> usize { 
116        debug_assert!((0..4).contains(&index));
117
118        match self.ntype {
119            X | Xm => (index + 2) % 4,
120            V => 3 - index,
121            H => (5 - index) % 4
122        }
123    }
124}
125
126impl From<[Edge; 4]> for Node {
127    fn from(edges: [Edge; 4]) -> Self {
128        Self::new(NodeType::X, edges)
129    }
130}
131
132impl Display for Node {
133    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
134        write!(f, "{}{:?}", self.ntype, self.edges)
135    }
136}
137
138#[cfg(test)]
139mod tests { 
140    use super::*;
141    
142    fn a_crossing(ntype:NodeType) -> Node {
143        Node{
144            ntype, 
145            edges: [0,1,2,3]
146        }
147    }
148
149    #[test]
150    fn crossing_is_resolved() {
151        let c = a_crossing(X);
152        assert!(c.is_crossing());
153
154        let c = a_crossing(Xm);
155        assert!(c.is_crossing());
156
157        let c = a_crossing(H);
158        assert!(c.is_resolved());
159
160        let c = a_crossing(V);
161        assert!(c.is_resolved());
162    }
163
164    #[test]
165    fn crossing_resolve() {
166        use Bit::{Bit0, Bit1};
167
168        let mut c = a_crossing(X);
169        
170        c.resolve(Bit0);
171        assert!(c.is_resolved());
172        assert_eq!(c.ntype(), H);
173
174        let mut c = a_crossing(X);
175        
176        c.resolve(Bit1);
177        assert!(c.is_resolved());
178        assert_eq!(c.ntype(), V);
179
180        let mut c = a_crossing(Xm);
181        
182        c.resolve(Bit0);
183        assert!(c.is_resolved());
184        assert_eq!(c.ntype(), V);
185
186        let mut c = a_crossing(Xm);
187        
188        c.resolve(Bit1);
189        assert!(c.is_resolved());
190        assert_eq!(c.ntype(), H);
191    }
192
193    #[test]
194    fn crossing_mirror() {
195        let c = a_crossing(X).clone_and(|c| c.cc());
196        assert_eq!(c.ntype(), Xm);
197
198        let c = a_crossing(Xm).clone_and(|c| c.cc());
199        assert_eq!(c.ntype(), X);
200
201        let c = a_crossing(H).clone_and(|c| c.cc());
202        assert_eq!(c.ntype(), H);
203
204        let c = a_crossing(V).clone_and(|c| c.cc());
205        assert_eq!(c.ntype(), V);
206    }
207
208    #[test]
209    fn crossing_pass() {
210        let c = a_crossing(X);
211        assert_eq!(c.traverse_inner(0), 2);
212        assert_eq!(c.traverse_inner(1), 3);
213        assert_eq!(c.traverse_inner(2), 0);
214        assert_eq!(c.traverse_inner(3), 1);
215
216        let c = a_crossing(Xm);
217        assert_eq!(c.traverse_inner(0), 2);
218        assert_eq!(c.traverse_inner(1), 3);
219        assert_eq!(c.traverse_inner(2), 0);
220        assert_eq!(c.traverse_inner(3), 1);
221
222        let c = a_crossing(V);
223        assert_eq!(c.traverse_inner(0), 3);
224        assert_eq!(c.traverse_inner(1), 2);
225        assert_eq!(c.traverse_inner(2), 1);
226        assert_eq!(c.traverse_inner(3), 0);
227
228        let c = a_crossing(H);
229        assert_eq!(c.traverse_inner(0), 1);
230        assert_eq!(c.traverse_inner(1), 0);
231        assert_eq!(c.traverse_inner(2), 3);
232        assert_eq!(c.traverse_inner(3), 2);
233    }
234}