feat: initial experimental wop-pbs

This commit is contained in:
rudy
2022-06-14 17:22:28 +02:00
committed by rudy-6-4
parent 8f2c21ddbe
commit b628cd64fb
8 changed files with 1189 additions and 14 deletions

View File

@@ -1 +1,2 @@
pub mod atomic_pattern;
pub mod wop_atomic_pattern;

View File

@@ -0,0 +1,43 @@
use concrete_commons::dispersion::{DispersionParameter, Variance};
use concrete_commons::key_kinds::BinaryKeyKind;
use concrete_commons::numeric::UnsignedInteger;
use concrete_npe::KeyDispersion;
use crate::parameters::PbsParameters;
use crate::utils::square;
pub fn estimate_packing_private_keyswitch<T>(
var_glwe: Variance,
var_ggsw: Variance,
param: PbsParameters,
) -> Variance
where
T: UnsignedInteger,
{
type K = BinaryKeyKind;
let l = param.br_decomposition_parameter.level as f64;
let b = (1 << param.br_decomposition_parameter.log2_base) as f64;
let n = (param.output_glwe_params.glwe_dimension * param.output_glwe_params.polynomial_size())
as f64; // param.internal_lwe_dimension.0 as f64;
let b2l = f64::powf(b, 2. * l);
let var_s_w = 1. / 4.;
let mean_s_w = 1. / 2.;
// println!("n = {}", n);
let res_1 =
(l * (n + 1.) * var_ggsw.get_modular_variance::<T>()) as f64 * (square(b) + 2.) / 12.;
#[allow(clippy::cast_possible_wrap)]
let log_q = T::BITS as i32;
let res_3 = ((square(f64::powi(2., log_q)) as f64 - b2l) / (12. * b2l)
* (1.
+ n * (K::variance_key_coefficient::<T>().get_modular_variance::<T>()
+ square(K::expectation_key_coefficient())))
+ n / 4. * K::variance_key_coefficient::<T>().get_modular_variance::<T>()
+ var_glwe.get_modular_variance::<T>())
* (var_s_w + square(mean_s_w));
let res_5 = var_s_w * (1. / 4. * square(1. - n * K::expectation_key_coefficient()));
Variance::from_modular_variance::<T>(res_1 + res_3 + res_5)
}

View File

@@ -1,2 +1,3 @@
pub mod atomic_pattern;
pub mod dag;
pub mod wop_atomic_pattern;

View File

@@ -0,0 +1,2 @@
pub mod optimize;
pub(self) mod pareto;

View File

@@ -0,0 +1,654 @@
use crate::computing_cost::complexity::Complexity;
use crate::computing_cost::operators::atomic_pattern as complexity_atomic_pattern;
use crate::computing_cost::operators::keyswitch_lwe::KeySwitchLWEComplexity;
use crate::computing_cost::operators::pbs::PbsComplexity;
use crate::noise_estimator::error::{
error_probability_of_sigma_scale, sigma_scale_of_error_probability,
};
use crate::noise_estimator::operators::atomic_pattern as noise_atomic_pattern;
use crate::noise_estimator::operators::wop_atomic_pattern::estimate_packing_private_keyswitch;
use crate::optimization::atomic_pattern;
use crate::optimization::wop_atomic_pattern::pareto::{
BR_BL, BR_BL_FOR_CB, CB_V1_BL, KS_BL, KS_BL_FOR_CB,
};
use crate::parameters::{
GlweParameters, KeyswitchParameters, KsDecompositionParameters, LweDimension, PbsParameters,
};
use crate::security;
use crate::utils::square;
use complexity_atomic_pattern::DEFAULT as DEFAULT_COMPLEXITY;
use concrete_commons::dispersion::{DispersionParameter, Variance};
use concrete_commons::numeric::UnsignedInteger;
use std::collections::HashMap;
pub fn find_p_error(kappa: f64, variance_max: f64, current_maximum_noise: f64) -> f64 {
let sigma = Variance(variance_max).get_standard_dev() * kappa;
let sigma_scale = sigma / Variance(current_maximum_noise).get_standard_dev();
error_probability_of_sigma_scale(sigma_scale)
}
#[derive(Clone, Debug)]
pub struct OptimizationState {
pub best_solution: Option<Solution>,
pub count_domain: usize,
}
#[derive(Clone, Debug)]
pub struct Solution {
pub input_lwe_dimension: u64,
//n_big
pub internal_ks_output_lwe_dimension: u64,
//n_small
pub ks_decomposition_level_count: u64,
//l(KS)
pub ks_decomposition_base_log: u64,
//b(KS)
pub glwe_polynomial_size: u64,
//N
pub glwe_dimension: u64,
//k
pub br_decomposition_level_count: u64,
//l(BR)
pub br_decomposition_base_log: u64,
//b(BR)
pub complexity: f64,
pub noise_max: f64,
pub p_error: f64,
// error probability
pub cb_decomposition_level_count: Option<u64>,
pub cb_decomposition_base_log: Option<u64>,
}
impl Solution {
pub fn init() -> Self {
Self {
input_lwe_dimension: 0,
internal_ks_output_lwe_dimension: 0,
ks_decomposition_level_count: 0,
ks_decomposition_base_log: 0,
glwe_polynomial_size: 0,
glwe_dimension: 0,
br_decomposition_level_count: 0,
br_decomposition_base_log: 0,
complexity: 0.,
noise_max: 0.0,
p_error: 0.0,
cb_decomposition_level_count: None,
cb_decomposition_base_log: None,
}
}
}
#[allow(clippy::type_complexity)]
#[derive(Debug)]
pub struct Tab {
pbs: HashMap<(u64, u64, u64, u64, u64), (f64, Complexity)>,
modulus_switching: HashMap<(u64, u64), (f64, f64)>,
key_switching: HashMap<(u64, u64, u64, u64, u64), (f64, Complexity)>,
// NEW VALUE MEMOIZED
pp_switching: HashMap<(u64, u64, u64, u64), (f64, Complexity)>,
}
#[allow(clippy::too_many_lines)]
pub fn tabulate_circuit_bootstrap<W: UnsignedInteger>(
security_level: u64,
maximum_acceptable_error_probability: f64,
glwe_log_polynomial_sizes: &[u64],
glwe_dimensions: &[u64],
internal_lwe_dimensions: &[u64],
) -> Tab {
assert_eq!(security_level, 128);
assert!(0.0 < maximum_acceptable_error_probability);
assert!(maximum_acceptable_error_probability < 1.0);
let ciphertext_modulus_log = W::BITS as u64;
let mut noise_cost_pbs = HashMap::new();
let mut noise_cost_modulus_switching = HashMap::new();
let mut noise_cost_key_switching = HashMap::new();
let mut noise_cost_pp_switching = HashMap::new();
for &glwe_dim in glwe_dimensions {
for &glwe_log_poly_size in glwe_log_polynomial_sizes {
assert!(8 <= glwe_log_poly_size);
assert!(glwe_log_poly_size < 18);
let glwe_poly_size = 1 << glwe_log_poly_size;
if glwe_dim * glwe_poly_size <= 1 << 13 {
let glwe_params = GlweParameters {
log2_polynomial_size: glwe_log_poly_size,
glwe_dimension: glwe_dim,
};
let variance_bsk = security::glwe::minimal_variance(
glwe_params,
ciphertext_modulus_log,
security_level,
);
for &internal_dim in internal_lwe_dimensions {
assert!(256 < internal_dim);
let variance_ksk = noise_atomic_pattern::variance_ksk(
internal_dim,
ciphertext_modulus_log,
security_level,
);
let noise_modulus_switching =
noise_atomic_pattern::estimate_modulus_switching_noise_with_binary_key::<W>(
internal_dim,
glwe_params.polynomial_size(),
)
.get_variance();
let _ = noise_cost_modulus_switching.insert(
(internal_dim, glwe_poly_size),
(noise_modulus_switching, 0.),
);
for &br_decomposition_parameter in BR_BL.iter() {
let pbs_parameters = PbsParameters {
internal_lwe_dimension: LweDimension(internal_dim),
br_decomposition_parameter,
output_glwe_params: glwe_params,
};
let complexity_pbs = DEFAULT_COMPLEXITY
.pbs
.complexity(pbs_parameters, ciphertext_modulus_log);
// let complexity_cmux =
// complexity_pbs / (pbs_parameters.internal_lwe_dimension.0 as f64);
// PBS of the first layer of the CB
let base_noise = noise_atomic_pattern::variance_bootstrap::<W>(
pbs_parameters,
ciphertext_modulus_log,
variance_bsk,
)
.get_variance();
let _ = noise_cost_pbs.insert(
(
glwe_dim,
glwe_poly_size,
internal_dim,
br_decomposition_parameter.log2_base,
br_decomposition_parameter.level,
),
(base_noise, complexity_pbs),
);
}
for &ks_decomposition_parameter in KS_BL_FOR_CB.iter() {
let keyswitch_parameter = KeyswitchParameters {
input_lwe_dimension: LweDimension(glwe_poly_size * glwe_dim),
output_lwe_dimension: LweDimension(internal_dim),
ks_decomposition_parameter,
};
let complexity_keyswitch = DEFAULT_COMPLEXITY
.ks_lwe
.complexity(keyswitch_parameter, ciphertext_modulus_log);
// Keyswitch before bootstrap
let noise_keyswitch = noise_atomic_pattern::variance_keyswitch::<W>(
keyswitch_parameter,
ciphertext_modulus_log,
variance_ksk,
)
.get_variance();
let _ = noise_cost_key_switching.insert(
(
glwe_dim,
glwe_poly_size,
internal_dim,
ks_decomposition_parameter.log2_base,
ks_decomposition_parameter.level,
),
(noise_keyswitch, complexity_keyswitch),
);
}
// let pp_ks_decomposition_parameter = pbs_parameters.br_decomposition_parameter;
for &pp_ks_decomposition_parameter in BR_BL.iter() {
let ppks_parameter = PbsParameters {
internal_lwe_dimension: LweDimension(
glwe_params.glwe_dimension * glwe_params.polynomial_size(),
),
br_decomposition_parameter: pp_ks_decomposition_parameter,
output_glwe_params: glwe_params,
};
// We assume the packing KS and theexternal product in a PBSto have
// the same parameters (base, level)
let noise_private_packing_ks = estimate_packing_private_keyswitch::<W>(
Variance(0.),
variance_bsk,
ppks_parameter,
)
.get_variance();
let ppks_parameter_complexity = KeyswitchParameters {
input_lwe_dimension: LweDimension(
glwe_params.glwe_dimension * glwe_params.polynomial_size(),
),
output_lwe_dimension: LweDimension(
glwe_params.glwe_dimension * glwe_params.polynomial_size(),
),
ks_decomposition_parameter: KsDecompositionParameters {
level: pp_ks_decomposition_parameter.level,
log2_base: pp_ks_decomposition_parameter.log2_base,
},
};
let complexity_ppks = DEFAULT_COMPLEXITY
.ks_lwe
.complexity(ppks_parameter_complexity, ciphertext_modulus_log);
let _ = noise_cost_pp_switching.insert(
(
glwe_dim,
glwe_poly_size,
pp_ks_decomposition_parameter.log2_base,
pp_ks_decomposition_parameter.level,
),
(noise_private_packing_ks, complexity_ppks),
);
}
}
}
}
}
Tab {
pbs: noise_cost_pbs,
modulus_switching: noise_cost_modulus_switching,
key_switching: noise_cost_key_switching,
pp_switching: noise_cost_pp_switching,
}
}
const BITS_PADDING_WITHOUT_NOISE: u64 = 1;
#[allow(clippy::expect_fun_call)]
#[allow(clippy::identity_op)]
#[allow(clippy::too_many_lines)]
pub fn optimise_one_with_memo<W: UnsignedInteger>(
precision: u64, // max precision of a word
log_norm: f64, // ?? norm2 of noise multisum, complexity of multisum is neglected
_security_level: u64,
maximum_acceptable_error_probability: f64,
glwe_log_polynomial_sizes: &[u64],
glwe_dimensions: &[u64],
internal_lwe_dimensions: &[u64],
n_functions_log: u64, // Many functions at the same time, stay at 1 for start
memo: &Tab,
n_inputs: u64, // Tau (nb blocks)
) -> OptimizationState {
assert!(n_functions_log == 0); // update complexity scaling
assert!(0.0 < maximum_acceptable_error_probability);
assert!(maximum_acceptable_error_probability < 1.0);
let ciphertext_modulus_log = W::BITS as u64;
// Circuit BS bound
// 1 bit of message only here =)
let no_noise_bits = 0 + 1 + BITS_PADDING_WITHOUT_NOISE;
let noise_bits = ciphertext_modulus_log - no_noise_bits;
let fatal_noise_limit = (1_u64 << noise_bits) as f64;
let kappa: f64 = sigma_scale_of_error_probability(maximum_acceptable_error_probability);
let safe_sigma = fatal_noise_limit / kappa;
// Bound for first bit extract in BitExtract (dominate others)
let variance_max = Variance::from_modular_variance::<W>(square(safe_sigma)).get_variance();
let mut state = OptimizationState {
best_solution: None,
count_domain: glwe_dimensions.len()
* glwe_log_polynomial_sizes.len()
* internal_lwe_dimensions.len()
* KS_BL.len()
* BR_BL.len(),
};
let mut best_complexity = f64::INFINITY;
for &glwe_dim in glwe_dimensions {
for &glwe_log_poly_size in glwe_log_polynomial_sizes {
let glwe_poly_size = 1 << glwe_log_poly_size;
if glwe_dim * glwe_poly_size <= 1 << 13 {
// Manual experimental CUT
let glwe_params = GlweParameters {
log2_polynomial_size: glwe_log_poly_size,
glwe_dimension: glwe_dim,
};
for &internal_dim in internal_lwe_dimensions {
let &(noise_modulus_switching, _) = memo
.modulus_switching
.get(&(internal_dim, glwe_poly_size))
.expect(&format!(
"Internal_dim : {} ; glwe poly size: {}",
internal_dim, glwe_poly_size
));
// BlindRotate dans Circuit BS
for &br_decomposition_parameter in BR_BL_FOR_CB.iter() {
// Pbs dans BitExtract et Circuit BS et FP-KS (partagés)
// TODO: choisir indépendemment(separate FP-KS)
let pbs_parameters = PbsParameters {
internal_lwe_dimension: LweDimension(internal_dim),
br_decomposition_parameter,
output_glwe_params: glwe_params,
};
let &(base_noise, complexity_pbs) = memo
.pbs
.get(&(
glwe_dim,
glwe_poly_size,
internal_dim,
br_decomposition_parameter.log2_base,
br_decomposition_parameter.level,
))
.unwrap();
// CircuitBootstrap: new parameters l,b
for &circuit_pbs_decomposition_parameter in CB_V1_BL.iter() {
// Hybrid packing
let nb_cmux = 1_u64;
let cmux_tree_blind_rotate_parameters = PbsParameters {
internal_lwe_dimension: LweDimension(nb_cmux), // complexity for 1 cmux
br_decomposition_parameter: circuit_pbs_decomposition_parameter,
output_glwe_params: pbs_parameters.output_glwe_params,
};
// Hybrid packing (rename)
let complexity_cmux_for_cb = DEFAULT_COMPLEXITY.pbs.complexity(
cmux_tree_blind_rotate_parameters,
ciphertext_modulus_log,
); // TODO: missing fft transform
// Hybrid packing (Do we have 1 or 2 groups)
#[allow(clippy::precedence)]
let complexity_cmux_tree = if precision * n_inputs as u64 // sum of precisions
> pbs_parameters.output_glwe_params.log2_polynomial_size
{
// 2 groups
complexity_cmux_for_cb
* (1 << (precision * n_inputs
- pbs_parameters.output_glwe_params.log2_polynomial_size)
- 1) as f64
// * (f64::exp2(
// (precision * n_inputs
// - pbs_parameters
// .output_glwe_params
// .log2_polynomial_size)
// as f64,
// ) - 1.)
} else {
// 1 group, no cmux tree
0.
};
// Hybrid packing blind rotate
let complexity_g_br = complexity_cmux_for_cb
* f64::min(
(pbs_parameters.output_glwe_params.log2_polynomial_size) as f64,
(precision * n_inputs) as f64,
);
// private packing keyswitch, <=> FP-KS (Circuit Boostrap)
let pp_ks_decomposition_parameter =
pbs_parameters.br_decomposition_parameter;
// for &pp_ks_decomposition_parameter in PP_KS_BL.iter() { // independant params for FP-KS
// Circuit Boostrap
let &(mut noise_private_packing_ks, complexity_ppks) = memo
.pp_switching
.get(&(
glwe_dim,
glwe_poly_size,
pp_ks_decomposition_parameter.log2_base,
pp_ks_decomposition_parameter.level,
))
.expect(&format!(
"{}, {}, {}, {}",
glwe_dim,
glwe_poly_size,
pp_ks_decomposition_parameter.log2_base,
pp_ks_decomposition_parameter.level,
));
noise_private_packing_ks += base_noise / 2.;
// Circuit Boostrap
if noise_private_packing_ks + noise_modulus_switching > variance_max
|| (precision - 1) as f64 * complexity_pbs + complexity_ppks
> best_complexity
{
continue;
}
let noise_ggsw = noise_private_packing_ks;
let noise_one_external_product_for_cmux_tree =
noise_atomic_pattern::variance_bootstrap::<W>(
cmux_tree_blind_rotate_parameters,
ciphertext_modulus_log,
Variance::from_variance(noise_ggsw),
)
.get_variance();
// all fp-ks
let complexity_all_ppks =
((pbs_parameters.output_glwe_params.glwe_dimension + 1)
* circuit_pbs_decomposition_parameter.level
* precision) as f64
* complexity_ppks;
// final out noise hybrid packing
let noise_cmux_tree_blind_rotate =
noise_one_external_product_for_cmux_tree
* (precision * n_inputs) as f64;
let noise_multisum =
(2_f64.powf(2. * log_norm as f64)) * noise_cmux_tree_blind_rotate; // out noise * weights
// Shared by all pbs (like brs)
for &ks_decomposition_parameter in KS_BL_FOR_CB.iter() {
let keyswitch_parameter = KeyswitchParameters {
input_lwe_dimension: LweDimension(glwe_poly_size * glwe_dim),
output_lwe_dimension: LweDimension(internal_dim),
ks_decomposition_parameter,
};
let &(noise_keyswitch, complexity_keyswitch) = memo
.key_switching
.get(&(
glwe_dim,
glwe_poly_size,
internal_dim,
ks_decomposition_parameter.log2_base,
ks_decomposition_parameter.level,
))
.unwrap();
let complexity_all_ks = precision as f64 * complexity_keyswitch;
if noise_private_packing_ks
+ noise_modulus_switching
+ noise_keyswitch
> variance_max
|| (precision - 1) as f64 * complexity_pbs
+ complexity_ppks
+ precision as f64 * complexity_keyswitch
> best_complexity
{
continue;
}
// new pbs key for the bit extract pbs, shared
let bit_extract_decomposition_parameter =
br_decomposition_parameter;
let &(_bit_extract_base_noise, complexity_bit_extract_pbs) = memo
.pbs
.get(&(
glwe_dim,
glwe_poly_size,
internal_dim,
bit_extract_decomposition_parameter.log2_base,
bit_extract_decomposition_parameter.level,
))
.unwrap();
// noise_multisum = dot
let current_maximal_noise = noise_multisum
* (1 << (2 * (precision - 1))) as f64
+ noise_keyswitch
+ noise_modulus_switching;
let complexity_all_pbs =
(precision * circuit_pbs_decomposition_parameter.level) as f64
* complexity_pbs
+ (precision - 1) as f64 * complexity_bit_extract_pbs;
let complexity_bias =
(complexity_all_ppks + complexity_all_pbs + complexity_all_ks)
* n_inputs as f64;
let complexity_slope = complexity_cmux_tree + complexity_g_br;
let current_complexity = complexity_slope
* (1 << n_functions_log) as f64
+ complexity_bias;
if current_complexity < best_complexity
&& current_maximal_noise < variance_max
{
best_complexity = current_complexity;
state.best_solution = Some(Solution {
input_lwe_dimension: pbs_parameters
.output_glwe_params
.glwe_dimension
* pbs_parameters.output_glwe_params.polynomial_size(),
internal_ks_output_lwe_dimension: keyswitch_parameter
.output_lwe_dimension
.0,
ks_decomposition_level_count: keyswitch_parameter
.ks_decomposition_parameter
.level,
ks_decomposition_base_log: keyswitch_parameter
.ks_decomposition_parameter
.log2_base,
glwe_polynomial_size: pbs_parameters
.output_glwe_params
.polynomial_size(),
glwe_dimension: pbs_parameters
.output_glwe_params
.glwe_dimension,
br_decomposition_level_count: pbs_parameters
.br_decomposition_parameter
.level,
br_decomposition_base_log: pbs_parameters
.br_decomposition_parameter
.log2_base,
noise_max: current_maximal_noise,
complexity: current_complexity,
p_error: find_p_error(
kappa,
variance_max,
current_maximal_noise,
), // consts.maximum_acceptable_error_probability,
cb_decomposition_level_count: Some(
circuit_pbs_decomposition_parameter.level,
),
cb_decomposition_base_log: Some(
circuit_pbs_decomposition_parameter.log2_base,
),
});
} else if current_complexity > best_complexity {
// next level is more costly
break;
}
}
}
}
}
}
}
}
state
}
#[allow(clippy::too_many_lines)]
pub fn optimize_one<W: UnsignedInteger>(
_sum_size: u64,
precision: u64,
security_level: u64,
noise_factor: f64,
maximum_acceptable_error_probability: f64,
glwe_log_polynomial_sizes: &[u64],
glwe_dimensions: &[u64],
internal_lwe_dimensions: &[u64],
memo_opt: &mut Option<Tab>,
) -> atomic_pattern::OptimizationState {
// Basic heuristic to split in several word
let no_sol = atomic_pattern::OptimizationState {
best_solution: None,
count_domain: 0,
};
#[allow(clippy::match_same_arms)]
let (nb_words, max_word_precision) = match precision {
1 => (1, 1),
2 => (1, 2),
3 => (2, 2),
4 => (2, 3),
5 => (2, 3),
6 => (3, 3),
7 => (3, 3),
8 => (3, 3),
9 => (3, 4),
10 => (3, 4),
11 => (3, 4),
12 => (4, 4),
13 => (4, 4),
14 => (4, 4),
15 => (4, 4),
16 => (4, 5),
_ => return no_sol,
};
let log_norm = noise_factor.log2();
let n_functions_log = 0;
let memo = memo_opt.get_or_insert_with(|| {
tabulate_circuit_bootstrap::<W>(
security_level,
maximum_acceptable_error_probability,
glwe_log_polynomial_sizes,
glwe_dimensions,
internal_lwe_dimensions,
)
});
let result = optimise_one_with_memo::<W>(
max_word_precision,
log_norm,
security_level,
maximum_acceptable_error_probability,
glwe_log_polynomial_sizes,
glwe_dimensions,
internal_lwe_dimensions,
n_functions_log,
memo,
nb_words, // Tau
);
let best_solution = result.best_solution.map(|sol| atomic_pattern::Solution {
input_lwe_dimension: sol.input_lwe_dimension,
internal_ks_output_lwe_dimension: sol.internal_ks_output_lwe_dimension,
ks_decomposition_level_count: sol.ks_decomposition_level_count,
ks_decomposition_base_log: sol.ks_decomposition_base_log,
glwe_polynomial_size: sol.glwe_polynomial_size,
glwe_dimension: sol.glwe_dimension,
br_decomposition_level_count: sol.br_decomposition_level_count,
br_decomposition_base_log: sol.br_decomposition_base_log,
complexity: sol.complexity,
lut_complexity: sol.complexity,
noise_max: sol.noise_max,
p_error: sol.p_error,
});
atomic_pattern::OptimizationState {
best_solution,
count_domain: result.count_domain,
}
}

View File

@@ -0,0 +1,408 @@
use crate::parameters::{BrDecompositionParameters, KsDecompositionParameters};
#[rustfmt::skip]
pub const BR_BL: &[BrDecompositionParameters; 71] = &[BrDecompositionParameters { level: 1, log2_base: 2 }, BrDecompositionParameters { level: 1, log2_base: 5 }, BrDecompositionParameters { level: 1, log2_base: 9 }, BrDecompositionParameters { level: 1, log2_base: 12 }, BrDecompositionParameters { level: 1, log2_base: 19 }, BrDecompositionParameters { level: 1, log2_base: 22 }, BrDecompositionParameters { level: 1, log2_base: 23 }, BrDecompositionParameters { level: 1, log2_base: 24 }, BrDecompositionParameters { level: 2, log2_base: 1 }, BrDecompositionParameters { level: 2, log2_base: 3 }, BrDecompositionParameters { level: 2, log2_base: 6 }, BrDecompositionParameters { level: 2, log2_base: 8 }, BrDecompositionParameters { level: 2, log2_base: 12 }, BrDecompositionParameters { level: 2, log2_base: 15 }, BrDecompositionParameters { level: 2, log2_base: 16 }, BrDecompositionParameters { level: 3, log2_base: 3 }, BrDecompositionParameters { level: 3, log2_base: 4 }, BrDecompositionParameters { level: 3, log2_base: 6 }, BrDecompositionParameters { level: 3, log2_base: 9 }, BrDecompositionParameters { level: 3, log2_base: 11 }, BrDecompositionParameters { level: 3, log2_base: 12 }, BrDecompositionParameters { level: 4, log2_base: 2 }, BrDecompositionParameters { level: 4, log2_base: 4 }, BrDecompositionParameters { level: 4, log2_base: 5 }, BrDecompositionParameters { level: 4, log2_base: 8 }, BrDecompositionParameters { level: 4, log2_base: 9 }, BrDecompositionParameters { level: 4, log2_base: 10 }, BrDecompositionParameters { level: 5, log2_base: 2 }, BrDecompositionParameters { level: 5, log2_base: 3 }, BrDecompositionParameters { level: 5, log2_base: 4 }, BrDecompositionParameters { level: 5, log2_base: 6 }, BrDecompositionParameters { level: 5, log2_base: 8 }, BrDecompositionParameters { level: 6, log2_base: 6 }, BrDecompositionParameters { level: 6, log2_base: 7 }, BrDecompositionParameters { level: 7, log2_base: 2 }, BrDecompositionParameters { level: 7, log2_base: 3 }, BrDecompositionParameters { level: 7, log2_base: 5 }, BrDecompositionParameters { level: 7, log2_base: 6 }, BrDecompositionParameters { level: 8, log2_base: 1 }, BrDecompositionParameters { level: 8, log2_base: 2 }, BrDecompositionParameters { level: 8, log2_base: 4 }, BrDecompositionParameters { level: 8, log2_base: 5 }, BrDecompositionParameters { level: 9, log2_base: 1 }, BrDecompositionParameters { level: 9, log2_base: 4 }, BrDecompositionParameters { level: 9, log2_base: 5 }, BrDecompositionParameters { level: 10, log2_base: 2 }, BrDecompositionParameters { level: 10, log2_base: 4 }, BrDecompositionParameters { level: 11, log2_base: 2 }, BrDecompositionParameters { level: 11, log2_base: 3 }, BrDecompositionParameters { level: 11, log2_base: 4 }, BrDecompositionParameters { level: 12, log2_base: 3 }, BrDecompositionParameters { level: 14, log2_base: 3 }, BrDecompositionParameters { level: 15, log2_base: 1 }, BrDecompositionParameters { level: 15, log2_base: 3 }, BrDecompositionParameters { level: 16, log2_base: 1 }, BrDecompositionParameters { level: 17, log2_base: 2 }, BrDecompositionParameters { level: 18, log2_base: 2 }, BrDecompositionParameters { level: 21, log2_base: 1 }, BrDecompositionParameters { level: 21, log2_base: 2 }, BrDecompositionParameters { level: 22, log2_base: 1 }, BrDecompositionParameters { level: 22, log2_base: 2 }, BrDecompositionParameters { level: 23, log2_base: 1 }, BrDecompositionParameters { level: 23, log2_base: 2 }, BrDecompositionParameters { level: 34, log2_base: 1 }, BrDecompositionParameters { level: 35, log2_base: 1 }, BrDecompositionParameters { level: 36, log2_base: 1 }, BrDecompositionParameters { level: 42, log2_base: 1 }, BrDecompositionParameters { level: 43, log2_base: 1 }, BrDecompositionParameters { level: 44, log2_base: 1 }, BrDecompositionParameters { level: 45, log2_base: 1 }, BrDecompositionParameters { level: 46, log2_base: 1 }];
#[rustfmt::skip]
pub const BR_BL_FOR_CB: &[BrDecompositionParameters; 71] = &[
BrDecompositionParameters {
level: 1,
log2_base: 2,
},
BrDecompositionParameters {
level: 1,
log2_base: 5,
},
BrDecompositionParameters {
level: 1,
log2_base: 9,
},
BrDecompositionParameters {
level: 1,
log2_base: 12,
},
BrDecompositionParameters {
level: 1,
log2_base: 19,
},
BrDecompositionParameters {
level: 1,
log2_base: 22,
},
BrDecompositionParameters {
level: 1,
log2_base: 23,
},
BrDecompositionParameters {
level: 1,
log2_base: 24,
},
BrDecompositionParameters {
level: 2,
log2_base: 1,
},
BrDecompositionParameters {
level: 2,
log2_base: 3,
},
BrDecompositionParameters {
level: 2,
log2_base: 6,
},
BrDecompositionParameters {
level: 2,
log2_base: 8,
},
BrDecompositionParameters {
level: 2,
log2_base: 12,
},
BrDecompositionParameters {
level: 2,
log2_base: 15,
},
BrDecompositionParameters {
level: 2,
log2_base: 16,
},
BrDecompositionParameters {
level: 3,
log2_base: 3,
},
BrDecompositionParameters {
level: 3,
log2_base: 4,
},
BrDecompositionParameters {
level: 3,
log2_base: 6,
},
BrDecompositionParameters {
level: 3,
log2_base: 9,
},
BrDecompositionParameters {
level: 3,
log2_base: 11,
},
BrDecompositionParameters {
level: 3,
log2_base: 12,
},
BrDecompositionParameters {
level: 4,
log2_base: 2,
},
BrDecompositionParameters {
level: 4,
log2_base: 4,
},
BrDecompositionParameters {
level: 4,
log2_base: 5,
},
BrDecompositionParameters {
level: 4,
log2_base: 8,
},
BrDecompositionParameters {
level: 4,
log2_base: 9,
},
BrDecompositionParameters {
level: 4,
log2_base: 10,
},
BrDecompositionParameters {
level: 5,
log2_base: 2,
},
BrDecompositionParameters {
level: 5,
log2_base: 3,
},
BrDecompositionParameters {
level: 5,
log2_base: 4,
},
BrDecompositionParameters {
level: 5,
log2_base: 6,
},
BrDecompositionParameters {
level: 5,
log2_base: 8,
},
BrDecompositionParameters {
level: 6,
log2_base: 6,
},
BrDecompositionParameters {
level: 6,
log2_base: 7,
},
BrDecompositionParameters {
level: 7,
log2_base: 2,
},
BrDecompositionParameters {
level: 7,
log2_base: 3,
},
BrDecompositionParameters {
level: 7,
log2_base: 5,
},
BrDecompositionParameters {
level: 7,
log2_base: 6,
},
BrDecompositionParameters {
level: 8,
log2_base: 1,
},
BrDecompositionParameters {
level: 8,
log2_base: 2,
},
BrDecompositionParameters {
level: 8,
log2_base: 4,
},
BrDecompositionParameters {
level: 8,
log2_base: 5,
},
BrDecompositionParameters {
level: 9,
log2_base: 1,
},
BrDecompositionParameters {
level: 9,
log2_base: 4,
},
BrDecompositionParameters {
level: 9,
log2_base: 5,
},
BrDecompositionParameters {
level: 10,
log2_base: 2,
},
BrDecompositionParameters {
level: 10,
log2_base: 4,
},
BrDecompositionParameters {
level: 11,
log2_base: 2,
},
BrDecompositionParameters {
level: 11,
log2_base: 3,
},
BrDecompositionParameters {
level: 11,
log2_base: 4,
},
BrDecompositionParameters {
level: 12,
log2_base: 3,
},
BrDecompositionParameters {
level: 14,
log2_base: 3,
},
BrDecompositionParameters {
level: 15,
log2_base: 1,
},
BrDecompositionParameters {
level: 15,
log2_base: 3,
},
BrDecompositionParameters {
level: 16,
log2_base: 1,
},
BrDecompositionParameters {
level: 17,
log2_base: 2,
},
BrDecompositionParameters {
level: 18,
log2_base: 2,
},
BrDecompositionParameters {
level: 21,
log2_base: 1,
},
BrDecompositionParameters {
level: 21,
log2_base: 2,
},
BrDecompositionParameters {
level: 22,
log2_base: 1,
},
BrDecompositionParameters {
level: 22,
log2_base: 2,
},
BrDecompositionParameters {
level: 23,
log2_base: 1,
},
BrDecompositionParameters {
level: 23,
log2_base: 2,
},
BrDecompositionParameters {
level: 34,
log2_base: 1,
},
BrDecompositionParameters {
level: 35,
log2_base: 1,
},
BrDecompositionParameters {
level: 36,
log2_base: 1,
},
BrDecompositionParameters {
level: 42,
log2_base: 1,
},
BrDecompositionParameters {
level: 43,
log2_base: 1,
},
BrDecompositionParameters {
level: 44,
log2_base: 1,
},
BrDecompositionParameters {
level: 45,
log2_base: 1,
},
BrDecompositionParameters {
level: 46,
log2_base: 1,
},
];
#[rustfmt::skip]
pub const KS_BL: &[KsDecompositionParameters; 50] = &[KsDecompositionParameters { level: 1, log2_base: 5 }, KsDecompositionParameters { level: 1, log2_base: 6 }, KsDecompositionParameters { level: 1, log2_base: 7 }, KsDecompositionParameters { level: 1, log2_base: 8 }, KsDecompositionParameters { level: 1, log2_base: 9 }, KsDecompositionParameters { level: 1, log2_base: 10 }, KsDecompositionParameters { level: 1, log2_base: 11 }, KsDecompositionParameters { level: 1, log2_base: 12 }, KsDecompositionParameters { level: 2, log2_base: 4 }, KsDecompositionParameters { level: 2, log2_base: 5 }, KsDecompositionParameters { level: 2, log2_base: 6 }, KsDecompositionParameters { level: 2, log2_base: 7 }, KsDecompositionParameters { level: 2, log2_base: 8 }, KsDecompositionParameters { level: 3, log2_base: 3 }, KsDecompositionParameters { level: 3, log2_base: 4 }, KsDecompositionParameters { level: 3, log2_base: 5 }, KsDecompositionParameters { level: 3, log2_base: 6 }, KsDecompositionParameters { level: 4, log2_base: 2 }, KsDecompositionParameters { level: 4, log2_base: 3 }, KsDecompositionParameters { level: 4, log2_base: 4 }, KsDecompositionParameters { level: 4, log2_base: 5 }, KsDecompositionParameters { level: 5, log2_base: 2 }, KsDecompositionParameters { level: 5, log2_base: 3 }, KsDecompositionParameters { level: 5, log2_base: 4 }, KsDecompositionParameters { level: 6, log2_base: 2 }, KsDecompositionParameters { level: 6, log2_base: 3 }, KsDecompositionParameters { level: 6, log2_base: 4 }, KsDecompositionParameters { level: 7, log2_base: 2 }, KsDecompositionParameters { level: 7, log2_base: 3 }, KsDecompositionParameters { level: 8, log2_base: 2 }, KsDecompositionParameters { level: 8, log2_base: 3 }, KsDecompositionParameters { level: 9, log2_base: 1 }, KsDecompositionParameters { level: 9, log2_base: 2 }, KsDecompositionParameters { level: 10, log2_base: 1 }, KsDecompositionParameters { level: 10, log2_base: 2 }, KsDecompositionParameters { level: 11, log2_base: 1 }, KsDecompositionParameters { level: 11, log2_base: 2 }, KsDecompositionParameters { level: 12, log2_base: 1 }, KsDecompositionParameters { level: 12, log2_base: 2 }, KsDecompositionParameters { level: 13, log2_base: 1 }, KsDecompositionParameters { level: 14, log2_base: 1 }, KsDecompositionParameters { level: 15, log2_base: 1 }, KsDecompositionParameters { level: 16, log2_base: 1 }, KsDecompositionParameters { level: 17, log2_base: 1 }, KsDecompositionParameters { level: 18, log2_base: 1 }, KsDecompositionParameters { level: 19, log2_base: 1 }, KsDecompositionParameters { level: 20, log2_base: 1 }, KsDecompositionParameters { level: 21, log2_base: 1 }, KsDecompositionParameters { level: 22, log2_base: 1 }, KsDecompositionParameters { level: 23, log2_base: 1 }];
#[rustfmt::skip]
pub const KS_BL_FOR_CB: &[KsDecompositionParameters; 27] = &[
KsDecompositionParameters {
level: 1,
log2_base: 4,
},
KsDecompositionParameters {
level: 1,
log2_base: 5,
},
KsDecompositionParameters {
level: 1,
log2_base: 6,
},
KsDecompositionParameters {
level: 1,
log2_base: 7,
},
KsDecompositionParameters {
level: 1,
log2_base: 8,
},
KsDecompositionParameters {
level: 2,
log2_base: 3,
},
KsDecompositionParameters {
level: 2,
log2_base: 4,
},
KsDecompositionParameters {
level: 2,
log2_base: 5,
},
KsDecompositionParameters {
level: 3,
log2_base: 2,
},
KsDecompositionParameters {
level: 3,
log2_base: 3,
},
KsDecompositionParameters {
level: 3,
log2_base: 4,
},
KsDecompositionParameters {
level: 4,
log2_base: 2,
},
KsDecompositionParameters {
level: 4,
log2_base: 3,
},
KsDecompositionParameters {
level: 5,
log2_base: 2,
},
KsDecompositionParameters {
level: 5,
log2_base: 3,
},
KsDecompositionParameters {
level: 6,
log2_base: 1,
},
KsDecompositionParameters {
level: 6,
log2_base: 2,
},
KsDecompositionParameters {
level: 7,
log2_base: 1,
},
KsDecompositionParameters {
level: 7,
log2_base: 2,
},
KsDecompositionParameters {
level: 8,
log2_base: 1,
},
KsDecompositionParameters {
level: 9,
log2_base: 1,
},
KsDecompositionParameters {
level: 10,
log2_base: 1,
},
KsDecompositionParameters {
level: 11,
log2_base: 1,
},
KsDecompositionParameters {
level: 12,
log2_base: 1,
},
KsDecompositionParameters {
level: 13,
log2_base: 1,
},
KsDecompositionParameters {
level: 14,
log2_base: 1,
},
KsDecompositionParameters {
level: 15,
log2_base: 1,
},
];
#[rustfmt::skip]
pub const CB_V1_BL: &[BrDecompositionParameters; 75] = &[BrDecompositionParameters { level: 1, log2_base: 1 }, BrDecompositionParameters { level: 1, log2_base: 2 }, BrDecompositionParameters { level: 1, log2_base: 3 }, BrDecompositionParameters { level: 1, log2_base: 4 }, BrDecompositionParameters { level: 1, log2_base: 5 }, BrDecompositionParameters { level: 1, log2_base: 6 }, BrDecompositionParameters { level: 2, log2_base: 1 }, BrDecompositionParameters { level: 2, log2_base: 2 }, BrDecompositionParameters { level: 2, log2_base: 3 }, BrDecompositionParameters { level: 2, log2_base: 4 }, BrDecompositionParameters { level: 2, log2_base: 5 }, BrDecompositionParameters { level: 3, log2_base: 1 }, BrDecompositionParameters { level: 3, log2_base: 2 }, BrDecompositionParameters { level: 3, log2_base: 3 }, BrDecompositionParameters { level: 3, log2_base: 4 }, BrDecompositionParameters { level: 3, log2_base: 5 }, BrDecompositionParameters { level: 3, log2_base: 6 }, BrDecompositionParameters { level: 4, log2_base: 1 }, BrDecompositionParameters { level: 4, log2_base: 2 }, BrDecompositionParameters { level: 4, log2_base: 3 }, BrDecompositionParameters { level: 4, log2_base: 4 }, BrDecompositionParameters { level: 4, log2_base: 5 }, BrDecompositionParameters { level: 5, log2_base: 1 }, BrDecompositionParameters { level: 5, log2_base: 2 }, BrDecompositionParameters { level: 5, log2_base: 3 }, BrDecompositionParameters { level: 5, log2_base: 4 }, BrDecompositionParameters { level: 6, log2_base: 1 }, BrDecompositionParameters { level: 6, log2_base: 2 }, BrDecompositionParameters { level: 6, log2_base: 3 }, BrDecompositionParameters { level: 6, log2_base: 4 }, BrDecompositionParameters { level: 7, log2_base: 1 }, BrDecompositionParameters { level: 7, log2_base: 2 }, BrDecompositionParameters { level: 7, log2_base: 3 }, BrDecompositionParameters { level: 7, log2_base: 4 }, BrDecompositionParameters { level: 8, log2_base: 1 }, BrDecompositionParameters { level: 8, log2_base: 2 }, BrDecompositionParameters { level: 8, log2_base: 3 }, BrDecompositionParameters { level: 9, log2_base: 1 }, BrDecompositionParameters { level: 9, log2_base: 2 }, BrDecompositionParameters { level: 9, log2_base: 3 }, BrDecompositionParameters { level: 10, log2_base: 1 }, BrDecompositionParameters { level: 10, log2_base: 2 }, BrDecompositionParameters { level: 10, log2_base: 3 }, BrDecompositionParameters { level: 11, log2_base: 1 }, BrDecompositionParameters { level: 11, log2_base: 2 }, BrDecompositionParameters { level: 12, log2_base: 1 }, BrDecompositionParameters { level: 12, log2_base: 2 }, BrDecompositionParameters { level: 13, log2_base: 1 }, BrDecompositionParameters { level: 13, log2_base: 2 }, BrDecompositionParameters { level: 14, log2_base: 1 }, BrDecompositionParameters { level: 14, log2_base: 2 }, BrDecompositionParameters { level: 15, log2_base: 1 }, BrDecompositionParameters { level: 15, log2_base: 2 }, BrDecompositionParameters { level: 16, log2_base: 1 }, BrDecompositionParameters { level: 16, log2_base: 2 }, BrDecompositionParameters { level: 17, log2_base: 1 }, BrDecompositionParameters { level: 17, log2_base: 2 }, BrDecompositionParameters { level: 18, log2_base: 1 }, BrDecompositionParameters { level: 19, log2_base: 1 }, BrDecompositionParameters { level: 20, log2_base: 1 }, BrDecompositionParameters { level: 21, log2_base: 1 }, BrDecompositionParameters { level: 22, log2_base: 1 }, BrDecompositionParameters { level: 23, log2_base: 1 }, BrDecompositionParameters { level: 24, log2_base: 1 }, BrDecompositionParameters { level: 25, log2_base: 1 }, BrDecompositionParameters { level: 26, log2_base: 1 }, BrDecompositionParameters { level: 27, log2_base: 1 }, BrDecompositionParameters { level: 28, log2_base: 1 }, BrDecompositionParameters { level: 29, log2_base: 1 }, BrDecompositionParameters { level: 30, log2_base: 1 }, BrDecompositionParameters { level: 31, log2_base: 1 }, BrDecompositionParameters { level: 32, log2_base: 1 }, BrDecompositionParameters { level: 33, log2_base: 1 }, BrDecompositionParameters { level: 34, log2_base: 1 }, BrDecompositionParameters { level: 35, log2_base: 1 }];

View File

@@ -8,6 +8,7 @@
use clap::Parser;
use concrete_optimizer::global_parameters::DEFAUT_DOMAINS;
use concrete_optimizer::optimization::atomic_pattern as optimize_atomic_pattern;
use concrete_optimizer::optimization::wop_atomic_pattern::optimize as optimize_wop_atomic_pattern;
use rayon_cond::CondIterator;
const _4_SIGMA: f64 = 1.0 - 0.999_936_657_516;
@@ -60,6 +61,9 @@ struct Args {
#[clap(long)]
no_parallelize: bool,
#[clap(long)]
wop_pbs: bool,
}
fn main() {
@@ -79,7 +83,11 @@ fn main() {
(args.min_intern_lwe_dim..=args.max_intern_lwe_dim).collect();
let precisions = args.min_precision..=args.max_precision;
let manps = 0..=31;
let manps = if args.wop_pbs {
vec![0, 2, 4, 6, 8, 10, 12]
} else {
(0..=31).collect()
};
// let guard = pprof::ProfilerGuard::new(100).unwrap();
@@ -88,19 +96,34 @@ fn main() {
#[rustfmt::skip]
let all_results = precisions_iter.map(|precision| {
let mut last_solution = None;
manps.clone().map(|manp| {
let mut memo = None;
manps.iter().map(|&manp| {
let noise_scale = 2_f64.powi(manp);
let result = optimize_atomic_pattern::optimize_one::<u64>(
sum_size,
precision,
security_level,
noise_scale,
p_error,
&glwe_log_polynomial_sizes,
&glwe_dimensions,
&internal_lwe_dimensions,
last_solution, // 33% gains
);
let result = if args.wop_pbs {
optimize_wop_atomic_pattern::optimize_one::<u64>(
sum_size,
precision,
security_level,
noise_scale,
p_error,
&glwe_log_polynomial_sizes,
&glwe_dimensions,
&internal_lwe_dimensions,
&mut memo,
)
} else {
optimize_atomic_pattern::optimize_one::<u64>(
sum_size,
precision,
security_level,
noise_scale,
p_error,
&glwe_log_polynomial_sizes,
&glwe_dimensions,
&internal_lwe_dimensions,
last_solution, // 33% gains
)
};
last_solution = result.best_solution;
result
})
@@ -120,7 +143,7 @@ fn main() {
println!("{{ /* {:1.1e} errors */", p_error);
for (precision_i, precision) in precisions.enumerate() {
println!("{{ /* precision {:2} */", precision);
for (manp_i, manp) in manps.clone().enumerate() {
for (manp_i, manp) in manps.clone().iter().enumerate() {
let solution = all_results[precision_i][manp_i].best_solution;
match solution {
Some(solution) => {
@@ -170,4 +193,36 @@ mod tests {
text_diff::assert_diff(&expected_output, actual_output, CMP_LINES, EXACT_EQUALITY);
}
#[test]
fn test_reference_wop_output() {
const REF_FILE: &str = "src/wop_parameters.ref-15-06-2022";
const V0_PARAMETERS_EXE: &str = "../target/release/v0-parameters";
const CMP_LINES: &str = "\n";
const EXACT_EQUALITY: i32 = 0;
let _ = std::process::Command::new("cargo")
.args(["build", "--release", "-q"])
.status()
.expect("Can't build");
assert!(std::path::Path::new(V0_PARAMETERS_EXE).exists());
#[rustfmt::skip]
let actual_output = std::process::Command::new(V0_PARAMETERS_EXE)
.args([
"--wop-pbs",
"--min-intern-lwe-dim", "257",
"--min-precision", "16",
"--max-precision", "16",
"--min-log-poly-size", "10",
"--max-log-poly-size", "12",
"--"
])
.output()
.expect("failed to execute process");
let actual_output = std::str::from_utf8(&actual_output.stdout).expect("Bad content");
let expected_output = std::fs::read_to_string(REF_FILE).expect("Can't read reference file");
text_diff::assert_diff(&expected_output, actual_output, CMP_LINES, EXACT_EQUALITY);
}
}

View File

@@ -0,0 +1,11 @@
{ /* 6.3e-5 errors */
{ /* precision 16 */
/* 0 */ V0Parameter( 1, 11, 482, 2, 16, 9, 1), // 8041 mops, 6.3e-5 errors
/* 2 */ V0Parameter( 1, 11, 491, 2, 15, 9, 1), // 10343 mops, 6.0e-5 errors
/* 4 */ V0Parameter( 1, 11, 491, 3, 12, 9, 1), // 11155 mops, 6.3e-5 errors
/* 6 */ V0Parameter( 1, 11, 520, 3, 12, 10, 1), // 14850 mops, 6.0e-5 errors
/* 8 */ V0Parameter( 1, 11, 486, 4, 9, 9, 1), // 25684 mops, 6.0e-5 errors
/* 10 */ V0Parameter( 1, 11, 503, 5, 8, 10, 1), // 32012 mops, 5.6e-5 errors
/* 12 */ V0Parameter( 1, 11, 503, 7, 6, 10, 1), // 49916 mops, 5.7e-5 errors
},
}