flag_algebra/flag.rs
1//! Definition of the flag-able objects.
2
3use crate::combinatorics::*;
4use crate::iterators::*;
5use canonical_form::Canonize;
6use serde::de::DeserializeOwned;
7use serde::{Deserialize, Deserializer, Serialize, Serializer};
8use std::cmp;
9use std::collections::BTreeSet;
10use std::fmt;
11use std::fmt::{Debug, Display};
12use std::marker::PhantomData;
13
14/// Trait for combinatorial objects that can be used as flags.
15///
16/// Flags must implement the `Canonize` trait
17/// from the `canonical_form` crate, that allows
18/// reduction modulo isomorphism.
19pub trait Flag
20where
21 Self: Canonize + Debug + Display + Serialize + DeserializeOwned,
22{
23 /// Returns the subflag induced by the vertices in the slice `set`.
24 fn induce(&self, set: &[usize]) -> Self;
25 /// Returns the set of all flags of size 0.
26 ///
27 /// This list is used for initialisation in the flag construction.
28 fn size_zero_flags() -> Vec<Self>;
29 /// Return the list of flags of size `self.size() + 1` that contain `self`
30 /// as an induced subflag.
31 ///
32 /// This list can have redundancy and is a priori not reduced modulo isomorphism.
33 fn superflags(&self) -> Vec<Self>;
34 /// A unique name for this type of flags. For instance "Graph".
35 /// This nameis used for naming the associated data subdirectory.
36 const NAME: &'static str;
37
38 // caracteristic
39 /// Setting this parameter to `false` deactivate checks that induced subflags exists.
40 /// Must be `true` in every classic case.
41 const HEREDITARY: bool = true;
42
43 // provided methods
44 /// Return the list of flags of size `self.size() + 1` that contain `self`
45 /// as an induced subflag reduced modulo isomorphism.
46 fn generate_next(previous: &[Self]) -> Vec<Self> {
47 let mut res: BTreeSet<Self> = BTreeSet::new();
48 for g in previous {
49 for h in g.superflags() {
50 let _ = res.insert(h.canonical());
51 }
52 }
53 res.into_iter().collect()
54 }
55
56 /// Return the list of flags of size `n` reduced modulo isomorphism.
57 fn generate(n: usize) -> Vec<Self> {
58 if n == 0 {
59 Self::size_zero_flags()
60 } else {
61 Self::generate_next(&Self::generate(n - 1))
62 }
63 }
64
65 /// Return the list of flags of `g_vec` that can be rooted on the
66 /// flag `type_flag`.
67 /// Each different way to root this flag give a different flag in the result.
68 fn generate_typed_up(type_flag: &Self, g_vec: &[Self]) -> Vec<Self> {
69 assert!(!g_vec.is_empty());
70 let n = g_vec[0].size();
71 let k = type_flag.size();
72 assert!(k <= n);
73 let mut res: BTreeSet<Self> = BTreeSet::new();
74 for g in g_vec {
75 // For every subset of size k
76 let mut iter = Choose::new(n, k);
77 while let Some(pre_selection) = iter.next() {
78 // If this subset induces the right type, then test all permutations
79 if &g.induce(pre_selection).canonical() == type_flag {
80 let mut iter2 = Injection::permutation(k);
81 while let Some(select2) = iter2.next() {
82 let selection = &compose(pre_selection, select2);
83 let h = g.induce(selection);
84 if &h == type_flag {
85 let p = invert(&permutation_of_injection(n, selection));
86 let _ = res.insert(g.apply_morphism(&p).canonical_typed(k));
87 }
88 }
89 }
90 }
91 }
92 res.into_iter().collect()
93 }
94
95 /// Return the list of flag of size `size` rooted on `type_flag`
96 /// reduced modulo (typed) isomorphism.
97 fn generate_typed(type_flag: &Self, size: usize) -> Vec<Self> {
98 Self::generate_typed_up(type_flag, &Self::generate(size))
99 }
100
101 /// Reorder self so that the `eta.len()` first vertices are the values
102 /// of `eta` in the corresponding order.
103 fn select_type(&self, eta: &[usize]) -> Self {
104 let type_selector = invert(&permutation_of_injection(self.size(), eta));
105 self.apply_morphism(&type_selector)
106 }
107}
108
109/// A wrapper type for flags from a sub-class of flags.
110///
111/// This structure is meant to be used with the [`SubFlag`](trait.SubFlag.html) trait.
112/// The second type parameter serves as an identifier for the subclass
113/// and should implement `SubFlag<F>`.
114///
115/// See the [`SubFlag`](trait.SubFlag.html) page for an example.
116pub struct SubClass<F, A> {
117 /// Type of flag wrapped.
118 pub content: F,
119 phantom: PhantomData<A>,
120}
121
122impl<F, A> From<F> for SubClass<F, A> {
123 #[inline]
124 fn from(x: F) -> Self {
125 Self {
126 content: x,
127 phantom: PhantomData,
128 }
129 }
130}
131
132impl<F: Flag, A> Clone for SubClass<F, A> {
133 #[inline]
134 fn clone(&self) -> Self {
135 self.content.clone().into()
136 }
137}
138impl<F: Flag, A> Serialize for SubClass<F, A> {
139 #[inline]
140 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
141 where
142 S: Serializer,
143 {
144 self.content.serialize(serializer)
145 }
146}
147impl<'de, F: Flag, A> Deserialize<'de> for SubClass<F, A> {
148 #[inline]
149 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
150 where
151 D: Deserializer<'de>,
152 {
153 F::deserialize(deserializer).map(Into::into)
154 }
155}
156impl<F: Flag, A> Display for SubClass<F, A> {
157 #[inline]
158 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
159 Display::fmt(&self.content, f)
160 }
161}
162impl<F: Flag, A> Debug for SubClass<F, A> {
163 #[inline]
164 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
165 Debug::fmt(&self.content, f)
166 }
167}
168impl<F: Flag, A> PartialEq for SubClass<F, A> {
169 #[inline]
170 fn eq(&self, other: &Self) -> bool {
171 self.content.eq(&other.content)
172 }
173}
174impl<F: Flag, A> Eq for SubClass<F, A> {}
175impl<F: Flag, A> PartialOrd for SubClass<F, A> {
176 #[inline]
177 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
178 Some(self.cmp(other))
179 }
180}
181impl<F: Flag, A> Ord for SubClass<F, A> {
182 #[inline]
183 fn cmp(&self, other: &Self) -> cmp::Ordering {
184 self.content.cmp(&other.content)
185 }
186}
187
188/// Trait for defining a class of flag as a subset of an already defined class of flag.
189///
190/// The dimension of the related flag algebra will be equal to the size of the subclass.
191///
192/// Flags of a sublass are generated by filtering flags with the
193/// `is_in_subclass` method when extending
194/// Flags of size `n` from flags of size `n-1` (in the subclass).
195/// Since filtering happens at each step, the exhaustive list of flags of
196/// the general class is never generated.
197///
198/// # Example
199/// ```
200/// // This shows how to define triangle-free graphs based on graphs.
201/// use flag_algebra::*;
202/// use flag_algebra::flags::Graph;
203///
204/// // We first define a (zero-sized) type identifying the subclass
205/// enum TriangleFree {}
206///
207/// // We want `SubClass<Graph, TriangleFree>` to be a subclass of `Graph`.
208/// // This is done by implementing `SubFlag<Graph>` for `TriangleFree`.
209/// impl SubFlag<Graph> for TriangleFree {
210/// const SUBCLASS_NAME: &'static str = "Triangle-free graph for the example";
211///
212/// // Compute if the graph is triangle-free.
213/// fn is_in_subclass(g: &Graph) -> bool {
214/// for (u, v) in g.edges() {
215/// for w in 0..u {
216/// if g.edge(u, w) && g.edge(v, w) {
217/// return false // Found a triangle
218/// }
219/// }
220/// }
221/// true
222/// }
223/// }
224///
225/// // We can now use `SubClass<Graph, TriangleFree>` as flags for triangle-free graphs.
226/// type F = SubClass<Graph, TriangleFree>;
227/// let basis: Basis<F> = Basis::new(4);
228/// assert_eq!(basis.get().len(), 7); // There are 7 triangle-free graphs of size 4
229/// ```
230pub trait SubFlag<F>
231where
232 F: Flag,
233 Self: Sized,
234{
235 /// Identifier function for the subclass.
236 fn is_in_subclass(flag: &F) -> bool;
237
238 /// Unique name for the subclass.
239 /// This is used for naming the memoization directory.
240 const SUBCLASS_NAME: &'static str;
241
242 const HEREDITARY: bool = F::HEREDITARY;
243}
244
245impl<F, A> Canonize for SubClass<F, A>
246where
247 F: Flag,
248{
249 #[inline]
250 fn size(&self) -> usize {
251 self.content.size()
252 }
253 fn invariant_neighborhood(&self, v: usize) -> Vec<Vec<usize>> {
254 self.content.invariant_neighborhood(v)
255 }
256 fn apply_morphism(&self, p: &[usize]) -> Self {
257 self.content.apply_morphism(p).into()
258 }
259}
260
261impl<F, A> Flag for SubClass<F, A>
262where
263 A: SubFlag<F>,
264 F: Flag,
265{
266 const NAME: &'static str = A::SUBCLASS_NAME;
267
268 const HEREDITARY: bool = A::HEREDITARY;
269
270 fn superflags(&self) -> Vec<Self> {
271 let mut res = Vec::new();
272 for flag in self.content.superflags() {
273 if A::is_in_subclass(&flag) {
274 res.push(flag.into())
275 }
276 }
277 res
278 }
279 // inherited methods
280 fn induce(&self, p: &[usize]) -> Self {
281 self.content.induce(p).into()
282 }
283 fn size_zero_flags() -> Vec<Self> {
284 F::size_zero_flags().into_iter().map(Into::into).collect()
285 }
286}