Lines
0 %
Functions
use conjure_cp::ast::{Atom, Expression as Expr, GroundDomain, Name, SymbolTable, matrix};
use conjure_cp::into_matrix_expr;
use conjure_cp::rule_engine::{
ApplicationError::RuleNotApplicable, ApplicationResult, Reduction, register_rule,
};
use itertools::Itertools;
#[register_rule(("Base", 8000))]
fn flatten_matrix(expr: &Expr, symbols: &SymbolTable) -> ApplicationResult {
if let Expr::Flatten(_, n, matrix) = expr {
if n.is_some() {
// TODO handle flatten with n dimension option
return Err(RuleNotApplicable);
}
let Expr::Atomic(_, Atom::Reference(decl)) = matrix.as_ref() else {
let Name::WithRepresentation(name, reprs) = &decl.name() as &Name else {
if reprs.first().is_none_or(|x| x.as_str() != "matrix_to_atom") {
let decl = symbols.lookup(name.as_ref()).unwrap();
let repr = symbols
.get_representation(name.as_ref(), &["matrix_to_atom"])
.unwrap()[0]
.clone();
// resolve index domains so that we can enumerate them later
let dom = decl.resolved_domain().ok_or(RuleNotApplicable)?;
let GroundDomain::Matrix(_, index_domains) = dom.as_ref() else {
let Ok(matrix_values) = repr.expression_down(symbols) else {
let flat_values = matrix::enumerate_indices(index_domains.clone())
.map(|i| {
matrix_values[&Name::Represented(Box::new((
name.as_ref().clone(),
"matrix_to_atom".into(),
i.iter().join("_").into(),
)))]
.clone()
})
.collect_vec();
return Ok(Reduction::pure(into_matrix_expr![flat_values]));
Err(RuleNotApplicable)