snark_tool/procedure/basic_procedures/
colour.rs

1use std::collections::HashMap;
2use std::marker;
3
4use crate::graph::undirected::UndirectedGraph;
5use crate::procedure::error::Error;
6use crate::procedure::helpers::config_helper;
7use crate::procedure::procedure::{GraphProperties, Procedure, Result};
8use crate::procedure::procedure_builder::{ConfigMap, ProcedureBuilder};
9use crate::service::colour::colouriser::Colouriser;
10use crate::service::colour::cvd::cvd;
11use crate::service::colour::cvd::cvd_dfs::CvdDfsColourizer;
12use crate::service::colour::cvd::cvd_sat::CvdSatColourizer;
13use crate::service::colour::matchings::matching_col::MatchingColouriser;
14use crate::service::colour::recursive::dfs_improved::DFSColourizer;
15use crate::service::colour::sat::sat::SATColourizer;
16
17// config params
18const COLOURISER_TYPE: &str = "colouriser-type";
19
20// result properties
21const COLOURABLE: &str = "colourable";
22
23// coloriser types
24const DFS: &str = "dfs";
25const SAT: &str = "sat";
26const CVD: &str = "cvd";
27const CVD_DFS: &str = "cvd-dfs";
28const CVD_SAT: &str = "cvd-sat";
29const MATCHING: &str = "matching";
30const AUTO: &str = "auto";
31
32#[derive(Clone)]
33pub enum ColouriserType {
34    Dfs,
35    Sat,
36    Cvd,
37    CvdDfs,
38    CvdSat,
39    Matching,
40    Auto,
41}
42
43impl ColouriserType {
44    pub fn from_string(string: &String) -> Result<ColouriserType> {
45        let col_type;
46        match string.as_str() {
47            DFS => col_type = ColouriserType::Dfs,
48            SAT => col_type = ColouriserType::Sat,
49            CVD => col_type = ColouriserType::Cvd,
50            CVD_DFS => col_type = ColouriserType::CvdDfs,
51            CVD_SAT => col_type = ColouriserType::CvdSat,
52            MATCHING => col_type = ColouriserType::Matching,
53            AUTO => col_type = ColouriserType::Auto,
54            &_ => {
55                return Err(Error::ConfigError(String::from(format!(
56                    "unknown colouriser type: {}, did you mean {}, {}, {}, {}, {}, {} or {}?",
57                    string, DFS, SAT, MATCHING, CVD, CVD_DFS, CVD_SAT, AUTO
58                ))));
59            }
60        }
61        Ok(col_type)
62    }
63}
64
65struct ColourProcedure<G: UndirectedGraph> {
66    config: ColourProcedureConfig,
67    _ph: marker::PhantomData<G>,
68}
69
70pub struct ColourProcedureConfig {
71    colouriser_type: ColouriserType,
72}
73
74pub struct ColourProcedureBuilder {}
75
76impl<G: UndirectedGraph> Procedure<G> for ColourProcedure<G> {
77    fn run(&self, graphs: &mut Vec<(G, GraphProperties)>) -> Result<()> {
78        println!("running colour procedure");
79        self.colour_graph(graphs)
80    }
81}
82
83impl<G: UndirectedGraph> ColourProcedure<G> {
84    pub fn colour_graph(&self, graphs: &mut Vec<(G, GraphProperties)>) -> Result<()> {
85        let colouriser_type = self.config.colouriser_type();
86        match colouriser_type {
87            ColouriserType::Dfs => {
88                Self::color_by_colourizer::<DFSColourizer>(graphs);
89            }
90            ColouriserType::Sat => {
91                Self::color_by_colourizer::<SATColourizer>(graphs);
92            }
93            ColouriserType::CvdDfs => {
94                Self::color_by_colourizer::<CvdDfsColourizer>(graphs);
95            }
96            ColouriserType::CvdSat => {
97                Self::color_by_colourizer::<CvdSatColourizer>(graphs);
98            }
99            ColouriserType::Matching => {
100                Self::color_by_colourizer::<MatchingColouriser>(graphs);
101            }
102            ColouriserType::Cvd => {
103                Self::color_by_colourizer_cvd(graphs);
104            }
105            _ => {
106                return Err(Error::ConfigError(String::from(
107                    "unknown colouriser type for colour procedure",
108                )));
109            }
110        }
111        Ok(())
112    }
113
114    fn color_by_colourizer<C: Colouriser>(graphs: &mut Vec<(G, GraphProperties)>) {
115        for graph in graphs {
116            let result = C::is_colorable(&graph.0);
117            graph
118                .1
119                .insert(COLOURABLE.to_string(), serde_json::Value::Bool(result));
120        }
121    }
122
123    ///
124    /// color by heuristic
125    ///
126    fn color_by_colourizer_cvd(graphs: &mut Vec<(G, GraphProperties)>) {
127        for graph in graphs {
128            let result_option = cvd::is_colorable(&graph.0);
129            if let Some(result) = result_option {
130                graph
131                    .1
132                    .insert(COLOURABLE.to_string(), serde_json::Value::Bool(result));
133            }
134        }
135    }
136}
137
138impl ColourProcedureConfig {
139    pub const PROC_TYPE: &'static str = "colour";
140
141    pub fn new(colouriser_type: ColouriserType) -> Self {
142        ColourProcedureConfig { colouriser_type }
143    }
144
145    pub fn default() -> Self {
146        ColourProcedureConfig {
147            colouriser_type: ColouriserType::Dfs,
148        }
149    }
150
151    pub fn colouriser_type(&self) -> &ColouriserType {
152        &self.colouriser_type
153    }
154
155    pub fn from_proc_config(config: &HashMap<String, serde_json::Value>) -> Result<Self> {
156        let colouriser_type = config_helper::resolve_value_or_default(
157            &config,
158            COLOURISER_TYPE,
159            DFS.to_string(),
160            Self::PROC_TYPE,
161        )?;
162
163        let result = ColourProcedureConfig {
164            colouriser_type: ColouriserType::from_string(&colouriser_type)?,
165        };
166        Ok(result)
167    }
168}
169
170impl<G: UndirectedGraph + 'static> ProcedureBuilder<G> for ColourProcedureBuilder {
171    fn build_from_map(&self, config: ConfigMap) -> Result<Box<dyn Procedure<G>>> {
172        let proc_config = ColourProcedureConfig::from_proc_config(&config)?;
173        Ok(Box::new(ColourProcedure {
174            config: proc_config,
175            _ph: marker::PhantomData,
176        }))
177    }
178}
179
180impl ColourProcedureBuilder {
181    pub fn build<G: UndirectedGraph + 'static>(
182        config: ColourProcedureConfig,
183    ) -> Box<dyn Procedure<G>> {
184        Box::new(ColourProcedure {
185            config,
186            _ph: marker::PhantomData,
187        })
188    }
189}