1
//! Generic normalising rules for associative-commutative operators.
2

            
3
use std::collections::VecDeque;
4
use std::mem::Discriminant;
5

            
6
use conjure_cp::ast::{Expression as Expr, SymbolTable};
7
use conjure_cp::rule_engine::{
8
    ApplicationError::RuleNotApplicable, ApplicationResult, Reduction, register_rule,
9
};
10
use uniplate::Biplate;
11

            
12
/// Normalises associative_commutative operations.
13
///
14
/// For now, this just removes nested expressions by associativity.
15
///
16
/// ```text
17
/// v(v(a,b,...),c,d,...) ~> v(a,b,c,d)
18
/// where v is an AC vector operator
19
/// ```
20
#[register_rule("Base", 8900, [And, Or, Product, Sum])]
21
2436492
fn normalise_associative_commutative(expr: &Expr, _: &SymbolTable) -> ApplicationResult {
22
2436492
    if !expr.is_associative_commutative_operator() {
23
2233805
        return Err(RuleNotApplicable);
24
202687
    }
25

            
26
    // remove nesting deeply
27
600662
    fn recurse_deeply(
28
600662
        root_discriminant: Discriminant<Expr>,
29
600662
        expr: Expr,
30
600662
        changed: &mut bool,
31
600662
    ) -> Vec<Expr> {
32
        // if expr a different expression type, stop recursing
33
600662
        if std::mem::discriminant(&expr) != root_discriminant {
34
411359
            return vec![expr];
35
189303
        }
36

            
37
189303
        let child_vecs: VecDeque<Vec<Expr>> = expr.children_bi();
38

            
39
        // empty expression
40
189303
        if child_vecs.is_empty() {
41
1900
            return vec![expr];
42
187403
        }
43

            
44
        // go deeper
45
187403
        let children = child_vecs[0].clone();
46
187403
        let old_len = children.len();
47

            
48
187403
        let new_children = children
49
187403
            .into_iter()
50
415539
            .flat_map(|child| recurse_deeply(root_discriminant, child, changed))
51
187403
            .collect::<Vec<_>>();
52
187403
        if new_children.len() != old_len {
53
2200
            *changed = true;
54
185203
        }
55

            
56
187403
        new_children
57
600662
    }
58

            
59
202687
    let child_vecs: VecDeque<Vec<Expr>> = expr.children_bi();
60
202687
    if child_vecs.is_empty() {
61
17564
        return Err(RuleNotApplicable);
62
185123
    }
63

            
64
185123
    let mut changed = false;
65
185123
    let new_children = recurse_deeply(std::mem::discriminant(expr), expr.clone(), &mut changed);
66

            
67
185123
    if !changed {
68
183153
        return Err(RuleNotApplicable);
69
1970
    }
70

            
71
1970
    let new_expr = expr.with_children_bi(vec![new_children].into());
72

            
73
1970
    Ok(Reduction::pure(new_expr))
74
2436492
}