1
use conjure_cp::ast::Metadata;
2
use conjure_cp::rule_engine::Reduction;
3

            
4
use conjure_cp::ast::AbstractLiteral;
5
use conjure_cp::ast::Atom;
6
use conjure_cp::ast::Expression as Expr;
7
use conjure_cp::ast::Literal;
8

            
9
use conjure_cp::ast::SymbolTable;
10
use conjure_cp::rule_engine::{
11
    ApplicationError::RuleNotApplicable, ApplicationResult, register_rule,
12
};
13

            
14
// turns an in expression into a w-inset expression where x is an integer decision variable
15
// and the set is a set of integers like:
16
// x in {1,2,3} => w-inset(x, [1,2,3])
17
#[register_rule(("Base", 1))]
18
fn in_set(expr: &Expr, _: &SymbolTable) -> ApplicationResult {
19
    match expr {
20
        Expr::In(_, a, b) => {
21
            let mut literals = Vec::new();
22

            
23
            if let Expr::Atomic(
24
                _,
25
                Atom::Literal(Literal::AbstractLiteral(AbstractLiteral::Set(c))),
26
            ) = b.as_ref()
27
            {
28
                for number in c {
29
                    literals.push(i32::try_from(number.clone()).unwrap());
30
                }
31
            }
32

            
33
            if literals.is_empty() {
34
                return Ok(Reduction::pure(false.into()));
35
            }
36
            if let Expr::Atomic(_, a) = a.as_ref() {
37
                Ok(Reduction::pure(Expr::MinionWInSet(
38
                    Metadata::new(),
39
                    a.clone(),
40
                    literals,
41
                )))
42
            } else {
43
                Err(RuleNotApplicable)
44
            }
45
        }
46
        _ => Err(RuleNotApplicable),
47
    }
48
}