Domains test

This commit is contained in:
2026-02-12 20:59:45 +01:00
parent 27af8c9263
commit 5458b3a822
9 changed files with 783 additions and 56 deletions

View File

@ -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(())
}
}