From 0ca92d7c4c6ed138d04999c9c6167c98e55776ef Mon Sep 17 00:00:00 2001 From: "Mayeul@Zama" Date: Fri, 8 Jul 2022 16:41:52 +0200 Subject: [PATCH] feat: add chart binaries --- Cargo.toml | 3 +- charts/Cargo.toml | 22 ++++++ charts/src/bin/norm2_complexity.rs | 89 +++++++++++++++++++++++++ charts/src/bin/precision_complexity.rs | 92 ++++++++++++++++++++++++++ charts/src/lib.rs | 86 ++++++++++++++++++++++++ v0-parameters/src/lib.rs | 8 +-- 6 files changed, 295 insertions(+), 5 deletions(-) create mode 100644 charts/Cargo.toml create mode 100644 charts/src/bin/norm2_complexity.rs create mode 100644 charts/src/bin/precision_complexity.rs create mode 100644 charts/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index e15a6d47b..58228ceb2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ members = [ "concrete-optimizer", "v0-parameters", - "concrete-optimizer-cpp" + "concrete-optimizer-cpp", + "charts", ] diff --git a/charts/Cargo.toml b/charts/Cargo.toml new file mode 100644 index 000000000..89bb41b96 --- /dev/null +++ b/charts/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "charts" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +concrete-optimizer = { path ="../concrete-optimizer" } +plotters = "0.3.1" + +[lib] +crate-type= [ + "lib", # rust +] + +[[bin]] +name = "precision_complexity" + +[[bin]] +name = "norm2_complexity" + diff --git a/charts/src/bin/norm2_complexity.rs b/charts/src/bin/norm2_complexity.rs new file mode 100644 index 000000000..db7df7be1 --- /dev/null +++ b/charts/src/bin/norm2_complexity.rs @@ -0,0 +1,89 @@ +use charts::{draw, Serie}; +use concrete_optimizer::computing_cost::cpu::CpuComplexity; +use concrete_optimizer::global_parameters::DEFAUT_DOMAINS; +use concrete_optimizer::optimization::atomic_pattern::{self as optimize_atomic_pattern}; +use concrete_optimizer::optimization::config::{Config, SearchSpace}; +use concrete_optimizer::optimization::wop_atomic_pattern::optimize as optimize_wop_atomic_pattern; + +pub const _4_SIGMA: f64 = 1.0 - 0.999_936_657_516; +const MIN_LOG_POLY_SIZE: u64 = DEFAUT_DOMAINS + .glwe_pbs_constrained + .log2_polynomial_size + .start as u64; +const MAX_LOG_POLY_SIZE: u64 = + DEFAUT_DOMAINS.glwe_pbs_constrained.log2_polynomial_size.end as u64 - 1; +pub const MAX_GLWE_DIM: u64 = DEFAUT_DOMAINS.glwe_pbs_constrained.glwe_dimension.end - 1; +pub const MIN_LWE_DIM: u64 = DEFAUT_DOMAINS.free_glwe.glwe_dimension.start as u64; +pub const MAX_LWE_DIM: u64 = DEFAUT_DOMAINS.free_glwe.glwe_dimension.end as u64 - 1; + +fn main() -> Result<(), Box> { + let sum_size = 4096; + let p_error = _4_SIGMA; + let security_level = 128; + let glwe_log_polynomial_sizes: Vec<_> = (MIN_LOG_POLY_SIZE..=MAX_LOG_POLY_SIZE).collect(); + let glwe_dimensions: Vec<_> = (1..=6).collect(); + let internal_lwe_dimensions: Vec<_> = (MIN_LWE_DIM..=MAX_LWE_DIM).step_by(10).collect(); + + let search_space = SearchSpace { + glwe_log_polynomial_sizes, + glwe_dimensions, + internal_lwe_dimensions, + }; + + let precision = 8; + let log_norm2s = 1_u64..=31; + + let config = Config { + security_level, + maximum_acceptable_error_probability: p_error, + ciphertext_modulus_log: 64, + complexity_model: &CpuComplexity::default(), + }; + + let solutions: Vec<_> = log_norm2s + .clone() + .filter_map(|log_norm2| { + let noise_scale = 2_f64.powi(log_norm2 as i32); + + optimize_atomic_pattern::optimize_one( + sum_size, + precision, + config, + noise_scale, + &search_space, + ) + .best_solution + .map(|a| (log_norm2, a.complexity)) + }) + .collect(); + + let wop_solutions: Vec<_> = log_norm2s + .filter_map(|log_norm2| { + let noise_scale = 2_f64.powi(log_norm2 as i32); + + optimize_wop_atomic_pattern::optimize_one(precision, config, noise_scale, &search_space) + .best_solution + .map(|a| (log_norm2, a.complexity)) + }) + .collect(); + + draw( + "comparison_cggi_bbbclot_norm2_vs_complexity.png", + &format!("Comparison CGGI vs BBBCLOT for precision={precision}"), + &[ + Serie { + label: "CGGI AP Complexity".to_owned(), + values: solutions, + }, + Serie { + label: "BBBCLOT AP Complexity".to_owned(), + values: wop_solutions, + }, + ], + (1024, 1024), + "Log Norm2", + "Complexity", + )?; + + Ok(()) +} diff --git a/charts/src/bin/precision_complexity.rs b/charts/src/bin/precision_complexity.rs new file mode 100644 index 000000000..2a82663bc --- /dev/null +++ b/charts/src/bin/precision_complexity.rs @@ -0,0 +1,92 @@ +use charts::{draw, Serie}; +use concrete_optimizer::computing_cost::cpu::CpuComplexity; +use concrete_optimizer::global_parameters::DEFAUT_DOMAINS; +use concrete_optimizer::optimization::atomic_pattern::{self as optimize_atomic_pattern}; +use concrete_optimizer::optimization::config::{Config, SearchSpace}; +use concrete_optimizer::optimization::wop_atomic_pattern::optimize as optimize_wop_atomic_pattern; + +pub const _4_SIGMA: f64 = 1.0 - 0.999_936_657_516; +const MIN_LOG_POLY_SIZE: u64 = DEFAUT_DOMAINS + .glwe_pbs_constrained + .log2_polynomial_size + .start as u64; +const MAX_LOG_POLY_SIZE: u64 = + DEFAUT_DOMAINS.glwe_pbs_constrained.log2_polynomial_size.end as u64 - 1; +pub const MAX_GLWE_DIM: u64 = DEFAUT_DOMAINS.glwe_pbs_constrained.glwe_dimension.end - 1; +pub const MIN_LWE_DIM: u64 = DEFAUT_DOMAINS.free_glwe.glwe_dimension.start as u64; +pub const MAX_LWE_DIM: u64 = DEFAUT_DOMAINS.free_glwe.glwe_dimension.end as u64 - 1; + +fn main() -> Result<(), Box> { + let sum_size = 4096; + let p_error = _4_SIGMA; + let security_level = 128; + let glwe_log_polynomial_sizes: Vec<_> = (MIN_LOG_POLY_SIZE..=MAX_LOG_POLY_SIZE).collect(); + let glwe_dimensions: Vec<_> = (1..=6).collect(); + let internal_lwe_dimensions: Vec<_> = (MIN_LWE_DIM..=MAX_LWE_DIM).step_by(10).collect(); + + let precisions = 1..=16; + let log_norm2 = 10; + + let search_space = SearchSpace { + glwe_log_polynomial_sizes, + glwe_dimensions, + internal_lwe_dimensions, + }; + + let config = Config { + security_level, + maximum_acceptable_error_probability: p_error, + ciphertext_modulus_log: 64, + complexity_model: &CpuComplexity::default(), + }; + + let solutions: Vec<_> = precisions + .clone() + .filter_map(|precision| { + let noise_factor = (log_norm2 as f64).exp2(); + + optimize_atomic_pattern::optimize_one( + sum_size, + precision, + config, + noise_factor, + &search_space, + ) + .best_solution + .map(|a| (precision, a.complexity)) + }) + .collect(); + + let wop_solutions: Vec<_> = precisions + .filter_map(|precision| { + optimize_wop_atomic_pattern::optimize_one( + precision, + config, + log_norm2 as f64, + &search_space, + ) + .best_solution + .map(|a| (precision, a.complexity)) + }) + .collect(); + + draw( + "comparison_cggi_bbbclot_precision_vs_complexity.png", + &format!("Comparison CGGI vs BBBCLOT for log_norm2={log_norm2}"), + &[ + Serie { + label: "PBS Complexity".to_owned(), + values: solutions, + }, + Serie { + label: "WoPPBS Complexity".to_owned(), + values: wop_solutions, + }, + ], + (1024, 1024), + "Precision", + "Complexity", + )?; + + Ok(()) +} diff --git a/charts/src/lib.rs b/charts/src/lib.rs new file mode 100644 index 000000000..cf21c9aee --- /dev/null +++ b/charts/src/lib.rs @@ -0,0 +1,86 @@ +#![warn(clippy::nursery)] +#![warn(clippy::pedantic)] +#![warn(clippy::style)] +#![allow(clippy::cast_precision_loss)] // u64 to f64 +#![allow(clippy::cast_possible_truncation)] // u64 to usize +#![allow(clippy::cast_sign_loss)] +#![allow(clippy::must_use_candidate)] +#![allow(clippy::missing_panics_doc)] +#![allow(clippy::missing_errors_doc)] +#![allow(clippy::range_plus_one)] + +use plotters::prelude::*; + +pub struct Serie { + pub label: String, + pub values: Vec<(u64, f64)>, +} + +pub fn draw( + path: &str, + caption: &str, + series: &[Serie], + resolution: (u32, u32), + x_description: &str, + y_description: &str, +) -> Result<(), Box> { + let mut min_x = u64::MAX; + let mut max_x = 0; + + let mut min_y = f64::INFINITY; + let mut max_y = f64::NEG_INFINITY; + + for Serie { values, .. } in series.iter() { + for &(x, y) in values.iter() { + if x < min_x { + min_x = x; + } + if max_x < x { + max_x = x; + } + if y < min_y { + min_y = y; + } + if max_y < y { + max_y = y; + } + } + } + + let root = BitMapBackend::new(path, resolution).into_drawing_area(); + root.fill(&WHITE)?; + + let mut chart = ChartBuilder::on(&root) + .caption(caption, ("sans-serif", 25).into_font()) + .margin(5) + .x_label_area_size(50) + .y_label_area_size(100) + .build_cartesian_2d( + (min_x - 1)..(max_x + 1), + ((min_y / 2.)..(max_y * 2.)).log_scale(), + )?; + + chart + .configure_mesh() + .x_desc(x_description) + .y_desc(y_description) + .y_label_formatter(&|y| format!("{y:+e}")) + .draw()?; + + for (idx, Serie { label, values }) in series.iter().enumerate() { + let color = Palette99::pick(idx).mix(0.9); + + chart + .draw_series(LineSeries::new(values.clone(), color.filled()))? + .label(label) + .legend(move |(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], color.filled())); + } + + chart + .configure_series_labels() + .background_style(WHITE.mix(0.8)) + .border_style(BLACK) + .draw()?; + + Ok(()) +} diff --git a/v0-parameters/src/lib.rs b/v0-parameters/src/lib.rs index 26eb63786..12fa31d8e 100644 --- a/v0-parameters/src/lib.rs +++ b/v0-parameters/src/lib.rs @@ -94,7 +94,7 @@ pub fn all_results(args: &Args) -> Vec> { }; let precisions = args.min_precision..=args.max_precision; - let manps: Vec<_> = (0..=31).collect(); + let log_norms2: Vec<_> = (0..=31).collect(); // let guard = pprof::ProfilerGuard::new(100).unwrap(); @@ -110,10 +110,10 @@ pub fn all_results(args: &Args) -> Vec> { precisions_iter .map(|precision| { let mut last_solution = None; - manps + log_norms2 .iter() - .map(|&manp| { - let noise_scale = 2_f64.powi(manp); + .map(|&log_norm2| { + let noise_scale = 2_f64.powi(log_norm2); let result = if args.wop_pbs { optimize_wop_atomic_pattern::optimize_one_compat( sum_size,