xcsp3_rust/utils/
utils_functions.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:55
34 * </p>
35 * <p>@this_file_name:xcsp3domain
36 * </p>
37 */
38
39pub mod xcsp3_utils {
40    use crate::data_structs::xint_val_var::xcsp3_core::XVarVal;
41    use crate::errors::xcsp3error::xcsp3_core::Xcsp3Error;
42    // use std::str::FromStr;
43
44    pub fn list_to_vec_var_val(list: &str) -> Result<Vec<XVarVal>, Xcsp3Error> {
45        let mut ret: Vec<XVarVal> = vec![];
46        let lists: Vec<&str> = list.split_whitespace().collect();
47        for e in lists.iter() {
48            match XVarVal::from_string(e) {
49                None => {
50                    return Err(Xcsp3Error::get_constraint_list_of_values_error(
51                        "parse the list of values error. ",
52                    ))
53                }
54                Some(vv) => {
55                    ret.push(vv);
56                }
57            }
58        }
59        Ok(ret)
60    }
61
62    // pub fn list_to_vec_var(list: &str) -> Vec<XVarVal> {
63    //     let mut ret: Vec<XVarVal> = vec![];
64    //     let lists: Vec<&str> = list.split_whitespace().collect();
65    //     for e in lists.into_iter() {
66    //         ret.push(XVarVal::IntVar(e.to_owned()));
67    //
68    //     }
69    //     ret
70    // }
71
72    pub fn size_to_string(id: &str, size: &[usize]) -> String {
73        let mut ret = id.to_string();
74
75        for e in size.iter() {
76            ret.push_str(&format!("[{}]", e))
77        }
78        ret
79    }
80
81    ///([2,3,4],[2,4,8]) -> [[2,3,4],[2,3,5],[2,3,6],[2,3,7],[2,3,8],[2,4,4],[2,4,5],[2,4,6],[2,4,7],[2,4,8]]
82    pub fn get_all_variables_between_lower_and_upper(
83        lower: Vec<usize>,
84        upper: Vec<usize>,
85    ) -> Vec<Vec<usize>> {
86        let mut ret: Vec<Vec<usize>> = vec![];
87        let mut tmp: Vec<Vec<usize>> = vec![];
88        // println!("{:?},{:?}", lower, upper);
89
90        // recursion_for_get_all_variables(0,&lower,&upper,&ret);
91        for i in lower[0]..upper[0] + 1 {
92            tmp.push(vec![i]);
93        }
94        for deep in 1..lower.len() {
95            for i in lower[deep]..upper[deep] + 1 {
96                for e in tmp.iter() {
97                    let mut ee = e.clone();
98                    ee.push(i);
99                    ret.push(ee)
100                }
101            }
102            tmp = ret.clone();
103            ret.clear();
104        }
105        // println!("ret = {:?}\n", ret);
106        // println!("tmp = {:?}\n", tmp);
107        tmp
108    }
109
110    /// return the nth of the [] in id(str)
111    /// eg x[2][5][] -> 2,  y[] -> 0, z[3][] ->1, zzz[4][][4] ->1
112    pub fn get_nth_square_of_name(id: &str) -> usize {
113        match id.find("[]") {
114            None => 0,
115            Some(v) => {
116                let mut cnt: usize = 0;
117                for (_, c) in id[..v].chars().enumerate() {
118                    if c == '[' {
119                        cnt += 1
120                    }
121                }
122                cnt
123            }
124        }
125    }
126
127    /// return the list of scopes,
128    /// eg str"x[1] x[3] x[5]" - > vec[x[1], x[3], x[5]]
129    pub fn list_to_scope_ids(list: &str) -> Vec<String> {
130        let mut ret: Vec<String> = Vec::new();
131        let lists: Vec<&str> = list.split_whitespace().collect();
132        for e in lists.iter() {
133            ret.push(e.to_string());
134        }
135        ret
136    }
137
138    /// return the transitions,
139    /// eg  "(a,0,a)(a,1,b)(b,1,c)(c,0,d)(d,0,d)(d,1,e)(e,0,e)" -> vec[ (a,0,a),(a,1,b),(b,1,c),(c,0,d),(d,0,d),(d,1,e),(e,0,e)]
140    pub fn list_to_transitions(list: &str) -> Result<Vec<(String, i32, String)>, Xcsp3Error> {
141        let mut ret: Vec<(String, i32, String)> = Vec::new();
142        let chars = list.chars();
143        if let Some(left) = list.find('(') {
144            if let Some(right) = list.find(')') {
145                ret.reserve(list.len() / (right - left));
146                // n = (right - left - 1) / 2;
147            }
148        }
149        let mut last = usize::MAX;
150        let mut last_comma1 = usize::MAX;
151        let mut last_comma2 = usize::MAX;
152        for (i, x) in chars.enumerate() {
153            if x == '(' {
154                last = i;
155            } else if x == ')' {
156                // println!("{}",&tuple_str[last+1..i]);
157                match list[last_comma1 + 1..last_comma2].parse::<i32>() {
158                    Ok(num) => ret.push((
159                        list[last + 1..last_comma1].to_string(),
160                        num,
161                        list[last_comma2 + 1..i].to_string(),
162                    )),
163                    Err(_) => {
164                        return Err(Xcsp3Error::get_constraint_regular_transitions_error(
165                            "parse the transitions error, ",
166                        ));
167                    }
168                }
169                last_comma1 = usize::MAX;
170            } else if x == ',' {
171                if last_comma1 == usize::MAX {
172                    last_comma1 = i;
173                } else {
174                    last_comma2 = i;
175                }
176            }
177        }
178        Ok(ret)
179    }
180
181    /// return the matrix,
182    /// eg str"(x1,x2,x3,x4,x5)(y1,y2,y3,y4,y5)(z1,z2,z3,z4,z5)" - > vec[[x1,x2,x3,x4,x5][y1,y2,y3,y4,y5][z1,z2,z3,z4,z5]]
183    pub fn list_to_matrix_ids(list: &str) -> Vec<Vec<String>> {
184        let mut ret: Vec<Vec<String>> = Vec::new();
185        let list = list
186            .to_string()
187            .replace(')', "@")
188            .replace('\n', "")
189            .replace('(', " ");
190        let lists: Vec<&str> = list.split('@').collect();
191        for e in lists.iter() {
192            if !e.is_empty() {
193                let ss = e.replace(',', " ");
194                ret.push(list_to_scope_ids(&ss));
195            }
196        }
197        ret
198    }
199
200    /// return the list of values,
201    /// eg str"1 3 5 76" -> vec[1,3,5,76],
202    pub fn list_to_values(list: &str) -> Result<Vec<i32>, Xcsp3Error> {
203        let mut ret: Vec<i32> = Vec::new();
204        let lists: Vec<&str> = list.split_whitespace().collect();
205        for l in lists.iter() {
206            match l.parse::<i32>() {
207                Ok(n) => ret.push(n),
208                Err(_) => {
209                    return Err(Xcsp3Error::get_constraint_list_of_values_error(
210                        "parse the list of values error. ",
211                    ));
212                }
213            }
214        }
215        Ok(ret)
216    }
217
218    /// return the list of values,
219    /// eg str"(1, 3, 5, 76)" -> vec[1,3,5,76],
220    pub fn list_with_bracket_comma_to_values(list: &str) -> Result<Vec<XVarVal>, Xcsp3Error> {
221        let mut ret: Vec<XVarVal> = Vec::new();
222        let list = list.to_string().replace(['(', ')', ','], " ");
223        let lists: Vec<&str> = list.split_whitespace().collect();
224        for e in lists.iter() {
225            match e.parse::<i32>() {
226                Ok(n) => ret.push(XVarVal::IntArgument(n)),
227                Err(_) => {
228                    return Err(Xcsp3Error::get_constraint_list_of_values_error(
229                        "parse the list of values error. ",
230                    ));
231                }
232            }
233        }
234        Ok(ret)
235    }
236
237    // fn string_to_i32(s: &str) -> Option<i32> {
238    //     let char = s.chars().rev();
239    //     let mut n: i32 = 0;
240    //     for (i, c) in char.enumerate() {
241    //         if !c.is_numeric() {
242    //             return None;
243    //         } else {
244    //             n += 10i32.pow((i as i32).try_into().unwrap()) * c as i32
245    //         }
246    //     }
247    //     Some(n)
248    // }
249    // fn str_to_2vec(string: &str) -> Vec<Vec<i32>> {
250    //     use serde::Deserialize;
251    //     #[derive(Debug, Deserialize)]
252    //     struct Tuples {
253    //         tuples: Vec<Vec<i32>>,
254    //     }
255    //     let s: Tuples = serde_json::from_str(string).unwrap();
256    //     s.tuples
257    // }
258    // pub fn tuple_to_vector1(tuple_str: &str, is_unary: bool) -> Result<Vec<Vec<i32>>, Xcsp3Error> {
259    //     let err = Xcsp3Error::get_constraint_extension_error("parse the tuple of extension error");
260    //     if is_unary {
261    //         let mut ret: Vec<Vec<i32>> = Vec::new();
262    //         let tuples: Vec<&str> = tuple_str.split_whitespace().collect();
263    //         for tuple in tuples.iter() {
264    //             if tuple.contains("..") {
265    //                 let interval: Vec<&str> = tuple.split("..").collect();
266    //                 if interval.len() == 2 {
267    //                     let left = interval[0].parse::<i32>();
268    //                     let right = interval[1].parse::<i32>();
269    //                     match left {
270    //                         Ok(l) => match right {
271    //                             Ok(r) => {
272    //                                 if l <= r {
273    //                                     for i in l..r + 1 {
274    //                                         ret.push(vec![i])
275    //                                     }
276    //                                 } else {
277    //                                     return Err(err);
278    //                                 }
279    //                             }
280    //                             Err(_) => {
281    //                                 return Err(err);
282    //                             }
283    //                         },
284    //                         Err(_) => {
285    //                             return Err(err);
286    //                         }
287    //                     }
288    //                 }
289    //             } else {
290    //                 match tuple.parse::<i32>() {
291    //                     Ok(v) => ret.push(vec![v]),
292    //                     Err(_) => {
293    //                         return Err(err);
294    //                     }
295    //                 }
296    //             }
297    //         }
298    //         Ok(ret)
299    //     } else {
300    //         let mut tuple_str = tuple_str
301    //             .replace(")(", "],[")
302    //             .replace('(', "[")
303    //             .replace(')', "]")
304    //             .replace("*", &i32::MAX.to_string());
305    //         tuple_str = "{\"tuples\":[".to_owned() + &tuple_str + "]}";
306    //         // println!("{}",tuple_str);
307    //         Ok(str_to_2vec(&tuple_str))
308    //         // println!("{:?}",ret);
309    //     }
310    //     // println!("parse Extension {:?}",ti.get());
311    // }
312    ///return the tuples by given string,
313    /// eg (0,0,1)(0,1,0)(1,0,0)(1,1,1) -> [[0,0,1],[0,1,0],[1,0,0],[1,1,1]]
314    pub fn tuple_to_vector(tuple_str: &str, is_unary: bool) -> Result<Vec<Vec<i32>>, Xcsp3Error> {
315        // let ti = TimeInterval::new();
316        let mut ret: Vec<Vec<i32>> = Vec::new();
317        let err = Xcsp3Error::get_constraint_extension_error("parse the tuple of extension error");
318        if is_unary {
319            let tuples: Vec<&str> = tuple_str.split_whitespace().collect();
320            for tuple in tuples.iter() {
321                if tuple.contains("..") {
322                    let interval: Vec<&str> = tuple.split("..").collect();
323                    if interval.len() == 2 {
324                        let left = interval[0].parse::<i32>();
325                        let right = interval[1].parse::<i32>();
326                        match left {
327                            Ok(l) => match right {
328                                Ok(r) => {
329                                    if l <= r {
330                                        for i in l..r + 1 {
331                                            ret.push(vec![i])
332                                        }
333                                    } else {
334                                        return Err(err);
335                                    }
336                                }
337                                Err(_) => {
338                                    return Err(err);
339                                }
340                            },
341                            Err(_) => {
342                                return Err(err);
343                            }
344                        }
345                    }
346                } else {
347                    match tuple.parse::<i32>() {
348                        Ok(v) => ret.push(vec![v]),
349                        Err(_) => {
350                            return Err(err);
351                        }
352                    }
353                }
354            }
355        } else {
356            let chars = tuple_str.chars();
357            let mut last = 0;
358            let mut tt: Vec<i32> = vec![];
359            let mut n: usize = 0;
360            if let Some(left) = tuple_str.find('(') {
361                if let Some(right) = tuple_str.find(')') {
362                    ret.reserve(tuple_str.len() / (right - left));
363                    n = (right - left - 1) / 2;
364                }
365            }
366            for (i, x) in chars.enumerate() {
367                if x == '(' {
368                    tt.clear();
369                    tt.reserve(n);
370                    last = i;
371                } else if x == ')' {
372                    // println!("{}",&tuple_str[last+1..i]);
373                    match tuple_str[last + 1..i].parse::<i32>() {
374                        Ok(num) => {
375                            tt.push(num);
376                        }
377                        Err(_) => {
378                            if &tuple_str[last + 1..i] == "*" {
379                                tt.push(i32::MAX);
380                            } else {
381                                return Err(err);
382                            }
383                        }
384                    }
385                    ret.push(tt.clone())
386                } else if x == ',' {
387                    // println!("{}",&tuple_str[last+1..i]);
388                    match tuple_str[last + 1..i].parse::<i32>() {
389                        Ok(num) => {
390                            tt.push(num);
391                        }
392                        Err(_) => {
393                            if &tuple_str[last + 1..i] == "*" {
394                                tt.push(i32::MAX);
395                            } else {
396                                return Err(err);
397                            }
398                        }
399                    }
400                    last = i;
401                }
402            }
403        }
404        // println!("parse Extension {:?}",ti.get());
405        Ok(ret)
406    }
407
408    /// transform the string size to vector sizes
409    /// eg:  [2][3..4][4..8] -> ([2,3,4],[2,4,8])
410    pub fn sizes_to_double_vec(sizes: &str) -> Result<(Vec<usize>, Vec<usize>), Xcsp3Error> {
411        let mut lower: Vec<usize> = vec![];
412        let mut upper: Vec<usize> = vec![];
413        let sizes = sizes.replace("[]", "[*]").replace(['[', ']'], " ");
414        let nums: Vec<&str> = sizes.split_whitespace().collect();
415        for n in nums.iter() {
416            if n.find('*').is_some() {
417                lower.push(usize::MAX);
418                upper.push(usize::MAX);
419            } else if n.contains("..") {
420                let interval: Vec<&str> = n.split("..").collect();
421                if interval.len() == 2 {
422                    let low = interval[0].parse::<usize>();
423                    let up = interval[1].parse::<usize>();
424
425                    match low {
426                        Ok(l) => match up {
427                            Ok(u) => {
428                                lower.push(l);
429                                upper.push(u);
430                            }
431                            Err(_) => {
432                                return Err(Xcsp3Error::get_domain_for_error(
433                                    "parse the domain for error",
434                                ));
435                            }
436                        },
437                        Err(_) => {
438                            return Err(Xcsp3Error::get_domain_for_error(
439                                "parse the domain for error",
440                            ));
441                        }
442                    }
443                }
444            } else {
445                match n.parse::<usize>() {
446                    Ok(v) => {
447                        lower.push(v);
448                        upper.push(v);
449                    }
450                    Err(_) => {
451                        return Err(Xcsp3Error::get_domain_for_error("parse the domain error"));
452                    }
453                };
454            }
455        }
456        Ok((lower, upper))
457    }
458
459    /// transform the string size to vector sizes
460    /// eg:  [2][3][4] -> ([2,3,4], 24)
461    pub fn sizes_to_vec(sizes: &str) -> Result<(Vec<usize>, usize), Xcsp3Error> {
462        let mut ret: Vec<usize> = vec![];
463        let mut sz: usize = 1;
464        let mut sizes = sizes.replace('[', " ");
465        sizes = sizes.replace(']', " ");
466        let nums: Vec<&str> = sizes.split_whitespace().collect();
467        for n in nums.iter() {
468            match n.parse::<usize>() {
469                Ok(v) => {
470                    ret.push(v);
471                    sz *= v;
472                }
473                Err(_) => {
474                    return Err(Xcsp3Error::get_variable_size_invalid_error(
475                        "parse the size of variable error",
476                    ));
477                }
478            };
479        }
480
481        Ok((ret, sz))
482    }
483}
484
485// #[allow(dead_code)]
486// pub mod xcsp3_core {
487//
488//     pub fn split_with_elems(s: &str, delim: &char, elems: &mut Vec<String>) {
489//         let de = format!("{}", delim);
490//         let result: Vec<&str> = s.split(de.as_str()).collect();
491//         for elem in result {
492//             elems.push(String::from(elem));
493//         }
494//     }
495//
496//     // pub fn parser_domain(domain: &String) -> XDomainInteger
497//     // {
498//     //     let mut ret:XDomainInteger = XDomainInteger::new();
499//     //     let domains :Vec<&str>= domain.split_whitespace().collect();
500//     //
501//     //     for d in domains.iter()
502//     //     {
503//     //         if d.find("..").is_some()
504//     //         {
505//     //             let interval: Vec<&str> = d.split("..").collect();
506//     //             if interval.len() == 2 {
507//     //                 let left = i32::from_str(interval[0]);
508//     //                 let right = i32::from_str(interval[1]);
509//     //                 match left {
510//     //                     Ok(l) => {
511//     //                         match right {
512//     //                             Ok(r) => {
513//     //                                 ret.add_interval(l,r);
514//     //                             }
515//     //                             Err(_) => {}
516//     //                         }
517//     //                     }
518//     //                     Err(_) => {}
519//     //                 }
520//     //             }
521//     //
522//     //
523//     //         }else {
524//     //              match  i32::from_str(d){
525//     //                 Ok(v) => {
526//     //                     ret.add_value(v)
527//     //                 }
528//     //                 Err(_) => { }
529//     //             } ;
530//     //         }
531//     //     }
532//     //
533//     //     ret
534//     // }
535//
536//     pub fn split(s: &str, delim: &char) -> Vec<String> {
537//         let mut elems: Vec<String> = vec![];
538//         split_with_elems(s, delim, &mut elems);
539//         elems
540//     }
541//
542//     pub fn replace_string_in_place(subject: &mut str, search: &str, replace: &str) {
543//         let _ = subject.replace(search, replace);
544//     }
545//
546//     pub fn remove_char(s: &mut str, c: char) {
547//         let _ = s.replace(c, "");
548//     }
549// }