conjure_core/rules/normalisers/lt_gt.rs
1//! Normalising rules for Lt and Gt.
2//!
3//! For Minion, these normalise into Leq and Geq respectively.
4
5use conjure_macros::register_rule;
6
7use crate::{
8 ast::{Atom, Expression as Expr, Literal as Lit, SymbolTable},
9 metadata::Metadata,
10 rule_engine::{ApplicationError::RuleNotApplicable, ApplicationResult, Reduction},
11};
12
13/// Converts Lt to Leq
14///
15/// Minion only for now, but this could be useful for other solvers too.
16///
17/// # Rationale
18///
19/// Minion supports Leq directly in some constraints, such as SumLeq, WeightedSumLeq, ...
20/// This transformation makes Lt work with these constraints too without needing special
21/// cases in the Minion conversion rules.
22#[register_rule(("Minion", 8400))]
23fn lt_to_leq(expr: &Expr, _: &SymbolTable) -> ApplicationResult {
24 let Expr::Lt(_, lhs, rhs) = expr.clone() else {
25 return Err(RuleNotApplicable);
26 };
27
28 // add to rhs so that this is in the correct form for ineq ( x <= y + k)
29 Ok(Reduction::pure(Expr::Leq(
30 Metadata::new(),
31 lhs,
32 Box::new(Expr::Sum(
33 Metadata::new(),
34 vec![
35 *rhs,
36 Expr::Atomic(Metadata::new(), Atom::Literal(Lit::Int(-1))),
37 ],
38 )),
39 )))
40}
41
42/// Converts Gt to Geq
43///
44/// Minion only for now, but this could be useful for other solvers too.
45///
46/// # Rationale
47///
48/// Minion supports Geq directly in some constraints, such as SumGeq, WeightedSumGeq, ...
49/// This transformation makes Gt work with these constraints too without needing special
50/// cases in the Minion conversion rules.
51#[register_rule(("Minion", 8400))]
52fn gt_to_geq(expr: &Expr, _: &SymbolTable) -> ApplicationResult {
53 let Expr::Gt(_, lhs, total) = expr.clone() else {
54 return Err(RuleNotApplicable);
55 };
56
57 Ok(Reduction::pure(Expr::Geq(
58 Metadata::new(),
59 Box::new(Expr::Sum(
60 Metadata::new(),
61 vec![
62 *lhs,
63 Expr::Atomic(Metadata::new(), Atom::Literal(Lit::Int(-1))),
64 ],
65 )),
66 total,
67 )))
68}