mirror of
https://github.com/zama-ai/concrete.git
synced 2026-02-09 03:55:04 -05:00
feat: atomic_pattern optimizer, with v0_parameters table generation
Resolve #11
This commit is contained in:
4
.github/workflows/rust.yml
vendored
4
.github/workflows/rust.yml
vendored
@@ -44,7 +44,7 @@ jobs:
|
||||
RUSTFLAGS: -D warnings
|
||||
with:
|
||||
command: build
|
||||
args: ${{ env.CARGO_ARGS }}
|
||||
args: ${{ env.CARGO_ARGS }} --lib --examples --tests
|
||||
|
||||
- name: cargo clippy
|
||||
uses: actions-rs/cargo@v1
|
||||
@@ -56,4 +56,4 @@ jobs:
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: test
|
||||
args: ${{ env.CARGO_ARGS }} --no-fail-fast
|
||||
args: ${{ env.CARGO_ARGS }} --no-fail-fast --all-targets
|
||||
|
||||
10
Cargo.toml
10
Cargo.toml
@@ -10,7 +10,15 @@ git-fetch-with-cli = true
|
||||
[dependencies]
|
||||
concrete-commons = { git = "ssh://git@github.com/zama-ai/concrete_internal.git", branch = "fix/optimizer_compat" }
|
||||
concrete-npe = { git = "ssh://git@github.com/zama-ai/concrete_internal.git", branch = "fix/optimizer_compat" }
|
||||
statrs = "0.15.0"
|
||||
|
||||
[dev-dependencies]
|
||||
approx = "0.5.1"
|
||||
pretty_assertions = "1"
|
||||
clap = { version = "3.1.2", features = ["derive"] }
|
||||
rayon-cond = "0.2" # to avoid rayon code coloring
|
||||
# pprof = { version = "0.4", features = ["flamegraph"] }
|
||||
rayon = "1.5.1"
|
||||
text-diff = "0.4.0"
|
||||
|
||||
[[example]]
|
||||
name = "v0_parameters"
|
||||
|
||||
240
examples/v0_parameters.ref-02-03-2022
Normal file
240
examples/v0_parameters.ref-02-03-2022
Normal file
@@ -0,0 +1,240 @@
|
||||
{ /* 6.3e-5 errors */
|
||||
{ /* precision 1 */
|
||||
/* 0 */ V0Parameter( 1, 10, 538, 2, 8, 3, 3), // 46 mops, 5.9e-5 errors
|
||||
/* 1 */ V0Parameter( 1, 10, 514, 2, 8, 5, 2), // 46 mops, 5.4e-5 errors
|
||||
/* 2 */ V0Parameter( 1, 10, 519, 2, 8, 5, 2), // 46 mops, 6.0e-5 errors
|
||||
/* 3 */ V0Parameter( 1, 10, 515, 3, 6, 5, 2), // 59 mops, 4.9e-5 errors
|
||||
/* 4 */ V0Parameter( 1, 10, 523, 3, 6, 5, 2), // 60 mops, 5.4e-5 errors
|
||||
/* 5 */ V0Parameter( 1, 11, 563, 1, 23, 3, 3), // 71 mops, 5.4e-5 errors
|
||||
/* 6 */ V0Parameter( 1, 11, 563, 1, 23, 3, 3), // 71 mops, 5.5e-5 errors
|
||||
/* 7 */ V0Parameter( 1, 11, 563, 1, 23, 3, 3), // 71 mops, 5.8e-5 errors
|
||||
/* 8 */ V0Parameter( 1, 11, 564, 1, 23, 3, 3), // 71 mops, 5.8e-5 errors
|
||||
/* 9 */ V0Parameter( 1, 11, 569, 1, 23, 3, 3), // 72 mops, 5.5e-5 errors
|
||||
/* 10 */ V0Parameter( 1, 11, 555, 1, 23, 5, 2), // 75 mops, 5.7e-5 errors
|
||||
/* 11 */ V0Parameter( 1, 11, 532, 2, 16, 5, 2), // 101 mops, 6.2e-5 errors
|
||||
/* 12 */ V0Parameter( 1, 11, 532, 2, 16, 5, 2), // 101 mops, 6.2e-5 errors
|
||||
/* 13 */ V0Parameter( 1, 11, 532, 2, 16, 5, 2), // 101 mops, 6.3e-5 errors
|
||||
/* 14 */ V0Parameter( 1, 11, 533, 2, 16, 5, 2), // 101 mops, 4.9e-5 errors
|
||||
/* 15 */ V0Parameter( 1, 11, 533, 2, 16, 5, 2), // 101 mops, 5.5e-5 errors
|
||||
/* 16 */ V0Parameter( 1, 11, 535, 2, 16, 5, 2), // 102 mops, 5.3e-5 errors
|
||||
/* 17 */ V0Parameter( 1, 11, 544, 2, 16, 5, 2), // 103 mops, 5.6e-5 errors
|
||||
/* 18 */ V0Parameter( 1, 11, 533, 3, 12, 5, 2), // 130 mops, 5.0e-5 errors
|
||||
/* 19 */ V0Parameter( 1, 11, 533, 3, 12, 5, 2), // 130 mops, 6.0e-5 errors
|
||||
/* 20 */ V0Parameter( 1, 11, 536, 3, 12, 5, 2), // 131 mops, 5.6e-5 errors
|
||||
/* 21 */ V0Parameter( 1, 11, 552, 3, 12, 5, 2), // 135 mops, 5.7e-5 errors
|
||||
/* 22 */ V0Parameter( 1, 11, 536, 4, 9, 5, 2), // 160 mops, 6.1e-5 errors
|
||||
/* 23 */ V0Parameter( 1, 11, 555, 4, 9, 5, 2), // 166 mops, 5.7e-5 errors
|
||||
/* 24 */ V0Parameter( 1, 11, 539, 5, 8, 5, 2), // 191 mops, 5.2e-5 errors
|
||||
/* 25 */ V0Parameter( 1, 11, 593, 5, 8, 5, 2), // 209 mops, 6.2e-5 errors
|
||||
/* 26 */ V0Parameter( 1, 11, 541, 7, 6, 5, 2), // 251 mops, 6.3e-5 errors
|
||||
/* 27 */ V0Parameter( 1, 11, 569, 8, 5, 5, 2), // 294 mops, 6.1e-5 errors
|
||||
/* 28 */ V0Parameter( 1, 11, 549, 11, 4, 5, 2), // 374 mops, 5.5e-5 errors
|
||||
/* 29 */ V0Parameter( 1, 11, 559, 15, 3, 5, 2), // 503 mops, 5.8e-5 errors
|
||||
/* 30 */ V0Parameter( 1, 11, 542, 44, 1, 10, 1), // 1358 mops, 6.0e-5 errors
|
||||
/* 31 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
},
|
||||
{ /* precision 2 */
|
||||
/* 0 */ V0Parameter( 1, 10, 557, 2, 8, 5, 2), // 49 mops, 5.2e-5 errors
|
||||
/* 1 */ V0Parameter( 1, 10, 564, 2, 8, 5, 2), // 50 mops, 5.7e-5 errors
|
||||
/* 2 */ V0Parameter( 1, 10, 558, 3, 6, 5, 2), // 63 mops, 5.1e-5 errors
|
||||
/* 3 */ V0Parameter( 1, 10, 569, 3, 6, 5, 2), // 65 mops, 5.7e-5 errors
|
||||
/* 4 */ V0Parameter( 1, 11, 579, 1, 23, 5, 2), // 78 mops, 6.0e-5 errors
|
||||
/* 5 */ V0Parameter( 1, 11, 579, 1, 23, 5, 2), // 78 mops, 6.1e-5 errors
|
||||
/* 6 */ V0Parameter( 1, 11, 580, 1, 23, 5, 2), // 78 mops, 5.3e-5 errors
|
||||
/* 7 */ V0Parameter( 1, 11, 581, 1, 23, 5, 2), // 78 mops, 5.4e-5 errors
|
||||
/* 8 */ V0Parameter( 1, 11, 585, 1, 23, 5, 2), // 78 mops, 6.3e-5 errors
|
||||
/* 9 */ V0Parameter( 1, 11, 639, 1, 23, 5, 2), // 85 mops, 6.3e-5 errors
|
||||
/* 10 */ V0Parameter( 1, 11, 579, 2, 16, 5, 2), // 109 mops, 6.0e-5 errors
|
||||
/* 11 */ V0Parameter( 1, 11, 579, 2, 16, 5, 2), // 109 mops, 6.0e-5 errors
|
||||
/* 12 */ V0Parameter( 1, 11, 579, 2, 16, 5, 2), // 109 mops, 6.1e-5 errors
|
||||
/* 13 */ V0Parameter( 1, 11, 579, 2, 16, 5, 2), // 109 mops, 6.3e-5 errors
|
||||
/* 14 */ V0Parameter( 1, 11, 580, 2, 16, 5, 2), // 109 mops, 5.9e-5 errors
|
||||
/* 15 */ V0Parameter( 1, 11, 583, 2, 16, 5, 2), // 110 mops, 5.7e-5 errors
|
||||
/* 16 */ V0Parameter( 1, 11, 599, 2, 16, 5, 2), // 113 mops, 6.3e-5 errors
|
||||
/* 17 */ V0Parameter( 1, 11, 580, 3, 12, 5, 2), // 141 mops, 5.2e-5 errors
|
||||
/* 18 */ V0Parameter( 1, 11, 581, 3, 12, 5, 2), // 141 mops, 5.3e-5 errors
|
||||
/* 19 */ V0Parameter( 1, 11, 585, 3, 12, 5, 2), // 142 mops, 5.7e-5 errors
|
||||
/* 20 */ V0Parameter( 1, 11, 622, 3, 12, 5, 2), // 151 mops, 6.3e-5 errors
|
||||
/* 21 */ V0Parameter( 1, 11, 585, 4, 9, 5, 2), // 174 mops, 6.3e-5 errors
|
||||
/* 22 */ V0Parameter( 1, 11, 639, 4, 9, 5, 2), // 190 mops, 6.3e-5 errors
|
||||
/* 23 */ V0Parameter( 1, 11, 589, 5, 8, 5, 2), // 208 mops, 6.1e-5 errors
|
||||
/* 24 */ V0Parameter( 1, 11, 591, 6, 7, 5, 2), // 241 mops, 6.3e-5 errors
|
||||
/* 25 */ V0Parameter( 1, 11, 595, 7, 6, 5, 2), // 275 mops, 5.7e-5 errors
|
||||
/* 26 */ V0Parameter( 1, 11, 627, 8, 5, 11, 2), // 338 mops, 6.3e-5 errors
|
||||
/* 27 */ V0Parameter( 1, 11, 611, 11, 4, 5, 2), // 416 mops, 6.2e-5 errors
|
||||
/* 28 */ V0Parameter( 1, 11, 617, 15, 3, 11, 2), // 569 mops, 5.8e-5 errors
|
||||
/* 29 */ V0Parameter( 1, 11, 600, 44, 1, 22, 1), // 1531 mops, 5.8e-5 errors
|
||||
/* 30 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 31 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
},
|
||||
{ /* precision 3 */
|
||||
/* 0 */ V0Parameter( 1, 10, 673, 2, 8, 5, 4), // 59 mops, 5.8e-5 errors
|
||||
/* 1 */ V0Parameter( 1, 10, 641, 3, 6, 5, 2), // 72 mops, 6.3e-5 errors
|
||||
/* 2 */ V0Parameter( 1, 10, 649, 3, 6, 7, 3), // 76 mops, 6.2e-5 errors
|
||||
/* 3 */ V0Parameter( 1, 11, 679, 1, 23, 5, 4), // 90 mops, 6.2e-5 errors
|
||||
/* 4 */ V0Parameter( 1, 11, 679, 1, 23, 5, 4), // 90 mops, 6.3e-5 errors
|
||||
/* 5 */ V0Parameter( 1, 11, 680, 1, 23, 5, 4), // 90 mops, 5.0e-5 errors
|
||||
/* 6 */ V0Parameter( 1, 11, 681, 1, 23, 5, 4), // 90 mops, 4.8e-5 errors
|
||||
/* 7 */ V0Parameter( 1, 11, 684, 1, 23, 5, 4), // 90 mops, 5.9e-5 errors
|
||||
/* 8 */ V0Parameter( 1, 11, 710, 1, 23, 5, 4), // 94 mops, 6.0e-5 errors
|
||||
/* 9 */ V0Parameter( 1, 11, 679, 2, 16, 5, 4), // 127 mops, 6.2e-5 errors
|
||||
/* 10 */ V0Parameter( 1, 11, 679, 2, 16, 5, 4), // 127 mops, 6.2e-5 errors
|
||||
/* 11 */ V0Parameter( 1, 11, 679, 2, 16, 5, 4), // 127 mops, 6.3e-5 errors
|
||||
/* 12 */ V0Parameter( 1, 11, 680, 2, 16, 5, 4), // 127 mops, 4.8e-5 errors
|
||||
/* 13 */ V0Parameter( 1, 11, 680, 2, 16, 5, 4), // 127 mops, 5.7e-5 errors
|
||||
/* 14 */ V0Parameter( 1, 11, 682, 2, 16, 5, 4), // 127 mops, 6.0e-5 errors
|
||||
/* 15 */ V0Parameter( 1, 11, 694, 2, 16, 5, 4), // 130 mops, 5.7e-5 errors
|
||||
/* 16 */ V0Parameter( 1, 11, 652, 3, 12, 7, 3), // 163 mops, 4.8e-5 errors
|
||||
/* 17 */ V0Parameter( 1, 11, 652, 3, 12, 7, 3), // 163 mops, 6.0e-5 errors
|
||||
/* 18 */ V0Parameter( 1, 11, 655, 3, 12, 7, 3), // 164 mops, 6.3e-5 errors
|
||||
/* 19 */ V0Parameter( 1, 11, 675, 3, 12, 7, 3), // 168 mops, 6.2e-5 errors
|
||||
/* 20 */ V0Parameter( 1, 11, 656, 4, 9, 7, 3), // 200 mops, 5.4e-5 errors
|
||||
/* 21 */ V0Parameter( 1, 11, 679, 4, 9, 7, 3), // 206 mops, 6.3e-5 errors
|
||||
/* 22 */ V0Parameter( 1, 11, 659, 5, 8, 7, 3), // 237 mops, 5.1e-5 errors
|
||||
/* 23 */ V0Parameter( 1, 11, 660, 6, 7, 7, 3), // 273 mops, 5.7e-5 errors
|
||||
/* 24 */ V0Parameter( 1, 11, 638, 7, 6, 11, 2), // 309 mops, 6.2e-5 errors
|
||||
/* 25 */ V0Parameter( 1, 11, 675, 8, 5, 11, 2), // 364 mops, 6.3e-5 errors
|
||||
/* 26 */ V0Parameter( 1, 11, 647, 11, 4, 11, 2), // 455 mops, 5.7e-5 errors
|
||||
/* 27 */ V0Parameter( 1, 11, 660, 15, 3, 11, 2), // 608 mops, 5.9e-5 errors
|
||||
/* 28 */ V0Parameter( 1, 11, 641, 44, 1, 22, 1), // 1635 mops, 6.3e-5 errors
|
||||
/* 29 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 30 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 31 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
},
|
||||
{ /* precision 4 */
|
||||
/* 0 */ V0Parameter( 1, 10, 691, 3, 6, 7, 3), // 80 mops, 6.2e-5 errors
|
||||
/* 1 */ V0Parameter( 1, 10, 731, 3, 6, 7, 3), // 85 mops, 6.3e-5 errors
|
||||
/* 2 */ V0Parameter( 1, 11, 720, 1, 23, 5, 4), // 95 mops, 5.5e-5 errors
|
||||
/* 3 */ V0Parameter( 1, 11, 720, 1, 23, 5, 4), // 95 mops, 5.6e-5 errors
|
||||
/* 4 */ V0Parameter( 1, 11, 720, 1, 23, 5, 4), // 95 mops, 6.0e-5 errors
|
||||
/* 5 */ V0Parameter( 1, 11, 721, 1, 23, 5, 4), // 95 mops, 6.0e-5 errors
|
||||
/* 6 */ V0Parameter( 1, 11, 726, 1, 23, 5, 4), // 95 mops, 5.4e-5 errors
|
||||
/* 7 */ V0Parameter( 1, 11, 764, 1, 23, 5, 4), // 100 mops, 6.3e-5 errors
|
||||
/* 8 */ V0Parameter( 1, 11, 720, 2, 16, 5, 4), // 134 mops, 5.5e-5 errors
|
||||
/* 9 */ V0Parameter( 1, 11, 720, 2, 16, 5, 4), // 134 mops, 5.5e-5 errors
|
||||
/* 10 */ V0Parameter( 1, 11, 720, 2, 16, 5, 4), // 134 mops, 5.6e-5 errors
|
||||
/* 11 */ V0Parameter( 1, 11, 720, 2, 16, 5, 4), // 134 mops, 5.8e-5 errors
|
||||
/* 12 */ V0Parameter( 1, 11, 721, 2, 16, 5, 4), // 134 mops, 5.3e-5 errors
|
||||
/* 13 */ V0Parameter( 1, 11, 723, 2, 16, 5, 4), // 135 mops, 6.2e-5 errors
|
||||
/* 14 */ V0Parameter( 1, 11, 738, 2, 16, 5, 4), // 137 mops, 5.9e-5 errors
|
||||
/* 15 */ V0Parameter( 1, 11, 692, 3, 12, 7, 3), // 172 mops, 5.6e-5 errors
|
||||
/* 16 */ V0Parameter( 1, 11, 693, 3, 12, 7, 3), // 173 mops, 5.4e-5 errors
|
||||
/* 17 */ V0Parameter( 1, 11, 697, 3, 12, 7, 3), // 174 mops, 5.3e-5 errors
|
||||
/* 18 */ V0Parameter( 1, 11, 724, 3, 12, 7, 3), // 180 mops, 6.1e-5 errors
|
||||
/* 19 */ V0Parameter( 1, 11, 697, 4, 9, 7, 3), // 212 mops, 6.0e-5 errors
|
||||
/* 20 */ V0Parameter( 1, 11, 731, 4, 9, 7, 3), // 222 mops, 6.2e-5 errors
|
||||
/* 21 */ V0Parameter( 1, 11, 700, 5, 8, 7, 3), // 251 mops, 6.3e-5 errors
|
||||
/* 22 */ V0Parameter( 1, 11, 702, 6, 7, 7, 3), // 290 mops, 6.1e-5 errors
|
||||
/* 23 */ V0Parameter( 1, 11, 681, 7, 6, 11, 2), // 329 mops, 5.8e-5 errors
|
||||
/* 24 */ V0Parameter( 1, 11, 686, 9, 5, 11, 2), // 407 mops, 5.6e-5 errors
|
||||
/* 25 */ V0Parameter( 1, 11, 692, 11, 4, 11, 2), // 486 mops, 6.2e-5 errors
|
||||
/* 26 */ V0Parameter( 1, 11, 715, 15, 3, 11, 2), // 658 mops, 6.3e-5 errors
|
||||
/* 27 */ V0Parameter( 1, 11, 690, 44, 1, 22, 1), // 1760 mops, 6.2e-5 errors
|
||||
/* 28 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 29 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 30 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 31 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
},
|
||||
{ /* precision 5 */
|
||||
/* 0 */ V0Parameter( 1, 11, 774, 1, 23, 5, 4), // 101 mops, 5.6e-5 errors
|
||||
/* 1 */ V0Parameter( 1, 11, 774, 1, 23, 5, 4), // 101 mops, 5.7e-5 errors
|
||||
/* 2 */ V0Parameter( 1, 11, 774, 1, 23, 5, 4), // 101 mops, 5.8e-5 errors
|
||||
/* 3 */ V0Parameter( 1, 11, 774, 1, 23, 5, 4), // 101 mops, 6.2e-5 errors
|
||||
/* 4 */ V0Parameter( 1, 11, 776, 1, 23, 5, 4), // 101 mops, 6.2e-5 errors
|
||||
/* 5 */ V0Parameter( 1, 11, 787, 1, 23, 5, 4), // 103 mops, 6.0e-5 errors
|
||||
/* 6 */ V0Parameter( 1, 11, 774, 2, 16, 5, 4), // 144 mops, 5.6e-5 errors
|
||||
/* 7 */ V0Parameter( 1, 11, 774, 2, 16, 5, 4), // 144 mops, 5.6e-5 errors
|
||||
/* 8 */ V0Parameter( 1, 11, 774, 2, 16, 5, 4), // 144 mops, 5.7e-5 errors
|
||||
/* 9 */ V0Parameter( 1, 11, 774, 2, 16, 5, 4), // 144 mops, 5.7e-5 errors
|
||||
/* 10 */ V0Parameter( 1, 11, 774, 2, 16, 5, 4), // 144 mops, 6.0e-5 errors
|
||||
/* 11 */ V0Parameter( 1, 11, 775, 2, 16, 5, 4), // 144 mops, 6.2e-5 errors
|
||||
/* 12 */ V0Parameter( 1, 11, 781, 2, 16, 5, 4), // 145 mops, 6.0e-5 errors
|
||||
/* 13 */ V0Parameter( 1, 11, 745, 3, 12, 7, 3), // 185 mops, 5.6e-5 errors
|
||||
/* 14 */ V0Parameter( 1, 11, 745, 3, 12, 7, 3), // 185 mops, 6.0e-5 errors
|
||||
/* 15 */ V0Parameter( 1, 11, 747, 3, 12, 7, 3), // 186 mops, 5.8e-5 errors
|
||||
/* 16 */ V0Parameter( 1, 11, 755, 3, 12, 7, 3), // 187 mops, 6.2e-5 errors
|
||||
/* 17 */ V0Parameter( 1, 11, 747, 4, 9, 7, 3), // 226 mops, 6.0e-5 errors
|
||||
/* 18 */ V0Parameter( 1, 11, 756, 4, 9, 7, 3), // 229 mops, 6.3e-5 errors
|
||||
/* 19 */ V0Parameter( 1, 11, 748, 5, 8, 7, 3), // 268 mops, 6.2e-5 errors
|
||||
/* 20 */ V0Parameter( 1, 11, 766, 5, 8, 7, 3), // 274 mops, 6.0e-5 errors
|
||||
/* 21 */ V0Parameter( 1, 11, 773, 6, 7, 7, 3), // 319 mops, 6.0e-5 errors
|
||||
/* 22 */ V0Parameter( 1, 11, 756, 7, 6, 11, 2), // 365 mops, 6.2e-5 errors
|
||||
/* 23 */ V0Parameter( 1, 11, 729, 11, 4, 11, 2), // 512 mops, 6.0e-5 errors
|
||||
/* 24 */ V0Parameter( 1, 11, 745, 14, 3, 11, 2), // 645 mops, 6.1e-5 errors
|
||||
/* 25 */ V0Parameter( 1, 11, 746, 22, 2, 11, 2), // 972 mops, 6.2e-5 errors
|
||||
/* 26 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 27 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 28 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 29 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 30 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 31 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
},
|
||||
{ /* precision 6 */
|
||||
/* 0 */ V0Parameter( 1, 12, 833, 1, 23, 5, 4), // 230 mops, 5.9e-5 errors
|
||||
/* 1 */ V0Parameter( 1, 12, 833, 1, 23, 5, 4), // 230 mops, 6.2e-5 errors
|
||||
/* 2 */ V0Parameter( 1, 12, 835, 1, 23, 5, 4), // 231 mops, 5.9e-5 errors
|
||||
/* 3 */ V0Parameter( 1, 12, 843, 1, 23, 5, 4), // 233 mops, 5.9e-5 errors
|
||||
/* 4 */ V0Parameter( 1, 12, 833, 2, 15, 5, 4), // 328 mops, 5.8e-5 errors
|
||||
/* 5 */ V0Parameter( 1, 12, 833, 2, 15, 5, 4), // 328 mops, 5.8e-5 errors
|
||||
/* 6 */ V0Parameter( 1, 12, 833, 2, 15, 5, 4), // 328 mops, 5.8e-5 errors
|
||||
/* 7 */ V0Parameter( 1, 12, 833, 2, 15, 5, 4), // 328 mops, 5.8e-5 errors
|
||||
/* 8 */ V0Parameter( 1, 12, 833, 2, 15, 5, 4), // 328 mops, 6.1e-5 errors
|
||||
/* 9 */ V0Parameter( 1, 12, 834, 2, 15, 5, 4), // 328 mops, 6.2e-5 errors
|
||||
/* 10 */ V0Parameter( 1, 12, 840, 2, 15, 5, 4), // 331 mops, 6.0e-5 errors
|
||||
/* 11 */ V0Parameter( 1, 12, 843, 2, 15, 11, 2), // 371 mops, 6.3e-5 errors
|
||||
/* 12 */ V0Parameter( 1, 12, 804, 3, 12, 7, 3), // 424 mops, 6.2e-5 errors
|
||||
/* 13 */ V0Parameter( 1, 12, 807, 3, 12, 7, 3), // 425 mops, 5.6e-5 errors
|
||||
/* 14 */ V0Parameter( 1, 12, 818, 3, 12, 7, 3), // 431 mops, 6.3e-5 errors
|
||||
/* 15 */ V0Parameter( 1, 12, 806, 4, 9, 7, 3), // 519 mops, 5.6e-5 errors
|
||||
/* 16 */ V0Parameter( 1, 12, 813, 4, 9, 7, 3), // 524 mops, 5.8e-5 errors
|
||||
/* 17 */ V0Parameter( 1, 12, 809, 5, 8, 7, 3), // 616 mops, 5.8e-5 errors
|
||||
/* 18 */ V0Parameter( 1, 12, 839, 5, 8, 7, 3), // 638 mops, 6.2e-5 errors
|
||||
/* 19 */ V0Parameter( 1, 12, 828, 6, 7, 11, 2), // 753 mops, 6.3e-5 errors
|
||||
/* 20 */ V0Parameter( 1, 12, 793, 8, 5, 11, 2), // 908 mops, 6.2e-5 errors
|
||||
/* 21 */ V0Parameter( 1, 12, 791, 11, 4, 11, 2), // 1184 mops, 6.3e-5 errors
|
||||
/* 22 */ V0Parameter( 1, 12, 805, 14, 3, 11, 2), // 1487 mops, 6.0e-5 errors
|
||||
/* 23 */ V0Parameter( 1, 12, 821, 22, 2, 11, 2), // 2286 mops, 6.3e-5 errors
|
||||
/* 24 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 25 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 26 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 27 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 28 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 29 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 30 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 31 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
},
|
||||
{ /* precision 7 */
|
||||
/* 0 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 1 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 2 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 3 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 4 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 5 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 6 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 7 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 8 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 9 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 10 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 11 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 12 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 13 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 14 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 15 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 16 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 17 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 18 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 19 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 20 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 21 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 22 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 23 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 24 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 25 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 26 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 27 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 28 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 29 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 30 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
/* 31 : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),
|
||||
},
|
||||
}
|
||||
154
examples/v0_parameters.rs
Normal file
154
examples/v0_parameters.rs
Normal file
@@ -0,0 +1,154 @@
|
||||
use clap::Parser;
|
||||
use rayon_cond::CondIterator;
|
||||
|
||||
use concrete_optimizer::optimisation::atomic_pattern as optimize_atomic_pattern;
|
||||
|
||||
const _4_SIGMA: f64 = 1.0 - 0.999_936_657_516;
|
||||
|
||||
/// Simple program to greet a person
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(author, version, about, long_about = None)]
|
||||
struct Args {
|
||||
#[clap(long, default_value_t = 1, help = "1..16")]
|
||||
min_precision: u64,
|
||||
|
||||
#[clap(long, default_value_t = 7, help = "1..16")]
|
||||
max_precision: u64,
|
||||
|
||||
#[clap(long, default_value_t = _4_SIGMA)]
|
||||
p_error: f64,
|
||||
|
||||
#[clap(long, default_value_t = 128, help = "Only 128 is supported")]
|
||||
security_level: u64,
|
||||
|
||||
#[clap(long, default_value_t = 10, help = "8..16")]
|
||||
min_log_poly_size: u64,
|
||||
|
||||
#[clap(long, default_value_t = 12, help = "8..16")]
|
||||
max_log_poly_size: u64,
|
||||
|
||||
#[clap(long, default_value_t = 1, help = "EXPERIMENTAL")]
|
||||
min_glwe_dim: u64,
|
||||
|
||||
#[clap(long, default_value_t = 1, help = "EXPERIMENTAL")]
|
||||
// only usefull for very low precision, some parts are not correcte if used with k > 1
|
||||
max_glwe_dim: u64,
|
||||
|
||||
#[clap(long, default_value_t = 512)]
|
||||
min_intern_lwe_dim: u64,
|
||||
|
||||
#[clap(long, default_value_t = 1024)]
|
||||
max_intern_lwe_dim: u64, // 16bits needs around 1300
|
||||
|
||||
#[clap(long, default_value_t = 4096)]
|
||||
sum_size: u64,
|
||||
|
||||
#[clap(long)]
|
||||
no_parallelize: bool,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = Args::parse();
|
||||
let sum_size = args.sum_size;
|
||||
let p_error = args.p_error;
|
||||
let security_level = args.security_level;
|
||||
if security_level != 128 {
|
||||
panic!("Only 128bits of security is supported")
|
||||
}
|
||||
|
||||
let glwe_log_polynomial_sizes: Vec<_> =
|
||||
(args.min_log_poly_size..=args.max_log_poly_size).collect();
|
||||
let glwe_dimensions: Vec<_> = (args.min_glwe_dim..=args.max_glwe_dim).collect();
|
||||
let internal_lwe_dimensions: Vec<_> =
|
||||
(args.min_intern_lwe_dim..=args.max_intern_lwe_dim).collect();
|
||||
|
||||
let precisions = args.min_precision..=args.max_precision;
|
||||
let manps = 0..=31;
|
||||
|
||||
// let guard = pprof::ProfilerGuard::new(100).unwrap();
|
||||
|
||||
let precisions_iter = CondIterator::new(precisions.clone(), !args.no_parallelize);
|
||||
|
||||
#[rustfmt::skip]
|
||||
let all_results = precisions_iter.map(|precision| {
|
||||
let mut last_solution = None;
|
||||
manps.clone().map(|manp| {
|
||||
let noise_scale = 2_f64.powi(manp);
|
||||
let result = optimize_atomic_pattern::optimise_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
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
/*
|
||||
if let Ok(report) = guard.report().build() {
|
||||
let file = std::fs::File::create("flamegraph.svg").unwrap();
|
||||
let mut options = pprof::flamegraph::Options::default();
|
||||
options.image_width = Some(32000);
|
||||
report.flamegraph_with_options(file, &mut options).unwrap();
|
||||
};
|
||||
*/
|
||||
|
||||
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() {
|
||||
let solution = all_results[precision_i][manp_i].best_solution;
|
||||
if let Some(solution) = solution {
|
||||
println!(" /* {:2} */ V0Parameter({:2}, {:2}, {:4}, {:2}, {:2}, {:2}, {:2}), \t\t // {:4} mops, {:1.1e} errors",
|
||||
manp, solution.glwe_dimension, (solution.glwe_polynomial_size as f64).log2() as u64,
|
||||
solution.internal_ks_output_lwe_dimension,
|
||||
solution.br_decomposition_level_count, solution.br_decomposition_base_log,
|
||||
solution.ks_decomposition_level_count, solution.ks_decomposition_base_log,
|
||||
(solution.complexity / (1024.0 * 1024.0)) as u64,
|
||||
solution.p_error
|
||||
)
|
||||
} else {
|
||||
println!(
|
||||
" /* {:2} : NO SOLUTION */ V0Parameter(0,0,0,0,0,0,0),",
|
||||
manp
|
||||
);
|
||||
}
|
||||
}
|
||||
println!(" }},");
|
||||
}
|
||||
println!("}}");
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_reference_output() {
|
||||
const REF_FILE: &str = "examples/v0_parameters.ref-02-03-2022";
|
||||
const V0_PARAMETERS_EXE: &str = "target/debug/examples/v0_parameters";
|
||||
const CMP_LINES: &str = "\n";
|
||||
const EXACT_EQUALITY: i32 = 0;
|
||||
let _ = std::process::Command::new("cargo")
|
||||
.args(["build", "-q", "--example", "v0_parameters"])
|
||||
.status()
|
||||
.expect("Can't build");
|
||||
assert!(std::path::Path::new(V0_PARAMETERS_EXE).exists());
|
||||
|
||||
let actual_output = std::process::Command::new(V0_PARAMETERS_EXE)
|
||||
.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);
|
||||
}
|
||||
}
|
||||
@@ -18,5 +18,7 @@ pub mod computing_cost;
|
||||
pub mod global_parameters;
|
||||
pub mod graph;
|
||||
pub mod noise_estimator;
|
||||
pub mod optimisation;
|
||||
pub mod parameters;
|
||||
pub mod security;
|
||||
pub mod weight;
|
||||
|
||||
40
src/noise_estimator/error.rs
Normal file
40
src/noise_estimator/error.rs
Normal file
@@ -0,0 +1,40 @@
|
||||
pub fn sigma_scale_of_error_probability(p_error: f64) -> f64 {
|
||||
// https://en.wikipedia.org/wiki/Error_function#Applications
|
||||
let p_in = 1.0 - p_error;
|
||||
statrs::function::erf::erf_inv(p_in) * 2_f64.sqrt()
|
||||
}
|
||||
|
||||
pub fn error_probability_of_sigma_scale(sigma_scale: f64) -> f64 {
|
||||
// https://en.wikipedia.org/wiki/Error_function#Applications
|
||||
1.0 - statrs::function::erf::erf(sigma_scale / 2_f64.sqrt())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn test_sigmas() {
|
||||
// https://en.wikipedia.org/wiki/Normal_distribution#Standard_deviation_and_coverage
|
||||
let reference = &[
|
||||
0.682_689_492_137, // +- 1 sigma
|
||||
0.954_499_736_104, // 2
|
||||
0.997_300_203_937, // ...
|
||||
0.999_936_657_516,
|
||||
0.999_999_426_697,
|
||||
];
|
||||
for (i, &p_in) in reference.iter().enumerate() {
|
||||
let p_out = 1.0 - p_in;
|
||||
let expected_scale = (i + 1) as f64;
|
||||
approx::assert_relative_eq!(
|
||||
expected_scale,
|
||||
sigma_scale_of_error_probability(p_out),
|
||||
max_relative = 1e-8
|
||||
);
|
||||
approx::assert_relative_eq!(
|
||||
p_out,
|
||||
error_probability_of_sigma_scale(sigma_scale_of_error_probability(p_out)),
|
||||
max_relative = 1e-8
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
pub mod error;
|
||||
pub mod operators;
|
||||
pub mod security;
|
||||
pub mod utils;
|
||||
|
||||
@@ -5,7 +5,7 @@ use concrete_commons::parameters::{
|
||||
DecompositionBaseLog, DecompositionLevelCount, GlweDimension, LweDimension, PolynomialSize,
|
||||
};
|
||||
|
||||
use super::super::security;
|
||||
use crate::security;
|
||||
|
||||
/// Additional noise generated by the keyswitch step.
|
||||
pub fn variance_keyswitch<W: UnsignedInteger>(
|
||||
@@ -30,17 +30,18 @@ pub fn variance_keyswitch<W: UnsignedInteger>(
|
||||
)
|
||||
}
|
||||
|
||||
/// Compute the variance paramater for `variance_keyswitch`
|
||||
/// Compute the variance parameter of the keyswitch key.
|
||||
pub fn variance_ksk(
|
||||
internal_ks_output_lwe_dimension: u64,
|
||||
ciphertext_modulus_log: u64,
|
||||
security_level: u64,
|
||||
) -> Variance {
|
||||
let glwe_poly_size = 1;
|
||||
let glwe_dim = internal_ks_output_lwe_dimension;
|
||||
security::variance_ksk(
|
||||
glwe_poly_size,
|
||||
glwe_dim,
|
||||
let glwe_polynomial_size = 1;
|
||||
let glwe_dimension = internal_ks_output_lwe_dimension;
|
||||
// https://github.com/zama-ai/concrete-optimizer/blob/prototype/python/optimizer/noise_formulas/keyswitch.py#L13
|
||||
security::glwe::minimal_variance(
|
||||
glwe_polynomial_size,
|
||||
glwe_dimension,
|
||||
ciphertext_modulus_log,
|
||||
security_level,
|
||||
)
|
||||
@@ -51,8 +52,8 @@ pub fn fft_noise<W: UnsignedInteger>(
|
||||
internal_ks_output_lwe_dimension: u64, //n_small
|
||||
glwe_polynomial_size: u64, //N
|
||||
_glwe_dimension: u64, //k, unused
|
||||
br_decomposition_level_count: u64, //l(KS)
|
||||
br_decomposition_base_log: u64, //b(ks)
|
||||
br_decomposition_level_count: u64,
|
||||
br_decomposition_base_log: u64,
|
||||
) -> Variance {
|
||||
// https://github.com/zama-ai/concrete-optimizer/blob/prototype/python/optimizer/noise_formulas/bootstrap.py#L25
|
||||
let n = internal_ks_output_lwe_dimension as f64;
|
||||
@@ -206,7 +207,8 @@ where
|
||||
D: DispersionParameter,
|
||||
W: UnsignedInteger,
|
||||
{
|
||||
let variance_bsk = security::variance_bsk(
|
||||
// https://github.com/zama-ai/concrete-optimizer/blob/prototype/python/optimizer/noise_formulas/bootstrap.py#L66
|
||||
let variance_bsk = security::glwe::minimal_variance(
|
||||
glwe_polynomial_size,
|
||||
glwe_dimension,
|
||||
ciphertext_modulus_log,
|
||||
@@ -288,7 +290,7 @@ mod tests {
|
||||
let br_decomposition_base_log = 24;
|
||||
let ciphertext_modulus_log = 64;
|
||||
let security = 128;
|
||||
let variance_bsk = security::variance_bsk(
|
||||
let variance_bsk = security::glwe::minimal_variance(
|
||||
glwe_polynomial_size,
|
||||
glwe_dimension,
|
||||
ciphertext_modulus_log,
|
||||
@@ -318,7 +320,7 @@ mod tests {
|
||||
let br_decomposition_base_log = 5;
|
||||
let ciphertext_modulus_log = 128;
|
||||
let security = 128;
|
||||
let variance_bsk = security::variance_bsk(
|
||||
let variance_bsk = security::glwe::minimal_variance(
|
||||
glwe_polynomial_size,
|
||||
glwe_dimension,
|
||||
ciphertext_modulus_log,
|
||||
|
||||
586
src/optimisation/atomic_pattern.rs
Normal file
586
src/optimisation/atomic_pattern.rs
Normal file
@@ -0,0 +1,586 @@
|
||||
use concrete_commons::dispersion::{DispersionParameter, Variance};
|
||||
use concrete_commons::numeric::UnsignedInteger;
|
||||
|
||||
use crate::computing_cost::operators::atomic_pattern as complexity_atomic_pattern;
|
||||
use complexity_atomic_pattern::AtomicPatternComplexity;
|
||||
|
||||
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::security;
|
||||
|
||||
#[rustfmt::skip]
|
||||
const BR_BL: &[(u64, u64); 35] = &[
|
||||
(12, 1), (23, 1), (8, 2), (15, 2), (16, 2), (3, 3), (6, 3), (12, 3), (2, 4),
|
||||
(5, 4), (9, 4), (4, 5), (8, 5), (7, 6), (3, 7), (6, 7), (1, 8), (5, 8), (1, 9),
|
||||
(5, 9), (2, 10), (4, 10), (2, 11), (4, 11), (3, 14), (3, 15), (1, 21), (2, 21), (1, 22),
|
||||
(2, 22), (2, 23), (1, 43), (1, 44), (1, 45), (1, 46)
|
||||
];
|
||||
|
||||
#[rustfmt::skip]
|
||||
const KS_BL: &[(u64, u64); 46] = &[
|
||||
(5, 1), (12, 1), (26, 1), (31, 1), (4, 2), (8, 2), (17, 2), (21, 2), (3, 3),
|
||||
(6, 3), (13, 3), (15, 3), (2, 4), (5, 4), (10, 4), (12, 4), (2, 5), (4, 5),
|
||||
(9, 5), (10, 5), (4, 6), (8, 6), (3, 7), (7, 7), (3, 8), (6, 8), (1, 9), (5, 9), (1, 10),
|
||||
(5, 10), (2, 11), (2, 12), (4, 12), (4, 13), (3, 16), (3, 17), (1, 22), (1, 23), (2, 24),
|
||||
(2, 25), (2, 26), (1, 48), (1, 49), (1, 50), (1, 51), (1, 52)
|
||||
];
|
||||
|
||||
fn square(v: f64) -> f64 {
|
||||
v * v
|
||||
}
|
||||
|
||||
/* enable to debug */
|
||||
const CHECKS: bool = false;
|
||||
/* disable to debug */
|
||||
// Ref time for v0 table 1 thread: 950ms
|
||||
const CUTS: bool = true; // 80ms
|
||||
const PARETO_CUTS: bool = true; // 75ms
|
||||
const CROSS_PARETO_CUTS: bool = PARETO_CUTS && true; // 70ms
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
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
|
||||
}
|
||||
|
||||
// Constants during optimisation of decompositions
|
||||
struct OptimizationDecompositionsConsts {
|
||||
kappa: f64,
|
||||
sum_size: u64,
|
||||
security_level: u64,
|
||||
noise_factor: f64,
|
||||
ciphertext_modulus_log: u64,
|
||||
keyswitch_decompositions: Vec<(u64, u64)>,
|
||||
blind_rotate_decompositions: Vec<(u64, u64)>,
|
||||
variance_max: f64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct ComplexityNoise {
|
||||
index: usize,
|
||||
complexity: f64,
|
||||
noise: f64,
|
||||
}
|
||||
|
||||
impl ComplexityNoise {
|
||||
const ZERO: Self = Self {
|
||||
index: 0,
|
||||
complexity: 0.0,
|
||||
noise: 0.0,
|
||||
};
|
||||
}
|
||||
|
||||
fn blind_rotate_quantities<W: UnsignedInteger>(
|
||||
consts: &OptimizationDecompositionsConsts,
|
||||
internal_dim: u64,
|
||||
glwe_poly_size: u64,
|
||||
glwe_dim: u64,
|
||||
cut_complexity: f64,
|
||||
cut_noise: f64,
|
||||
) -> Vec<ComplexityNoise> {
|
||||
let br_decomp_len = consts.blind_rotate_decompositions.len();
|
||||
let mut quantities = vec![ComplexityNoise::ZERO; br_decomp_len];
|
||||
|
||||
let ciphertext_modulus_log = consts.ciphertext_modulus_log;
|
||||
let security_level = consts.security_level;
|
||||
let variance_bsk = security::glwe::minimal_variance(
|
||||
glwe_poly_size,
|
||||
glwe_dim,
|
||||
ciphertext_modulus_log,
|
||||
security_level,
|
||||
);
|
||||
let mut increasing_complexity = 0.0;
|
||||
let mut decreasing_variance = f64::INFINITY;
|
||||
let mut size = 0;
|
||||
for (i_br, &(br_b, br_l)) in consts.blind_rotate_decompositions.iter().enumerate() {
|
||||
let complexity_pbs = complexity_atomic_pattern::DEFAULT.pbs.complexity(
|
||||
internal_dim,
|
||||
glwe_poly_size,
|
||||
glwe_dim,
|
||||
br_l,
|
||||
br_b,
|
||||
consts.ciphertext_modulus_log,
|
||||
);
|
||||
if cut_complexity < complexity_pbs && CUTS {
|
||||
break; // complexity is increasing
|
||||
}
|
||||
let base_noise = noise_atomic_pattern::variance_bootstrap::<W>(
|
||||
internal_dim,
|
||||
glwe_poly_size,
|
||||
glwe_dim,
|
||||
br_l,
|
||||
br_b,
|
||||
consts.ciphertext_modulus_log,
|
||||
variance_bsk,
|
||||
);
|
||||
let noise_in = base_noise.get_variance() * square(consts.noise_factor);
|
||||
if cut_noise < noise_in && CUTS {
|
||||
continue; // noise is decreasing
|
||||
}
|
||||
if decreasing_variance < noise_in && PARETO_CUTS {
|
||||
// the current case is dominated
|
||||
continue;
|
||||
}
|
||||
let delta_complexity = complexity_pbs - increasing_complexity;
|
||||
size -= if delta_complexity == 0.0 && PARETO_CUTS {
|
||||
1 // the previous case is dominated
|
||||
} else {
|
||||
0
|
||||
};
|
||||
quantities[size] = ComplexityNoise {
|
||||
index: i_br,
|
||||
complexity: complexity_pbs,
|
||||
noise: noise_in,
|
||||
};
|
||||
assert!(
|
||||
0.0 <= delta_complexity,
|
||||
"blind_rotate_decompositions should be by increasing complexity"
|
||||
);
|
||||
increasing_complexity = complexity_pbs;
|
||||
decreasing_variance = noise_in;
|
||||
size += 1;
|
||||
}
|
||||
assert!(!PARETO_CUTS || size < 64);
|
||||
quantities.truncate(size);
|
||||
quantities
|
||||
}
|
||||
|
||||
fn keyswitch_quantities<W: UnsignedInteger>(
|
||||
consts: &OptimizationDecompositionsConsts,
|
||||
in_dim: u64,
|
||||
internal_dim: u64,
|
||||
cut_complexity: f64,
|
||||
cut_noise: f64,
|
||||
) -> Vec<ComplexityNoise> {
|
||||
let ks_decomp_len = consts.keyswitch_decompositions.len();
|
||||
let mut quantities = vec![ComplexityNoise::ZERO; ks_decomp_len];
|
||||
|
||||
let ciphertext_modulus_log = consts.ciphertext_modulus_log;
|
||||
let security_level = consts.security_level;
|
||||
let variance_ksk =
|
||||
noise_atomic_pattern::variance_ksk(internal_dim, ciphertext_modulus_log, security_level);
|
||||
let mut increasing_complexity = 0.0;
|
||||
let mut decreasing_variance = f64::INFINITY;
|
||||
let mut size = 0;
|
||||
for (i_ks, &(ks_b, ks_l)) in consts.keyswitch_decompositions.iter().enumerate() {
|
||||
let complexity_keyswitch = complexity_atomic_pattern::DEFAULT.ks_lwe.complexity(
|
||||
in_dim,
|
||||
internal_dim,
|
||||
ks_l,
|
||||
ks_b,
|
||||
ciphertext_modulus_log,
|
||||
);
|
||||
if cut_complexity < complexity_keyswitch && CUTS {
|
||||
break;
|
||||
}
|
||||
let noise_keyswitch = noise_atomic_pattern::variance_keyswitch::<W>(
|
||||
in_dim,
|
||||
ks_l,
|
||||
ks_b,
|
||||
ciphertext_modulus_log,
|
||||
variance_ksk,
|
||||
)
|
||||
.get_variance();
|
||||
if cut_noise < noise_keyswitch && CUTS {
|
||||
continue; // noise is decreasing
|
||||
}
|
||||
if decreasing_variance < noise_keyswitch && PARETO_CUTS {
|
||||
// the current case is dominated
|
||||
continue;
|
||||
}
|
||||
let delta_complexity = complexity_keyswitch - increasing_complexity;
|
||||
size -= if delta_complexity == 0.0 && PARETO_CUTS {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
};
|
||||
quantities[size] = ComplexityNoise {
|
||||
index: i_ks,
|
||||
complexity: complexity_keyswitch,
|
||||
noise: noise_keyswitch,
|
||||
};
|
||||
assert!(
|
||||
0.0 <= delta_complexity,
|
||||
"keyswitch_decompositions should be by increasing complexity"
|
||||
);
|
||||
increasing_complexity = complexity_keyswitch;
|
||||
decreasing_variance = noise_keyswitch;
|
||||
size += 1;
|
||||
}
|
||||
assert!(!PARETO_CUTS || size < 64);
|
||||
quantities.truncate(size);
|
||||
quantities
|
||||
}
|
||||
|
||||
pub struct OptimizationState {
|
||||
pub best_solution: Option<Solution>,
|
||||
pub count_domain: usize,
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn update_state_with_best_decompositions<W: UnsignedInteger>(
|
||||
state: &mut OptimizationState,
|
||||
consts: &OptimizationDecompositionsConsts,
|
||||
internal_dim: u64,
|
||||
glwe_poly_size: u64,
|
||||
glwe_dim: u64,
|
||||
) {
|
||||
let input_lwe_dimension = glwe_dim * glwe_poly_size;
|
||||
let noise_modulus_switching =
|
||||
noise_atomic_pattern::estimate_modulus_switching_noise_with_binary_key::<W>(
|
||||
internal_dim,
|
||||
glwe_poly_size,
|
||||
)
|
||||
.get_variance();
|
||||
let variance_max = consts.variance_max;
|
||||
if CUTS && noise_modulus_switching > variance_max {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut best_complexity = state.best_solution.map_or(f64::INFINITY, |s| s.complexity);
|
||||
let mut best_variance = state.best_solution.map_or(f64::INFINITY, |s| s.noise_max);
|
||||
|
||||
let complexity_multisum = (consts.sum_size * input_lwe_dimension) as f64;
|
||||
let mut cut_complexity = best_complexity - complexity_multisum;
|
||||
let mut cut_noise = variance_max - noise_modulus_switching;
|
||||
let br_quantities = blind_rotate_quantities::<W>(
|
||||
consts,
|
||||
internal_dim,
|
||||
glwe_poly_size,
|
||||
glwe_dim,
|
||||
cut_complexity,
|
||||
cut_noise,
|
||||
);
|
||||
if br_quantities.is_empty() {
|
||||
return;
|
||||
}
|
||||
if PARETO_CUTS {
|
||||
cut_noise -= br_quantities[br_quantities.len() - 1].noise;
|
||||
cut_complexity -= br_quantities[0].complexity;
|
||||
}
|
||||
let ks_quantities = keyswitch_quantities::<W>(
|
||||
consts,
|
||||
input_lwe_dimension,
|
||||
internal_dim,
|
||||
cut_complexity,
|
||||
cut_noise,
|
||||
);
|
||||
if ks_quantities.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let i_max_ks = ks_quantities.len() - 1;
|
||||
let mut i_current_max_ks = i_max_ks;
|
||||
for br_quantity in br_quantities {
|
||||
// increasing complexity, decreasing variance
|
||||
let noise_in = br_quantity.noise;
|
||||
let noise_max = noise_in + noise_modulus_switching;
|
||||
if noise_max > variance_max && CUTS {
|
||||
continue;
|
||||
}
|
||||
let complexity_pbs = br_quantity.complexity;
|
||||
let complexity = complexity_multisum + complexity_pbs;
|
||||
if complexity > best_complexity {
|
||||
// As best can evolves it is complementary to blind_rotate_quantities cuts.
|
||||
if PARETO_CUTS {
|
||||
break;
|
||||
} else if CUTS {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
for i_ks_pareto in (0..=i_current_max_ks).rev() {
|
||||
// increasing variance, decreasing complexity
|
||||
let ks_quantity = ks_quantities[i_ks_pareto];
|
||||
let noise_keyswitch = ks_quantity.noise;
|
||||
let noise_max = noise_in + noise_keyswitch + noise_modulus_switching;
|
||||
let complexity_keyswitch = ks_quantity.complexity;
|
||||
let complexity = complexity_multisum + complexity_keyswitch + complexity_pbs;
|
||||
|
||||
if CHECKS {
|
||||
assert_checks::<W>(
|
||||
consts,
|
||||
internal_dim,
|
||||
glwe_poly_size,
|
||||
glwe_dim,
|
||||
input_lwe_dimension,
|
||||
ks_quantity,
|
||||
br_quantity,
|
||||
noise_max,
|
||||
complexity_multisum,
|
||||
complexity,
|
||||
);
|
||||
}
|
||||
|
||||
if noise_max > variance_max {
|
||||
if CROSS_PARETO_CUTS {
|
||||
// the pareto of 2 added pareto is scanned linearly
|
||||
// but with all cuts, pre-computing => no gain
|
||||
i_current_max_ks = usize::min(i_ks_pareto + 1, i_max_ks);
|
||||
break;
|
||||
// it's compatible with next i_br but with the worst complexity
|
||||
} else if PARETO_CUTS {
|
||||
// increasing variance => we can skip all remaining
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
} else if complexity > best_complexity {
|
||||
continue;
|
||||
}
|
||||
|
||||
// feasible and at least as good complexity
|
||||
if complexity < best_complexity || noise_max < best_variance {
|
||||
let sigma = Variance(variance_max).get_standard_dev() * consts.kappa;
|
||||
let sigma_scale = sigma / Variance(noise_max).get_standard_dev();
|
||||
let p_error = error_probability_of_sigma_scale(sigma_scale);
|
||||
|
||||
let i_br = br_quantity.index;
|
||||
let i_ks = ks_quantity.index;
|
||||
let (br_b, br_l) = consts.blind_rotate_decompositions[i_br];
|
||||
let (ks_b, ks_l) = consts.keyswitch_decompositions[i_ks];
|
||||
|
||||
best_complexity = complexity;
|
||||
best_variance = noise_max;
|
||||
state.best_solution = Some(Solution {
|
||||
input_lwe_dimension,
|
||||
internal_ks_output_lwe_dimension: internal_dim,
|
||||
ks_decomposition_level_count: ks_l,
|
||||
ks_decomposition_base_log: ks_b,
|
||||
glwe_polynomial_size: glwe_poly_size,
|
||||
glwe_dimension: glwe_dim,
|
||||
br_decomposition_level_count: br_l,
|
||||
br_decomposition_base_log: br_b,
|
||||
noise_max,
|
||||
complexity,
|
||||
p_error,
|
||||
});
|
||||
}
|
||||
}
|
||||
} // br ks
|
||||
}
|
||||
|
||||
// This function provides reference values with unoptimised code, until we have non regeression tests
|
||||
#[allow(clippy::float_cmp)]
|
||||
fn assert_checks<W: UnsignedInteger>(
|
||||
consts: &OptimizationDecompositionsConsts,
|
||||
internal_dim: u64,
|
||||
glwe_poly_size: u64,
|
||||
glwe_dim: u64,
|
||||
input_lwe_dimension: u64,
|
||||
ks_c_n: ComplexityNoise,
|
||||
br_c_n: ComplexityNoise,
|
||||
noise_max: f64,
|
||||
complexity_multisum: f64,
|
||||
complexity: f64,
|
||||
) {
|
||||
let i_ks = ks_c_n.index;
|
||||
let i_br = br_c_n.index;
|
||||
let noise_in = br_c_n.noise;
|
||||
let noise_keyswitch = ks_c_n.noise;
|
||||
let complexity_keyswitch = ks_c_n.complexity;
|
||||
let complexity_pbs = br_c_n.complexity;
|
||||
let ciphertext_modulus_log = consts.ciphertext_modulus_log;
|
||||
let security_level = consts.security_level;
|
||||
let (br_b, br_l) = consts.blind_rotate_decompositions[i_br];
|
||||
let (ks_b, ks_l) = consts.keyswitch_decompositions[i_ks];
|
||||
let variance_bsk = security::glwe::minimal_variance(
|
||||
glwe_poly_size,
|
||||
glwe_dim,
|
||||
ciphertext_modulus_log,
|
||||
security_level,
|
||||
);
|
||||
let base_noise_ = noise_atomic_pattern::variance_bootstrap::<W>(
|
||||
internal_dim,
|
||||
glwe_poly_size,
|
||||
glwe_dim,
|
||||
br_l,
|
||||
br_b,
|
||||
ciphertext_modulus_log,
|
||||
variance_bsk,
|
||||
);
|
||||
let noise_in_ = base_noise_.get_variance() * square(consts.noise_factor);
|
||||
let complexity_pbs_ = complexity_atomic_pattern::DEFAULT.pbs.complexity(
|
||||
internal_dim,
|
||||
glwe_poly_size,
|
||||
glwe_dim,
|
||||
br_l,
|
||||
br_b,
|
||||
ciphertext_modulus_log,
|
||||
);
|
||||
assert!(complexity_pbs == complexity_pbs_);
|
||||
assert!(noise_in == noise_in_);
|
||||
let variance_ksk =
|
||||
noise_atomic_pattern::variance_ksk(internal_dim, ciphertext_modulus_log, security_level);
|
||||
let noise_keyswitch_ = noise_atomic_pattern::variance_keyswitch::<W>(
|
||||
input_lwe_dimension,
|
||||
ks_l,
|
||||
ks_b,
|
||||
ciphertext_modulus_log,
|
||||
variance_ksk,
|
||||
)
|
||||
.get_variance();
|
||||
let complexity_keyswitch_ = complexity_atomic_pattern::DEFAULT.ks_lwe.complexity(
|
||||
input_lwe_dimension,
|
||||
internal_dim,
|
||||
ks_l,
|
||||
ks_b,
|
||||
ciphertext_modulus_log,
|
||||
);
|
||||
assert!(complexity_keyswitch == complexity_keyswitch_);
|
||||
assert!(noise_keyswitch == noise_keyswitch_);
|
||||
|
||||
let check_max_noise = noise_atomic_pattern::maximal_noise::<Variance, W>(
|
||||
Variance(noise_in),
|
||||
input_lwe_dimension,
|
||||
internal_dim,
|
||||
ks_l,
|
||||
ks_b,
|
||||
glwe_poly_size,
|
||||
ciphertext_modulus_log,
|
||||
security_level,
|
||||
)
|
||||
.get_variance();
|
||||
assert!(f64::abs(noise_max - check_max_noise) / check_max_noise < 0.00000000001);
|
||||
let check_complexity = complexity_atomic_pattern::DEFAULT.complexity(
|
||||
consts.sum_size,
|
||||
input_lwe_dimension,
|
||||
internal_dim,
|
||||
ks_l,
|
||||
ks_b,
|
||||
glwe_poly_size,
|
||||
glwe_dim,
|
||||
br_l,
|
||||
br_b,
|
||||
ciphertext_modulus_log,
|
||||
);
|
||||
|
||||
let diff_complexity = f64::abs(complexity - check_complexity) / check_complexity;
|
||||
if diff_complexity > 0.0001 {
|
||||
println!(
|
||||
"{} + {} + {} != {}",
|
||||
complexity_multisum, complexity_keyswitch, complexity_pbs, check_complexity,
|
||||
);
|
||||
}
|
||||
assert!(diff_complexity < 0.0001);
|
||||
}
|
||||
|
||||
const BITS_CARRY: u64 = 1;
|
||||
const BITS_PADDING_WITHOUT_NOISE: u64 = 1;
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
pub fn optimise_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],
|
||||
restart_at: Option<Solution>,
|
||||
) -> OptimizationState {
|
||||
assert!(0 < precision && precision <= 16);
|
||||
assert!(security_level == 128);
|
||||
assert!(1.0 <= noise_factor);
|
||||
assert!(0.0 < maximum_acceptable_error_probability);
|
||||
assert!(maximum_acceptable_error_probability < 1.0);
|
||||
|
||||
// this assumed the noise level is equal at input/output
|
||||
// the security of the noise level of ouput is controlled by
|
||||
// the blind rotate decomposition
|
||||
|
||||
let ciphertext_modulus_log = W::BITS as u64;
|
||||
|
||||
let no_noise_bits = BITS_CARRY + precision + BITS_PADDING_WITHOUT_NOISE;
|
||||
let noise_bits = ciphertext_modulus_log - no_noise_bits;
|
||||
let fatal_noise_limit = (1_u64 << noise_bits) as f64;
|
||||
|
||||
// Now we search for P(x not in [-+fatal_noise_limit] | σ = safe_sigma) = p_error
|
||||
// P(x not in [-+kappa] | σ = 1) = p_error
|
||||
let kappa: f64 = sigma_scale_of_error_probability(maximum_acceptable_error_probability);
|
||||
let safe_sigma = fatal_noise_limit / kappa;
|
||||
let variance_max = Variance::from_modular_variance::<W>(square(safe_sigma));
|
||||
|
||||
let consts = OptimizationDecompositionsConsts {
|
||||
kappa,
|
||||
sum_size,
|
||||
security_level,
|
||||
noise_factor,
|
||||
ciphertext_modulus_log,
|
||||
keyswitch_decompositions: KS_BL.to_vec(),
|
||||
blind_rotate_decompositions: BR_BL.to_vec(),
|
||||
variance_max: variance_max.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(),
|
||||
};
|
||||
|
||||
// cut only on glwe_poly_size based of modulus switching noise
|
||||
// assume this noise is increasing with lwe_intern_dim
|
||||
let min_internal_lwe_dimensions = internal_lwe_dimensions[0];
|
||||
let lower_bound_cut = |glwe_poly_size| {
|
||||
// TODO: cut if min complexity is higher than current best
|
||||
CUTS && noise_atomic_pattern::estimate_modulus_switching_noise_with_binary_key::<W>(
|
||||
min_internal_lwe_dimensions,
|
||||
glwe_poly_size,
|
||||
)
|
||||
.get_variance()
|
||||
> consts.variance_max
|
||||
};
|
||||
|
||||
let skip = |glwe_dim, glwe_poly_size| match restart_at {
|
||||
Some(solution) => {
|
||||
(glwe_dim, glwe_poly_size) < (solution.glwe_dimension, solution.glwe_polynomial_size)
|
||||
}
|
||||
None => false,
|
||||
};
|
||||
|
||||
for &glwe_dim in glwe_dimensions {
|
||||
assert!(1 <= glwe_dim);
|
||||
assert!(glwe_dim < 4);
|
||||
|
||||
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 lower_bound_cut(glwe_poly_size) {
|
||||
continue;
|
||||
}
|
||||
if skip(glwe_dim, glwe_poly_size) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for &internal_dim in internal_lwe_dimensions {
|
||||
assert!(256 < internal_dim);
|
||||
update_state_with_best_decompositions::<W>(
|
||||
&mut state,
|
||||
&consts,
|
||||
internal_dim,
|
||||
glwe_poly_size,
|
||||
glwe_dim,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state
|
||||
}
|
||||
1
src/optimisation/mod.rs
Normal file
1
src/optimisation/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod atomic_pattern;
|
||||
@@ -2,7 +2,7 @@ use concrete_commons::dispersion::Variance;
|
||||
|
||||
/// Noise ensuring security
|
||||
// It was 128 bits of security on the 30th August 2021 with https://bitbucket.org/malb/lwe-estimator/commits/fb7deba98e599df10b665eeb6a26332e43fb5004
|
||||
pub fn variance_glwe(
|
||||
pub fn minimal_variance(
|
||||
glwe_polynomial_size: u64,
|
||||
glwe_dimension: u64,
|
||||
ciphertext_modulus_log: u64,
|
||||
@@ -23,52 +23,20 @@ pub fn variance_glwe(
|
||||
Variance(f64::exp2(log2_var))
|
||||
}
|
||||
|
||||
/// Noise ensuring ksk security
|
||||
pub fn variance_ksk(
|
||||
glwe_polynomial_size: u64,
|
||||
glwe_dimension: u64,
|
||||
ciphertext_modulus_log: u64,
|
||||
security_level: u64,
|
||||
) -> Variance {
|
||||
// https://github.com/zama-ai/concrete-optimizer/blob/prototype/python/optimizer/noise_formulas/keyswitch.py#L13
|
||||
variance_glwe(
|
||||
glwe_polynomial_size,
|
||||
glwe_dimension,
|
||||
ciphertext_modulus_log,
|
||||
security_level,
|
||||
)
|
||||
}
|
||||
|
||||
/// Noise ensuring bsk security
|
||||
pub fn variance_bsk(
|
||||
glwe_polynomial_size: u64,
|
||||
glwe_dimension: u64,
|
||||
ciphertext_modulus_log: u64,
|
||||
security_level: u64,
|
||||
) -> Variance {
|
||||
// https://github.com/zama-ai/concrete-optimizer/blob/prototype/python/optimizer/noise_formulas/bootstrap.py#L66
|
||||
variance_glwe(
|
||||
glwe_polynomial_size,
|
||||
glwe_dimension,
|
||||
ciphertext_modulus_log,
|
||||
security_level,
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use concrete_commons::dispersion::DispersionParameter;
|
||||
|
||||
#[test]
|
||||
fn golden_python_prototype_security_variance_glwe_low() {
|
||||
fn golden_python_prototype_security_security_glwe_variance_low() {
|
||||
// python securityFunc(10,14,64)= 0.3120089883926036
|
||||
let log_poly_size = 14;
|
||||
let glwe_dimension = 10;
|
||||
let integer_size = 64;
|
||||
let golden_std_dev = 0.312_008_988_392_6036;
|
||||
let security_level = 128;
|
||||
let actual = variance_glwe(log_poly_size, glwe_dimension, integer_size, security_level);
|
||||
let actual = minimal_variance(log_poly_size, glwe_dimension, integer_size, security_level);
|
||||
approx::assert_relative_eq!(
|
||||
golden_std_dev,
|
||||
actual.get_standard_dev(),
|
||||
@@ -77,14 +45,14 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn golden_python_prototype_security_variance_glwe_high() {
|
||||
fn golden_python_prototype_security_security_glwe_variance_high() {
|
||||
// python securityFunc(3,8,32)= 2.6011445832514504
|
||||
let log_poly_size = 8;
|
||||
let glwe_dimension = 3;
|
||||
let integer_size = 32;
|
||||
let golden_std_dev = 2.6011445832514504;
|
||||
let security_level = 128;
|
||||
let actual = variance_glwe(log_poly_size, glwe_dimension, integer_size, security_level);
|
||||
let actual = minimal_variance(log_poly_size, glwe_dimension, integer_size, security_level);
|
||||
approx::assert_relative_eq!(
|
||||
golden_std_dev,
|
||||
actual.get_standard_dev(),
|
||||
1
src/security/mod.rs
Normal file
1
src/security/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod glwe;
|
||||
Reference in New Issue
Block a user