mirror of
https://github.com/powdr-labs/powdr.git
synced 2026-01-09 14:48:16 -05:00
Booleanize changed constraints. (#3208)
The boolean extractor currently handles newly incoming algebraic constraints. Substitutions that are performed during solving can lead to constraints being boolean-extractable where we were not able to do boolean extraction before. This PR tries to perform boolean extraction on all constraints that potentially changed because of a substitution. --------- Co-authored-by: schaeff <thibaut@powdrlabs.com>
This commit is contained in:
@@ -317,6 +317,9 @@ impl<T: RuntimeConstant + Substitutable<V>, V: Clone + Hash + Ord + Eq>
|
||||
///
|
||||
/// Note this does NOT work properly if the variable is used inside a
|
||||
/// known SymbolicExpression.
|
||||
///
|
||||
/// It does not delete the occurrence of `variable` so that it can be used to check
|
||||
/// which constraints it used to occur in.
|
||||
pub fn substitute_by_unknown(&mut self, variable: &V, substitution: &GroupedExpression<T, V>) {
|
||||
let items = self
|
||||
.variable_occurrences
|
||||
@@ -464,6 +467,9 @@ where
|
||||
|
||||
/// Substitutes a variable with a known value in the whole system.
|
||||
/// This function also updates the queue accordingly.
|
||||
///
|
||||
/// It does not delete the occurrence of `variable` so that it can be used to check
|
||||
/// which constraints it used to occur in.
|
||||
pub fn substitute_by_unknown(&mut self, variable: &V, substitution: &GroupedExpression<T, V>) {
|
||||
self.constraint_system
|
||||
.substitute_by_unknown(variable, substitution);
|
||||
|
||||
@@ -17,6 +17,7 @@ use crate::utils::possible_concrete_values;
|
||||
use std::collections::{BTreeSet, HashMap, HashSet};
|
||||
use std::fmt::Display;
|
||||
use std::hash::Hash;
|
||||
use std::iter::once;
|
||||
|
||||
/// Given a list of constraints, tries to derive as many variable assignments as possible.
|
||||
///
|
||||
@@ -333,6 +334,7 @@ where
|
||||
+ Hash
|
||||
+ ExpressionConvertible<T::FieldType, V>
|
||||
+ Substitutable<V>,
|
||||
VD: VarDispenser<V>,
|
||||
{
|
||||
fn loop_until_no_progress(&mut self) -> Result<(), Error> {
|
||||
loop {
|
||||
@@ -524,10 +526,32 @@ where
|
||||
fn apply_assignment(&mut self, variable: &V, expr: &GroupedExpression<T, V>) -> bool {
|
||||
log::debug!("({variable} := {expr})");
|
||||
self.constraint_system.substitute_by_unknown(variable, expr);
|
||||
|
||||
let mut vars_to_boolean_constrain = vec![];
|
||||
let new_constraints = self
|
||||
.constraint_system
|
||||
.system()
|
||||
.constraints_referencing_variables(once(variable.clone()))
|
||||
.filter_map(|constr| match constr {
|
||||
ConstraintRef::AlgebraicConstraint(c) => Some(c),
|
||||
ConstraintRef::BusInteraction(_) => None,
|
||||
})
|
||||
.flat_map(|constr| {
|
||||
let (constr, new_var) = self
|
||||
.boolean_extractor
|
||||
.try_extract_boolean(constr, &mut || self.var_dispenser.next_boolean())?;
|
||||
vars_to_boolean_constrain.extend(new_var);
|
||||
Some(constr)
|
||||
})
|
||||
.collect_vec();
|
||||
for v in vars_to_boolean_constrain {
|
||||
self.add_range_constraint(&v, RangeConstraint::from_mask(1));
|
||||
}
|
||||
|
||||
self.add_algebraic_constraints(new_constraints);
|
||||
|
||||
self.assignments_to_return
|
||||
.push((variable.clone(), expr.clone()));
|
||||
// TODO we could check if the variable already has an assignment,
|
||||
// but usually it should not be in the system once it has been assigned.
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user