From 0f43be24ad4979b93926baf62d5eabafe7572e57 Mon Sep 17 00:00:00 2001
From: STEVAN Antoine <antoine.stevan@isae-supaero.fr>
Date: Thu, 23 May 2024 11:23:03 +0000
Subject: [PATCH] Refactor plot commands (dragoon/komodo!104)

this MR moves run and plot commands from `examples/benches/README.md` to
- `scripts/setup/`: `run.nu` and `plot.nu`
- `scripts/commit/`: `run.nu` and `plot.nu`
- `scripts/recoding/`: `run.nu` and `plot.nu`
- `scripts/fec/`: `run.nu` and `plot.nu`
- `scripts/inbreeding/`: `build.nu`, `run.nu` and `plot.nu`

to generate all the figures at once
```bash
use scripts/setup/run.nu; seq 0 13 | each { 2 ** $in } | run --output data/setup.ndjson
use ./scripts/setup/plot.nu; plot data/setup.ndjson --save ~/setup.pdf

use scripts/commit/run.nu; seq 0 13 | each { 2 ** $in } | run --output data/commit.ndjson
use ./scripts/commit/plot.nu; plot data/commit.ndjson --save ~/commit.pdf

use scripts/recoding/run.nu; seq 0 18 | each { 512 * 2 ** $in } | run --ks [2, 4, 8, 16] --output data/recoding.ndjson
use ./scripts/recoding/plot.nu; plot data/recoding.ndjson --save ~/recoding.pdf

use scripts/fec/run.nu; seq 0 18 | each { 512 * 2 ** $in } | run --ks [2, 4, 8, 16] --output data/fec.ndjson
use ./scripts/fec/plot.nu; plot encoding data/fec.ndjson --save ~/encoding.pdf
use ./scripts/fec/plot.nu; plot decoding data/fec.ndjson --save ~/decoding.pdf
use ./scripts/fec/plot.nu; plot e2e data/fec.ndjson --save ~/e2e.pdf

use ./scripts/fec/plot.nu; plot combined data/fec.ndjson --recoding data/recoding.ndjson --save ~/comparison.pdf
use ./scripts/fec/plot.nu; plot ratio data/fec.ndjson --recoding data/recoding.ndjson --save ~/ratio.pdf

./scripts/inbreeding/build.nu
./scripts/inbreeding/run.nu --output data/inbreeding.nuon
./scripts/inbreeding/plot.nu data/inbreeding.nuon --save ~/inbreeding.pdf
```

> :bulb: **Note**
> this took around 27min 18sec in total on my machine with 14min 45sec for the inbreeding section only and 12min 33sec for the rest
---
 examples/benches/README.md    | 354 ++--------------------------------
 examples/inbreeding/mod.rs    | 156 +--------------
 scripts/commit/plot.nu        |  32 +++
 scripts/commit/run.nu         |   5 +
 scripts/fec/plot.nu           | 264 +++++++++++++++++++++++++
 scripts/fec/run.nu            |  26 +++
 scripts/fs.nu                 |  11 ++
 scripts/inbreeding/build.nu   |   3 +
 scripts/inbreeding/options.nu |  19 ++
 scripts/inbreeding/plot.nu    | 101 ++++++++++
 scripts/inbreeding/run.nu     |  44 +++++
 scripts/plot.nu               |   7 +
 scripts/recoding/plot.nu      |  31 +++
 scripts/recoding/run.nu       |  25 +++
 scripts/setup/plot.nu         |  37 ++++
 scripts/setup/run.nu          |   5 +
 scripts/venv.nu               |   1 +
 17 files changed, 634 insertions(+), 487 deletions(-)
 create mode 100644 scripts/commit/plot.nu
 create mode 100644 scripts/commit/run.nu
 create mode 100644 scripts/fec/plot.nu
 create mode 100644 scripts/fec/run.nu
 create mode 100644 scripts/fs.nu
 create mode 100755 scripts/inbreeding/build.nu
 create mode 100644 scripts/inbreeding/options.nu
 create mode 100755 scripts/inbreeding/plot.nu
 create mode 100755 scripts/inbreeding/run.nu
 create mode 100644 scripts/recoding/plot.nu
 create mode 100644 scripts/recoding/run.nu
 create mode 100644 scripts/setup/plot.nu
 create mode 100644 scripts/setup/run.nu
 create mode 100644 scripts/venv.nu

diff --git a/examples/benches/README.md b/examples/benches/README.md
index c70442ad..ad97741a 100644
--- a/examples/benches/README.md
+++ b/examples/benches/README.md
@@ -77,369 +77,47 @@ for graph in [
 
 ## trusted setup
 ```nushell
-let degrees = seq 0 13 | each { 2 ** $in }
-cargo run --release --example bench_setup -- --nb-measurements 10 ...$degrees out> setup.ndjson
+use scripts/setup/run.nu; seq 0 13 | each { 2 ** $in } | run --output setup.ndjson
 ```
 ```nushell
-gplt plot ...[
-    # --title "time to create trusted setups for certain curves"
-    --x-label "degree"
-    --y-label "time (in ms)"
-    (
-        open setup.ndjson
-            | ns-to-ms $.times
-            | compute-stats $.times
-            | insert degree { get label | parse "degree {d}" | into record | get d | into int}
-            | update name {|it| if ($it.name | str starts-with  "ARK") {
-                let c = $it.name | parse "ARK setup on {curve}" | into record | get curve
-                $"($c)-ark"
-            } else {
-                $it.name | parse "setup on {curve}" | into record | get curve
-            }}
-            | rename --column { degree: "x", mean: "y", stddev: "e" }
-            | select name x y e
-            | group-by name --to-table
-            | reject items.name
-            | rename --column { group: "name", items: "points" }
-            | sort-by name
-            | to json
-    )
-    --fullscreen
-    --dpi 150
-    --fig-size ...[16, 9]
-    --font ({ size: 30, family: serif, sans-serif: Helvetica } | to json)
-    --use-tex
-    # --save setup.pdf
-]
+use ./scripts/setup/plot.nu; plot setup.ndjson
 ```
 
 ## commit
 ```nushell
-let degrees = seq 0 15 | each { 2 ** $in }
-cargo run --release --example bench_commit -- --nb-measurements 10 ...$degrees out> commit.ndjson
+use scripts/commit/run.nu; seq 0 13 | each { 2 ** $in } | run --output commit.ndjson
 ```
 ```nushell
-gplt plot ...[
-    # --title "time to commit polynomials for certain curves"
-    --x-label "degree"
-    --y-label "time (in ms)"
-    (
-        open commit.ndjson
-            | where name !~ '^SEC'
-            | ns-to-ms $.times
-            | compute-stats $.times
-            | insert degree { get label | parse "degree {d}" | into record | get d | into int }
-            | rename --column { degree: "x", mean: "y", stddev: "e" }
-            | select name x y e
-            | group-by name --to-table
-            | reject items.name
-            | rename --column { group: "name", items: "points" }
-            | sort-by name
-            | to json
-    )
-    --fullscreen
-    --dpi 150
-    --fig-size ...[16, 9]
-    --font ({ size: 30, family: serif, sans-serif: Helvetica } | to json)
-    --use-tex
-    # --save commit.pdf
-]
+use ./scripts/commit/plot.nu; plot commit.ndjson
 ```
 
 ## end-to-end benchmarks
-```nushell
-use scripts/plot.nu [
-    into-duration-tick-labels,
-    into-filesize-tick-labels,
-    into-axis-options,
-    COMMON_OPTIONS,
-]
-```
-
 ### recoding
 ```nushell
-"" out> recoding.ndjson
-
-[2, 4, 8, 16] | each { |k|
-    cargo run --release --example bench_recoding -- ...[
-        --nb-measurements 10
-        ...(seq 0 18 | each { 512 * 2 ** $in })
-        --shards $k
-        --ks $k
-    ] | from ndnuon | to ndjson out>> recoding.ndjson
-}
+use scripts/recoding/run.nu
+seq 0 18 | each { 512 * 2 ** $in } | run --ks [2, 4, 8, 16] --output recoding.ndjson
 ```
 ```nushell
-let graphs = open recoding.ndjson
-    | ns-to-ms $.times
-    | compute-stats $.times
-    | update label { from nuon }
-    | flatten --all label
-    | where name == "BLS12-381"
-    | rename --column { bytes: "x", mean: "y", stddev: "e" }
-    | select shards x y e
-    | group-by shards --to-table
-    | reject items.shards
-    | rename --column { group: "name", items: "points" }
-    | update name { $"$k = ($in)$"}
-
-gplt plot ($graphs | to json) ...[
-    # --y-label "time (in ms)"
-    ...($graphs.points | flatten | into-axis-options)
-    --no-legend
-    ...$COMMON_OPTIONS
-    # --save recoding.pdf
-]
+use ./scripts/recoding/plot.nu; plot recoding.ndjson
 ```
 
 ### FEC
 ```nushell
-"" out> fec.ndjson
-
-[2, 4, 8, 16] | each { |k|
-    cargo run --release --example bench_fec  -- ...[
-        ...(seq 0 18 | each { 512 * 2 ** $in })
-        --encoding vandermonde
-        -k $k
-        -n 1
-        --nb-measurements 10
-    ] | from ndnuon | to ndjson out>> fec.ndjson
-}
+use scripts/fec/run.nu
+seq 0 18 | each { 512 * 2 ** $in } | run --ks [2, 4, 8, 16] --output fec.ndjson
 ```
 ```nushell
-let graphs = open fec.ndjson
-    | update label { from json }
-    | flatten label
-    | ns-to-ms times
-    | compute-stats times
-    | where name == "BLS12-381" and step == "encode"
-    | rename --column { bytes: "x", mean: "y", stddev: "e" }
-    | select k x y e
-    | sort-by x
-    | group-by k --to-table
-    | reject items.k
-    | rename --column { group: "name", items: "points" }
-    | update name { $"$k = ($in)$" }
-
-gplt plot ($graphs | to json) ...[
-    # --title "1-encoding"
-    ...($graphs.points | flatten | into-axis-options -y "duration")
-    ...$COMMON_OPTIONS
-    # --save encoding.pdf
-]
-
-let graphs = open fec.ndjson
-    | update label { from json }
-    | flatten label
-    | ns-to-ms times
-    | compute-stats times
-    | where name == "BLS12-381" and step == "decode"
-    | rename --column { bytes: "x", mean: "y", stddev: "e" }
-    | select k x y e
-    | sort-by x
-    | group-by k --to-table
-    | reject items.k
-    | rename --column { group: "name", items: "points" }
-    | update name { $"$k = ($in)$" }
-
-gplt plot ($graphs | to json) ...[
-    # --title "k-decoding"
-    --y-label "time (in ms)"
-    ...($graphs.points | flatten | into-axis-options -y "duration")
-    --no-legend
-    ...$COMMON_OPTIONS
-    # --save decoding.pdf
-]
-
-let graphs = open fec.ndjson
-    | update label { from json }
-    | flatten label
-    | insert foo { $"($in.name) / ($in.k) / ($in.bytes)" }
-    | group-by foo --to-table
-    | update items {|it|
-        $it.items
-            | update step e2e
-            | update times { $it.items.0.times | zip $it.items.1.times | each { $in.0 + $in.1 } }
-    }
-    | flatten --all
-    | reject group foo
-    | ns-to-ms times
-    | compute-stats times
-    | reject times
-    | where name == "BLS12-381"
-    | rename --column { bytes: "x", mean: "y", stddev: "e" }
-    | select k x y e
-    | sort-by x
-    | group-by k --to-table
-    | reject items.k
-    | rename --column { group: "name", items: "points" }
-    | update name { $"$k = ($in)$" }
-
-gplt plot ($graphs | to json) ...[
-    # --title "e2e: k-decoding + 1-encoding"
-    --y-label "time (in ms)"
-    ...($graphs.points | flatten | into-axis-options -y "duration")
-    --no-legend
-    ...$COMMON_OPTIONS
-    # --save e2e.pdf
-]
+use ./scripts/fec/plot.nu; plot encoding fec.ndjson
+use ./scripts/fec/plot.nu; plot decoding fec.ndjson
+use ./scripts/fec/plot.nu; plot e2e fec.ndjson
 ```
 
-combined graph
+## combined graph
 ```nushell
-let true_recoding_graphs = open recoding.ndjson
-    | ns-to-ms $.times
-    | compute-stats $.times
-    | update label { from nuon }
-    | flatten --all label
-    | where name == "BLS12-381"
-    | rename --column { bytes: "x", mean: "y", stddev: "e" }
-    | select shards x y e
-    | sort-by x
-    | group-by shards --to-table
-    | insert style.color {|it|
-        match $it.items.shards.0 {
-            2 => "tab:blue"
-            4 => "tab:orange"
-            8 => "tab:green"
-            16 => "tab:red"
-            _ => "tab:grey"
-        }
-    }
-    | reject items.shards
-    | insert style.line.type "solid"
-    | rename --column { group: "name", items: "points" }
-    | update name { $"$k = ($in)$" }
-
-let naive_recoding_graphs = open fec.ndjson
-    | update label { from json }
-    | flatten label
-    | insert key { $"($in.name) / ($in.k) / ($in.bytes)" }
-    | group-by key --to-table
-    | update items {|it|
-        $it.items
-            | update step e2e
-            | update times { $it.items.0.times | zip $it.items.1.times | each { $in.0 + $in.1 } }
-    }
-    | flatten --all
-    | reject group key
-    | ns-to-ms times
-    | compute-stats times
-    | reject times
-    | where name == "BLS12-381"
-    | rename --column { bytes: "x", mean: "y", stddev: "e" }
-    | select k x y e
-    | sort-by x
-    | group-by k --to-table
-    | insert style.color {|it|
-        match $it.items.k.0 {
-            2 => "tab:blue"
-            4 => "tab:orange"
-            8 => "tab:green"
-            16 => "tab:red"
-            _ => "tab:grey"
-        }
-    }
-    | insert style.line.type "dashed"
-    | reject items.k
-    | rename --column { group: "name", items: "points" }
-    | reject name
-
-let graphs = $true_recoding_graphs
-    | append $naive_recoding_graphs
-    | append {
-        name: "naive recoding ($k$-decoding + $1$-encoding)",
-        legend: "second",
-        points: [],
-        style: {
-            color: "grey",
-            line: {
-                type: "dashed",
-                marker: {
-                    size: 0,
-                },
-            },
-        },
-    }
-    | append {
-        name: "true recoding ($k$-recoding)",
-        legend: "second",
-        points: [],
-        style: {
-            color: "grey",
-            line: {
-                type: "solid",
-                marker: {
-                    size: 0,
-                },
-            },
-        },
-    }
-
-gplt plot ($graphs | to json) ...[
-    ...($graphs.points | flatten | into-axis-options -y "duration")
-    ...$COMMON_OPTIONS
-    --legend-loc "upper left" "lower right"
-    # --save comparison.png
-]
+use ./scripts/fec/plot.nu; plot combined fec.ndjson --recoding recoding.ndjson
 ```
 
-ratio graph
+## ratio graph
 ```nushell
-let true_recoding_graphs = open recoding.ndjson
-    | ns-to-ms times
-    | compute-stats $.times
-    | update label { from nuon }
-    | flatten --all label
-    | where name == "BLS12-381"
-    | select shards bytes mean
-    | rename --column { shards: "k" }
-
-let naive_recoding_graphs = open fec.ndjson
-    | update label { from json }
-    | flatten label
-    | insert key { $"($in.name) / ($in.k) / ($in.bytes)" }
-    | group-by key --to-table
-    | update items {|it|
-        $it.items
-            | update step e2e
-            | update times { $it.items.0.times | zip $it.items.1.times | each { $in.0 + $in.1 } }
-    }
-    | flatten --all
-    | reject group key
-    | ns-to-ms times
-    | compute-stats times
-    | where name == "BLS12-381"
-    | select k bytes mean
-    | uniq
-
-let graphs = $true_recoding_graphs
-    | rename --column { mean: "true" }
-    | insert key { $"($in.k) ($in.bytes)" }
-    | join ($naive_recoding_graphs | rename --column { mean: "naive" } | insert key { $"($in.k) ($in.bytes)" }) key
-    | select k bytes $.true naive
-    | sort-by k bytes
-    | insert cmp { $in.naive / $in.true }
-    | rename --column { bytes: "x", cmp: "y" }
-    | select k x y
-    | group-by k --to-table
-    | insert style.color {|it|
-        match $it.items.k.0 {
-            2 => "tab:blue"
-            4 => "tab:orange"
-            8 => "tab:green"
-            16 => "tab:red"
-            _ => "tab:grey"
-        }
-    }
-    | reject items.k
-    | rename --column { group: "name", items: "points" }
-    | update name { $"$k = ($in)$" }
-
-gplt plot ($graphs | to json) ...[
-    ...($graphs.points | flatten | into-axis-options)
-    ...$COMMON_OPTIONS
-    --legend-loc "upper right"
-    # --save ratio.png
-]
+use ./scripts/fec/plot.nu; plot ratio fec.ndjson --recoding recoding.ndjson
 ```
diff --git a/examples/inbreeding/mod.rs b/examples/inbreeding/mod.rs
index 01bdd0a3..6a442581 100644
--- a/examples/inbreeding/mod.rs
+++ b/examples/inbreeding/mod.rs
@@ -1,154 +1,12 @@
+/// - build the example for best performance with [`./../../scripts/inbreeding/build.nu`]
+/// - run the experiment with [`./../../scripts/inbreeding/run.nu`]
+/// - plot the results with [`./../../scripts/inbreeding/plot.nu`]
+///
 /// # Example
-/// - build the example for best performance
 /// ```shell
-/// cargo build --release --example inbreeding
-/// ```
-/// - run the experiment
-/// ```nushell
-/// const NB_BYTES = 1_024 * 10
-/// const K = 10
-/// const N = 2 * $K
-/// const NB_MEASUREMENTS = 1_000
-/// const MEASUREMENT_SCHEDULE = 1
-/// const MAX_T = 150
-///
-/// ./target/release/examples/inbreeding ...[
-///     $NB_BYTES,
-///     -k $K
-///     -n $N
-///     --nb-measurements $NB_MEASUREMENTS
-///     --measurement-schedule $MEASUREMENT_SCHEDULE
-///     -t $MAX_T
-///     --test-case end-to-end
-/// ] | lines | into float | save --force baseline.nuon
-///
-/// let strategies = seq 1 $K
-///     | each { $"single:($in)" }
-///     | append [
-///         "double:0.5:1:2",
-///         "double:0.5:2:3",
-///         "double:0.333:1:2",
-///         "double:0.666:1:2",
-///         "double:0.333:2:3",
-///         "double:0.666:2:3"
-///     ]
-/// let environment = "fixed:0"
-///
-/// $strategies | each {|s|
-///     let diversity = ./target/release/examples/inbreeding ...[
-///         $NB_BYTES,
-///         -k $K
-///         -n $N
-///         --nb-measurements $NB_MEASUREMENTS
-///         --measurement-schedule $MEASUREMENT_SCHEDULE
-///         -t $MAX_T
-///         --test-case recoding
-///         --strategy $s
-///         --environment $environment
-///     ] | lines | into float
-///
-///     {
-///         strategy: $s,
-///         diversity: $diversity,
-///     }
-/// } | save --force inbreeding.nuon
-/// ```
-/// - plot the results
-/// ```nushell
-/// let data = open inbreeding.nuon
-/// let w = 3
-/// let l = $data.diversity.0 | length
-///
-/// use std repeat
-///
-/// def "parse strategy" []: string -> record<type: string> {
-///     let s = $in
-///
-///     if ($s | str starts-with "single") {
-///         let res = $s
-///             | parse "single:{n}"
-///             | into record
-///             | into int n
-///         { type: "single", n: $res.n }
-///     } else {
-///         let res = $s
-///             | parse "double:{p}:{n}:{m}"
-///             | into record
-///             | into float p
-///             | into int n
-///             | into int m
-///         { type: "double", p: $res.p, n: $res.n, m: $res.m }
-///     }
-/// }
-///
-/// # let raw = $data | update diversity { take ($l - $w + 1)}
-/// # let smooth = $data | update diversity { prepend (1 | repeat $w) | window $w | each { math avg } }
-/// let smooth = $data
-///
-/// $smooth
-///     | update strategy { parse strategy }
-///     | insert sort {|it|
-///         match $it.strategy.type {
-///             "single" => [$it.strategy.n, 1.0]
-///             "double" => [$it.strategy.n, $it.strategy.p]
-///         }
-///     }
-///     | sort-by sort
-///     | reverse
-///     | reject sort
-///     | insert name {|it|
-///         match $it.strategy.type {
-///             "single" => {
-///                 let sigma = if $it.strategy.n == $K { "k" }  else { $"k - ($K - $it.strategy.n)" }
-///                 $"$\\sigma = ($sigma) = ($it.strategy.n)$"
-///             }
-///             "double" => $"($it.strategy.p)? ($it.strategy.n) ; ($it.strategy.m)"
-///         }
-///     }
-///     # | append ($raw | insert name null | insert style { line: { alpha: 0.1 } })
-///     | update diversity {|it|
-///         let l = $it.diversity | length
-///         $it.diversity | wrap y | merge (seq 0 $l | wrap x) | insert e 0
-///     }
-///     | rename --column { diversity: "points" }
-///     | insert style {|it|
-///         let color = match $it.strategy.n {
-///             10 => "tab:red",
-///             9 => "tab:orange",
-///             8 => "tab:olive",
-///             7 => "tab:blue",
-///             6 => "tab:purple",
-///             5 => "tab:green",
-///             4 => "tab:cyan",
-///             3 => "tab:brown",
-///             2 => "tab:pink",
-///             _ => "tab:gray",
-///         }
-///
-///         { color: $color, line: { alpha: ($it.strategy.p? | default 1.0) } }
-///     }
-///     | reject strategy
-///     | save --force /tmp/graphs.json
-/// ```
-/// ```
-/// let x_min = open /tmp/graphs.json | get points.0.x | math min
-/// let x_max = open /tmp/graphs.json | get points.0.x | math max
-///
-/// gplt plot ...[
-///     --json-data-file /tmp/graphs.json
-///     --x-lim ($x_min - 1) ($x_max + 1)
-///     --y-lim -0.01 1.01
-///     --fullscreen
-///     # --title "diversity over time when recoding shards $r$ shards"
-///     --x-label "time (in nb of steps)"
-///     --y-label "diversity $\\delta$"
-///     --dpi 150
-///     --fig-size ...[16, 5]
-///     --font ({ size: 15, family: serif, sans-serif: Helvetica } | to json)
-///     --use-tex
-///     --legend-loc "upper right"
-///     # --save inbreeding.pdf
-/// ]
+/// ./scripts/inbreeding/build.nu
+/// ./scripts/inbreeding/run.nu --output data/inbreeding.nuon
+/// ./scripts/inbreeding/plot.nu data/inbreeding.nuon --save ~/inbreeding.pdf
 /// ```
 use std::process::exit;
 
diff --git a/scripts/commit/plot.nu b/scripts/commit/plot.nu
new file mode 100644
index 00000000..daf5d490
--- /dev/null
+++ b/scripts/commit/plot.nu
@@ -0,0 +1,32 @@
+use ../math.nu *
+use ../fs.nu check-file
+use ../plot.nu gplt
+
+export def main [data: path, --save: path] {
+    let options = [
+        # --title "time to commit polynomials for certain curves"
+        --x-label "degree"
+        --y-label "time (in ms)"
+        --fullscreen
+        --dpi 150
+        --fig-size ...[16, 9]
+        --font ({ size: 30, family: serif, sans-serif: Helvetica } | to json)
+        --use-tex
+        (if $save != null { [ --save $save ] })
+    ]
+
+    check-file $data --span (metadata $data).span
+
+    open $data
+        | where name !~ '^SEC'
+        | ns-to-ms $.times
+        | compute-stats $.times
+        | insert degree { get label | parse "degree {d}" | into record | get d | into int }
+        | rename --column { degree: "x", mean: "y", stddev: "e" }
+        | select name x y e
+        | group-by name --to-table
+        | reject items.name
+        | rename --column { group: "name", items: "points" }
+        | sort-by name
+        | gplt plot ($in | to json) ...($options | flatten | compact)
+}
diff --git a/scripts/commit/run.nu b/scripts/commit/run.nu
new file mode 100644
index 00000000..9c0df230
--- /dev/null
+++ b/scripts/commit/run.nu
@@ -0,0 +1,5 @@
+export def main [--output: path = "./commit.ndjson", --nb-measurements: int = 10]: list<int> -> nothing {
+    cargo run --release --example bench_commit -- --nb-measurements $nb_measurements ...$in out> $output
+
+    print $"results saved to `($output)`"
+}
diff --git a/scripts/fec/plot.nu b/scripts/fec/plot.nu
new file mode 100644
index 00000000..95cec1e3
--- /dev/null
+++ b/scripts/fec/plot.nu
@@ -0,0 +1,264 @@
+use ../math.nu *
+use ../plot.nu [ into-axis-options, COMMON_OPTIONS ]
+use ../fs.nu check-file
+use ../plot.nu gplt
+
+export def encoding [data: path, --save: path] {
+    check-file $data --span (metadata $data).span
+
+    let graphs = open $data
+        | update label { from json }
+        | flatten label
+        | ns-to-ms times
+        | compute-stats times
+        | where name == "BLS12-381" and step == "encode"
+        | rename --column { bytes: "x", mean: "y", stddev: "e" }
+        | select k x y e
+        | sort-by x
+        | group-by k --to-table
+        | reject items.k
+        | rename --column { group: "name", items: "points" }
+        | update name { $"$k = ($in)$" }
+
+    let options = [
+        # --title "1-encoding"
+        ...($graphs.points | flatten | into-axis-options -y "duration")
+        ...$COMMON_OPTIONS
+        (if $save != null { [ --save $save ] })
+    ]
+
+    gplt plot ($graphs | to json) ...($options | flatten | compact)
+}
+
+export def decoding [data: path, --save: path] {
+    check-file $data --span (metadata $data).span
+
+    let graphs = open $data
+        | update label { from json }
+        | flatten label
+        | ns-to-ms times
+        | compute-stats times
+        | where name == "BLS12-381" and step == "decode"
+        | rename --column { bytes: "x", mean: "y", stddev: "e" }
+        | select k x y e
+        | sort-by x
+        | group-by k --to-table
+        | reject items.k
+        | rename --column { group: "name", items: "points" }
+        | update name { $"$k = ($in)$" }
+
+    let options = [
+        # --title "k-encoding"
+        ...($graphs.points | flatten | into-axis-options -y "duration")
+        --no-legend
+        ...$COMMON_OPTIONS
+        (if $save != null { [ --save $save ] })
+    ]
+
+    gplt plot ($graphs | to json) ...($options | flatten | compact)
+}
+
+export def e2e [data: path, --save: path] {
+    check-file $data --span (metadata $data).span
+
+    let graphs = open $data
+        | update label { from json }
+        | flatten label
+        | insert foo { $"($in.name) / ($in.k) / ($in.bytes)" }
+        | group-by foo --to-table
+        | update items {|it|
+            $it.items
+                | update step e2e
+                | update times { $it.items.0.times | zip $it.items.1.times | each { $in.0 + $in.1 } }
+        }
+        | flatten --all
+        | reject group foo
+        | ns-to-ms times
+        | compute-stats times
+        | reject times
+        | where name == "BLS12-381"
+        | rename --column { bytes: "x", mean: "y", stddev: "e" }
+        | select k x y e
+        | sort-by x
+        | group-by k --to-table
+        | reject items.k
+        | rename --column { group: "name", items: "points" }
+        | update name { $"$k = ($in)$" }
+
+    let options = [
+        # --title "k-encoding + 1-encoding"
+        ...($graphs.points | flatten | into-axis-options -y "duration")
+        --no-legend
+        ...$COMMON_OPTIONS
+        (if $save != null { [ --save $save ] })
+    ]
+
+    gplt plot ($graphs | to json) ...($options | flatten | compact)
+}
+
+export def combined [data: path, --recoding: path, --save: path] {
+    check-file $data --span (metadata $data).span
+    check-file $recoding --span (metadata $recoding).span
+
+    let true_recoding_graphs = open $recoding
+        | ns-to-ms $.times
+        | compute-stats $.times
+        | update label { from nuon }
+        | flatten --all label
+        | where name == "BLS12-381"
+        | rename --column { bytes: "x", mean: "y", stddev: "e" }
+        | select shards x y e
+        | sort-by x
+        | group-by shards --to-table
+        | insert style.color {|it|
+            match $it.items.shards.0 {
+                2 => "tab:blue"
+                4 => "tab:orange"
+                8 => "tab:green"
+                16 => "tab:red"
+                _ => "tab:grey"
+            }
+        }
+        | reject items.shards
+        | insert style.line.type "solid"
+        | rename --column { group: "name", items: "points" }
+        | update name { $"$k = ($in)$" }
+
+    let naive_recoding_graphs = open $data
+        | update label { from json }
+        | flatten label
+        | insert key { $"($in.name) / ($in.k) / ($in.bytes)" }
+        | group-by key --to-table
+        | update items {|it|
+            $it.items
+                | update step e2e
+                | update times { $it.items.0.times | zip $it.items.1.times | each { $in.0 + $in.1 } }
+        }
+        | flatten --all
+        | reject group key
+        | ns-to-ms times
+        | compute-stats times
+        | reject times
+        | where name == "BLS12-381"
+        | rename --column { bytes: "x", mean: "y", stddev: "e" }
+        | select k x y e
+        | sort-by x
+        | group-by k --to-table
+        | insert style.color {|it|
+            match $it.items.k.0 {
+                2 => "tab:blue"
+                4 => "tab:orange"
+                8 => "tab:green"
+                16 => "tab:red"
+                _ => "tab:grey"
+            }
+        }
+        | insert style.line.type "dashed"
+        | reject items.k
+        | rename --column { group: "name", items: "points" }
+        | reject name
+
+    let graphs = $true_recoding_graphs
+        | append $naive_recoding_graphs
+        | append {
+            name: "naive recoding ($k$-decoding + $1$-encoding)",
+            legend: "second",
+            points: [],
+            style: {
+                color: "grey",
+                line: {
+                    type: "dashed",
+                    marker: {
+                        size: 0,
+                    },
+                },
+            },
+        }
+        | append {
+            name: "true recoding ($k$-recoding)",
+            legend: "second",
+            points: [],
+            style: {
+                color: "grey",
+                line: {
+                    type: "solid",
+                    marker: {
+                        size: 0,
+                    },
+                },
+            },
+        }
+
+    let options = [
+        ...($graphs.points | flatten | into-axis-options -y "duration")
+        --legend-loc "upper left" "lower right"
+        ...$COMMON_OPTIONS
+        (if $save != null { [ --save $save ] })
+    ]
+
+    gplt plot ($graphs | to json) ...($options | flatten | compact)
+}
+
+export def ratio [data: path, --recoding: path, --save: path] {
+    check-file $data --span (metadata $data).span
+    check-file $recoding --span (metadata $recoding).span
+
+    let true_recoding_graphs = open $recoding
+        | ns-to-ms times
+        | compute-stats $.times
+        | update label { from nuon }
+        | flatten --all label
+        | where name == "BLS12-381"
+        | select shards bytes mean
+        | rename --column { shards: "k" }
+
+    let naive_recoding_graphs = open $data
+        | update label { from json }
+        | flatten label
+        | insert key { $"($in.name) / ($in.k) / ($in.bytes)" }
+        | group-by key --to-table
+        | update items {|it|
+            $it.items
+                | update step e2e
+                | update times { $it.items.0.times | zip $it.items.1.times | each { $in.0 + $in.1 } }
+        }
+        | flatten --all
+        | reject group key
+        | ns-to-ms times
+        | compute-stats times
+        | where name == "BLS12-381"
+        | select k bytes mean
+        | uniq
+
+    let graphs = $true_recoding_graphs
+        | rename --column { mean: "true" }
+        | insert key { $"($in.k) ($in.bytes)" }
+        | join ($naive_recoding_graphs | rename --column { mean: "naive" } | insert key { $"($in.k) ($in.bytes)" }) key
+        | select k bytes $.true naive
+        | sort-by k bytes
+        | insert cmp { $in.naive / $in.true }
+        | rename --column { bytes: "x", cmp: "y" }
+        | select k x y
+        | group-by k --to-table
+        | insert style.color {|it|
+            match $it.items.k.0 {
+                2 => "tab:blue"
+                4 => "tab:orange"
+                8 => "tab:green"
+                16 => "tab:red"
+                _ => "tab:grey"
+            }
+        }
+        | reject items.k
+        | rename --column { group: "name", items: "points" }
+        | update name { $"$k = ($in)$" }
+
+    let options = [
+        ...($graphs.points | flatten | into-axis-options)
+        --legend-loc "upper right"
+        ...$COMMON_OPTIONS
+        (if $save != null { [ --save $save ] })
+    ]
+
+    gplt plot ($graphs | to json) ...($options | flatten | compact)
+}
diff --git a/scripts/fec/run.nu b/scripts/fec/run.nu
new file mode 100644
index 00000000..8027b861
--- /dev/null
+++ b/scripts/fec/run.nu
@@ -0,0 +1,26 @@
+use ../formats.nu *
+
+export def main [
+    --output: path = "./fec.ndjson",
+    --nb-measurements: int = 10,
+    --ks: list<int>
+]: list<int> -> nothing {
+    let input = $in
+
+    if ($ks | is-empty) {
+        print "nothing to do"
+        return
+    }
+
+    "" out> $output
+
+    for k in $ks {
+        cargo run --release --example bench_fec -- ...[
+            --nb-measurements $nb_measurements
+            ...$input
+            --encoding vandermonde
+            -k $k
+            -n 1
+        ] | from ndnuon | to ndjson out>> $output
+    }
+}
diff --git a/scripts/fs.nu b/scripts/fs.nu
new file mode 100644
index 00000000..4f2d4018
--- /dev/null
+++ b/scripts/fs.nu
@@ -0,0 +1,11 @@
+export def check-file [file: path, --span: record<start: int, end: int>] {
+    if not ($file | path exists) {
+        error make {
+            msg: "invalid path",
+            label: {
+                text: "no such file",
+                span: $span,
+            }
+        }
+    }
+}
diff --git a/scripts/inbreeding/build.nu b/scripts/inbreeding/build.nu
new file mode 100755
index 00000000..4437a570
--- /dev/null
+++ b/scripts/inbreeding/build.nu
@@ -0,0 +1,3 @@
+#!/usr/bin/env nu
+
+cargo build --release --example inbreeding
diff --git a/scripts/inbreeding/options.nu b/scripts/inbreeding/options.nu
new file mode 100644
index 00000000..c38150cb
--- /dev/null
+++ b/scripts/inbreeding/options.nu
@@ -0,0 +1,19 @@
+export const NB_BYTES = 1_024 * 10
+
+export const K = 10
+export const N = 2 * $K
+
+export const NB_MEASUREMENTS = 1_000
+export const MEASUREMENT_SCHEDULE = 1
+
+export const MAX_T = 150
+
+export const EXTRA_STRATEGIES = [
+    "double:0.5:1:2",
+    "double:0.5:2:3",
+    "double:0.333:1:2",
+    "double:0.666:1:2",
+    "double:0.333:2:3",
+    "double:0.666:2:3"
+]
+export const ENVIRONMENT = "fixed:0"
diff --git a/scripts/inbreeding/plot.nu b/scripts/inbreeding/plot.nu
new file mode 100755
index 00000000..da26bef0
--- /dev/null
+++ b/scripts/inbreeding/plot.nu
@@ -0,0 +1,101 @@
+#!/usr/bin/env nu
+
+use std repeat
+
+use options.nu
+use ../plot.nu gplt
+
+def "parse strategy" []: string -> record<type: string> {
+    let s = $in
+
+    if ($s | str starts-with "single") {
+        let res = $s
+            | parse "single:{n}"
+            | into record
+            | into int n
+        { type: "single", n: $res.n }
+    } else {
+        let res = $s
+            | parse "double:{p}:{n}:{m}"
+            | into record
+            | into float p
+            | into int n
+            | into int m
+        { type: "double", p: $res.p, n: $res.n, m: $res.m }
+    }
+}
+
+def main [data: path, --save: path] {
+    let data = open $data
+    let l = $data.diversity.0 | length
+
+    $data
+        | update strategy { parse strategy }
+        | insert sort {|it|
+            match $it.strategy.type {
+                "single" => [$it.strategy.n, 1.0]
+                "double" => [$it.strategy.n, $it.strategy.p]
+            }
+        }
+        | sort-by sort
+        | reverse
+        | reject sort
+        | insert name {|it|
+            match $it.strategy.type {
+                "single" => {
+                    let sigma = if $it.strategy.n == $options.K {
+                        "k"
+                    } else {
+                        $"k - ($options.K - $it.strategy.n)"
+                    }
+                    $"$\\sigma = ($sigma) = ($it.strategy.n)$"
+                }
+                "double" => $"($it.strategy.p)? ($it.strategy.n) ; ($it.strategy.m)"
+            }
+        }
+        | update diversity {|it|
+            let l = $it.diversity | length
+            $it.diversity | wrap y | merge (seq 0 $l | wrap x) | insert e 0
+        }
+        | rename --column { diversity: "points" }
+        | insert style {|it|
+            let color = match $it.strategy.n {
+                10 => "tab:red",
+                9 => "tab:orange",
+                8 => "tab:olive",
+                7 => "tab:blue",
+                6 => "tab:purple",
+                5 => "tab:green",
+                4 => "tab:cyan",
+                3 => "tab:brown",
+                2 => "tab:pink",
+                _ => "tab:gray",
+            }
+
+            { color: $color, line: { alpha: ($it.strategy.p? | default 1.0) } }
+        }
+        | reject strategy
+        | save --force /tmp/graphs.json
+
+    let x_min = open /tmp/graphs.json | get points.0.x | math min
+    let x_max = open /tmp/graphs.json | get points.0.x | math max
+
+    let args = [
+        --json-data-file /tmp/graphs.json
+        --x-lim ($x_min - 1) ($x_max + 1)
+        --y-lim -0.01 1.01
+        --fullscreen
+        # --title "diversity over time when recoding shards $r$ shards"
+        --x-label "time (in nb of steps)"
+        --y-label "diversity $\\delta$"
+        --dpi 150
+        --fig-size ...[16, 5]
+        --font ({ size: 15, family: serif, sans-serif: Helvetica } | to json)
+        --use-tex
+        --legend-loc "upper right"
+        (if $save != null { [ --save $save ] })
+    ]
+
+    gplt plot ...($args | flatten | compact)
+
+}
diff --git a/scripts/inbreeding/run.nu b/scripts/inbreeding/run.nu
new file mode 100755
index 00000000..f9142e9c
--- /dev/null
+++ b/scripts/inbreeding/run.nu
@@ -0,0 +1,44 @@
+#!/usr/bin/env nu
+
+use options.nu
+
+const BIN = "./target/release/examples/inbreeding"
+
+def main [--output: path = "./inbreeding.nuon", --baseline] {
+    if $baseline {
+        ^$BIN ...[
+            $options.NB_BYTES,
+            -k $options.K
+            -n $options.N
+            --nb-measurements $options.NB_MEASUREMENTS
+            --measurement-schedule $options.MEASUREMENT_SCHEDULE
+            -t $options.MAX_T
+            --test-case end-to-end
+        ] | lines | into float | save --force baseline.nuon
+
+        print "baseline saved to `baseline.nuon`"
+    }
+
+    let strategies = seq 1 $options.K | each { $"single:($in)" } | append $options.EXTRA_STRATEGIES
+
+    $strategies | each {|s|
+        let diversity = ^$BIN ...[
+            $options.NB_BYTES,
+            -k $options.K
+            -n $options.N
+            --nb-measurements $options.NB_MEASUREMENTS
+            --measurement-schedule $options.MEASUREMENT_SCHEDULE
+            -t $options.MAX_T
+            --test-case recoding
+            --strategy $s
+            --environment $options.ENVIRONMENT
+        ] | lines | into float
+
+        {
+            strategy: $s,
+            diversity: $diversity,
+        }
+    } | save --force $output
+
+    print $"results saved to `($output)`"
+}
diff --git a/scripts/plot.nu b/scripts/plot.nu
index a95b757b..254476e1 100644
--- a/scripts/plot.nu
+++ b/scripts/plot.nu
@@ -1,3 +1,5 @@
+use venv.nu VENV
+
 export const COMMON_OPTIONS = [
     --x-scale log
     --x-scale-base 2
@@ -58,3 +60,8 @@ export def into-axis-options [-y: string]: table<x: float, y: float> -> list<str
         --y-tick-labels ...$y_tick_labels
     ]
 }
+
+export def --wrapped gplt [...args: string] {
+    overlay use $VENV
+    ^gplt ...$args
+}
diff --git a/scripts/recoding/plot.nu b/scripts/recoding/plot.nu
new file mode 100644
index 00000000..486657e1
--- /dev/null
+++ b/scripts/recoding/plot.nu
@@ -0,0 +1,31 @@
+use ../math.nu *
+use ../plot.nu [ into-axis-options, COMMON_OPTIONS ]
+use ../fs.nu check-file
+use ../plot.nu gplt
+
+export def main [data: path, --save: path] {
+    check-file $data --span (metadata $data).span
+
+    let graphs = open $data
+        | ns-to-ms $.times
+        | compute-stats $.times
+        | update label { from nuon }
+        | flatten --all label
+        | where name == "BLS12-381"
+        | rename --column { bytes: "x", mean: "y", stddev: "e" }
+        | select shards x y e
+        | group-by shards --to-table
+        | reject items.shards
+        | rename --column { group: "name", items: "points" }
+        | update name { $"$k = ($in)$"}
+
+    let options = [
+        # --y-label "time (in ms)"
+        ...($graphs.points | flatten | into-axis-options -y "duration")
+        --no-legend
+        ...$COMMON_OPTIONS
+        (if $save != null { [ --save $save ] })
+    ]
+
+    gplt plot ($graphs | to json) ...($options | flatten | compact)
+}
diff --git a/scripts/recoding/run.nu b/scripts/recoding/run.nu
new file mode 100644
index 00000000..c716546e
--- /dev/null
+++ b/scripts/recoding/run.nu
@@ -0,0 +1,25 @@
+use ../formats.nu *
+
+export def main [
+    --output: path = "./recoding.ndjson",
+    --nb-measurements: int = 10,
+    --ks: list<int>
+]: list<int> -> nothing {
+    let input = $in
+
+    if ($ks | is-empty) {
+        print "nothing to do"
+        return
+    }
+
+    "" out> $output
+
+    for k in $ks {
+        cargo run --release --example bench_recoding -- ...[
+            --nb-measurements $nb_measurements
+            ...$input
+            --shards $k
+            --ks $k
+        ] | from ndnuon | to ndjson out>> $output
+    }
+}
diff --git a/scripts/setup/plot.nu b/scripts/setup/plot.nu
new file mode 100644
index 00000000..001d6aac
--- /dev/null
+++ b/scripts/setup/plot.nu
@@ -0,0 +1,37 @@
+use ../math.nu *
+use ../fs.nu check-file
+use ../plot.nu gplt
+
+export def main [data: path, --save: path] {
+    let options = [
+        # --title "time to create trusted setups for certain curves"
+        --x-label "degree"
+        --y-label "time (in ms)"
+        --fullscreen
+        --dpi 150
+        --fig-size ...[16, 9]
+        --font ({ size: 30, family: serif, sans-serif: Helvetica } | to json)
+        --use-tex
+        (if $save != null { [ --save $save ] })
+    ]
+
+    check-file $data --span (metadata $data).span
+
+    open $data
+        | ns-to-ms times
+        | compute-stats times
+        | insert degree { get label | parse "degree {d}" | into record | get d | into int}
+        | update name {|it| if ($it.name | str starts-with  "ARK") {
+            let c = $it.name | parse "ARK setup on {curve}" | into record | get curve
+            $"($c)-ark"
+        } else {
+            $it.name | parse "setup on {curve}" | into record | get curve
+        }}
+        | rename --column { degree: "x", mean: "y", stddev: "e" }
+        | select name x y e
+        | group-by name --to-table
+        | reject items.name
+        | rename --column { group: "name", items: "points" }
+        | sort-by name
+        | gplt plot ($in | to json) ...($options | flatten | compact)
+}
diff --git a/scripts/setup/run.nu b/scripts/setup/run.nu
new file mode 100644
index 00000000..d5ad502b
--- /dev/null
+++ b/scripts/setup/run.nu
@@ -0,0 +1,5 @@
+export def main [--output: path = "./setup.ndjson", --nb-measurements: int = 10]: list<int> -> nothing {
+    cargo run --release --example bench_setup -- --nb-measurements $nb_measurements ...$in out> $output
+
+    print $"results saved to `($output)`"
+}
diff --git a/scripts/venv.nu b/scripts/venv.nu
new file mode 100644
index 00000000..38a6002b
--- /dev/null
+++ b/scripts/venv.nu
@@ -0,0 +1 @@
+export const VENV = ($nu.home-path | path join ".local/share/venvs/gplt/bin/activate.nu")
-- 
GitLab