1use crate::combinatorics;
4use crate::flag::{Flag, SubClass};
5use crate::flags::common::*;
6use crate::flags::Colored;
7use crate::iterators;
8use crate::iterators::StreamingIterator;
9use canonical_form::Canonize;
10use const_format::concatcp;
11use std::fmt;
12use std::fmt::Debug;
13
14#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Serialize, Deserialize)]
19pub struct CGraph<const K: u8> {
20 pub size: usize,
21 edge: SymNonRefl<u8>,
22}
23
24impl<const K: u8> CGraph<K> {
25 pub fn is_edge(&self, u: usize, v: usize) -> bool {
27 u != v && self.edge[(u, v)] > 0
28 }
29 pub fn edge(&self, u: usize, v: usize) -> u8 {
32 self.edge[(u, v)]
33 }
34 pub fn nbrs(&self, v: usize) -> Vec<usize> {
36 let mut res = Vec::new();
37 for u in 0..self.size {
38 if self.is_edge(u, v) {
39 res.push(u);
40 }
41 }
42 res
43 }
44 pub fn new(n: usize, edge: &[((usize, usize), u8)]) -> Self {
47 let mut res = Self::empty(n);
48 for &((u, v), val) in edge {
49 assert!(u < n);
50 assert!(v < n);
51 assert!(u != v);
52 assert!(val < K);
53 assert_eq!(res.edge[(u, v)], 0);
54 res.edge[(u, v)] = val;
55 }
56 res
57 }
58 pub fn empty(n: usize) -> Self {
60 Self {
61 size: n,
62 edge: SymNonRefl::new(0, n),
63 }
64 }
65}
66
67impl<const K: u8> fmt::Display for CGraph<K> {
68 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
69 let sep = if self.size < 10 { "" } else { "-" };
70 write!(f, "(|V|={}, E={{", self.size)?;
71 for u in 0..self.size {
72 for v in 0..u {
73 let uv = self.edge[(u, v)];
74 if uv > 0 {
75 write!(f, " {v}{sep}{u}:{uv}")?
76 }
77 }
78 }
79 write!(f, " }})")
80 }
81}
82
83impl<const K: u8> Canonize for CGraph<K> {
84 fn size(&self) -> usize {
85 self.size
86 }
87 fn invariant_neighborhood(&self, v: usize) -> Vec<Vec<usize>> {
88 assert!(v < self.size);
89 let mut res = vec![Vec::new(); (K - 1) as usize];
90 for u in 0..self.size() {
91 if u != v {
92 let edge = self.edge[(u, v)];
93 if edge > 0 {
94 res[edge as usize - 1].push(u)
95 }
96 }
97 }
98 res
99 }
100
101 fn apply_morphism(&self, p: &[usize]) -> Self {
102 self.induce(&combinatorics::invert(p))
103 }
104}
105
106macro_rules! name {
107 ($i:expr) => {
108 concatcp!("CGraph_", $i)
109 };
110}
111
112impl<const K: u8> Flag for CGraph<K> {
113 fn induce(&self, p: &[usize]) -> Self {
114 Self {
115 size: p.len(),
116 edge: self.edge.induce0(p),
117 }
118 }
119
120 const NAME: &'static str = [
123 name!(0u8),
124 name!(1u8),
125 name!(2u8),
126 name!(3u8),
127 name!(4u8),
128 name!(5u8),
129 name!(6u8),
130 name!(7u8),
131 name!(8u8),
132 ][K as usize];
133
134 fn size_zero_flags() -> Vec<Self> {
135 vec![Self::empty(0)]
136 }
137
138 fn superflags(&self) -> Vec<Self> {
139 let n = self.size;
140 let mut res = Vec::new();
141 let mut iter = iterators::Functions::new(n, K as usize);
142 while let Some(map) = iter.next() {
143 let mut edge = self.edge.clone();
144 edge.resize(n + 1, 0);
145 for (v, &c) in map.iter().enumerate() {
146 edge[(v, n)] = c as u8;
147 }
148 res.push(Self { edge, size: n + 1 });
149 }
150 res
151 }
152}
153
154impl<A, const K: u8> SubClass<CGraph<K>, A> {
157 pub fn size(&self) -> usize {
158 self.content.size
159 }
160 pub fn is_edge(&self, u: usize, v: usize) -> bool {
161 self.content.is_edge(u, v)
162 }
163 pub fn edge(&self, u: usize, v: usize) -> u8 {
164 self.content.edge(u, v)
165 }
166}
167
168impl<const K: u8, const N: u8> Colored<CGraph<K>, N> {
169 pub fn size(&self) -> usize {
170 self.content.size
171 }
172 pub fn is_edge(&self, u: usize, v: usize) -> bool {
173 self.content.is_edge(u, v)
174 }
175 pub fn edge(&self, u: usize, v: usize) -> u8 {
176 self.content.edge(u, v)
177 }
178}
179
180impl<A, const K: u8, const N: u8> SubClass<Colored<CGraph<K>, N>, A> {
181 pub fn size(&self) -> usize {
182 self.content.size()
183 }
184 pub fn is_edge(&self, u: usize, v: usize) -> bool {
185 self.content.is_edge(u, v)
186 }
187 pub fn edge(&self, u: usize, v: usize) -> u8 {
188 self.content.edge(u, v)
189 }
190}
191
192#[cfg(test)]
194mod tests {
195 use super::*;
196
197 #[test]
198 fn new_unit() {
199 let g =
200 CGraph::<3>::new(4, &[((0, 1), 1), ((2, 3), 1), ((0, 2), 2), ((0, 3), 2)]).canonical();
201 let h =
202 CGraph::<3>::new(4, &[((1, 0), 2), ((2, 1), 2), ((3, 1), 1), ((0, 2), 1)]).canonical();
203 assert_eq!(g, h);
204 }
205
206 #[test]
207 fn generate_cgraph() {
208 type G1 = CGraph<1>;
209 type G2 = CGraph<2>;
210 type G3 = CGraph<3>;
211
212 assert_eq!(G1::generate(12).len(), 1);
213 assert_eq!(G2::generate(6).len(), 156);
214 assert_eq!(G3::generate(3).len(), 10);
215 }
216}