pub mod xcsp3_core {
use std::fmt::{Display, Formatter};
use crate::errors::xcsp3error::xcsp3_core::Xcsp3Error;
use crate::utils::utils_functions::xcsp3_utils::{
get_all_variables_between_lower_and_upper, size_to_string, sizes_to_double_vec,
sizes_to_vec,
};
use crate::variables::xdomain::xcsp3_core::XDomainInteger;
#[derive(Clone)]
pub struct XVariableTree {
nodes: Vec<XVariableTreeNode>,
others: XVariableTreeNode,
pub(crate) id: String,
sizes: Vec<usize>,
}
impl XVariableTree {
fn get_node_by_vec(&self, v: &[usize]) -> &XVariableTreeNode {
for e in self.nodes.iter() {
if e.belongs_to_this_node(v) {
return e;
}
}
&self.others
}
pub fn find_variable(
&self,
id: &str,
) -> Result<Vec<(String, &XDomainInteger)>, Xcsp3Error> {
let mut ret: Vec<(String, &XDomainInteger)> = vec![];
match id.find('[') {
None => {
return Err(Xcsp3Error::get_variable_size_invalid_error(
"find_variable in XVariableTree error",
));
}
Some(v) => match sizes_to_double_vec(&id[v..]) {
Ok((mut lower, mut upper)) => {
for i in 0..lower.len() {
if lower[i] == usize::MAX && upper[i] == usize::MAX {
lower[i] = 0;
upper[i] = self.sizes[i] - 1;
}
}
let all_variable = get_all_variables_between_lower_and_upper(lower, upper);
for size_vec in all_variable.iter() {
let node = self.get_node_by_vec(size_vec);
ret.push((size_to_string(&id[..v], size_vec), &node.domain));
}
}
Err(e) => {
return Err(e);
}
},
}
Ok(ret)
}
pub fn new(
id: &str,
sizes: &str,
domain_for: Vec<&String>,
domain_value: Vec<&String>,
) -> Result<Self, Xcsp3Error> {
match sizes_to_vec(sizes) {
Ok((size_vec, _)) => {
let mut nodes: Vec<XVariableTreeNode> = Vec::new();
let mut others_domain = Default::default();
for i in 0..domain_for.len() {
match XDomainInteger::from_string(domain_value[i]) {
Ok(domain) => {
if domain_for[i].eq("others") {
others_domain = domain;
} else {
let for_strs: Vec<&str> =
domain_for[i].split_whitespace().collect();
for e in for_strs.iter() {
let for_str = e.to_string().replace(id, "");
match sizes_to_double_vec(&for_str) {
Ok((lower, upper)) => {
nodes.push(XVariableTreeNode::new(
lower,
upper,
domain.clone(),
));
}
Err(e) => {
eprintln!("{}", e);
return Err(e);
}
}
}
}
}
Err(e) => {
return Err(e);
}
}
}
Ok(XVariableTree {
id: id.to_string(),
sizes: size_vec,
others: XVariableTreeNode::new_other(others_domain),
nodes,
})
}
Err(e) => Err(e),
}
}
}
#[derive(Clone)]
struct XVariableTreeNode {
upper: Vec<usize>,
lower: Vec<usize>,
domain: XDomainInteger,
is_other: bool,
}
impl XVariableTreeNode {
pub fn belongs_to_this_node(&self, v: &[usize]) -> bool {
for (i, v) in v.iter().enumerate() {
if !(self.lower[i] == usize::MAX && self.upper[i] == usize::MAX
|| self.lower[i] <= *v && self.upper[i] >= *v)
{
return false;
}
}
true
}
pub fn to_string(&self, id: &str) -> String {
let mut ret = format!("[for = {}", id);
if self.is_other {
ret.push_str("[others]..");
} else {
for i in 0..self.upper.len() {
ret.push('[');
if self.lower[i] == self.upper[i] {
if self.lower[i] == usize::MAX {
ret.push('*');
} else {
ret.push_str(&self.lower[i].to_string());
}
} else {
ret.push_str(&self.lower[i].to_string());
ret.push_str("..");
ret.push_str(&self.upper[i].to_string());
}
ret.push(']');
}
}
ret.push_str(" domain = ");
ret.push_str(&self.domain.to_string());
ret
}
pub fn new(
lower: Vec<usize>,
upper: Vec<usize>,
domain: XDomainInteger,
) -> XVariableTreeNode {
XVariableTreeNode {
upper,
lower,
domain,
is_other: false,
}
}
pub fn new_other(domain: XDomainInteger) -> XVariableTreeNode {
XVariableTreeNode {
upper: Vec::default(),
lower: Vec::default(),
domain,
is_other: true,
}
}
}
impl Display for XVariableTree {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut ret = String::default();
for e in self.sizes.iter() {
ret.push('[');
ret.push_str(e.to_string().as_str());
ret.push(']');
}
ret.push_str("nodes = ");
for e in self.nodes.iter() {
ret += &e.to_string(&self.id);
ret += "] ";
}
write!(f, "XVariableTree: id = {}, sizes = {}", self.id, ret)
}
}
}