Domains test
This commit is contained in:
@ -4,11 +4,15 @@ use std::fmt::Display;
|
||||
use crate::ast::Body;
|
||||
use crate::ast::Predicate;
|
||||
use crate::ast::Variable;
|
||||
use crate::domain;
|
||||
use crate::domain::Domain;
|
||||
use crate::prover::predicate;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Constraints
|
||||
{
|
||||
pub(crate) set: HashMap<Variable, Predicate>,
|
||||
pub(crate) predicates: HashMap<Variable, Predicate>,
|
||||
pub(crate) domains: HashMap<Variable, Domain>,
|
||||
}
|
||||
|
||||
impl Constraints
|
||||
@ -16,20 +20,33 @@ impl Constraints
|
||||
pub fn none() -> Self
|
||||
{
|
||||
Constraints {
|
||||
set: HashMap::new(),
|
||||
predicates: HashMap::new(),
|
||||
domains: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with(variable: Variable, predicate: Predicate) -> Self
|
||||
pub fn with(variable: Variable, predicate: Option<Predicate>, domain: Option<Domain>) -> Self
|
||||
{
|
||||
let mut c = Constraints::none();
|
||||
c.set.insert(variable, predicate);
|
||||
if let Some(predicate) = predicate
|
||||
{
|
||||
c.predicates.insert(variable.clone(), predicate);
|
||||
}
|
||||
if let Some(domain) = domain
|
||||
{
|
||||
c.domains.insert(variable, domain);
|
||||
}
|
||||
c
|
||||
}
|
||||
|
||||
pub fn try_append(&mut self, variable: &Variable, predicate: &Predicate) -> bool
|
||||
pub fn try_append(
|
||||
&mut self,
|
||||
variable: &Variable,
|
||||
predicate: &Predicate,
|
||||
domain: &Domain,
|
||||
) -> bool
|
||||
{
|
||||
if let Some(other_predicate) = self.set.get(variable)
|
||||
let predicates = if let Some(other_predicate) = self.predicates.get(variable)
|
||||
{
|
||||
if predicate == other_predicate
|
||||
{
|
||||
@ -46,7 +63,7 @@ impl Constraints
|
||||
// We can try adding the unification contraints which is implicitely the same
|
||||
if self.try_merge(&unification_contraints)
|
||||
{
|
||||
self.set.insert(variable.clone(), predicate.clone());
|
||||
self.predicates.insert(variable.clone(), predicate.clone());
|
||||
true
|
||||
}
|
||||
else
|
||||
@ -63,18 +80,40 @@ impl Constraints
|
||||
else
|
||||
{
|
||||
// No constraint
|
||||
self.set.insert(variable.clone(), predicate.clone());
|
||||
self.predicates
|
||||
.insert(variable.clone(), (predicate.clone(), domain.clone()));
|
||||
true
|
||||
};
|
||||
|
||||
// Check if domains are compatible
|
||||
let domains = if let Some((_, other_domain)) = self.predicates.get_mut(variable)
|
||||
{
|
||||
let intersection = domain.intersection(other_domain);
|
||||
if intersection.empty()
|
||||
{
|
||||
false
|
||||
}
|
||||
else
|
||||
{
|
||||
*other_domain = intersection;
|
||||
true
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
true
|
||||
};
|
||||
|
||||
domains && predicates
|
||||
}
|
||||
|
||||
pub fn try_merge(&mut self, constraints: &Constraints) -> bool
|
||||
{
|
||||
// Trying to merge, is just trying to add all of the constraints into self
|
||||
let mut ok = self.clone();
|
||||
for (var, pred) in constraints.set.iter()
|
||||
for (var, (pred, domain)) in constraints.predicates.iter()
|
||||
{
|
||||
if !ok.try_append(var, pred)
|
||||
if !ok.try_append(var, pred, domain)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -93,24 +132,26 @@ impl Constraints
|
||||
pub fn simplified(&self) -> Constraints
|
||||
{
|
||||
let mut max_sub = Constraints::none();
|
||||
for (var, pred) in self.set.iter()
|
||||
for (var, (pred, domain)) in self.predicates.iter()
|
||||
{
|
||||
max_sub.set.insert(var.clone(), pred.substitute(self));
|
||||
max_sub
|
||||
.predicates
|
||||
.insert(var.clone(), (pred.substitute(self), domain.clone()));
|
||||
}
|
||||
|
||||
let mut stripped = max_sub.clone();
|
||||
'outer: for (var, _) in max_sub.set.iter()
|
||||
'outer: for (var, _) in max_sub.predicates.iter()
|
||||
{
|
||||
if var.0.chars().next().is_some_and(|x| x == '_') || var.1.is_some()
|
||||
{
|
||||
for (_, other_pred) in max_sub.set.iter()
|
||||
for (_, (other_pred, _)) in max_sub.predicates.iter()
|
||||
{
|
||||
if other_pred.contains_variable(var)
|
||||
{
|
||||
continue 'outer;
|
||||
}
|
||||
}
|
||||
stripped.set.remove(var);
|
||||
stripped.predicates.remove(var);
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,7 +167,7 @@ impl Predicate
|
||||
{
|
||||
Predicate::Variable(name) =>
|
||||
{
|
||||
if let Some(pred) = constraints.set.get(name)
|
||||
if let Some((pred, _)) = constraints.predicates.get(name)
|
||||
{
|
||||
pred.substitute(constraints)
|
||||
}
|
||||
@ -142,6 +183,7 @@ impl Predicate
|
||||
.map(|x| x.substitute(constraints))
|
||||
.collect(),
|
||||
),
|
||||
Predicate::Domain(domain) => Predicate::Domain(domain.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,6 +193,7 @@ impl Predicate
|
||||
{
|
||||
Predicate::Variable(var_name) => name == var_name,
|
||||
Predicate::Fixed(_, predicates) => predicates.iter().any(|x| x.contains_variable(name)),
|
||||
Predicate::Domain(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -183,8 +226,8 @@ impl Display for Constraints
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
|
||||
{
|
||||
let len = self.set.len();
|
||||
for (i, (var, pred)) in self.set.iter().enumerate()
|
||||
let len = self.predicates.len();
|
||||
for (i, (var, (pred, _))) in self.predicates.iter().enumerate()
|
||||
{
|
||||
write!(f, "{} = {}", var, pred)?;
|
||||
if i != len - 1
|
||||
@ -192,6 +235,15 @@ impl Display for Constraints
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
}
|
||||
write!(f, " ;; ")?;
|
||||
for (i, (var, (_, domain))) in self.predicates.iter().enumerate()
|
||||
{
|
||||
write!(f, "{} in {}", var, domain)?;
|
||||
if i != len - 1
|
||||
{
|
||||
write!(f, ", ")?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user