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}