1use crate::io_utils::parse_next;
3use crate::{CriticalGrade, OneCriticalGrade, Value};
4use rand::prelude::SliceRandom;
5use rand::thread_rng;
6use std::cmp::{max, Ordering};
7use std::fmt::{Display, Formatter};
8use std::hash::{Hash, Hasher};
9use std::io::BufRead;
10
11pub trait Edge {
13 fn u(&self) -> usize;
16
17 fn u_mut(&mut self) -> &mut usize;
19
20 fn v(&self) -> usize;
23
24 fn v_mut(&mut self) -> &mut usize;
26
27 fn max(&self) -> usize {
29 std::cmp::max(self.u(), self.v())
30 }
31
32 fn min(&self) -> usize {
34 std::cmp::min(self.u(), self.v())
35 }
36
37 fn minmax(&self) -> (usize, usize) {
40 (self.min(), self.max())
41 }
42}
43
44#[derive(Debug, Clone, Copy)]
46pub struct BareEdge(pub usize, pub usize);
47
48impl Edge for BareEdge {
49 fn u(&self) -> usize {
50 self.0
51 }
52
53 fn u_mut(&mut self) -> &mut usize {
54 &mut self.0
55 }
56
57 fn v(&self) -> usize {
58 self.1
59 }
60
61 fn v_mut(&mut self) -> &mut usize {
62 &mut self.1
63 }
64}
65
66impl PartialEq for BareEdge {
67 fn eq(&self, other: &Self) -> bool {
68 self.minmax() == other.minmax()
69 }
70}
71
72impl Eq for BareEdge {}
73
74impl PartialOrd for BareEdge {
76 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
77 Some(self.cmp(other))
78 }
79}
80
81impl Ord for BareEdge {
83 fn cmp(&self, other: &Self) -> Ordering {
84 self.minmax().cmp(&other.minmax())
85 }
86}
87
88impl Hash for BareEdge {
89 fn hash<H: Hasher>(&self, state: &mut H) {
90 self.minmax().hash(state);
91 }
92}
93
94impl std::fmt::Display for BareEdge {
95 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
96 write!(f, "[{}, {}]", self.0, self.1)
97 }
98}
99
100#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
102pub struct FilteredEdge<G> {
103 pub grade: G,
105 pub edge: BareEdge,
107}
108
109impl<G> Edge for FilteredEdge<G> {
110 fn u(&self) -> usize {
111 self.edge.u()
112 }
113
114 fn u_mut(&mut self) -> &mut usize {
115 self.edge.u_mut()
116 }
117
118 fn v(&self) -> usize {
119 self.edge.v()
120 }
121
122 fn v_mut(&mut self) -> &mut usize {
123 self.edge.v_mut()
124 }
125}
126
127impl<G: Ord> PartialOrd<Self> for FilteredEdge<G> {
129 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
130 Some(self.cmp(other))
131 }
132}
133
134impl<G: Ord> Ord for FilteredEdge<G> {
137 fn cmp(&self, other: &Self) -> Ordering {
138 match self.grade.cmp(&other.grade) {
139 Ordering::Equal => self.edge.cmp(&other.edge),
140 not_eq => not_eq,
141 }
142 }
143}
144
145impl<G: Ord> FilteredEdge<G> {
146 fn cmp_by(&self, other: &Self, grade_cmp: impl Fn(&G, &G) -> Ordering) -> Ordering {
149 match grade_cmp(&self.grade, &other.grade) {
150 Ordering::Equal => self.edge.cmp(&other.edge),
151 not_eq => not_eq,
152 }
153 }
154}
155
156impl<G: std::fmt::Display> std::fmt::Display for FilteredEdge<G> {
157 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
158 write!(f, "{}.{}", self.edge, self.grade)?;
159 Ok(())
160 }
161}
162
163impl<G> From<FilteredEdge<G>> for BareEdge {
164 fn from(e: FilteredEdge<G>) -> Self {
165 e.edge
166 }
167}
168
169#[derive(Debug, Clone)]
172pub struct EdgeList<E> {
173 pub n_vertices: usize,
175 edges: Vec<E>,
176}
177
178impl<E: Edge> EdgeList<E> {
179 pub fn new(n_vertices: usize) -> Self {
181 Self {
182 n_vertices,
183 edges: Vec::new(),
184 }
185 }
186
187 pub fn edges(&self) -> &[E] {
189 &self.edges
190 }
191
192 pub fn edges_mut(&mut self) -> &mut [E] {
194 &mut self.edges
195 }
196
197 pub fn len(&self) -> usize {
199 self.edges.len()
200 }
201
202 pub fn is_empty(&self) -> bool {
204 self.len() == 0
205 }
206
207 pub fn from_iterator<I: Iterator<Item = E>>(it: I) -> Self {
209 let edges: Vec<E> = it.collect();
210 edges.into()
211 }
212
213 pub fn number_of_vertices(&self) -> usize {
215 self.n_vertices
216 }
217
218 pub fn add_edge(&mut self, e: E) {
221 let u = e.u();
222 let v = e.v();
223 assert_ne!(u, v, "Trying to add a self loop to a graph");
224
225 let greatest_vertex = max(u, v);
226 self.n_vertices = max(self.n_vertices, greatest_vertex + 1);
227 self.edges.push(e);
228 }
229
230 pub fn edge_iter(&self) -> impl Iterator<Item = &E> + '_ {
232 self.edges.iter()
233 }
234
235 pub fn degrees(&self) -> Vec<usize> {
237 let mut degree_count = vec![0; self.n_vertices];
238 for e in self.edge_iter() {
239 degree_count[e.u()] += 1;
240 degree_count[e.v()] += 1;
241 }
242 degree_count
243 }
244
245 pub fn maximum_degree(&self) -> usize {
247 self.degrees().into_iter().max().unwrap_or(0usize)
249 }
250
251 fn count_vertices(edges: &[E]) -> usize {
252 let mut n_vertices = 0;
253
254 for e in edges.iter() {
255 n_vertices = max(n_vertices, e.max() + 1);
256 }
257
258 n_vertices
259 }
260}
261
262impl<VF: Value, const N: usize> EdgeList<FilteredEdge<OneCriticalGrade<VF, N>>> {
263 pub fn sort_lexicographically(&mut self) {
265 self.edges.sort()
266 }
267
268 pub fn sort_reverse_lexicographically(&mut self) {
270 self.edges.sort_by(|a, b| b.cmp(a))
271 }
272
273 pub fn sort_colexicographically(&mut self) {
275 self.edges
276 .sort_by(|a, b| a.cmp_by(b, OneCriticalGrade::cmp_colexicographically))
277 }
278
279 pub fn sort_reverse_colexicographically(&mut self) {
281 self.edges
282 .sort_by(|a, b| b.cmp_by(a, OneCriticalGrade::cmp_colexicographically))
283 }
284
285 pub fn shuffle(&mut self) {
287 self.edges.shuffle(&mut thread_rng())
288 }
289}
290
291impl<E: Edge> From<Vec<E>> for EdgeList<E> {
292 fn from(edges: Vec<E>) -> Self {
293 let n_vertices = Self::count_vertices(&edges);
294 Self { n_vertices, edges }
295 }
296}
297
298pub fn write_edge_list<T: Value + Display, W: std::io::Write, const N: usize>(
299 edges: &EdgeList<FilteredEdge<OneCriticalGrade<T, N>>>,
300 writer: &mut W,
301 write_number: bool,
302) -> std::io::Result<()> {
303 if write_number {
304 writeln!(writer, "{}", edges.len())?;
305 }
306
307 for e in edges.edge_iter() {
308 write!(writer, "{} {}", e.edge.0, e.edge.1)?;
309 for i in 0..N {
310 write!(writer, " {}", e.grade.0[i])?;
311 }
312 writeln!(writer)?;
313 }
314
315 Ok(())
316}
317
318pub fn read_edge_list<T: Value + std::str::FromStr, R: std::io::Read, const N: usize>(
319 reader: std::io::BufReader<R>,
320) -> std::io::Result<EdgeList<FilteredEdge<OneCriticalGrade<T, N>>>>
321where
322 <T as std::str::FromStr>::Err: std::error::Error + Send + Sync + 'static,
323{
324 let mut edge_list = EdgeList::new(0);
325 for l in reader.lines() {
326 let l = l?;
327 let mut line_parts = l.split_whitespace();
328 let u: usize = parse_next(&mut line_parts)?;
329 let v: usize = parse_next(&mut line_parts)?;
330
331 let mut grade = OneCriticalGrade::zero();
332 for grade_coord in grade.0.iter_mut() {
333 *grade_coord = parse_next(&mut line_parts)?;
334 }
335
336 edge_list.add_edge(FilteredEdge {
337 grade,
338 edge: BareEdge(u, v),
339 });
340 }
341 Ok(edge_list)
342}
343
344#[cfg(test)]
345mod tests {
346 use crate::edges::{BareEdge, EdgeList, FilteredEdge};
347 use crate::OneCriticalGrade;
348
349 #[test]
350 fn edge_list_lexicographic_order() {
351 let mut edges: EdgeList<_> = sorting_test_dataset();
352 edges.sort_lexicographically();
353 let grades: Vec<OneCriticalGrade<usize, 2>> = edges.edge_iter().map(|e| e.grade).collect();
354 let expected_grades: Vec<OneCriticalGrade<usize, 2>> =
355 vec![[1, 1].into(), [1, 2].into(), [2, 1].into(), [2, 2].into()];
356 assert_eq!(grades, expected_grades);
357 }
358
359 #[test]
360 fn edge_list_reverse_lexicographic_order() {
361 let mut edges: EdgeList<_> = sorting_test_dataset();
362 edges.sort_reverse_lexicographically();
363 let grades: Vec<OneCriticalGrade<usize, 2>> = edges.edge_iter().map(|e| e.grade).collect();
364 let expected_grades: Vec<OneCriticalGrade<usize, 2>> =
365 vec![[2, 2].into(), [2, 1].into(), [1, 2].into(), [1, 1].into()];
366 assert_eq!(grades, expected_grades);
367 }
368
369 #[test]
370 fn edge_list_colexicographic_order() {
371 let mut edges: EdgeList<_> = sorting_test_dataset();
372 edges.sort_colexicographically();
373 let grades: Vec<OneCriticalGrade<usize, 2>> = edges.edge_iter().map(|e| e.grade).collect();
374 let expected_grades: Vec<OneCriticalGrade<usize, 2>> =
375 vec![[1, 1].into(), [2, 1].into(), [1, 2].into(), [2, 2].into()];
376 assert_eq!(grades, expected_grades);
377 }
378
379 #[test]
380 fn edge_list_reverse_colexicographic_order() {
381 let mut edges: EdgeList<_> = sorting_test_dataset();
382 edges.sort_reverse_colexicographically();
383 let grades: Vec<OneCriticalGrade<usize, 2>> = edges.edge_iter().map(|e| e.grade).collect();
384 let expected_grades: Vec<OneCriticalGrade<usize, 2>> =
385 vec![[2, 2].into(), [1, 2].into(), [2, 1].into(), [1, 1].into()];
386 assert_eq!(grades, expected_grades);
387 }
388
389 fn sorting_test_dataset() -> EdgeList<FilteredEdge<OneCriticalGrade<usize, 2>>> {
390 vec![
391 FilteredEdge {
392 grade: [1, 1].into(),
393 edge: BareEdge(0, 1),
394 },
395 FilteredEdge {
396 grade: [2, 2].into(),
397 edge: BareEdge(5, 3),
398 },
399 FilteredEdge {
400 grade: [2, 1].into(),
401 edge: BareEdge(0, 3),
402 },
403 FilteredEdge {
404 grade: [1, 2].into(),
405 edge: BareEdge(2, 1),
406 },
407 ]
408 .into()
409 }
410}