From cffe5e4ab04c3c995825fc232bb4ec2a013bedf1 Mon Sep 17 00:00:00 2001 From: rudy Date: Tue, 31 May 2022 10:33:53 +0200 Subject: [PATCH] feat(cpp): expose dag optimization --- .../src/concrete-optimizer.rs | 37 ++++++ .../src/cpp/concrete-optimizer.cpp | 107 +++++++++++++++++- .../src/cpp/concrete-optimizer.hpp | 73 +++++++++++- concrete-optimizer/src/dag/unparametrized.rs | 14 ++- 4 files changed, 226 insertions(+), 5 deletions(-) diff --git a/concrete-optimizer-cpp/src/concrete-optimizer.rs b/concrete-optimizer-cpp/src/concrete-optimizer.rs index 2c6781cab..ab4b5e7f4 100644 --- a/concrete-optimizer-cpp/src/concrete-optimizer.rs +++ b/concrete-optimizer-cpp/src/concrete-optimizer.rs @@ -119,6 +119,35 @@ impl OperationDag { .add_levelled_op(inputs, complexity, manp, out_shape, comment) .into() } + + fn optimize_v0( + &self, + security_level: u64, + maximum_acceptable_error_probability: f64, + ) -> ffi::Solution { + use concrete_optimizer::global_parameters::DEFAUT_DOMAINS; + let glwe_log_polynomial_sizes = DEFAUT_DOMAINS + .glwe_pbs_constrained + .log2_polynomial_size + .as_vec(); + let glwe_dimensions = DEFAUT_DOMAINS.glwe_pbs_constrained.glwe_dimension.as_vec(); + let internal_lwe_dimensions = DEFAUT_DOMAINS.free_glwe.glwe_dimension.as_vec(); + let result = concrete_optimizer::optimization::dag::solo_key::optimize::optimize::( + &self.0, + security_level, + maximum_acceptable_error_probability, + &glwe_log_polynomial_sizes, + &glwe_dimensions, + &internal_lwe_dimensions, + ); + result + .best_solution + .map_or_else(no_solution, |solution| solution.into()) + } + + fn dump(&self) -> String { + self.0.dump() + } } pub struct Weights(operator::Weights); @@ -188,6 +217,14 @@ mod ffi { comment: &str, ) -> OperatorIndex; + fn optimize_v0( + self: &OperationDag, + security_level: u64, + maximum_acceptable_error_probability: f64, + ) -> Solution; + + fn dump(self: &OperationDag) -> String; + type Weights; #[namespace = "concrete_optimizer::weights"] diff --git a/concrete-optimizer-cpp/src/cpp/concrete-optimizer.cpp b/concrete-optimizer-cpp/src/cpp/concrete-optimizer.cpp index 12d69195c..0b8ca78a3 100644 --- a/concrete-optimizer-cpp/src/cpp/concrete-optimizer.cpp +++ b/concrete-optimizer-cpp/src/cpp/concrete-optimizer.cpp @@ -19,18 +19,85 @@ template void panic [[noreturn]] (const char *msg); #endif // CXXBRIDGE1_PANIC +struct unsafe_bitcopy_t; + namespace { template class impl; } // namespace -class String; - template ::std::size_t size_of(); template ::std::size_t align_of(); +#ifndef CXXBRIDGE1_RUST_STRING +#define CXXBRIDGE1_RUST_STRING +class String final { +public: + String() noexcept; + String(const String &) noexcept; + String(String &&) noexcept; + ~String() noexcept; + + String(const std::string &); + String(const char *); + String(const char *, std::size_t); + String(const char16_t *); + String(const char16_t *, std::size_t); + + static String lossy(const std::string &) noexcept; + static String lossy(const char *) noexcept; + static String lossy(const char *, std::size_t) noexcept; + static String lossy(const char16_t *) noexcept; + static String lossy(const char16_t *, std::size_t) noexcept; + + String &operator=(const String &) &noexcept; + String &operator=(String &&) &noexcept; + + explicit operator std::string() const; + + const char *data() const noexcept; + std::size_t size() const noexcept; + std::size_t length() const noexcept; + bool empty() const noexcept; + + const char *c_str() noexcept; + + std::size_t capacity() const noexcept; + void reserve(size_t new_cap) noexcept; + + using iterator = char *; + iterator begin() noexcept; + iterator end() noexcept; + + using const_iterator = const char *; + const_iterator begin() const noexcept; + const_iterator end() const noexcept; + const_iterator cbegin() const noexcept; + const_iterator cend() const noexcept; + + bool operator==(const String &) const noexcept; + bool operator!=(const String &) const noexcept; + bool operator<(const String &) const noexcept; + bool operator<=(const String &) const noexcept; + bool operator>(const String &) const noexcept; + bool operator>=(const String &) const noexcept; + + void swap(String &) noexcept; + + String(unsafe_bitcopy_t, const String &) noexcept; + +private: + struct lossy_t; + String(lossy_t, const char *, std::size_t) noexcept; + String(lossy_t, const char16_t *, std::size_t) noexcept; + friend void swap(String &lhs, String &rhs) noexcept { lhs.swap(rhs); } + + std::array repr; +}; +#endif // CXXBRIDGE1_RUST_STRING + #ifndef CXXBRIDGE1_RUST_STR #define CXXBRIDGE1_RUST_STR class Str final { @@ -601,6 +668,26 @@ std::size_t align_of() { return layout::align_of(); } #endif // CXXBRIDGE1_LAYOUT + +namespace detail { +template +struct operator_new { + void *operator()(::std::size_t sz) { return ::operator new(sz); } +}; + +template +struct operator_new { + void *operator()(::std::size_t sz) { return T::operator new(sz); } +}; +} // namespace detail + +template +union MaybeUninit { + T value; + void *operator new(::std::size_t sz) { return detail::operator_new{}(sz); } + MaybeUninit() {} + ~MaybeUninit() {} +}; } // namespace cxxbridge1 } // namespace rust @@ -623,6 +710,8 @@ struct OperationDag final : public ::rust::Opaque { ::concrete_optimizer::dag::OperatorIndex add_lut(::concrete_optimizer::dag::OperatorIndex input, ::rust::Slice table, ::std::uint8_t out_precision) noexcept; ::concrete_optimizer::dag::OperatorIndex add_dot(::rust::Slice inputs, ::rust::Box<::concrete_optimizer::Weights> weights) noexcept; ::concrete_optimizer::dag::OperatorIndex add_levelled_op(::rust::Slice inputs, double lwe_dim_cost_factor, double fixed_cost, double manp, ::rust::Slice out_shape, ::rust::Str comment) noexcept; + ::concrete_optimizer::v0::Solution optimize_v0(::std::uint64_t security_level, double maximum_acceptable_error_probability) const noexcept; + ::rust::String dump() const noexcept; ~OperationDag() = delete; private: @@ -703,6 +792,10 @@ extern "C" { ::concrete_optimizer::dag::OperatorIndex concrete_optimizer$cxxbridge1$OperationDag$add_dot(::concrete_optimizer::OperationDag &self, ::rust::Slice inputs, ::concrete_optimizer::Weights *weights) noexcept; ::concrete_optimizer::dag::OperatorIndex concrete_optimizer$cxxbridge1$OperationDag$add_levelled_op(::concrete_optimizer::OperationDag &self, ::rust::Slice inputs, double lwe_dim_cost_factor, double fixed_cost, double manp, ::rust::Slice out_shape, ::rust::Str comment) noexcept; + +::concrete_optimizer::v0::Solution concrete_optimizer$cxxbridge1$OperationDag$optimize_v0(const ::concrete_optimizer::OperationDag &self, ::std::uint64_t security_level, double maximum_acceptable_error_probability) noexcept; + +void concrete_optimizer$cxxbridge1$OperationDag$dump(const ::concrete_optimizer::OperationDag &self, ::rust::String *return$) noexcept; ::std::size_t concrete_optimizer$cxxbridge1$Weights$operator$sizeof() noexcept; ::std::size_t concrete_optimizer$cxxbridge1$Weights$operator$alignof() noexcept; } // extern "C" @@ -749,6 +842,16 @@ namespace dag { return concrete_optimizer$cxxbridge1$OperationDag$add_levelled_op(*this, inputs, lwe_dim_cost_factor, fixed_cost, manp, out_shape, comment); } +::concrete_optimizer::v0::Solution OperationDag::optimize_v0(::std::uint64_t security_level, double maximum_acceptable_error_probability) const noexcept { + return concrete_optimizer$cxxbridge1$OperationDag$optimize_v0(*this, security_level, maximum_acceptable_error_probability); +} + +::rust::String OperationDag::dump() const noexcept { + ::rust::MaybeUninit<::rust::String> return$; + concrete_optimizer$cxxbridge1$OperationDag$dump(*this, &return$.value); + return ::std::move(return$.value); +} + ::std::size_t Weights::layout::size() noexcept { return concrete_optimizer$cxxbridge1$Weights$operator$sizeof(); } diff --git a/concrete-optimizer-cpp/src/cpp/concrete-optimizer.hpp b/concrete-optimizer-cpp/src/cpp/concrete-optimizer.hpp index c58c2bc15..8deaea1fe 100644 --- a/concrete-optimizer-cpp/src/cpp/concrete-optimizer.hpp +++ b/concrete-optimizer-cpp/src/cpp/concrete-optimizer.hpp @@ -20,18 +20,85 @@ template void panic [[noreturn]] (const char *msg); #endif // CXXBRIDGE1_PANIC +struct unsafe_bitcopy_t; + namespace { template class impl; } // namespace -class String; - template ::std::size_t size_of(); template ::std::size_t align_of(); +#ifndef CXXBRIDGE1_RUST_STRING +#define CXXBRIDGE1_RUST_STRING +class String final { +public: + String() noexcept; + String(const String &) noexcept; + String(String &&) noexcept; + ~String() noexcept; + + String(const std::string &); + String(const char *); + String(const char *, std::size_t); + String(const char16_t *); + String(const char16_t *, std::size_t); + + static String lossy(const std::string &) noexcept; + static String lossy(const char *) noexcept; + static String lossy(const char *, std::size_t) noexcept; + static String lossy(const char16_t *) noexcept; + static String lossy(const char16_t *, std::size_t) noexcept; + + String &operator=(const String &) &noexcept; + String &operator=(String &&) &noexcept; + + explicit operator std::string() const; + + const char *data() const noexcept; + std::size_t size() const noexcept; + std::size_t length() const noexcept; + bool empty() const noexcept; + + const char *c_str() noexcept; + + std::size_t capacity() const noexcept; + void reserve(size_t new_cap) noexcept; + + using iterator = char *; + iterator begin() noexcept; + iterator end() noexcept; + + using const_iterator = const char *; + const_iterator begin() const noexcept; + const_iterator end() const noexcept; + const_iterator cbegin() const noexcept; + const_iterator cend() const noexcept; + + bool operator==(const String &) const noexcept; + bool operator!=(const String &) const noexcept; + bool operator<(const String &) const noexcept; + bool operator<=(const String &) const noexcept; + bool operator>(const String &) const noexcept; + bool operator>=(const String &) const noexcept; + + void swap(String &) noexcept; + + String(unsafe_bitcopy_t, const String &) noexcept; + +private: + struct lossy_t; + String(lossy_t, const char *, std::size_t) noexcept; + String(lossy_t, const char16_t *, std::size_t) noexcept; + friend void swap(String &lhs, String &rhs) noexcept { lhs.swap(rhs); } + + std::array repr; +}; +#endif // CXXBRIDGE1_RUST_STRING + #ifndef CXXBRIDGE1_RUST_STR #define CXXBRIDGE1_RUST_STR class Str final { @@ -624,6 +691,8 @@ struct OperationDag final : public ::rust::Opaque { ::concrete_optimizer::dag::OperatorIndex add_lut(::concrete_optimizer::dag::OperatorIndex input, ::rust::Slice table, ::std::uint8_t out_precision) noexcept; ::concrete_optimizer::dag::OperatorIndex add_dot(::rust::Slice inputs, ::rust::Box<::concrete_optimizer::Weights> weights) noexcept; ::concrete_optimizer::dag::OperatorIndex add_levelled_op(::rust::Slice inputs, double lwe_dim_cost_factor, double fixed_cost, double manp, ::rust::Slice out_shape, ::rust::Str comment) noexcept; + ::concrete_optimizer::v0::Solution optimize_v0(::std::uint64_t security_level, double maximum_acceptable_error_probability) const noexcept; + ::rust::String dump() const noexcept; ~OperationDag() = delete; private: diff --git a/concrete-optimizer/src/dag/unparametrized.rs b/concrete-optimizer/src/dag/unparametrized.rs index de6d4e028..be9f108df 100644 --- a/concrete-optimizer/src/dag/unparametrized.rs +++ b/concrete-optimizer/src/dag/unparametrized.rs @@ -1,10 +1,12 @@ +use std::fmt::Write; + use crate::dag::operator::{ FunctionTable, LevelledComplexity, Operator, OperatorIndex, Precision, Shape, Weights, }; pub(crate) type UnparameterizedOperator = Operator<(), (), (), ()>; -#[derive(Clone, PartialEq)] +#[derive(Clone, PartialEq, Debug)] #[must_use] pub struct OperationDag { pub(crate) operators: Vec, @@ -88,6 +90,16 @@ impl OperationDag { pub fn len(&self) -> usize { self.operators.len() } + + pub fn dump(&self) -> String { + let mut acc = String::new(); + let err_msg = "Optimizer: Can't dump OperationDag"; + writeln!(acc, "Dag:").expect(err_msg); + for (i, op) in self.operators.iter().enumerate() { + writeln!(acc, "%{i} <- {op:?}").expect(err_msg); + } + acc + } } #[cfg(test)]