snark_tool/procedure/basic_procedures/
constructions.rs

1use crate::graph::graph::GraphConstructor;
2use crate::graph::undirected::UndirectedGraph;
3use crate::procedure::helpers::config_helper;
4use crate::procedure::procedure;
5use crate::procedure::procedure::{GraphProperties, Procedure};
6use crate::procedure::procedure_builder::{ConfigMap, ProcedureBuilder};
7use crate::service::colour::colouriser::Colouriser;
8use crate::service::colour::recursive::dfs_improved::DFSColourizer;
9use crate::service::constructions::dot_product::DotProducts;
10use crate::service::constructions::error::ConstructionError;
11use crate::service::constructions::i_extension::IExtensions;
12use crate::service::constructions::y_extension::YExtensions;
13use std::collections::HashMap;
14use std::str::FromStr;
15use std::{marker, result};
16
17pub type Result<T> = result::Result<T, ConstructionError>;
18
19// config fields
20const CONSTRUCTION_TYPE: &str = "construction-type";
21
22#[derive(Debug)]
23pub enum ConstructionType {
24    DotProduct,
25    IExtension,
26    YExtension,
27}
28
29impl FromStr for ConstructionType {
30    type Err = ConstructionError;
31
32    fn from_str(input: &str) -> Result<Self> {
33        match input {
34            "dot-product" => Ok(ConstructionType::DotProduct),
35            "i-extension" => Ok(ConstructionType::IExtension),
36            "y-extension" => Ok(ConstructionType::YExtension),
37            _ => Err(ConstructionError::new(format!(
38                "unknown construction type: {}",
39                input
40            ))),
41        }
42    }
43}
44
45struct ConstructionProcedure<G> {
46    config: ConstructionProcedureConfig,
47    _ph: marker::PhantomData<G>,
48}
49
50pub struct ConstructionProcedureConfig {
51    construction_type: ConstructionType,
52}
53
54pub struct ConstructionProcedureBuilder {}
55
56impl<G: UndirectedGraph + GraphConstructor + Clone> Procedure<G> for ConstructionProcedure<G> {
57    fn run(&self, graphs: &mut Vec<(G, GraphProperties)>) -> procedure::Result<()> {
58        println!(
59            "running {} procedure",
60            ConstructionProcedureConfig::PROC_TYPE
61        );
62        self.construct(graphs)?;
63        Ok(())
64    }
65}
66
67impl<G: UndirectedGraph + GraphConstructor + Clone> ConstructionProcedure<G> {
68    pub fn construct(&self, graphs: &mut Vec<(G, GraphProperties)>) -> Result<()> {
69        // for now just constructing fist possible extension of given graph
70
71        let mut extended_graphs = vec![];
72        for graph in graphs.iter() {
73            match self.config.construction_type {
74                ConstructionType::DotProduct => {
75                    let mut dot_products = DotProducts::new(&graph.0, &graph.0);
76                    let extended = dot_products.next().unwrap();
77                    extended_graphs.push((extended, GraphProperties::new()));
78                }
79                ConstructionType::IExtension => {
80                    let colouriser = DFSColourizer::new();
81                    let mut i_extensions = IExtensions::new(&graph.0, &colouriser);
82                    let extended = i_extensions.next().unwrap();
83                    extended_graphs.push((extended, GraphProperties::new()));
84                }
85                ConstructionType::YExtension => {
86                    let colouriser = DFSColourizer::new();
87                    let mut y_extensions = YExtensions::new(&graph.0, &colouriser);
88                    let extended = y_extensions.next().unwrap();
89                    extended_graphs.push((extended, GraphProperties::new()));
90                }
91            }
92        }
93        graphs.append(&mut extended_graphs);
94        Ok(())
95    }
96}
97
98impl ConstructionProcedureConfig {
99    pub const PROC_TYPE: &'static str = "construction";
100
101    pub fn new(construction_type: ConstructionType) -> Self {
102        ConstructionProcedureConfig { construction_type }
103    }
104
105    pub fn from_proc_config(config: &HashMap<String, serde_json::Value>) -> Result<Self> {
106        let construction_type_string: String =
107            config_helper::resolve_value(&config, CONSTRUCTION_TYPE, Self::PROC_TYPE)?;
108        let construction_type = ConstructionType::from_str(&construction_type_string)?;
109        let result = ConstructionProcedureConfig { construction_type };
110        Ok(result)
111    }
112
113    pub fn construction_type(&self) -> &ConstructionType {
114        &self.construction_type
115    }
116}
117
118impl<G: UndirectedGraph + 'static + GraphConstructor + Clone> ProcedureBuilder<G>
119    for ConstructionProcedureBuilder
120{
121    fn build_from_map(&self, config: ConfigMap) -> procedure::Result<Box<dyn Procedure<G>>> {
122        let proc_config = ConstructionProcedureConfig::from_proc_config(&config)?;
123        Ok(Box::new(ConstructionProcedure {
124            config: proc_config,
125            _ph: marker::PhantomData,
126        }))
127    }
128}
129
130impl ConstructionProcedureBuilder {
131    pub fn build<G: UndirectedGraph + GraphConstructor + Clone + 'static>(
132        config: ConstructionProcedureConfig,
133    ) -> Box<dyn Procedure<G>> {
134        Box::new(ConstructionProcedure {
135            config,
136            _ph: marker::PhantomData,
137        })
138    }
139}