xcsp3_rust/variables/
xvariable_set.rs

1/*=============================================================================
2* parser for CSP instances represented in XCSP3 Format
3*
4* Copyright (c) 2023 xcsp.org (contact @ xcsp.org)
5*
6* Permission is hereby granted, free of charge, to any person obtaining a copy
7* of this software and associated documentation files (the "Software"), to deal
8* in the Software without restriction, including without limitation the rights
9* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10* copies of the Software, and to permit persons to whom the Software is
11* furnished to do so, subject to the following conditions:
12*
13* The above copyright notice and this permission notice shall be included in
14* all copies or substantial portions of the Software.
15*
16* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22* THE SOFTWARE.
23*=============================================================================
24*/
25
26/*
27 * <p>@project_name: XCSP3-Rust
28 * </p>
29 * <p>@author: luhanzhen
30 * </p>
31 * <p>@date: 2023/6/30
32 * </p>
33 * <p>@time: 13:47
34 * </p>
35 * <p>@this_file_name:XCSP3Variable
36 * </p>
37 */
38
39pub mod xcsp3_core {
40    use crate::errors::xcsp3error::xcsp3_core::Xcsp3Error;
41    use crate::variables::xdomain::xcsp3_core::XDomainInteger;
42    use crate::variables::xvariable_type::xcsp3_core::XVariableType;
43    use std::collections::HashMap;
44    use std::fmt::{Display, Formatter};
45
46    // use regex::Regex;
47    use std::slice::Iter;
48    /**
49    the XVariableSet is a container that store all variables.
50     */
51    pub struct XVariableSet {
52        variables: Vec<XVariableType>,
53        id_to_index: HashMap<String, usize>, //store the id and the index of the variable
54                                             // empty_domain: XDomainInteger,
55    }
56
57    impl Default for XVariableSet {
58        fn default() -> Self {
59            Self::new()
60        }
61    }
62
63    impl Display for XVariableSet {
64        fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
65            let mut ret = String::default();
66            for e in self.variables.iter() {
67                ret = format!("{} \t{}\n", ret, e);
68            }
69            write!(f, "XVariableSet: \n{}", ret)
70        }
71    }
72
73    impl XVariableSet {
74        pub fn iter(&self) -> Iter<'_, XVariableType> {
75            self.variables.iter()
76        }
77
78        // pub fn to_string(&self) -> String {
79        //     let mut ret = String::from("XVariableSet: \n");
80        //     for e in self.variables.iter() {
81        //         ret = format!("{} \t{}\n", ret, e);
82        //     }
83        //     ret
84        // }
85        pub fn new() -> XVariableSet {
86            XVariableSet {
87                variables: vec![],
88                id_to_index: HashMap::default(),
89                // empty_domain: XDomainInteger::new(),
90            }
91        }
92
93        pub fn build_variable_int(&mut self, id: &str, domain_string: &str, symbolic: &String) {
94            if symbolic.eq("symbolic") {
95                let domain = XDomainInteger::from_symbolic(domain_string);
96                let var = XVariableType::new_int(id, domain);
97                self.id_to_index.insert(var.get_id(), self.variables.len());
98                self.variables.push(var);
99            } else {
100                match XDomainInteger::from_string(domain_string) {
101                    Ok(domain) => {
102                        let var = XVariableType::new_int(id, domain);
103                        self.id_to_index.insert(var.get_id(), self.variables.len());
104                        self.variables.push(var);
105                    }
106                    Err(e) => {
107                        // eprintln!("{}", e.to_string());
108                        self.variables.push(XVariableType::XVariableNone(e));
109                    }
110                }
111            }
112        }
113
114        pub fn build_variable_int_as(&mut self, id: &str, as_str: &str) {
115            match self.find_variable(as_str) {
116                Ok(v) => {
117                    if let XVariableType::XVariableInt(vv) = v {
118                        let var = XVariableType::new_int(id, vv.domain.clone());
119                        self.id_to_index.insert(var.get_id(), self.variables.len());
120                        self.variables.push(var);
121                    }
122                }
123                Err(e) => {
124                    // eprintln!("{}", e.to_string());
125                    self.variables.push(XVariableType::XVariableNone(e));
126                }
127            }
128        }
129
130        pub fn build_variable_array(&mut self, id: &str, sizes: &str, domain_string: &str) {
131            match XDomainInteger::from_string(domain_string) {
132                Ok(domain) => {
133                    let array = XVariableType::new_array(id, sizes, domain);
134                    match array {
135                        XVariableType::XVariableArray(_) => {
136                            self.id_to_index
137                                .insert(array.get_id(), self.variables.len());
138                            self.variables.push(array);
139                        }
140                        _ => {
141                            self.variables.push(XVariableType::XVariableNone(
142                                Xcsp3Error::get_variable_size_invalid_error(""),
143                            ));
144                        }
145                    }
146                }
147                Err(e) => {
148                    self.variables.push(XVariableType::XVariableNone(e));
149                }
150            };
151        }
152
153        pub fn build_variable_tree(
154            &mut self,
155            id: &str,
156            sizes: &str,
157            domain_for: Vec<&String>,
158            domain_value: Vec<&String>,
159        ) {
160            let tree = XVariableType::new_tree(id, sizes, domain_for, domain_value);
161            match tree {
162                Ok(tree) => {
163                    self.id_to_index.insert(tree.get_id(), self.variables.len());
164                    self.variables.push(tree);
165                }
166                Err(e) => {
167                    self.variables.push(XVariableType::XVariableNone(e));
168                }
169            }
170        }
171
172        pub fn find_variable(&self, id: &str) -> Result<&XVariableType, Xcsp3Error> {
173            let name = match id.find('[') {
174                None => id,
175                Some(n) => &id[..n],
176            };
177            match self.id_to_index.get(name) {
178                None => Err(Xcsp3Error::get_variable_not_found_error(
179                    &("not find the variable named ".to_owned() + name),
180                )),
181                Some(v) => Ok(&self.variables[*v]),
182            }
183        }
184
185        ///construct the scope from XVariableSet, when scope is equal to %x, where x is an i32 number, return empty tuple
186        pub fn construct_scope(
187            &self,
188            scope_str: &[&String],
189        ) -> Result<Vec<(String, &XDomainInteger)>, Xcsp3Error> {
190            let mut ret: Vec<(String, &XDomainInteger)> = vec![];
191            for e in scope_str.iter() {
192                {
193                    match self.find_variable(e) {
194                        Ok(var_type) => match var_type {
195                            XVariableType::XVariableArray(a) => match a.find_variable(e) {
196                                Ok(mut vec) => {
197                                    for (e1, e2) in vec.iter_mut() {
198                                        ret.push((e1.to_string(), e2));
199                                    }
200                                }
201                                Err(e) => {
202                                    return Err(e);
203                                }
204                            },
205                            XVariableType::XVariableInt(i) => ret.push((i.id.clone(), &i.domain)),
206                            XVariableType::XVariableTree(t) => match t.find_variable(e) {
207                                Ok(mut vec) => {
208                                    for (e1, e2) in vec.iter_mut() {
209                                        ret.push((e1.to_string(), e2));
210                                    }
211                                }
212                                Err(e) => {
213                                    return Err(e);
214                                }
215                            },
216                            _ => {}
217                        },
218                        Err(_) => {
219                            return Err(Xcsp3Error::get_variable_not_found_error(
220                                "the scope not found, ",
221                            ));
222                        }
223                    }
224                }
225            }
226            Ok(ret)
227        }
228    }
229}