Skip to main content

conjure_cp_core/
objective.rs

1//! Normalisation of optimisation objectives before rewriting.
2
3use crate::ast::{Atom, Expression, Metadata, Model, Moo, Reference};
4use crate::bug;
5
6/// Introduces an auxiliary find variable for a non-atomic optimisation objective and links it
7/// with an aux declaration constraint.
8///
9/// Objectives that are already atoms (for example `minimising z`) are left unchanged.
10pub fn introduce_objective_auxiliary(mut model: Model) -> Model {
11    let Some(objective) = model.objective.as_ref() else {
12        return model;
13    };
14
15    if matches!(&objective.expression, Expression::Atomic(_, _)) {
16        return model;
17    }
18
19    let expr = objective.expression.clone();
20
21    let Some(domain) = expr.domain_of() else {
22        bug!(
23            "objective expression has no domain and could not be introduced as an auxiliary variable: {expr}"
24        );
25    };
26
27    let mut symbols = model.symbols().clone();
28    let decl = symbols.gen_find_auxiliary(&domain);
29    let aux_reference = Expression::Atomic(Metadata::new(), Atom::new_ref(decl.clone()));
30    let aux_constraint =
31        Expression::AuxDeclaration(Metadata::new(), Reference::new(decl), Moo::new(expr));
32
33    model.symbols_mut().extend(symbols);
34    model.add_constraint(aux_constraint);
35    model
36        .objective
37        .as_mut()
38        .expect("objective should still be present")
39        .expression = aux_reference;
40
41    model
42}