diff --git a/compilers/concrete-optimizer/concrete-optimizer-cpp/src/concrete-optimizer.rs b/compilers/concrete-optimizer/concrete-optimizer-cpp/src/concrete-optimizer.rs index 1e61cc33e0..c1fd705749 100644 --- a/compilers/concrete-optimizer/concrete-optimizer-cpp/src/concrete-optimizer.rs +++ b/compilers/concrete-optimizer/concrete-optimizer-cpp/src/concrete-optimizer.rs @@ -318,6 +318,7 @@ fn convert_to_circuit_solution(sol: &ffi::DagSolution, dag: &OperationDag) -> ff global_p_error: sol.global_p_error, is_feasible, error_msg, + error_nodes: vec![], } } @@ -332,6 +333,7 @@ impl From for ffi::CircuitSolution { global_p_error: v.global_p_error, is_feasible: v.is_feasible, error_msg: v.error_msg, + error_nodes: v.error_nodes, } } } @@ -950,6 +952,7 @@ mod ffi { pub global_p_error: f64, pub is_feasible: bool, pub error_msg: String, + pub error_nodes: Vec, } } diff --git a/compilers/concrete-optimizer/concrete-optimizer-cpp/src/cpp/concrete-optimizer.cpp b/compilers/concrete-optimizer/concrete-optimizer-cpp/src/cpp/concrete-optimizer.cpp index 77a08cc307..081c73c79d 100644 --- a/compilers/concrete-optimizer/concrete-optimizer-cpp/src/cpp/concrete-optimizer.cpp +++ b/compilers/concrete-optimizer/concrete-optimizer-cpp/src/cpp/concrete-optimizer.cpp @@ -1241,6 +1241,7 @@ struct CircuitSolution final { double global_p_error; bool is_feasible; ::rust::String error_msg; + ::rust::Vec<::std::size_t> error_nodes; ::rust::String dump() const noexcept; ::rust::String short_dump() const noexcept; diff --git a/compilers/concrete-optimizer/concrete-optimizer-cpp/src/cpp/concrete-optimizer.hpp b/compilers/concrete-optimizer/concrete-optimizer-cpp/src/cpp/concrete-optimizer.hpp index 4636598f50..59014c62e8 100644 --- a/compilers/concrete-optimizer/concrete-optimizer-cpp/src/cpp/concrete-optimizer.hpp +++ b/compilers/concrete-optimizer/concrete-optimizer-cpp/src/cpp/concrete-optimizer.hpp @@ -1222,6 +1222,7 @@ struct CircuitSolution final { double global_p_error; bool is_feasible; ::rust::String error_msg; + ::rust::Vec<::std::size_t> error_nodes; ::rust::String dump() const noexcept; ::rust::String short_dump() const noexcept; diff --git a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/analyze.rs b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/analyze.rs index bf1450803e..b30266a9de 100644 --- a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/analyze.rs +++ b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/analyze.rs @@ -330,6 +330,7 @@ fn variance_constraint( nb_constraints, safe_variance_bound, variance, + nodes: vec![op_i], } } diff --git a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/feasible.rs b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/feasible.rs index f0bf81fc0c..a6b88fb4c6 100644 --- a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/feasible.rs +++ b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/feasible.rs @@ -213,7 +213,7 @@ impl Feasible { } let compress = |c: &VarianceConstraint| VarianceConstraint { variance: c.variance.compress(&detect_used), - ..(*c) + ..c.clone() }; let constraints = self.constraints.iter().map(compress).collect(); let undominated_constraints = self.undominated_constraints.iter().map(compress).collect(); diff --git a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/keys_spec.rs b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/keys_spec.rs index eca3009ebe..179f619270 100644 --- a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/keys_spec.rs +++ b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/keys_spec.rs @@ -117,16 +117,18 @@ pub struct CircuitSolution { pub crt_decomposition: Vec, // empty in native case pub is_feasible: bool, pub error_msg: String, + pub error_nodes: Vec } impl CircuitSolution { - pub fn no_solution(error_msg: impl Into) -> Self { + pub fn no_solution(error_msg: impl Into, error_nodes: Vec) -> Self { Self { is_feasible: false, complexity: f64::INFINITY, p_error: 1.0, global_p_error: 1.0, error_msg: error_msg.into(), + error_nodes: error_nodes, ..Self::default() } } @@ -216,6 +218,7 @@ impl CircuitSolution { crt_decomposition: sol.crt_decomposition, is_feasible: true, error_msg, + error_nodes: vec![], } } @@ -260,6 +263,7 @@ impl CircuitSolution { global_p_error: sol.global_p_error, is_feasible, error_msg, + error_nodes: vec![], }; } let small_key = SecretLweKey { @@ -315,6 +319,7 @@ impl CircuitSolution { global_p_error: sol.global_p_error, is_feasible, error_msg, + error_nodes: vec![], } } } diff --git a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/optimize/mod.rs b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/optimize/mod.rs index 2786ec584f..18062aff7e 100644 --- a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/optimize/mod.rs +++ b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/optimize/mod.rs @@ -60,6 +60,7 @@ pub struct Parameters { pub p_error: f64, pub global_p_error: f64, pub complexity: f64, + pub worst_nodes: Vec, } #[derive(Debug, Clone)] @@ -778,6 +779,8 @@ fn optimize_macro( continue; } best_partition_p_error = partition_p_error; + // retain non satisfied constraint + let (_, _, worst_constraint) = feasible.worst_constraint(&operations.variance); let p_error = feasible.p_error(&operations.variance); let global_p_error = feasible.global_p_error(&operations.variance); let mut pbs = init_parameters.micro_params.pbs.clone(); @@ -795,6 +798,7 @@ fn optimize_macro( macro_params, is_lower_bound: true, is_feasible: false, + worst_nodes: worst_constraint.nodes.clone(), }; continue; } @@ -880,6 +884,7 @@ fn optimize_macro( macro_params, is_lower_bound, is_feasible: true, + worst_nodes: vec![], }; } else { // the macro parameters are feasible @@ -941,6 +946,7 @@ pub fn optimize( p_error: 1.0, global_p_error: 1.0, complexity: f64::INFINITY, + worst_nodes: vec![], }; let mut params = init_parameters; @@ -973,7 +979,7 @@ pub fn optimize( params = new_params; if !params.is_feasible { if nb_partitions == 1 { - return Err(NoParametersFound); + return Err(NoParametersFound(params.worst_nodes)); } if DEBUG { eprintln!( @@ -1021,7 +1027,7 @@ pub fn optimize( fix_point = params.clone(); } if best_params.is_none() { - return Err(NoParametersFound); + return Err(NoParametersFound(params.worst_nodes)); } let best_params = best_params.unwrap(); sanity_check( @@ -1167,6 +1173,7 @@ pub fn optimize_to_circuit_solution( if config.composable { return keys_spec::CircuitSolution::no_solution( NotComposable("No luts in the circuit.".into()).to_string(), + vec![], ); } let nb_instr = dag.operators.len(); @@ -1174,7 +1181,8 @@ pub fn optimize_to_circuit_solution( { return keys_spec::CircuitSolution::from_native_solution(sol, nb_instr); } - return keys_spec::CircuitSolution::no_solution(NoParametersFound.to_string()); + let err = NoParametersFound(vec![]); + return keys_spec::CircuitSolution::no_solution(err.to_string(), err.error_nodes()); } let default_partition = 0; let dag_and_params = optimize( @@ -1187,7 +1195,7 @@ pub fn optimize_to_circuit_solution( ); #[allow(clippy::option_if_let_else)] match dag_and_params { - Err(e) => keys_spec::CircuitSolution::no_solution(e.to_string()), + Err(e) => keys_spec::CircuitSolution::no_solution(e.to_string(), e.error_nodes()), Ok((dag, params)) => { let ext_keys = keys_spec::ExpandedCircuitKeys::of(¶ms); let instructions_keys = analyze::original_instrs_partition(&dag, &ext_keys); @@ -1209,6 +1217,7 @@ pub fn optimize_to_circuit_solution( global_p_error: params.global_p_error, is_feasible: true, error_msg: String::default(), + error_nodes: vec![], } } } diff --git a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/optimize_generic.rs b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/optimize_generic.rs index 98d9e0865c..fd3c5a5a4d 100644 --- a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/optimize_generic.rs +++ b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/optimize_generic.rs @@ -35,6 +35,7 @@ fn crt_optimize( if analyze::has_round(dag) || analyze::has_unsafe_cast(dag) { return CircuitSolution::no_solution( "Crt does not support round/reinterpret_precision operator", + vec![], // TODO: report round and reinterpret ); } // TODO: dag to params let max_precision = max_precision(dag); diff --git a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/variance_constraint.rs b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/variance_constraint.rs index adbe3bec54..379b129e27 100644 --- a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/variance_constraint.rs +++ b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/variance_constraint.rs @@ -11,6 +11,7 @@ pub struct VarianceConstraint { pub nb_constraints: u64, pub safe_variance_bound: f64, pub variance: SymbolicVariance, + pub nodes: Vec, } impl fmt::Display for VarianceConstraint { diff --git a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/mod.rs b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/mod.rs index 0ccf0061bc..0672062055 100644 --- a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/mod.rs +++ b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/mod.rs @@ -7,14 +7,23 @@ pub mod wop_atomic_pattern; #[derive(Clone, Debug, PartialEq, Eq)] pub enum Err { NotComposable(String), - NoParametersFound, + NoParametersFound(Vec), +} + +impl Err { + fn error_nodes(&self) -> Vec { + match self { + Self::NotComposable(_details) => vec![], + Self::NoParametersFound(nodes) => nodes.clone(), + } + } } impl std::fmt::Display for Err { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { Self::NotComposable(details) => write!(f, "Program can not be composed: {details}"), - Self::NoParametersFound => write!(f, "No crypto parameters could be found"), + Self::NoParametersFound(_) => write!(f, "No crypto parameters could be found"), } } } diff --git a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/wop_atomic_pattern/optimize.rs b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/wop_atomic_pattern/optimize.rs index 776f790208..a00af18168 100644 --- a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/wop_atomic_pattern/optimize.rs +++ b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/wop_atomic_pattern/optimize.rs @@ -548,6 +548,7 @@ pub fn optimize_to_circuit_solution( let Ok(coprimes) = crt_decomposition::default_coprimes(precision as Precision) else { return keys_spec::CircuitSolution::no_solution( "Crt decomposition is not unknown for {precision}:bits", + vec![], ); }; let n_functions = 1; @@ -569,7 +570,7 @@ pub fn optimize_to_circuit_solution( } else { keys_spec::CircuitSolution { crt_decomposition: coprimes, - ..keys_spec::CircuitSolution::no_solution("No crypto parameters") + ..keys_spec::CircuitSolution::no_solution("No crypto parameters", vec![]) } } }