rust_igraph/algorithms/properties/
is_ptolemaic.rs1use crate::algorithms::chordality::is_chordal;
14use crate::algorithms::properties::is_distance_hereditary::is_distance_hereditary;
15use crate::core::{Graph, IgraphResult};
16
17pub fn is_ptolemaic(graph: &Graph) -> IgraphResult<bool> {
50 if graph.is_directed() {
51 return Ok(false);
52 }
53
54 let n = graph.vcount();
55 if n <= 3 {
56 return Ok(true);
57 }
58
59 let chordal_result = is_chordal(graph, None)?;
60 if !chordal_result.chordal {
61 return Ok(false);
62 }
63
64 is_distance_hereditary(graph)
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 #[test]
72 fn empty_graph() {
73 let g = Graph::with_vertices(0);
74 assert!(is_ptolemaic(&g).unwrap());
75 }
76
77 #[test]
78 fn single_vertex() {
79 let g = Graph::with_vertices(1);
80 assert!(is_ptolemaic(&g).unwrap());
81 }
82
83 #[test]
84 fn single_edge() {
85 let mut g = Graph::with_vertices(2);
86 g.add_edge(0, 1).unwrap();
87 assert!(is_ptolemaic(&g).unwrap());
88 }
89
90 #[test]
91 fn triangle_is_ptolemaic() {
92 let mut g = Graph::with_vertices(3);
93 g.add_edge(0, 1).unwrap();
94 g.add_edge(1, 2).unwrap();
95 g.add_edge(2, 0).unwrap();
96 assert!(is_ptolemaic(&g).unwrap());
97 }
98
99 #[test]
100 fn path_is_ptolemaic() {
101 let mut g = Graph::with_vertices(5);
102 g.add_edge(0, 1).unwrap();
103 g.add_edge(1, 2).unwrap();
104 g.add_edge(2, 3).unwrap();
105 g.add_edge(3, 4).unwrap();
106 assert!(is_ptolemaic(&g).unwrap());
107 }
108
109 #[test]
110 fn tree_is_ptolemaic() {
111 let mut g = Graph::with_vertices(7);
112 g.add_edge(0, 1).unwrap();
113 g.add_edge(0, 2).unwrap();
114 g.add_edge(1, 3).unwrap();
115 g.add_edge(1, 4).unwrap();
116 g.add_edge(2, 5).unwrap();
117 g.add_edge(2, 6).unwrap();
118 assert!(is_ptolemaic(&g).unwrap());
119 }
120
121 #[test]
122 fn k4_is_ptolemaic() {
123 let mut g = Graph::with_vertices(4);
124 for u in 0..4u32 {
125 for v in (u + 1)..4 {
126 g.add_edge(u, v).unwrap();
127 }
128 }
129 assert!(is_ptolemaic(&g).unwrap());
130 }
131
132 #[test]
133 fn star_is_ptolemaic() {
134 let mut g = Graph::with_vertices(5);
135 for i in 1..5u32 {
136 g.add_edge(0, i).unwrap();
137 }
138 assert!(is_ptolemaic(&g).unwrap());
139 }
140
141 #[test]
142 fn c4_not_ptolemaic() {
143 let mut g = Graph::with_vertices(4);
145 g.add_edge(0, 1).unwrap();
146 g.add_edge(1, 2).unwrap();
147 g.add_edge(2, 3).unwrap();
148 g.add_edge(3, 0).unwrap();
149 assert!(!is_ptolemaic(&g).unwrap());
150 }
151
152 #[test]
153 fn c5_not_ptolemaic() {
154 let mut g = Graph::with_vertices(5);
156 g.add_edge(0, 1).unwrap();
157 g.add_edge(1, 2).unwrap();
158 g.add_edge(2, 3).unwrap();
159 g.add_edge(3, 4).unwrap();
160 g.add_edge(4, 0).unwrap();
161 assert!(!is_ptolemaic(&g).unwrap());
162 }
163
164 #[test]
165 fn two_triangles_sharing_vertex_is_ptolemaic() {
166 let mut g = Graph::with_vertices(5);
168 g.add_edge(0, 1).unwrap();
169 g.add_edge(1, 2).unwrap();
170 g.add_edge(2, 0).unwrap();
171 g.add_edge(2, 3).unwrap();
172 g.add_edge(3, 4).unwrap();
173 g.add_edge(4, 2).unwrap();
174 assert!(is_ptolemaic(&g).unwrap());
175 }
176
177 #[test]
178 fn gem_not_ptolemaic() {
179 let mut g = Graph::with_vertices(5);
181 g.add_edge(0, 1).unwrap();
182 g.add_edge(1, 2).unwrap();
183 g.add_edge(2, 3).unwrap();
184 g.add_edge(4, 0).unwrap();
185 g.add_edge(4, 1).unwrap();
186 g.add_edge(4, 2).unwrap();
187 g.add_edge(4, 3).unwrap();
188 assert!(!is_ptolemaic(&g).unwrap());
189 }
190
191 #[test]
192 fn house_not_ptolemaic() {
193 let mut g = Graph::with_vertices(5);
195 g.add_edge(0, 1).unwrap();
196 g.add_edge(1, 2).unwrap();
197 g.add_edge(2, 3).unwrap();
198 g.add_edge(3, 0).unwrap();
199 g.add_edge(2, 4).unwrap();
200 g.add_edge(3, 4).unwrap();
201 assert!(!is_ptolemaic(&g).unwrap());
202 }
203
204 #[test]
205 fn edgeless_is_ptolemaic() {
206 let g = Graph::with_vertices(5);
207 assert!(is_ptolemaic(&g).unwrap());
208 }
209
210 #[test]
211 fn disconnected_trees_ptolemaic() {
212 let mut g = Graph::with_vertices(6);
213 g.add_edge(0, 1).unwrap();
214 g.add_edge(1, 2).unwrap();
215 g.add_edge(3, 4).unwrap();
216 g.add_edge(4, 5).unwrap();
217 assert!(is_ptolemaic(&g).unwrap());
218 }
219
220 #[test]
221 fn directed_returns_false() {
222 let mut g = Graph::new(3, true).unwrap();
223 g.add_edge(0, 1).unwrap();
224 g.add_edge(1, 2).unwrap();
225 assert!(!is_ptolemaic(&g).unwrap());
226 }
227
228 #[test]
229 fn diamond_chordal_but_not_dh() {
230 let mut g = Graph::with_vertices(4);
237 g.add_edge(0, 1).unwrap();
238 g.add_edge(0, 2).unwrap();
239 g.add_edge(0, 3).unwrap();
240 g.add_edge(1, 2).unwrap();
241 g.add_edge(1, 3).unwrap();
242 assert!(is_ptolemaic(&g).unwrap());
243 }
244}