1
//! Lower sparse modelling rows to Minion's native short-table relation.
2
use conjure_cp::ast::{Expression as Expr, Literal, Metadata, Moo, SymbolTable, eval_constant};
3
use conjure_cp::rule_engine::{
4
    ApplicationError::RuleNotApplicable, ApplicationResult, RuleEffect, register_rule,
5
};
6

            
7
use crate::shared::utils::{checked_short_table_row, table_ordered_entries, table_rows};
8

            
9
/// Use native short tuples, introducing equality indicators for variable-valued cells.
10
#[register_rule("Minion", 4050, [ShortTable])]
11
1024
fn flatten_short_table(expr: &Expr, symbols: &SymbolTable) -> ApplicationResult {
12
1024
    let Expr::ShortTable(_, inputs, rows) = expr else {
13
947
        return Err(RuleNotApplicable);
14
    };
15
77
    let inputs = table_ordered_entries(inputs).ok_or(RuleNotApplicable)?;
16
77
    let rows = table_rows(rows).ok_or(RuleNotApplicable)?;
17
77
    let width = inputs.len();
18
77
    let mut symbols = symbols.clone();
19
77
    let mut top = vec![];
20
77
    let mut inputs = inputs
21
77
        .into_iter()
22
175
        .map(|input| super::flatten_expression_to_atom(input, &mut symbols, &mut top))
23
        .collect::<Result<Vec<_>, _>>()?;
24
77
    let mut short_rows = Vec::with_capacity(rows.len());
25
77
    for row in rows {
26
133
        let pairs = checked_short_table_row(&row, width).ok_or(RuleNotApplicable)?;
27
133
        let mut short_row = Vec::with_capacity(pairs.len());
28
133
        for (position, value) in pairs {
29
238
            match eval_constant(&value) {
30
231
                Some(Literal::Int(value)) => short_row.push((position, value)),
31
                Some(Literal::Bool(value)) => short_row.push((position, i32::from(value))),
32
                Some(_) => return Err(RuleNotApplicable),
33
                None => {
34
7
                    let equality = Expr::Eq(
35
7
                        Metadata::new(),
36
7
                        Moo::new(Expr::Atomic(Metadata::new(), inputs[position].clone())),
37
7
                        Moo::new(value.clone()),
38
7
                    );
39
                    let indicator =
40
7
                        super::flatten_expression_to_atom(equality, &mut symbols, &mut top)?;
41
7
                    short_row.push((inputs.len(), 1));
42
7
                    inputs.push(indicator);
43
                }
44
            }
45
        }
46
133
        short_rows.push(short_row);
47
    }
48
77
    Ok(RuleEffect::new(
49
77
        Expr::FlatShortTable(Metadata::new(), inputs, short_rows),
50
77
        top,
51
77
        symbols,
52
77
    ))
53
1024
}