conjure_core/rules/matrix/
bubble.rs
1use conjure_core::ast::Expression;
2use conjure_core::metadata::Metadata;
3use conjure_core::rule_engine::{
4 register_rule, ApplicationError, ApplicationError::RuleNotApplicable, ApplicationResult,
5 Reduction,
6};
7use itertools::{izip, Itertools as _};
8
9use crate::ast::{Domain, SymbolTable};
10use crate::{bug, into_matrix_expr};
11
12#[register_rule(("Bubble", 6000))]
14fn index_to_bubble(expr: &Expression, symbols: &SymbolTable) -> ApplicationResult {
15 let Expression::UnsafeIndex(_, subject, indices) = expr else {
16 return Err(RuleNotApplicable);
17 };
18
19 let domain = subject
20 .domain_of(symbols)
21 .ok_or(ApplicationError::DomainError)?;
22
23 let Domain::DomainMatrix(_, index_domains) = domain else {
24 bug!("subject of an index expression should have a matrix domain. subject: {:?}, with domain: {:?}", subject, domain);
25 };
26
27 assert_eq!(index_domains.len(),indices.len(),"in an index expression, there should be the same number of indices as the subject has index domains");
28
29 let bubble_constraints = Box::new(into_matrix_expr![izip!(index_domains, indices)
30 .map(|(domain, index)| {
31 Expression::InDomain(Metadata::new(), Box::new(index.clone()), domain)
32 })
33 .collect_vec()]);
34
35 let new_expr = Box::new(Expression::SafeIndex(
36 Metadata::new(),
37 subject.clone(),
38 indices.clone(),
39 ));
40
41 Ok(Reduction::pure(Expression::Bubble(
42 Metadata::new(),
43 new_expr,
44 Box::new(Expression::And(Metadata::new(), bubble_constraints)),
45 )))
46}
47
48#[register_rule(("Bubble", 6000))]
50fn slice_to_bubble(expr: &Expression, symbols: &SymbolTable) -> ApplicationResult {
51 let Expression::UnsafeSlice(_, subject, indices) = expr else {
52 return Err(RuleNotApplicable);
53 };
54
55 let domain = subject
56 .domain_of(symbols)
57 .ok_or(ApplicationError::DomainError)?;
58
59 let Domain::DomainMatrix(_, index_domains) = domain else {
60 bug!("subject of a slice expression should have a matrix domain. subject: {:?}, with domain: {:?}", subject, domain);
61 };
62
63 assert_eq!(index_domains.len(),indices.len(),"in a slice expression, there should be the same number of indices as the subject has index domains");
64
65 let bubble_constraints = Box::new(into_matrix_expr![izip!(index_domains, indices)
67 .filter_map(|(domain, index)| {
68 index
69 .clone()
70 .map(|index| Expression::InDomain(Metadata::new(), Box::new(index.clone()), domain))
71 })
72 .collect_vec()]);
73
74 let new_expr = Box::new(Expression::SafeSlice(
75 Metadata::new(),
76 subject.clone(),
77 indices.clone(),
78 ));
79
80 Ok(Reduction::pure(Expression::Bubble(
81 Metadata::new(),
82 new_expr,
83 Box::new(Expression::And(Metadata::new(), bubble_constraints)),
84 )))
85}