diff --git a/compilers/concrete-compiler/compiler/include/concretelang/Common/Keysets.h b/compilers/concrete-compiler/compiler/include/concretelang/Common/Keysets.h index 271254d1ae..6e2382f980 100644 --- a/compilers/concrete-compiler/compiler/include/concretelang/Common/Keysets.h +++ b/compilers/concrete-compiler/compiler/include/concretelang/Common/Keysets.h @@ -98,8 +98,11 @@ class KeysetCache { }; Message keysetInfoFromVirtualCircuit( - std::vector partitions, - bool generate_fks, std::optional options); + std::vector + internalPartitions, + std::vector + externalPartitions, + std::optional options); } // namespace keysets } // namespace concretelang diff --git a/compilers/concrete-compiler/compiler/lib/Bindings/Python/CompilerAPIModule.cpp b/compilers/concrete-compiler/compiler/lib/Bindings/Python/CompilerAPIModule.cpp index d699427966..13d4ef6a3f 100644 --- a/compilers/concrete-compiler/compiler/lib/Bindings/Python/CompilerAPIModule.cpp +++ b/compilers/concrete-compiler/compiler/lib/Bindings/Python/CompilerAPIModule.cpp @@ -647,6 +647,12 @@ void mlir::concretelang::python::populateCompilerAPISubmodule( }, "Enable or disable overflow detection during simulation.", arg("enable_overflow_detection")) + .def( + "get_optimizer_options", + [](CompilationOptions &options) -> concrete_optimizer::Options { + return options_from_config(options.optimizerConfig); + }, + "Returns the associated optimizer configuration") .doc() = "Holds different flags and options of the compilation process."; pybind11::enum_(m, @@ -1069,18 +1075,39 @@ void mlir::concretelang::python::populateCompilerAPISubmodule( // ------------------------------------------------------------------------------// // PARTITION DEFINITION // // ------------------------------------------------------------------------------// - // - pybind11::class_( - m, "PartitionDefinition") + pybind11::class_( + m, "InternalPartitionDefinition") .def(init([](uint8_t precision, double norm2) - -> concrete_optimizer::utils::PartitionDefinition { - return concrete_optimizer::utils::PartitionDefinition{precision, - norm2}; + -> concrete_optimizer::utils::InternalPartitionDefinition { + return concrete_optimizer::utils::InternalPartitionDefinition{ + precision, norm2}; }), arg("precision"), arg("norm2")) .doc() = "Definition of a partition (in terms of precision in bits and " "norm2 in value)."; + // ------------------------------------------------------------------------------// + // EXTERNAL PARTITION // + // ------------------------------------------------------------------------------// + pybind11::class_( + m, "ExternalPartitionDefinition") + .def(init([](std::string name, uint64_t macroLog2PolynomialSize, + uint64_t macroGlweDimension, uint64_t macroInternalDim, + uint64_t pbsLevel, uint64_t pbsBaseLog) + -> concrete_optimizer::utils::ExternalPartitionDefinition { + return concrete_optimizer::utils::ExternalPartitionDefinition{ + name, + macroLog2PolynomialSize, + macroGlweDimension, + macroInternalDim, + pbsLevel, + pbsBaseLog}; + }), + arg("name"), arg("macro_log2_polynomial_size"), + arg("macro_glwe_dimension"), arg("macro_internal_dim"), + arg("pbs_level"), arg("pbs_base_log")) + .doc() = "Definition of an external partition."; + // ------------------------------------------------------------------------------// // KEYSET INFO // // ------------------------------------------------------------------------------// @@ -1088,16 +1115,17 @@ void mlir::concretelang::python::populateCompilerAPISubmodule( pybind11::class_(m, "KeysetInfo") .def_static( "generate_virtual", - [](std::vector - partitions, - bool generateFks, + [](std::vector + internalPartitions, + std::vector + externalPartitions, std::optional options) -> KeysetInfo { - if (partitions.size() < 2) { + if (internalPartitions.size() + externalPartitions.size() < 2) { throw std::runtime_error("Need at least two partition defs to " "generate a virtual keyset info."); } return ::concretelang::keysets::keysetInfoFromVirtualCircuit( - partitions, generateFks, options); + internalPartitions, externalPartitions, options); }, arg("partition_defs"), arg("generate_fks"), arg("options") = std::nullopt, diff --git a/compilers/concrete-compiler/compiler/lib/Common/Keysets.cpp b/compilers/concrete-compiler/compiler/lib/Common/Keysets.cpp index 8a5964ed27..830c854811 100644 --- a/compilers/concrete-compiler/compiler/lib/Common/Keysets.cpp +++ b/compilers/concrete-compiler/compiler/lib/Common/Keysets.cpp @@ -559,14 +559,22 @@ generateKeysetInfoFromParameters(CircuitKeys parameters, } Message keysetInfoFromVirtualCircuit( - std::vector partitionDefs, - bool generateFks, std::optional options) { + std::vector partitionDefs, + std::vector + externalPartitions, + std::optional options) { - rust::Vec rustPartitionDefs{}; + rust::Vec rustPartitionDefs{}; for (auto def : partitionDefs) { rustPartitionDefs.push_back(def); } + rust::Vec + rustExternalPartitions{}; + for (auto def : externalPartitions) { + rustExternalPartitions.push_back(def); + } + auto defaultOptions = concrete_optimizer::Options{}; defaultOptions.security_level = 128; defaultOptions.maximum_acceptable_error_probability = 0.000063342483999973; @@ -577,7 +585,7 @@ Message keysetInfoFromVirtualCircuit( auto opts = options.value_or(defaultOptions); auto parameters = concrete_optimizer::utils::generate_virtual_keyset_info( - rustPartitionDefs, generateFks, opts); + rustPartitionDefs, rustExternalPartitions, opts); return generateKeysetInfoFromParameters(parameters, opts); } diff --git a/compilers/concrete-compiler/compiler/lib/Dialect/FHE/Analysis/ConcreteOptimizer.cpp b/compilers/concrete-compiler/compiler/lib/Dialect/FHE/Analysis/ConcreteOptimizer.cpp index fe18267479..66219343ab 100644 --- a/compilers/concrete-compiler/compiler/lib/Dialect/FHE/Analysis/ConcreteOptimizer.cpp +++ b/compilers/concrete-compiler/compiler/lib/Dialect/FHE/Analysis/ConcreteOptimizer.cpp @@ -274,8 +274,8 @@ struct FunctionToDag { options, logPolySize, glweDim, lweDim, pbsLevel, pbsLogBase); auto name = partitionAttr.getName().getValue().str(); // TODO: max_variance vs variance - return concrete_optimizer::utils::get_external_partition( - name, logPolySize, glweDim, lweDim, max_variance, max_variance); + return concrete_optimizer::utils::ExternalPartition{ + name, logPolySize, glweDim, lweDim, max_variance, max_variance}; }; if (auto srcPartitionAttr = @@ -287,14 +287,14 @@ struct FunctionToDag { auto partition = partitionBuilder(srcPartitionAttr); index[val] = dagBuilder.add_change_partition_with_src( - encrypted_input, *partition, *loc_to_location(val.getLoc())); + encrypted_input, partition, *loc_to_location(val.getLoc())); } else if (auto destPartitionAttr = op.getAttrOfType( "dest")) { auto partition = partitionBuilder(destPartitionAttr); index[val] = dagBuilder.add_change_partition_with_dst( - encrypted_input, *partition, *loc_to_location(val.getLoc())); + encrypted_input, partition, *loc_to_location(val.getLoc())); } else { assert(false && "ChangePartition: one of src or dest partitions need to be set"); diff --git a/compilers/concrete-compiler/compiler/lib/Support/V0Parameters.cpp b/compilers/concrete-compiler/compiler/lib/Support/V0Parameters.cpp index ccf5ed30b9..a7035556a4 100644 --- a/compilers/concrete-compiler/compiler/lib/Support/V0Parameters.cpp +++ b/compilers/concrete-compiler/compiler/lib/Support/V0Parameters.cpp @@ -391,6 +391,8 @@ getSolution(optimizer::Description &descr, ProgramCompilationFeedback &feedback, if (sol.is_feasible || !config.composition_rules.empty()) { displayOptimizer(sol, descr, config); return toCompilerSolution(sol, feedback, config); + } else { + assert(false); } } config.strategy = optimizer::Strategy::DAG_MONO; 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 7c1e784b41..8c7c9e605e 100644 --- a/compilers/concrete-optimizer/concrete-optimizer-cpp/src/concrete-optimizer.rs +++ b/compilers/concrete-optimizer/concrete-optimizer-cpp/src/concrete-optimizer.rs @@ -1,7 +1,7 @@ -#![allow(clippy::boxed_local)] -#![allow(clippy::too_many_arguments)] +// #![allow(clippy::boxed_local)] +// #![allow(clippy::too_many_arguments)] -use core::panic; +// use core::panic; use concrete_optimizer::computing_cost::cpu::CpuComplexity; use concrete_optimizer::config; @@ -16,7 +16,9 @@ use concrete_optimizer::optimization::dag::multi_parameters::optimize::{ KeysetRestriction, MacroParameters, NoSearchSpaceRestriction, RangeRestriction, SearchSpaceRestriction, }; -use concrete_optimizer::optimization::dag::multi_parameters::partition_cut::PartitionCut; +use concrete_optimizer::optimization::dag::multi_parameters::partition_cut::{ + ExternalPartition, PartitionCut, +}; use concrete_optimizer::optimization::dag::multi_parameters::virtual_circuit::generate_virtual_parameters; use concrete_optimizer::optimization::dag::multi_parameters::{keys_spec, PartitionIndex}; use concrete_optimizer::optimization::dag::solo_key::optimize_generic::{ @@ -62,35 +64,6 @@ fn caches_from(options: &ffi::Options) -> decomposition::PersistDecompCaches { ) } -#[derive(Clone)] -pub struct ExternalPartition( - concrete_optimizer::optimization::dag::multi_parameters::partition_cut::ExternalPartition, -); - -pub fn get_external_partition( - name: String, - log2_polynomial_size: u64, - glwe_dimension: u64, - internal_dim: u64, - max_variance: f64, - variance: f64, -) -> Box { - Box::new(ExternalPartition( - concrete_optimizer::optimization::dag::multi_parameters::partition_cut::ExternalPartition { - name, - macro_params: MacroParameters { - glwe_params: GlweParameters { - log2_polynomial_size, - glwe_dimension, - }, - internal_dim, - }, - max_variance, - variance, - }, - )) -} - pub fn get_noise_br( options: &ffi::Options, log2_polynomial_size: u64, @@ -852,13 +825,13 @@ impl DagBuilder<'_> { fn add_change_partition_with_src( &mut self, input: ffi::OperatorIndex, - src_partition: &ExternalPartition, + src_partition: &ffi::ExternalPartition, location: &Location, ) -> ffi::OperatorIndex { self.0 .add_change_partition( input.into(), - Some(src_partition.0.clone()), + Some(src_partition.clone().into()), None, location.0.clone(), ) @@ -868,14 +841,14 @@ impl DagBuilder<'_> { fn add_change_partition_with_dst( &mut self, input: ffi::OperatorIndex, - dst_partition: &ExternalPartition, + dst_partition: &ffi::ExternalPartition, location: &Location, ) -> ffi::OperatorIndex { self.0 .add_change_partition( input.into(), None, - Some(dst_partition.0.clone()), + Some(dst_partition.clone().into()), location.0.clone(), ) .into() @@ -915,8 +888,8 @@ fn location_from_string(string: &str) -> Box { } fn generate_virtual_keyset_info( - inputs: Vec, - generate_fks: bool, + internal_partitions: Vec, + external_partitions: Vec, options: &ffi::Options, ) -> ffi::CircuitKeys { let config = Config { @@ -927,14 +900,18 @@ fn generate_virtual_keyset_info( fft_precision: options.fft_precision, complexity_model: &CpuComplexity::default(), }; + generate_virtual_parameters( - inputs + internal_partitions .into_iter() .map( - |ffi::PartitionDefinition { precision, norm2 }| concrete_optimizer::optimization::dag::multi_parameters::virtual_circuit::PartitionDefinition { precision, norm2 }, + |ffi::InternalPartitionDefinition { precision, norm2 }| concrete_optimizer::optimization::dag::multi_parameters::virtual_circuit::InternalPartition { precision, norm2 }, ) .collect(), - generate_fks, + external_partitions.into_iter().map(|def| { + let noise = get_noise_br(options, def.log2_polynomial_size, def.glwe_dimension, def.internal_dim, def.pbs_level, def.pbs_base_log); + ExternalPartition { name: def.name, macro_params: MacroParameters { glwe_params: GlweParameters { log2_polynomial_size: def.log2_polynomial_size, glwe_dimension: def.glwe_dimension }, internal_dim: def.internal_dim } , max_variance: noise, variance: noise } + }).collect(), config ) .into() @@ -975,6 +952,24 @@ impl Into for ffi::Encoding { } } +#[allow(clippy::from_over_into)] +impl Into for ffi::ExternalPartition { + fn into(self) -> ExternalPartition { + ExternalPartition { + name: self.name, + macro_params: MacroParameters { + glwe_params: GlweParameters { + log2_polynomial_size: self.macro_log2_polynomial_size, + glwe_dimension: self.macro_glwe_dimension, + }, + internal_dim: self.macro_internal_dim, + }, + max_variance: self.max_variance, + variance: self.variance, + } + } +} + #[allow( unused_must_use, clippy::needless_lifetimes, @@ -1000,8 +995,6 @@ mod ffi { type Location; - type ExternalPartition; - #[namespace = "concrete_optimizer::utils"] fn location_unknown() -> Box; @@ -1010,21 +1003,11 @@ mod ffi { #[namespace = "concrete_optimizer::utils"] fn generate_virtual_keyset_info( - partitions: Vec, - generate_fks: bool, + internal_partitions: Vec, + external_partitions: Vec, options: &Options, ) -> CircuitKeys; - #[namespace = "concrete_optimizer::utils"] - fn get_external_partition( - name: String, - log2_polynomial_size: u64, - glwe_dimension: u64, - internal_dim: u64, - max_variance: f64, - variance: f64, - ) -> Box; - #[namespace = "concrete_optimizer::utils"] fn get_noise_br( options: &Options, @@ -1396,10 +1379,32 @@ mod ffi { #[namespace = "concrete_optimizer::utils"] #[derive(Debug, Clone)] - pub struct PartitionDefinition { + pub struct InternalPartitionDefinition { pub precision: u8, pub norm2: f64, } + + #[namespace = "concrete_optimizer::utils"] + #[derive(Debug, Clone)] + pub struct ExternalPartitionDefinition { + pub name: String, + pub log2_polynomial_size: u64, + pub glwe_dimension: u64, + pub internal_dim: u64, + pub pbs_level: u64, + pub pbs_base_log: u64, + } + + #[namespace = "concrete_optimizer::utils"] + #[derive(Debug, Clone)] + pub struct ExternalPartition { + pub name: String, + pub macro_log2_polynomial_size: u64, + pub macro_glwe_dimension: u64, + pub macro_internal_dim: u64, + pub max_variance: f64, + pub variance: f64, + } } fn processing_unit(options: &ffi::Options) -> ProcessingUnit { 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 9d00ce3875..4a216e4a1f 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 @@ -952,7 +952,6 @@ namespace concrete_optimizer { struct Dag; struct DagBuilder; struct Location; - struct ExternalPartition; struct Weights; enum class Encoding : ::std::uint8_t; enum class MultiParamStrategy : ::std::uint8_t; @@ -982,7 +981,9 @@ namespace concrete_optimizer { struct KeysetRestriction; } namespace utils { - struct PartitionDefinition; + struct InternalPartitionDefinition; + struct ExternalPartitionDefinition; + struct ExternalPartition; } } @@ -1022,8 +1023,8 @@ struct DagBuilder final : public ::rust::Opaque { ::concrete_optimizer::dag::OperatorIndex add_max_noise(::rust::Slice<::concrete_optimizer::dag::OperatorIndex const> inputs, ::rust::Slice<::std::uint64_t const> out_shape, ::concrete_optimizer::Location const &location) noexcept; ::concrete_optimizer::dag::OperatorIndex add_round_op(::concrete_optimizer::dag::OperatorIndex input, ::std::uint8_t rounded_precision, ::concrete_optimizer::Location const &location) noexcept; ::concrete_optimizer::dag::OperatorIndex add_unsafe_cast_op(::concrete_optimizer::dag::OperatorIndex input, ::std::uint8_t rounded_precision, ::concrete_optimizer::Location const &location) noexcept; - ::concrete_optimizer::dag::OperatorIndex add_change_partition_with_src(::concrete_optimizer::dag::OperatorIndex input, ::concrete_optimizer::ExternalPartition const &src_partition, ::concrete_optimizer::Location const &location) noexcept; - ::concrete_optimizer::dag::OperatorIndex add_change_partition_with_dst(::concrete_optimizer::dag::OperatorIndex input, ::concrete_optimizer::ExternalPartition const &dst_partition, ::concrete_optimizer::Location const &location) noexcept; + ::concrete_optimizer::dag::OperatorIndex add_change_partition_with_src(::concrete_optimizer::dag::OperatorIndex input, ::concrete_optimizer::utils::ExternalPartition const &src_partition, ::concrete_optimizer::Location const &location) noexcept; + ::concrete_optimizer::dag::OperatorIndex add_change_partition_with_dst(::concrete_optimizer::dag::OperatorIndex input, ::concrete_optimizer::utils::ExternalPartition const &dst_partition, ::concrete_optimizer::Location const &location) noexcept; void tag_operator_as_output(::concrete_optimizer::dag::OperatorIndex op) noexcept; ~DagBuilder() = delete; @@ -1050,20 +1051,6 @@ struct Location final : public ::rust::Opaque { }; #endif // CXXBRIDGE1_STRUCT_concrete_optimizer$Location -#ifndef CXXBRIDGE1_STRUCT_concrete_optimizer$ExternalPartition -#define CXXBRIDGE1_STRUCT_concrete_optimizer$ExternalPartition -struct ExternalPartition final : public ::rust::Opaque { - ~ExternalPartition() = delete; - -private: - friend ::rust::layout; - struct layout { - static ::std::size_t size() noexcept; - static ::std::size_t align() noexcept; - }; -}; -#endif // CXXBRIDGE1_STRUCT_concrete_optimizer$ExternalPartition - #ifndef CXXBRIDGE1_STRUCT_concrete_optimizer$Weights #define CXXBRIDGE1_STRUCT_concrete_optimizer$Weights struct Weights final : public ::rust::Opaque { @@ -1398,15 +1385,43 @@ struct KeysetRestriction final { } // namespace restriction namespace utils { -#ifndef CXXBRIDGE1_STRUCT_concrete_optimizer$utils$PartitionDefinition -#define CXXBRIDGE1_STRUCT_concrete_optimizer$utils$PartitionDefinition -struct PartitionDefinition final { +#ifndef CXXBRIDGE1_STRUCT_concrete_optimizer$utils$InternalPartitionDefinition +#define CXXBRIDGE1_STRUCT_concrete_optimizer$utils$InternalPartitionDefinition +struct InternalPartitionDefinition final { ::std::uint8_t precision; double norm2; using IsRelocatable = ::std::true_type; }; -#endif // CXXBRIDGE1_STRUCT_concrete_optimizer$utils$PartitionDefinition +#endif // CXXBRIDGE1_STRUCT_concrete_optimizer$utils$InternalPartitionDefinition + +#ifndef CXXBRIDGE1_STRUCT_concrete_optimizer$utils$ExternalPartitionDefinition +#define CXXBRIDGE1_STRUCT_concrete_optimizer$utils$ExternalPartitionDefinition +struct ExternalPartitionDefinition final { + ::rust::String name; + ::std::uint64_t log2_polynomial_size; + ::std::uint64_t glwe_dimension; + ::std::uint64_t internal_dim; + ::std::uint64_t pbs_level; + ::std::uint64_t pbs_base_log; + + using IsRelocatable = ::std::true_type; +}; +#endif // CXXBRIDGE1_STRUCT_concrete_optimizer$utils$ExternalPartitionDefinition + +#ifndef CXXBRIDGE1_STRUCT_concrete_optimizer$utils$ExternalPartition +#define CXXBRIDGE1_STRUCT_concrete_optimizer$utils$ExternalPartition +struct ExternalPartition final { + ::rust::String name; + ::std::uint64_t macro_log2_polynomial_size; + ::std::uint64_t macro_glwe_dimension; + ::std::uint64_t macro_internal_dim; + double max_variance; + double variance; + + using IsRelocatable = ::std::true_type; +}; +#endif // CXXBRIDGE1_STRUCT_concrete_optimizer$utils$ExternalPartition } // namespace utils namespace v0 { @@ -1430,8 +1445,6 @@ ::std::size_t concrete_optimizer$cxxbridge1$DagBuilder$operator$sizeof() noexcep ::std::size_t concrete_optimizer$cxxbridge1$DagBuilder$operator$alignof() noexcept; ::std::size_t concrete_optimizer$cxxbridge1$Location$operator$sizeof() noexcept; ::std::size_t concrete_optimizer$cxxbridge1$Location$operator$alignof() noexcept; -::std::size_t concrete_optimizer$cxxbridge1$ExternalPartition$operator$sizeof() noexcept; -::std::size_t concrete_optimizer$cxxbridge1$ExternalPartition$operator$alignof() noexcept; } // extern "C" namespace utils { @@ -1440,9 +1453,7 @@ ::concrete_optimizer::Location *concrete_optimizer$utils$cxxbridge1$location_unk ::concrete_optimizer::Location *concrete_optimizer$utils$cxxbridge1$location_from_string(::rust::Str string) noexcept; -void concrete_optimizer$utils$cxxbridge1$generate_virtual_keyset_info(::rust::Vec<::concrete_optimizer::utils::PartitionDefinition> *partitions, bool generate_fks, ::concrete_optimizer::Options const &options, ::CircuitKeys *return$) noexcept; - -::concrete_optimizer::ExternalPartition *concrete_optimizer$utils$cxxbridge1$get_external_partition(::rust::String *name, ::std::uint64_t log2_polynomial_size, ::std::uint64_t glwe_dimension, ::std::uint64_t internal_dim, double max_variance, double variance) noexcept; +void concrete_optimizer$utils$cxxbridge1$generate_virtual_keyset_info(::rust::Vec<::concrete_optimizer::utils::InternalPartitionDefinition> *internal_partitions, ::rust::Vec<::concrete_optimizer::utils::ExternalPartitionDefinition> *external_partitions, ::concrete_optimizer::Options const &options, ::CircuitKeys *return$) noexcept; double concrete_optimizer$utils$cxxbridge1$get_noise_br(::concrete_optimizer::Options const &options, ::std::uint64_t log2_polynomial_size, ::std::uint64_t glwe_dimension, ::std::uint64_t lwe_dim, ::std::uint64_t pbs_level, ::std::uint64_t pbs_log2_base) noexcept; } // extern "C" @@ -1477,9 +1488,9 @@ ::concrete_optimizer::dag::OperatorIndex concrete_optimizer$cxxbridge1$DagBuilde ::concrete_optimizer::dag::OperatorIndex concrete_optimizer$cxxbridge1$DagBuilder$add_unsafe_cast_op(::concrete_optimizer::DagBuilder &self, ::concrete_optimizer::dag::OperatorIndex input, ::std::uint8_t rounded_precision, ::concrete_optimizer::Location const &location) noexcept; -::concrete_optimizer::dag::OperatorIndex concrete_optimizer$cxxbridge1$DagBuilder$add_change_partition_with_src(::concrete_optimizer::DagBuilder &self, ::concrete_optimizer::dag::OperatorIndex input, ::concrete_optimizer::ExternalPartition const &src_partition, ::concrete_optimizer::Location const &location) noexcept; +::concrete_optimizer::dag::OperatorIndex concrete_optimizer$cxxbridge1$DagBuilder$add_change_partition_with_src(::concrete_optimizer::DagBuilder &self, ::concrete_optimizer::dag::OperatorIndex input, ::concrete_optimizer::utils::ExternalPartition const &src_partition, ::concrete_optimizer::Location const &location) noexcept; -::concrete_optimizer::dag::OperatorIndex concrete_optimizer$cxxbridge1$DagBuilder$add_change_partition_with_dst(::concrete_optimizer::DagBuilder &self, ::concrete_optimizer::dag::OperatorIndex input, ::concrete_optimizer::ExternalPartition const &dst_partition, ::concrete_optimizer::Location const &location) noexcept; +::concrete_optimizer::dag::OperatorIndex concrete_optimizer$cxxbridge1$DagBuilder$add_change_partition_with_dst(::concrete_optimizer::DagBuilder &self, ::concrete_optimizer::dag::OperatorIndex input, ::concrete_optimizer::utils::ExternalPartition const &dst_partition, ::concrete_optimizer::Location const &location) noexcept; void concrete_optimizer$cxxbridge1$DagBuilder$tag_operator_as_output(::concrete_optimizer::DagBuilder &self, ::concrete_optimizer::dag::OperatorIndex op) noexcept; @@ -1567,14 +1578,6 @@ ::std::size_t Location::layout::align() noexcept { return concrete_optimizer$cxxbridge1$Location$operator$alignof(); } -::std::size_t ExternalPartition::layout::size() noexcept { - return concrete_optimizer$cxxbridge1$ExternalPartition$operator$sizeof(); -} - -::std::size_t ExternalPartition::layout::align() noexcept { - return concrete_optimizer$cxxbridge1$ExternalPartition$operator$alignof(); -} - namespace utils { ::rust::Box<::concrete_optimizer::Location> location_unknown() noexcept { return ::rust::Box<::concrete_optimizer::Location>::from_raw(concrete_optimizer$utils$cxxbridge1$location_unknown()); @@ -1584,17 +1587,14 @@ ::rust::Box<::concrete_optimizer::Location> location_from_string(::rust::Str str return ::rust::Box<::concrete_optimizer::Location>::from_raw(concrete_optimizer$utils$cxxbridge1$location_from_string(string)); } -::CircuitKeys generate_virtual_keyset_info(::rust::Vec<::concrete_optimizer::utils::PartitionDefinition> partitions, bool generate_fks, ::concrete_optimizer::Options const &options) noexcept { - ::rust::ManuallyDrop<::rust::Vec<::concrete_optimizer::utils::PartitionDefinition>> partitions$(::std::move(partitions)); +::CircuitKeys generate_virtual_keyset_info(::rust::Vec<::concrete_optimizer::utils::InternalPartitionDefinition> internal_partitions, ::rust::Vec<::concrete_optimizer::utils::ExternalPartitionDefinition> external_partitions, ::concrete_optimizer::Options const &options) noexcept { + ::rust::ManuallyDrop<::rust::Vec<::concrete_optimizer::utils::InternalPartitionDefinition>> internal_partitions$(::std::move(internal_partitions)); + ::rust::ManuallyDrop<::rust::Vec<::concrete_optimizer::utils::ExternalPartitionDefinition>> external_partitions$(::std::move(external_partitions)); ::rust::MaybeUninit<::CircuitKeys> return$; - concrete_optimizer$utils$cxxbridge1$generate_virtual_keyset_info(&partitions$.value, generate_fks, options, &return$.value); + concrete_optimizer$utils$cxxbridge1$generate_virtual_keyset_info(&internal_partitions$.value, &external_partitions$.value, options, &return$.value); return ::std::move(return$.value); } -::rust::Box<::concrete_optimizer::ExternalPartition> get_external_partition(::rust::String name, ::std::uint64_t log2_polynomial_size, ::std::uint64_t glwe_dimension, ::std::uint64_t internal_dim, double max_variance, double variance) noexcept { - return ::rust::Box<::concrete_optimizer::ExternalPartition>::from_raw(concrete_optimizer$utils$cxxbridge1$get_external_partition(&name, log2_polynomial_size, glwe_dimension, internal_dim, max_variance, variance)); -} - double get_noise_br(::concrete_optimizer::Options const &options, ::std::uint64_t log2_polynomial_size, ::std::uint64_t glwe_dimension, ::std::uint64_t lwe_dim, ::std::uint64_t pbs_level, ::std::uint64_t pbs_log2_base) noexcept { return concrete_optimizer$utils$cxxbridge1$get_noise_br(options, log2_polynomial_size, glwe_dimension, lwe_dim, pbs_level, pbs_log2_base); } @@ -1654,11 +1654,11 @@ ::concrete_optimizer::dag::OperatorIndex DagBuilder::add_unsafe_cast_op(::concre return concrete_optimizer$cxxbridge1$DagBuilder$add_unsafe_cast_op(*this, input, rounded_precision, location); } -::concrete_optimizer::dag::OperatorIndex DagBuilder::add_change_partition_with_src(::concrete_optimizer::dag::OperatorIndex input, ::concrete_optimizer::ExternalPartition const &src_partition, ::concrete_optimizer::Location const &location) noexcept { +::concrete_optimizer::dag::OperatorIndex DagBuilder::add_change_partition_with_src(::concrete_optimizer::dag::OperatorIndex input, ::concrete_optimizer::utils::ExternalPartition const &src_partition, ::concrete_optimizer::Location const &location) noexcept { return concrete_optimizer$cxxbridge1$DagBuilder$add_change_partition_with_src(*this, input, src_partition, location); } -::concrete_optimizer::dag::OperatorIndex DagBuilder::add_change_partition_with_dst(::concrete_optimizer::dag::OperatorIndex input, ::concrete_optimizer::ExternalPartition const &dst_partition, ::concrete_optimizer::Location const &location) noexcept { +::concrete_optimizer::dag::OperatorIndex DagBuilder::add_change_partition_with_dst(::concrete_optimizer::dag::OperatorIndex input, ::concrete_optimizer::utils::ExternalPartition const &dst_partition, ::concrete_optimizer::Location const &location) noexcept { return concrete_optimizer$cxxbridge1$DagBuilder$add_change_partition_with_dst(*this, input, dst_partition, location); } @@ -1744,18 +1744,23 @@ ::concrete_optimizer::Location *cxxbridge1$box$concrete_optimizer$Location$alloc void cxxbridge1$box$concrete_optimizer$Location$dealloc(::concrete_optimizer::Location *) noexcept; void cxxbridge1$box$concrete_optimizer$Location$drop(::rust::Box<::concrete_optimizer::Location> *ptr) noexcept; -void cxxbridge1$rust_vec$concrete_optimizer$utils$PartitionDefinition$new(::rust::Vec<::concrete_optimizer::utils::PartitionDefinition> const *ptr) noexcept; -void cxxbridge1$rust_vec$concrete_optimizer$utils$PartitionDefinition$drop(::rust::Vec<::concrete_optimizer::utils::PartitionDefinition> *ptr) noexcept; -::std::size_t cxxbridge1$rust_vec$concrete_optimizer$utils$PartitionDefinition$len(::rust::Vec<::concrete_optimizer::utils::PartitionDefinition> const *ptr) noexcept; -::std::size_t cxxbridge1$rust_vec$concrete_optimizer$utils$PartitionDefinition$capacity(::rust::Vec<::concrete_optimizer::utils::PartitionDefinition> const *ptr) noexcept; -::concrete_optimizer::utils::PartitionDefinition const *cxxbridge1$rust_vec$concrete_optimizer$utils$PartitionDefinition$data(::rust::Vec<::concrete_optimizer::utils::PartitionDefinition> const *ptr) noexcept; -void cxxbridge1$rust_vec$concrete_optimizer$utils$PartitionDefinition$reserve_total(::rust::Vec<::concrete_optimizer::utils::PartitionDefinition> *ptr, ::std::size_t new_cap) noexcept; -void cxxbridge1$rust_vec$concrete_optimizer$utils$PartitionDefinition$set_len(::rust::Vec<::concrete_optimizer::utils::PartitionDefinition> *ptr, ::std::size_t len) noexcept; -void cxxbridge1$rust_vec$concrete_optimizer$utils$PartitionDefinition$truncate(::rust::Vec<::concrete_optimizer::utils::PartitionDefinition> *ptr, ::std::size_t len) noexcept; - -::concrete_optimizer::ExternalPartition *cxxbridge1$box$concrete_optimizer$ExternalPartition$alloc() noexcept; -void cxxbridge1$box$concrete_optimizer$ExternalPartition$dealloc(::concrete_optimizer::ExternalPartition *) noexcept; -void cxxbridge1$box$concrete_optimizer$ExternalPartition$drop(::rust::Box<::concrete_optimizer::ExternalPartition> *ptr) noexcept; +void cxxbridge1$rust_vec$concrete_optimizer$utils$InternalPartitionDefinition$new(::rust::Vec<::concrete_optimizer::utils::InternalPartitionDefinition> const *ptr) noexcept; +void cxxbridge1$rust_vec$concrete_optimizer$utils$InternalPartitionDefinition$drop(::rust::Vec<::concrete_optimizer::utils::InternalPartitionDefinition> *ptr) noexcept; +::std::size_t cxxbridge1$rust_vec$concrete_optimizer$utils$InternalPartitionDefinition$len(::rust::Vec<::concrete_optimizer::utils::InternalPartitionDefinition> const *ptr) noexcept; +::std::size_t cxxbridge1$rust_vec$concrete_optimizer$utils$InternalPartitionDefinition$capacity(::rust::Vec<::concrete_optimizer::utils::InternalPartitionDefinition> const *ptr) noexcept; +::concrete_optimizer::utils::InternalPartitionDefinition const *cxxbridge1$rust_vec$concrete_optimizer$utils$InternalPartitionDefinition$data(::rust::Vec<::concrete_optimizer::utils::InternalPartitionDefinition> const *ptr) noexcept; +void cxxbridge1$rust_vec$concrete_optimizer$utils$InternalPartitionDefinition$reserve_total(::rust::Vec<::concrete_optimizer::utils::InternalPartitionDefinition> *ptr, ::std::size_t new_cap) noexcept; +void cxxbridge1$rust_vec$concrete_optimizer$utils$InternalPartitionDefinition$set_len(::rust::Vec<::concrete_optimizer::utils::InternalPartitionDefinition> *ptr, ::std::size_t len) noexcept; +void cxxbridge1$rust_vec$concrete_optimizer$utils$InternalPartitionDefinition$truncate(::rust::Vec<::concrete_optimizer::utils::InternalPartitionDefinition> *ptr, ::std::size_t len) noexcept; + +void cxxbridge1$rust_vec$concrete_optimizer$utils$ExternalPartitionDefinition$new(::rust::Vec<::concrete_optimizer::utils::ExternalPartitionDefinition> const *ptr) noexcept; +void cxxbridge1$rust_vec$concrete_optimizer$utils$ExternalPartitionDefinition$drop(::rust::Vec<::concrete_optimizer::utils::ExternalPartitionDefinition> *ptr) noexcept; +::std::size_t cxxbridge1$rust_vec$concrete_optimizer$utils$ExternalPartitionDefinition$len(::rust::Vec<::concrete_optimizer::utils::ExternalPartitionDefinition> const *ptr) noexcept; +::std::size_t cxxbridge1$rust_vec$concrete_optimizer$utils$ExternalPartitionDefinition$capacity(::rust::Vec<::concrete_optimizer::utils::ExternalPartitionDefinition> const *ptr) noexcept; +::concrete_optimizer::utils::ExternalPartitionDefinition const *cxxbridge1$rust_vec$concrete_optimizer$utils$ExternalPartitionDefinition$data(::rust::Vec<::concrete_optimizer::utils::ExternalPartitionDefinition> const *ptr) noexcept; +void cxxbridge1$rust_vec$concrete_optimizer$utils$ExternalPartitionDefinition$reserve_total(::rust::Vec<::concrete_optimizer::utils::ExternalPartitionDefinition> *ptr, ::std::size_t new_cap) noexcept; +void cxxbridge1$rust_vec$concrete_optimizer$utils$ExternalPartitionDefinition$set_len(::rust::Vec<::concrete_optimizer::utils::ExternalPartitionDefinition> *ptr, ::std::size_t len) noexcept; +void cxxbridge1$rust_vec$concrete_optimizer$utils$ExternalPartitionDefinition$truncate(::rust::Vec<::concrete_optimizer::utils::ExternalPartitionDefinition> *ptr, ::std::size_t len) noexcept; ::concrete_optimizer::Dag *cxxbridge1$box$concrete_optimizer$Dag$alloc() noexcept; void cxxbridge1$box$concrete_optimizer$Dag$dealloc(::concrete_optimizer::Dag *) noexcept; @@ -1924,48 +1929,68 @@ void Box<::concrete_optimizer::Location>::drop() noexcept { cxxbridge1$box$concrete_optimizer$Location$drop(this); } template <> -Vec<::concrete_optimizer::utils::PartitionDefinition>::Vec() noexcept { - cxxbridge1$rust_vec$concrete_optimizer$utils$PartitionDefinition$new(this); +Vec<::concrete_optimizer::utils::InternalPartitionDefinition>::Vec() noexcept { + cxxbridge1$rust_vec$concrete_optimizer$utils$InternalPartitionDefinition$new(this); +} +template <> +void Vec<::concrete_optimizer::utils::InternalPartitionDefinition>::drop() noexcept { + return cxxbridge1$rust_vec$concrete_optimizer$utils$InternalPartitionDefinition$drop(this); +} +template <> +::std::size_t Vec<::concrete_optimizer::utils::InternalPartitionDefinition>::size() const noexcept { + return cxxbridge1$rust_vec$concrete_optimizer$utils$InternalPartitionDefinition$len(this); +} +template <> +::std::size_t Vec<::concrete_optimizer::utils::InternalPartitionDefinition>::capacity() const noexcept { + return cxxbridge1$rust_vec$concrete_optimizer$utils$InternalPartitionDefinition$capacity(this); +} +template <> +::concrete_optimizer::utils::InternalPartitionDefinition const *Vec<::concrete_optimizer::utils::InternalPartitionDefinition>::data() const noexcept { + return cxxbridge1$rust_vec$concrete_optimizer$utils$InternalPartitionDefinition$data(this); +} +template <> +void Vec<::concrete_optimizer::utils::InternalPartitionDefinition>::reserve_total(::std::size_t new_cap) noexcept { + return cxxbridge1$rust_vec$concrete_optimizer$utils$InternalPartitionDefinition$reserve_total(this, new_cap); } template <> -void Vec<::concrete_optimizer::utils::PartitionDefinition>::drop() noexcept { - return cxxbridge1$rust_vec$concrete_optimizer$utils$PartitionDefinition$drop(this); +void Vec<::concrete_optimizer::utils::InternalPartitionDefinition>::set_len(::std::size_t len) noexcept { + return cxxbridge1$rust_vec$concrete_optimizer$utils$InternalPartitionDefinition$set_len(this, len); } template <> -::std::size_t Vec<::concrete_optimizer::utils::PartitionDefinition>::size() const noexcept { - return cxxbridge1$rust_vec$concrete_optimizer$utils$PartitionDefinition$len(this); +void Vec<::concrete_optimizer::utils::InternalPartitionDefinition>::truncate(::std::size_t len) { + return cxxbridge1$rust_vec$concrete_optimizer$utils$InternalPartitionDefinition$truncate(this, len); } template <> -::std::size_t Vec<::concrete_optimizer::utils::PartitionDefinition>::capacity() const noexcept { - return cxxbridge1$rust_vec$concrete_optimizer$utils$PartitionDefinition$capacity(this); +Vec<::concrete_optimizer::utils::ExternalPartitionDefinition>::Vec() noexcept { + cxxbridge1$rust_vec$concrete_optimizer$utils$ExternalPartitionDefinition$new(this); } template <> -::concrete_optimizer::utils::PartitionDefinition const *Vec<::concrete_optimizer::utils::PartitionDefinition>::data() const noexcept { - return cxxbridge1$rust_vec$concrete_optimizer$utils$PartitionDefinition$data(this); +void Vec<::concrete_optimizer::utils::ExternalPartitionDefinition>::drop() noexcept { + return cxxbridge1$rust_vec$concrete_optimizer$utils$ExternalPartitionDefinition$drop(this); } template <> -void Vec<::concrete_optimizer::utils::PartitionDefinition>::reserve_total(::std::size_t new_cap) noexcept { - return cxxbridge1$rust_vec$concrete_optimizer$utils$PartitionDefinition$reserve_total(this, new_cap); +::std::size_t Vec<::concrete_optimizer::utils::ExternalPartitionDefinition>::size() const noexcept { + return cxxbridge1$rust_vec$concrete_optimizer$utils$ExternalPartitionDefinition$len(this); } template <> -void Vec<::concrete_optimizer::utils::PartitionDefinition>::set_len(::std::size_t len) noexcept { - return cxxbridge1$rust_vec$concrete_optimizer$utils$PartitionDefinition$set_len(this, len); +::std::size_t Vec<::concrete_optimizer::utils::ExternalPartitionDefinition>::capacity() const noexcept { + return cxxbridge1$rust_vec$concrete_optimizer$utils$ExternalPartitionDefinition$capacity(this); } template <> -void Vec<::concrete_optimizer::utils::PartitionDefinition>::truncate(::std::size_t len) { - return cxxbridge1$rust_vec$concrete_optimizer$utils$PartitionDefinition$truncate(this, len); +::concrete_optimizer::utils::ExternalPartitionDefinition const *Vec<::concrete_optimizer::utils::ExternalPartitionDefinition>::data() const noexcept { + return cxxbridge1$rust_vec$concrete_optimizer$utils$ExternalPartitionDefinition$data(this); } template <> -::concrete_optimizer::ExternalPartition *Box<::concrete_optimizer::ExternalPartition>::allocation::alloc() noexcept { - return cxxbridge1$box$concrete_optimizer$ExternalPartition$alloc(); +void Vec<::concrete_optimizer::utils::ExternalPartitionDefinition>::reserve_total(::std::size_t new_cap) noexcept { + return cxxbridge1$rust_vec$concrete_optimizer$utils$ExternalPartitionDefinition$reserve_total(this, new_cap); } template <> -void Box<::concrete_optimizer::ExternalPartition>::allocation::dealloc(::concrete_optimizer::ExternalPartition *ptr) noexcept { - cxxbridge1$box$concrete_optimizer$ExternalPartition$dealloc(ptr); +void Vec<::concrete_optimizer::utils::ExternalPartitionDefinition>::set_len(::std::size_t len) noexcept { + return cxxbridge1$rust_vec$concrete_optimizer$utils$ExternalPartitionDefinition$set_len(this, len); } template <> -void Box<::concrete_optimizer::ExternalPartition>::drop() noexcept { - cxxbridge1$box$concrete_optimizer$ExternalPartition$drop(this); +void Vec<::concrete_optimizer::utils::ExternalPartitionDefinition>::truncate(::std::size_t len) { + return cxxbridge1$rust_vec$concrete_optimizer$utils$ExternalPartitionDefinition$truncate(this, len); } template <> ::concrete_optimizer::Dag *Box<::concrete_optimizer::Dag>::allocation::alloc() 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 8cc0a87068..e0dbe394c1 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 @@ -926,7 +926,6 @@ namespace concrete_optimizer { struct Dag; struct DagBuilder; struct Location; - struct ExternalPartition; struct Weights; enum class Encoding : ::std::uint8_t; enum class MultiParamStrategy : ::std::uint8_t; @@ -956,7 +955,9 @@ namespace concrete_optimizer { struct KeysetRestriction; } namespace utils { - struct PartitionDefinition; + struct InternalPartitionDefinition; + struct ExternalPartitionDefinition; + struct ExternalPartition; } } @@ -996,8 +997,8 @@ struct DagBuilder final : public ::rust::Opaque { ::concrete_optimizer::dag::OperatorIndex add_max_noise(::rust::Slice<::concrete_optimizer::dag::OperatorIndex const> inputs, ::rust::Slice<::std::uint64_t const> out_shape, ::concrete_optimizer::Location const &location) noexcept; ::concrete_optimizer::dag::OperatorIndex add_round_op(::concrete_optimizer::dag::OperatorIndex input, ::std::uint8_t rounded_precision, ::concrete_optimizer::Location const &location) noexcept; ::concrete_optimizer::dag::OperatorIndex add_unsafe_cast_op(::concrete_optimizer::dag::OperatorIndex input, ::std::uint8_t rounded_precision, ::concrete_optimizer::Location const &location) noexcept; - ::concrete_optimizer::dag::OperatorIndex add_change_partition_with_src(::concrete_optimizer::dag::OperatorIndex input, ::concrete_optimizer::ExternalPartition const &src_partition, ::concrete_optimizer::Location const &location) noexcept; - ::concrete_optimizer::dag::OperatorIndex add_change_partition_with_dst(::concrete_optimizer::dag::OperatorIndex input, ::concrete_optimizer::ExternalPartition const &dst_partition, ::concrete_optimizer::Location const &location) noexcept; + ::concrete_optimizer::dag::OperatorIndex add_change_partition_with_src(::concrete_optimizer::dag::OperatorIndex input, ::concrete_optimizer::utils::ExternalPartition const &src_partition, ::concrete_optimizer::Location const &location) noexcept; + ::concrete_optimizer::dag::OperatorIndex add_change_partition_with_dst(::concrete_optimizer::dag::OperatorIndex input, ::concrete_optimizer::utils::ExternalPartition const &dst_partition, ::concrete_optimizer::Location const &location) noexcept; void tag_operator_as_output(::concrete_optimizer::dag::OperatorIndex op) noexcept; ~DagBuilder() = delete; @@ -1024,20 +1025,6 @@ struct Location final : public ::rust::Opaque { }; #endif // CXXBRIDGE1_STRUCT_concrete_optimizer$Location -#ifndef CXXBRIDGE1_STRUCT_concrete_optimizer$ExternalPartition -#define CXXBRIDGE1_STRUCT_concrete_optimizer$ExternalPartition -struct ExternalPartition final : public ::rust::Opaque { - ~ExternalPartition() = delete; - -private: - friend ::rust::layout; - struct layout { - static ::std::size_t size() noexcept; - static ::std::size_t align() noexcept; - }; -}; -#endif // CXXBRIDGE1_STRUCT_concrete_optimizer$ExternalPartition - #ifndef CXXBRIDGE1_STRUCT_concrete_optimizer$Weights #define CXXBRIDGE1_STRUCT_concrete_optimizer$Weights struct Weights final : public ::rust::Opaque { @@ -1372,15 +1359,43 @@ struct KeysetRestriction final { } // namespace restriction namespace utils { -#ifndef CXXBRIDGE1_STRUCT_concrete_optimizer$utils$PartitionDefinition -#define CXXBRIDGE1_STRUCT_concrete_optimizer$utils$PartitionDefinition -struct PartitionDefinition final { +#ifndef CXXBRIDGE1_STRUCT_concrete_optimizer$utils$InternalPartitionDefinition +#define CXXBRIDGE1_STRUCT_concrete_optimizer$utils$InternalPartitionDefinition +struct InternalPartitionDefinition final { ::std::uint8_t precision; double norm2; using IsRelocatable = ::std::true_type; }; -#endif // CXXBRIDGE1_STRUCT_concrete_optimizer$utils$PartitionDefinition +#endif // CXXBRIDGE1_STRUCT_concrete_optimizer$utils$InternalPartitionDefinition + +#ifndef CXXBRIDGE1_STRUCT_concrete_optimizer$utils$ExternalPartitionDefinition +#define CXXBRIDGE1_STRUCT_concrete_optimizer$utils$ExternalPartitionDefinition +struct ExternalPartitionDefinition final { + ::rust::String name; + ::std::uint64_t log2_polynomial_size; + ::std::uint64_t glwe_dimension; + ::std::uint64_t internal_dim; + ::std::uint64_t pbs_level; + ::std::uint64_t pbs_base_log; + + using IsRelocatable = ::std::true_type; +}; +#endif // CXXBRIDGE1_STRUCT_concrete_optimizer$utils$ExternalPartitionDefinition + +#ifndef CXXBRIDGE1_STRUCT_concrete_optimizer$utils$ExternalPartition +#define CXXBRIDGE1_STRUCT_concrete_optimizer$utils$ExternalPartition +struct ExternalPartition final { + ::rust::String name; + ::std::uint64_t macro_log2_polynomial_size; + ::std::uint64_t macro_glwe_dimension; + ::std::uint64_t macro_internal_dim; + double max_variance; + double variance; + + using IsRelocatable = ::std::true_type; +}; +#endif // CXXBRIDGE1_STRUCT_concrete_optimizer$utils$ExternalPartition } // namespace utils namespace v0 { @@ -1396,9 +1411,7 @@ ::rust::Box<::concrete_optimizer::Location> location_unknown() noexcept; ::rust::Box<::concrete_optimizer::Location> location_from_string(::rust::Str string) noexcept; -::CircuitKeys generate_virtual_keyset_info(::rust::Vec<::concrete_optimizer::utils::PartitionDefinition> partitions, bool generate_fks, ::concrete_optimizer::Options const &options) noexcept; - -::rust::Box<::concrete_optimizer::ExternalPartition> get_external_partition(::rust::String name, ::std::uint64_t log2_polynomial_size, ::std::uint64_t glwe_dimension, ::std::uint64_t internal_dim, double max_variance, double variance) noexcept; +::CircuitKeys generate_virtual_keyset_info(::rust::Vec<::concrete_optimizer::utils::InternalPartitionDefinition> internal_partitions, ::rust::Vec<::concrete_optimizer::utils::ExternalPartitionDefinition> external_partitions, ::concrete_optimizer::Options const &options) noexcept; double get_noise_br(::concrete_optimizer::Options const &options, ::std::uint64_t log2_polynomial_size, ::std::uint64_t glwe_dimension, ::std::uint64_t lwe_dim, ::std::uint64_t pbs_level, ::std::uint64_t pbs_log2_base) noexcept; } // namespace utils diff --git a/compilers/concrete-optimizer/concrete-optimizer/src/dag/unparametrized.rs b/compilers/concrete-optimizer/concrete-optimizer/src/dag/unparametrized.rs index c96fc2a924..042b717e2c 100644 --- a/compilers/concrete-optimizer/concrete-optimizer/src/dag/unparametrized.rs +++ b/compilers/concrete-optimizer/concrete-optimizer/src/dag/unparametrized.rs @@ -472,6 +472,7 @@ impl DagBuilder<'_> { | Operator::UnsafeCast { input, .. } | Operator::Round { input, .. } | Operator::ChangePartition { input, .. } => self.dag.out_shapes[input.0].clone(), + Operator::Dot { kind: DotKind::Simple | DotKind::Tensor | DotKind::CompatibleTensor, .. 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 9cdb338447..4cec47e640 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 @@ -237,6 +237,7 @@ impl VariancedDag { noise_expression: variance.clone(), noise_evaluator: None, location: op.location.clone(), + operator_index: op.id, }; self.external_variance_constraints.push(constraint); } @@ -276,6 +277,7 @@ impl VariancedDag { noise_expression: variance.clone(), noise_evaluator: None, location: dag_op.location.clone(), + operator_index: dag_op.id, }; self.external_variance_constraints.push(constraint); } @@ -397,7 +399,7 @@ impl VariancedDag { #[derive(Debug)] pub struct AnalyzedDag { - pub operators: Vec, + pub dag: Dag, // Collect all operators ouput variances pub nb_partitions: usize, pub instrs_partition: Vec, @@ -443,8 +445,8 @@ pub fn analyze( .into_iter() .reduce(Add::add) .unwrap(); - Ok(AnalyzedDag { - operators: varianced_dag.dag.operators, + let output = AnalyzedDag { + dag: varianced_dag.dag, instruction_rewrite_index, nb_partitions: varianced_dag.partitions.nb_partitions, instrs_partition: varianced_dag.partitions.instrs_partition, @@ -455,7 +457,8 @@ pub fn analyze( operations_count_per_instrs, operations_count, p_cut, - }) + }; + Ok(output) } pub fn original_instrs_partition( @@ -479,7 +482,7 @@ pub fn original_instrs_partition( for (i, new_instruction) in new_instructions.iter().enumerate() { // focus on TLU information let new_instr_part = &dag.instrs_partition[new_instruction.0]; - if let Operator::Lut { .. } = dag.operators[new_instruction.0] { + if let Operator::Lut { .. } = dag.dag.operators[new_instruction.0] { let ks_dst = new_instr_part.instruction_partition; partition = Some(ks_dst); #[allow(clippy::match_on_vec_items)] @@ -641,6 +644,7 @@ fn variance_constraint( let nb_constraints = dag.out_shapes[op_i].flat_size(); let safe_variance_bound = safe_noise_bound(precision, noise_config); let location = dag.locations[op_i].clone(); + let operator_index = OperatorIndex(op_i); VarianceConstraint { precision, partition, @@ -650,6 +654,7 @@ fn variance_constraint( noise_expression: noise, noise_evaluator: None, location, + operator_index, } } @@ -1175,7 +1180,7 @@ pub mod tests { for op_i in (input1.0 + 1)..rounded1.0 { if let Operator::Dot { weights, inputs, .. - } = &dag.operators[op_i] + } = &dag.dag.operators[op_i] { let bit_extract = weights.values.len() == 1; let first_bit_extract = bit_extract && !first_bit_extract_verified; @@ -1383,7 +1388,11 @@ pub mod tests { "∅", // cast "1¢Br[1] + 1¢K[0→1]", // _lut1 ]; - for ((c, ec), op) in instrs_counts.iter().zip(expected_counts).zip(dag.operators) { + for ((c, ec), op) in instrs_counts + .iter() + .zip(expected_counts) + .zip(dag.dag.operators) + { assert!( c == ec, "\nBad count on {op}\nActual: {c}\nTruth : {ec} (expected)\n" 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 0b8cdf9b10..0ebf6600d4 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 @@ -1029,6 +1029,7 @@ pub fn optimize( .or(Some(PartitionCut::for_each_precision(dag))); let mut dag = analyze(dag, &noise_config, &dag_p_cut, default_partition)?; + crate::utils::viz::viz!(&dag); let kappa = error::sigma_scale_of_error_probability(config.maximum_acceptable_error_probability); diff --git a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/partition_cut.rs b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/partition_cut.rs index 6640487cb8..0cabd90125 100644 --- a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/partition_cut.rs +++ b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/partition_cut.rs @@ -4,7 +4,7 @@ use ordered_float::OrderedFloat; use crate::dag::operator::{Operator, OperatorIndex, Precision}; use crate::dag::rewrite::round::expand_round_and_index_map; -use crate::dag::unparametrized; +use crate::dag::unparametrized::{self, Dag}; use crate::optimization::dag::multi_parameters::partitions::PartitionIndex; use crate::optimization::dag::solo_key::analyze::out_variances; use crate::optimization::dag::solo_key::symbolic_variance::SymbolicVariance; @@ -46,6 +46,11 @@ impl std::fmt::Display for ExternalPartition { } } +pub struct PrePartitionDag { + pub p_cut: PartitionCut, + pub dag: Dag, +} + // TODO: keep both precisions // TODO: rounding lut should have its own partition based on max norm2 and precisions #[derive(Clone, Debug)] @@ -150,9 +155,10 @@ impl PartitionCut { Operator::Lut { input, .. } => { assert!(self.has_internal_partitions); for (partition, &(precision_cut, norm2_cut)) in self.p_cut.iter().enumerate() { - if dag.out_precisions[input.0] <= precision_cut - && self.rnorm2(op_i) <= norm2_cut - { + let precision_ok = dag.out_precisions[input.0] <= precision_cut; + let rnorm2 = self.rnorm2(op_i); + let norm_ok = rnorm2 <= norm2_cut; + if precision_ok && norm_ok { return Some(PartitionIndex(partition)); } } @@ -288,12 +294,14 @@ impl PartitionCut { } } } + for op in dag.get_output_operators_iter() { for &origin in &noise_origins[op.id.0] { max_output_norm2[origin] = max_output_norm2[origin].max(out_norm2(op.id.0)); assert!(!max_output_norm2[origin].is_nan()); } } + let mut round_done: HashMap = HashMap::default(); // reassociate all lut's output_norm2 and precisions for (op_i, output_norm2) in max_output_norm2.iter_mut().enumerate() { diff --git a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/partitionning.rs b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/partitionning.rs index 4cc5c8b801..ba348420c7 100644 --- a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/partitionning.rs +++ b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/partitionning.rs @@ -390,7 +390,7 @@ pub mod tests { } pub const GLWE_PARAMS: GlweParameters = GlweParameters { - log2_polynomial_size: 11, + log2_polynomial_size: 12, glwe_dimension: 1, }; @@ -398,7 +398,7 @@ pub mod tests { pub const TFHERS_MACRO_PARAMS: MacroParameters = MacroParameters { glwe_params: GLWE_PARAMS, - internal_dim: 841, + internal_dim: 909, }; pub fn get_tfhers_noise_br() -> f64 { 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 1acf7a7abb..b825db30b4 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 @@ -1,4 +1,4 @@ -use crate::dag::operator::{Location, Precision}; +use crate::dag::operator::{Location, OperatorIndex, Precision}; use crate::optimization::dag::multi_parameters::partitions::PartitionIndex; use std::fmt; @@ -18,6 +18,7 @@ pub struct VarianceConstraint { pub noise_expression: NoiseExpression, pub noise_evaluator: Option, pub location: Location, + pub operator_index: OperatorIndex, } impl fmt::Display for VarianceConstraint { diff --git a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/virtual_circuit.rs b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/virtual_circuit.rs index 5d0089cd46..5a4652190b 100644 --- a/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/virtual_circuit.rs +++ b/compilers/concrete-optimizer/concrete-optimizer/src/optimization/dag/multi_parameters/virtual_circuit.rs @@ -13,19 +13,19 @@ use crate::{ use super::{ keys_spec::{CircuitKeys, ExpandedCircuitKeys}, optimize::{optimize, NoSearchSpaceRestriction}, - partition_cut::PartitionCut, + partition_cut::{ExternalPartition, PartitionCut}, PartitionIndex, }; const _4_SIGMA: f64 = 0.000_063_342_483_999_973; #[derive(Debug, Clone, PartialEq)] -pub struct PartitionDefinition { +pub struct InternalPartition { pub precision: Precision, pub norm2: f64, } -impl PartialOrd for PartitionDefinition { +impl PartialOrd for InternalPartition { fn partial_cmp(&self, other: &Self) -> Option { match self.precision.cmp(&other.precision) { std::cmp::Ordering::Equal => self.norm2.partial_cmp(&other.norm2), @@ -34,62 +34,60 @@ impl PartialOrd for PartitionDefinition { } } -fn generate_virtual_circuit( - partitions: &[PartitionDefinition], - generate_fks: bool, -) -> unparametrized::Dag { - let mut dag = unparametrized::Dag::new(); - - for def_a in partitions.iter() { - for def_b in partitions.iter() { - if def_a == def_b { - continue; - } +/// Adds subgraphs to the dag, to force the generation of pbs and ks parameters. +fn build_internal_pbs_ks(dag: &mut unparametrized::Dag, internal_partitions: &[InternalPartition]) { + for def_a in internal_partitions.iter() { + for def_b in internal_partitions.iter() { let inp_a = dag.add_input(def_a.precision, Shape::number()); - let lut_a = dag.add_lut(inp_a, FunctionTable::UNKWOWN, def_a.precision); - let _weighted_a = dag.add_linear_noise( + let lut_a = dag.add_lut(inp_a, FunctionTable::UNKWOWN, def_b.precision); + let weighted_a = dag.add_linear_noise( [lut_a], LevelledComplexity::ZERO, [def_a.norm2.sqrt()], Shape::number(), "", ); - - let inp_b = dag.add_input(def_b.precision, Shape::number()); - let lut_b = dag.add_lut(inp_b, FunctionTable::UNKWOWN, def_b.precision); - let weighted_b = dag.add_linear_noise( + let lut_b = dag.add_lut(weighted_a, FunctionTable::UNKWOWN, def_b.precision); + let _ = dag.add_linear_noise( [lut_b], LevelledComplexity::ZERO, [def_b.norm2.sqrt()], Shape::number(), "", ); + } + } +} - dag.add_composition(weighted_b, inp_a); - - if generate_fks && def_a > def_b { - let inp_a = dag.add_input(def_a.precision, Shape::number()); - let lut_a = dag.add_lut(inp_a, FunctionTable::UNKWOWN, def_a.precision); - let _weighted_a = dag.add_linear_noise( - [lut_a], +/// Adds subgraphs to the dag, to force the generation of fks parameters. +fn build_internal_fks(dag: &mut unparametrized::Dag, internal_partitions: &[InternalPartition]) { + for def_big in internal_partitions.iter() { + for def_small in internal_partitions.iter() { + if def_big > def_small { + let inp_small = dag.add_input(def_small.precision, Shape::number()); + let lut_small = dag.add_lut(inp_small, FunctionTable::UNKWOWN, def_small.precision); + let weighted_small = dag.add_linear_noise( + [lut_small], LevelledComplexity::ZERO, - [def_a.norm2.sqrt()], + [def_small.norm2.sqrt()], Shape::number(), "", ); + let _ = dag.add_lut(weighted_small, FunctionTable::UNKWOWN, def_small.precision); - let inp_b = dag.add_input(def_b.precision, Shape::number()); - let lut_b = dag.add_lut(inp_b, FunctionTable::UNKWOWN, def_b.precision); - let _weighted_b = dag.add_linear_noise( - [lut_b], + let inp_big = dag.add_input(def_big.precision, Shape::number()); + let lut_big = dag.add_lut(inp_big, FunctionTable::UNKWOWN, def_big.precision); + let weighted_big = dag.add_linear_noise( + [lut_big], LevelledComplexity::ZERO, - [def_b.norm2.sqrt()], + [def_big.norm2.sqrt()], Shape::number(), "", ); + let _ = dag.add_lut(weighted_big, FunctionTable::UNKWOWN, def_big.precision); let _ = dag.add_linear_noise( - [lut_a, lut_b], + [lut_big, lut_small], LevelledComplexity::ZERO, [0., 0.], Shape::number(), @@ -98,19 +96,106 @@ fn generate_virtual_circuit( } } } +} + +fn build_internal_to_external_fks( + dag: &mut unparametrized::Dag, + internal_partitions: &[InternalPartition], + external_partitions: &[ExternalPartition], +) { + for def_ext in external_partitions { + for def_int in internal_partitions { + let inp_int = dag.add_input(def_int.precision, Shape::number()); + let lut_int = dag.add_lut(inp_int, FunctionTable::UNKWOWN, def_int.precision); + let weighted_int = dag.add_linear_noise( + [lut_int], + LevelledComplexity::ZERO, + [def_int.norm2.sqrt()], + Shape::number(), + "", + ); + let lut_int = dag.add_lut(weighted_int, FunctionTable::UNKWOWN, def_int.precision); + let weighted_int = dag.add_linear_noise( + [lut_int], + LevelledComplexity::ZERO, + [def_int.norm2.sqrt()], + Shape::number(), + "", + ); + + let inp_ext = dag.add_input(0, Shape::number()); + let _ = dag.add_change_partition(inp_ext, Some(def_ext.clone()), None); + + dag.add_composition(weighted_int, inp_ext); + } + } +} + +/// Adds subgraphs to the dag, to force the generation of external to internal ks parameters. +fn build_external_to_internal_ks( + dag: &mut unparametrized::Dag, + internal_partitions: &[InternalPartition], + external_partitions: &[ExternalPartition], +) { + for def_ext in external_partitions { + for def_int in internal_partitions { + let inp_ext = dag.add_input(def_int.precision, Shape::number()); + let oup_ext = dag.add_change_partition(inp_ext, Some(def_ext.clone()), None); + let lut_int = dag.add_lut(oup_ext, FunctionTable::UNKWOWN, def_int.precision); + let _ = dag.add_linear_noise( + [lut_int], + LevelledComplexity::ZERO, + [def_int.norm2.sqrt()], + Shape::number(), + "", + ); + } + } +} + +fn build_virtual_circuit( + internal_partitions: &[InternalPartition], + external_partitions: &[ExternalPartition], +) -> unparametrized::Dag { + let mut dag = unparametrized::Dag::new(); + build_internal_pbs_ks(&mut dag, internal_partitions); + build_internal_fks(&mut dag, internal_partitions); + build_internal_to_external_fks(&mut dag, internal_partitions, external_partitions); + build_external_to_internal_ks(&mut dag, internal_partitions, external_partitions); dag } pub fn generate_virtual_parameters( - partitions: Vec, - generate_fks: bool, + mut internal_partitions: Vec, + external_partitions: Vec, config: Config, ) -> CircuitKeys { - let dag = generate_virtual_circuit(partitions.as_slice(), generate_fks); + internal_partitions.sort_by(|a, b| a.partial_cmp(b).unwrap()); + internal_partitions + .iter() + .zip(internal_partitions.iter().skip(1)) + .for_each(|(l, r)| { + assert_ne!( + l.precision, r.precision, + "Only one partition by precision can be specified." + ) + }); + + let dag = build_virtual_circuit( + internal_partitions.as_slice(), + external_partitions.as_slice(), + ); + + let n_internal_partitions = internal_partitions.len(); + let n_external_partitions = external_partitions.len(); + + let precisions = internal_partitions + .iter() + .map(|i| i.precision) + .collect::>(); + let p_cut = + PartitionCut::from_precisions_and_external_partitions(&precisions, &external_partitions); - let precisions: Vec<_> = partitions.iter().map(|def| def.precision).collect(); - let n_partitions = precisions.len(); - let p_cut = PartitionCut::maximal_partitionning(&dag); let search_space = SearchSpace::default_cpu(); let cache = decomposition::cache(128, ProcessingUnit::Cpu, None, true, 64, 53); let parameters = optimize( @@ -122,23 +207,42 @@ pub fn generate_virtual_parameters( &Some(p_cut), PartitionIndex(0), ) - .map_or(None, |v| Some(v.1)) - .unwrap(); + .unwrap() + .1; - for i in 0..n_partitions { - for j in 0..n_partitions { + assert_eq!( + parameters.macro_params.len(), + n_internal_partitions + n_external_partitions + ); + + for i in 0..n_internal_partitions { + for j in 0..n_internal_partitions { assert!( parameters.micro_params.ks[i][j].is_some(), - "Ksk[{i},{j}] missing." + "Internal Ksk[{i},{j}] missing." ); if i > j { assert!( parameters.micro_params.fks[i][j].is_some(), - "Fksk[{i},{j}] missing." + "Internal Fksk[{i},{j}] missing." ); } } } + for i in 0..n_internal_partitions { + for j in 0..n_external_partitions { + assert!( + parameters.micro_params.fks[i][n_internal_partitions + j].is_some(), + "Internal -> External Fksk[{i},{}] missing.", + n_internal_partitions + j + ); + assert!( + parameters.micro_params.ks[n_internal_partitions + j][i].is_some(), + "External -> Internal Ksk[{},{i}] missing.", + n_internal_partitions + j + ); + } + } ExpandedCircuitKeys::of(¶meters).compacted() } @@ -146,9 +250,12 @@ pub fn generate_virtual_parameters( mod test { use super::*; use crate::computing_cost::cpu::CpuComplexity; + use crate::optimization::dag::multi_parameters::partitionning::tests::{ + get_tfhers_noise_br, TFHERS_MACRO_PARAMS, + }; #[test] - fn test_generate_generic_parameters() { + fn test_generate_generic_parameters_without_externals() { let config = Config { security_level: 128, maximum_acceptable_error_probability: _4_SIGMA, @@ -159,20 +266,52 @@ mod test { }; let _a = generate_virtual_parameters( vec![ - PartitionDefinition { + InternalPartition { precision: 3, - norm2: 1., + norm2: 10., }, - PartitionDefinition { - precision: 3, + InternalPartition { + precision: 4, norm2: 100., }, - PartitionDefinition { + InternalPartition { + precision: 5, + norm2: 100., + }, + ], + vec![], + config, + ); + } + + #[test] + fn test_generate_generic_parameters_with_external() { + let config = Config { + security_level: 128, + maximum_acceptable_error_probability: _4_SIGMA, + key_sharing: true, + ciphertext_modulus_log: 64, + fft_precision: 53, + complexity_model: &CpuComplexity::default(), + }; + let variance = get_tfhers_noise_br(); + let _a = generate_virtual_parameters( + vec![ + InternalPartition { precision: 3, - norm2: 1000., + norm2: 10., + }, + InternalPartition { + precision: 5, + norm2: 100., }, ], - true, + vec![ExternalPartition { + name: String::from("tfhers"), + macro_params: TFHERS_MACRO_PARAMS, + max_variance: variance, + variance, + }], config, ); } diff --git a/compilers/concrete-optimizer/concrete-optimizer/src/utils/viz.rs b/compilers/concrete-optimizer/concrete-optimizer/src/utils/viz.rs index 0e726f9dd3..aeb4f75ff5 100644 --- a/compilers/concrete-optimizer/concrete-optimizer/src/utils/viz.rs +++ b/compilers/concrete-optimizer/concrete-optimizer/src/utils/viz.rs @@ -125,6 +125,27 @@ impl Viz for crate::dag::unparametrized::DagOperator<'_> { } } +impl Viz for crate::optimization::dag::multi_parameters::partition_cut::PrePartitionDag { + fn viz_node(&self) -> String { + let mut output = self.dag.viz_node(); + self.p_cut + .rnorm2 + .iter() + .enumerate() + .for_each(|(i, rnorm2)| { + let circuit = &self.dag.circuit_tags[i]; + // let color = partition.0 + 1; + output.push_str(&format!("subgraph cluster_circuit_{circuit} {{\n")); + output.push_str(&format!("rnorm2_{i} [label =\"{rnorm2}\"];\n")); + output.push_str(&format!( + "rnorm2_{i} -> {i} [arrowhead=none, color=gray80, weight=99];\n" + )); + output.push_str("}\n"); + }); + output + } +} + impl Viz for crate::optimization::dag::multi_parameters::analyze::PartitionedDag { fn viz_node(&self) -> String { let mut output = self.dag.viz_node(); @@ -181,6 +202,38 @@ impl Viz for crate::optimization::dag::multi_parameters::analyze::VariancedDag { } } +impl Viz for crate::optimization::dag::multi_parameters::analyze::AnalyzedDag { + fn viz_node(&self) -> String { + let mut output = self.dag.viz_node(); + self.variance_constraints + .iter() + .enumerate() + .for_each(|(symb, constraint)| { + let i = constraint.operator_index.0; + let circuit = &self.dag.circuit_tags[i]; + let constraint_string = format!("{}", constraint); + let constraint_string = constraint_string.replace("<", "\\<"); + let constraint_string = constraint_string.replace("(", "|("); + let constraint_string = constraint_string.replace("|(2²)", "(2²)"); + let label = format!("\"{{Constraint | {constraint_string} }}\""); + output.push_str(&format!("subgraph cluster_circuit_{circuit} {{\n")); + let color = if self.undominated_variance_constraints.contains(constraint) { + "gray80".to_string() + } else { + "gray90".to_string() + }; + output.push_str(&format!( + "constraint_{symb} [label ={label} color=gray70 fillcolor={color}];\n" + )); + output.push_str(&format!( + "{i} -> constraint_{symb} [arrowhead=none, color=gray70, weight=99];\n" + )); + output.push_str("}\n"); + }); + output + } +} + macro_rules! _viz { ($path: expr, $object:expr) => {{ let mut path = std::env::temp_dir(); diff --git a/frontends/concrete-python/concrete/fhe/compilation/configuration.py b/frontends/concrete-python/concrete/fhe/compilation/configuration.py index 5d239c1597..083220e1a9 100644 --- a/frontends/concrete-python/concrete/fhe/compilation/configuration.py +++ b/frontends/concrete-python/concrete/fhe/compilation/configuration.py @@ -10,6 +10,22 @@ import numpy as np from mlir._mlir_libs._concretelang._compiler import KeysetRestriction, RangeRestriction +from concrete.compiler import ( + Backend, + ClientProgram, + CompilationContext, + CompilationOptions, + Compiler, + KeyType, + Library, + MoreCircuitCompilationFeedback, + OptimizerMultiParameterStrategy, + OptimizerStrategy, + Parameter, + PrimitiveOperation, + ProgramInfo, + ServerProgram, +) from ..dtypes import Integer from ..representation import GraphProcessor @@ -1292,6 +1308,83 @@ def fork( } ) + def to_compilation_options(self) -> CompilationOptions: + + backend = Backend.GPU if self.use_gpu else Backend.CPU + options = CompilationOptions(backend) + options.set_loop_parallelize(self.loop_parallelize) + options.set_dataflow_parallelize(self.dataflow_parallelize) + options.set_auto_parallelize(self.auto_parallelize) + options.set_compress_evaluation_keys(self.compress_evaluation_keys) + options.set_compress_input_ciphertexts(self.compress_input_ciphertexts) + options.set_enable_overflow_detection_in_simulation( + self.detect_overflow_in_simulation + ) + options.set_composable(self.composable) + + + global_p_error_is_set = self.global_p_error is not None + p_error_is_set = self.p_error is not None + + if global_p_error_is_set and p_error_is_set: # pragma: no cover + options.set_global_p_error(self.global_p_error) + options.set_p_error(self.p_error) + + elif global_p_error_is_set: # pragma: no cover + options.set_global_p_error(self.global_p_error) + options.set_p_error(1.0) + + elif p_error_is_set: # pragma: no cover + options.set_global_p_error(1.0) + options.set_p_error(self.p_error) + + else: # pragma: no cover + if DEFAULT_GLOBAL_P_ERROR is not None: + options.set_global_p_error(DEFAULT_GLOBAL_P_ERROR) + else: + options.set_global_p_error(1.0) + + if DEFAULT_P_ERROR is not None: + options.set_p_error(DEFAULT_P_ERROR) + else: + options.set_p_error(1.0) + + show_optimizer = ( + self.show_optimizer + if self.show_optimizer is not None + else self.verbose + ) + options.set_display_optimizer_choice(show_optimizer) + + parameter_selection_strategy = self.parameter_selection_strategy + if parameter_selection_strategy == ParameterSelectionStrategy.V0: # pragma: no cover + options.set_optimizer_strategy(OptimizerStrategy.V0) + elif parameter_selection_strategy == ParameterSelectionStrategy.MONO: # pragma: no cover + options.set_optimizer_strategy(OptimizerStrategy.DAG_MONO) + elif parameter_selection_strategy == ParameterSelectionStrategy.MULTI: # pragma: no cover + options.set_optimizer_strategy(OptimizerStrategy.DAG_MULTI) + + multi_parameter_strategy = self.multi_parameter_strategy + converter = { + MultiParameterStrategy.PRECISION: OptimizerMultiParameterStrategy.PRECISION, + MultiParameterStrategy.PRECISION_AND_NORM2: ( + OptimizerMultiParameterStrategy.PRECISION_AND_NORM2 + ), + } + options.set_optimizer_multi_parameter_strategy(converter[multi_parameter_strategy]) + + options.set_enable_tlu_fusing(self.enable_tlu_fusing) + options.set_print_tlu_fusing(self.print_tlu_fusing) + if self.keyset_restriction: + options.set_keyset_restriction(self.keyset_restriction) + + if self.range_restriction: + options.set_range_restriction(self.range_restriction) + + options.set_security_level(self.security_level) + + return options + def _validate(self): """ Validate configuration. diff --git a/frontends/concrete-python/concrete/fhe/compilation/server.py b/frontends/concrete-python/concrete/fhe/compilation/server.py index 2a79696ea8..151444df5c 100644 --- a/frontends/concrete-python/concrete/fhe/compilation/server.py +++ b/frontends/concrete-python/concrete/fhe/compilation/server.py @@ -107,87 +107,17 @@ def create( composition rules to be applied when compiling """ - backend = Backend.GPU if configuration.use_gpu else Backend.CPU - options = CompilationOptions(backend) + options = configuration.to_compilation_options() + options.simulation(is_simulated) - options.set_loop_parallelize(configuration.loop_parallelize) - options.set_dataflow_parallelize(configuration.dataflow_parallelize) - options.set_auto_parallelize(configuration.auto_parallelize) - options.set_compress_evaluation_keys(configuration.compress_evaluation_keys) - options.set_compress_input_ciphertexts(configuration.compress_input_ciphertexts) - options.set_enable_overflow_detection_in_simulation( - configuration.detect_overflow_in_simulation - ) - options.set_composable(configuration.composable) composition_rules = list(composition_rules) if composition_rules else [] for rule in composition_rules: options.add_composition(rule.from_.func, rule.from_.pos, rule.to.func, rule.to.pos) - if configuration.auto_parallelize or configuration.dataflow_parallelize: # pylint: disable=c-extension-no-member,no-member concrete.compiler.init_dfr() # pylint: enable=c-extension-no-member,no-member - global_p_error_is_set = configuration.global_p_error is not None - p_error_is_set = configuration.p_error is not None - - if global_p_error_is_set and p_error_is_set: # pragma: no cover - options.set_global_p_error(configuration.global_p_error) - options.set_p_error(configuration.p_error) - - elif global_p_error_is_set: # pragma: no cover - options.set_global_p_error(configuration.global_p_error) - options.set_p_error(1.0) - - elif p_error_is_set: # pragma: no cover - options.set_global_p_error(1.0) - options.set_p_error(configuration.p_error) - - else: # pragma: no cover - if DEFAULT_GLOBAL_P_ERROR is not None: - options.set_global_p_error(DEFAULT_GLOBAL_P_ERROR) - else: - options.set_global_p_error(1.0) - - if DEFAULT_P_ERROR is not None: - options.set_p_error(DEFAULT_P_ERROR) - else: - options.set_p_error(1.0) - - show_optimizer = ( - configuration.show_optimizer - if configuration.show_optimizer is not None - else configuration.verbose - ) - options.set_display_optimizer_choice(show_optimizer) - - parameter_selection_strategy = configuration.parameter_selection_strategy - if parameter_selection_strategy == ParameterSelectionStrategy.V0: # pragma: no cover - options.set_optimizer_strategy(OptimizerStrategy.V0) - elif parameter_selection_strategy == ParameterSelectionStrategy.MONO: # pragma: no cover - options.set_optimizer_strategy(OptimizerStrategy.DAG_MONO) - elif parameter_selection_strategy == ParameterSelectionStrategy.MULTI: # pragma: no cover - options.set_optimizer_strategy(OptimizerStrategy.DAG_MULTI) - - multi_parameter_strategy = configuration.multi_parameter_strategy - converter = { - MultiParameterStrategy.PRECISION: OptimizerMultiParameterStrategy.PRECISION, - MultiParameterStrategy.PRECISION_AND_NORM2: ( - OptimizerMultiParameterStrategy.PRECISION_AND_NORM2 - ), - } - options.set_optimizer_multi_parameter_strategy(converter[multi_parameter_strategy]) - - options.set_enable_tlu_fusing(configuration.enable_tlu_fusing) - options.set_print_tlu_fusing(configuration.print_tlu_fusing) - if configuration.keyset_restriction: - options.set_keyset_restriction(configuration.keyset_restriction) - - if configuration.range_restriction: - options.set_range_restriction(configuration.range_restriction) - - options.set_security_level(configuration.security_level) - try: if configuration.compiler_debug_mode: # pragma: no cover set_llvm_debug_flag(True) diff --git a/frontends/concrete-python/concrete/fhe/tfhers/dtypes.py b/frontends/concrete-python/concrete/fhe/tfhers/dtypes.py index 36134526a9..feef6e6be6 100644 --- a/frontends/concrete-python/concrete/fhe/tfhers/dtypes.py +++ b/frontends/concrete-python/concrete/fhe/tfhers/dtypes.py @@ -5,10 +5,12 @@ from enum import Enum from functools import partial from typing import Any, Union +import math import numpy as np from ..dtypes import Integer +from mlir._mlir_libs._concretelang._compiler import ExternalPartitionDefinition class EncryptionKeyChoice(Enum): @@ -212,6 +214,23 @@ def decode(self, value: Union[list, np.ndarray]) -> Union[int, np.ndarray]: cts = value.reshape((-1, expected_ct_shape)) return np.array([self.decode(ct) for ct in cts]).reshape(value.shape[:-1]) + def external_partition_definition(self) -> ExternalPartitionDefinition: + """Get the associated external partition definition. + + This will return the associated external partition definition to be used in a virtual circuit generation. + + Returns: + ExternalPartitionDefinition: The definition + """ + return ExternalPartitionDefinition( + f"TFHERS_{self.carry_width}_{self.msg_width}", + int(math.log2(self.params.polynomial_size)), + self.params.glwe_dimension, + self.params.lwe_dimension, + self.params.pbs_level, + self.params.pbs_base_log + ) + int8 = partial(TFHERSIntegerType, True, 8) uint8 = partial(TFHERSIntegerType, False, 8) diff --git a/frontends/concrete-python/tests/compilation/test_restrictions.py b/frontends/concrete-python/tests/compilation/test_restrictions.py index 4e06ef97f1..5cb66d10bc 100644 --- a/frontends/concrete-python/tests/compilation/test_restrictions.py +++ b/frontends/concrete-python/tests/compilation/test_restrictions.py @@ -2,16 +2,19 @@ Tests of everything related to restrictions. """ +import math import numpy as np import pytest from mlir._mlir_libs._concretelang._compiler import ( KeysetInfo, KeysetRestriction, - PartitionDefinition, + InternalPartitionDefinition, + ExternalPartitionDefinition, RangeRestriction, ) from concrete import fhe +from concrete.fhe import tfhers # pylint: disable=missing-class-docstring, missing-function-docstring, no-self-argument, unused-variable, no-member, unused-argument, function-redefined, expression-not-assigned # same disables for ruff: @@ -103,13 +106,13 @@ def inc(x): assert small_keyset_info != restricted_keyset_info -def test_generic_restriction(): +def test_generic_restriction_without_external(): """ Test that compiling a module works. """ generic_keyset_info = KeysetInfo.generate_virtual( - [PartitionDefinition(8, 10.0), PartitionDefinition(10, 10000.0)], True + [InternalPartitionDefinition(8, 10.0), InternalPartitionDefinition(10, 10000.0)], [] ) @fhe.module() @@ -126,3 +129,67 @@ def inc(x): ) compiled_keyset_info = restricted_module.keys.specs.program_info.get_keyset_info() assert all([k in generic_keyset_info.secret_keys() for k in compiled_keyset_info.secret_keys()]) + + +def test_generic_restriction_with_external(helpers): + """ + Test that compiling a module works. + """ + + dtype = tfhers.TFHERSIntegerType( + False, + bit_width=8, + carry_width=3, + msg_width=2, + params=tfhers.CryptoParams( + lwe_dimension=909, + glwe_dimension=1, + polynomial_size=4096, + pbs_base_log=15, + pbs_level=2, + lwe_noise_distribution=0, + glwe_noise_distribution=2.168404344971009e-19, + encryption_key_choice=tfhers.EncryptionKeyChoice.BIG, + ), + ) + config = helpers.configuration() + options = config.to_compilation_options().get_optimizer_options() + + generic_keyset_info = KeysetInfo.generate_virtual( + [ + InternalPartitionDefinition(3, 10.0), + InternalPartitionDefinition(5, 10.0) + ], + [ + dtype.external_partition_definition() + ], + options + ) + + parameters = { + "x": {"range": [0, 2**7], "status": "encrypted"}, + "y": {"range": [0, 2**7], "status": "encrypted"}, + } + + parameter_encryption_statuses = helpers.generate_encryption_statuses(parameters) + + def binary_tfhers(x, y, binary_op, tfhers_type): + """wrap binary op in tfhers conversion (2 tfhers inputs)""" + x = tfhers.to_native(x) + y = tfhers.to_native(y) + return tfhers.from_native(binary_op(x, y), tfhers_type) + + compiler = fhe.Compiler( + lambda x, y: binary_tfhers(x, y, lambda x, y: x + y, dtype), + parameter_encryption_statuses, + ) + + inputset = [ + tuple(tfhers.TFHERSInteger(dtype, arg) for arg in inpt) + for inpt in helpers.generate_inputset(parameters) + ] + + circuit = compiler.compile(inputset, config, keyset_restriction=generic_keyset_info.get_restriction()) + + compiled_keyset_info = circuit._module.keys.specs.program_info.get_keyset_info() + assert all([k in generic_keyset_info.secret_keys() for k in compiled_keyset_info.secret_keys()])