//! Plan a wrap level's opening without proving: for each parameter set,
//! lens's WHIR schedule, the opening's expected bytes (multi-opening
//! siblings by simulation over random query positions), the native
//! verifier's leaf-and-path permutations, the weakest ledger row with
//! grinding priced (ROM) and without (interactive), the grinding work and
//! the prover's round-0 codeword size.
//!
//! `wrap_plan <n> <rates> <pows> <folds> [final_vars] [arity]`: `n` the
//! level's `log2` rows (`โ„“ = n + 6`), the rest comma lists, e.g.
//! `wrap_plan 14 8,9,10 18,20,22,30 4,5 8 2`. `ZHENG_INPUTS=2` plans an
//! inner level's two-word batch (round-0 leaves of both words).

use zheng::recursion::wrap::{self, Mode, WrapParams};

fn list(s: &str) -> Vec<u32> {
    s.split(',').map(|x| x.parse().expect("number")).collect()
}

/// Expected siblings of a multi-opening of `q` uniform leaves in a tree of
/// `depth` levels and fan-in `a` (2 or 4; `a โˆ’ 1` siblings per level).
fn siblings(q: usize, depth: u32, a: usize) -> f64 {
    let trials = 400;
    let mut seed = 0x9e37_79b9_7f4a_7c15u64;
    let mut rnd = || {
        seed ^= seed << 13;
        seed ^= seed >> 7;
        seed ^= seed << 17;
        seed
    };
    let lv = if a == 4 { depth / 2 } else { depth };
    let mut total = 0usize;
    for _ in 0..trials {
        let mut cur: Vec<u64> = (0..q).map(|_| rnd() & ((1u64 << depth) - 1)).collect();
        cur.sort_unstable();
        cur.dedup();
        for _ in 0..lv {
            let mut parents: Vec<u64> = cur.iter().map(|&x| x / a as u64).collect();
            parents.dedup();
            // every parent needs its a children; the known ones are `cur`
            total += parents.len() * a - cur.len();
            cur = parents;
        }
        if a == 4 && depth % 2 == 1 {
            let mut parents: Vec<u64> = cur.iter().map(|&x| x / 2).collect();
            parents.dedup();
            total += parents.len() * 2 - cur.len();
        }
    }
    total as f64 / trials as f64
}

fn distinct(q: usize, depth: u32) -> f64 {
    let n = (1u64 << depth) as f64;
    n * (1.0 - (1.0 - 1.0 / n).powi(q as i32))
}

fn main() {
    let a: Vec<String> = std::env::args().skip(1).collect();
    let n: usize = a.first().map_or(14, |x| x.parse().expect("n"));
    let rates = list(a.get(1).map_or("8", |s| s));
    let pows = list(a.get(2).map_or("30", |s| s));
    let folds = list(a.get(3).map_or("4", |s| s));
    let fin: u8 = a.get(4).map_or(8, |x| x.parse().expect("final vars"));
    let arity: usize = a.get(5).map_or(2, |x| x.parse().expect("arity"));
    let inputs: usize = std::env::var("ZHENG_INPUTS")
        .ok()
        .and_then(|v| v.parse().ok())
        .unwrap_or(1);
    let ell = n + wrap::CBITS;
    println!("n {n} ยท โ„“ {ell} ยท final vars โ‰ค {fin} ยท arity {arity} ยท inputs {inputs}");
    println!(
        "rate pow k | queries per round | opening B | leaf+path perms | ROM min | interactive min | grind 2^x total | round-0 code (2^)"
    );
    for &r in &rates {
        for &k in &folds {
            for &p in &pows {
                let mut whir = zheng::execution::succinct::params_for(20);
                whir.log_inv_rate = r as u8;
                whir.pow_bits = p as u8;
                whir.folding_factor = k as u8;
                whir.max_final_vars = fin;
                let mode = if inputs == 1 {
                    Mode::Final
                } else {
                    Mode::Inner
                };
                let params = WrapParams { whir, n, mode };
                let groups: Vec<usize> = vec![1; inputs];
                let cfg =
                    match zheng::recursion::whir::Config::derive(&whir, ell, &groups, inputs + 3) {
                        Ok(c) => c,
                        Err(e) => {
                            let wc = lens::rspcs::whir::WhirConfig::derive(&whir, ell)
                                .expect("schedule");
                            let weak: Vec<String> = wc
                                .terms()
                                .into_iter()
                                .filter(|t| t.1 < 128.0)
                                .map(|(a, b)| format!("{a} {b:.1}"))
                                .collect();
                            println!("1/{} {p} {k} | {e} ({})", 1u64 << r, weak.join(", "));
                            continue;
                        }
                    };
                let wc = &cfg.wc;
                let mut bytes = 0.0;
                let mut perms = 0.0;
                let mut grind = 0.0f64;
                let mut inter = f64::INFINITY;
                let rows = wrap::ledger(&params, &cfg, 250, 1 << 18);
                let rom = rows.iter().map(|x| x.1).fold(f64::INFINITY, f64::min);
                for (name, b) in &rows {
                    // the grinding each term carries
                    let g = if let Some(i) = name.strip_prefix("shift_") {
                        wc.rounds[i.parse::<usize>().unwrap() - 1].query_pow
                    } else if let Some(i) = name.strip_prefix("fold_") {
                        wc.rounds[i.parse::<usize>().unwrap()].fold_pow
                    } else if name == "fin" {
                        wc.rounds.last().unwrap().query_pow
                    } else {
                        0
                    };
                    inter = inter.min(b - g as f64);
                }
                let mut qs = Vec::new();
                for (i, s) in wc.rounds.iter().enumerate() {
                    let fold_n = if s.fold_pow > 0 { s.fold } else { 0 };
                    bytes += (s.ood * 24 + 2 * s.fold * 24 + 8 * fold_n) as f64;
                    for _ in 0..fold_n {
                        grind += 2f64.powi(s.fold_pow as i32);
                    }
                    if s.query_pow > 0 {
                        grind += 2f64.powi(s.query_pow as i32);
                        bytes += 8.0;
                    }
                    if i > 0 {
                        bytes += 32.0;
                    }
                    let depth = s.log_leaves();
                    let q = s.queries;
                    qs.push(q);
                    let words = if i == 0 { inputs } else { 1 };
                    let sym = if i == 0 { 8.0 } else { 24.0 };
                    let lanes = if i == 0 {
                        1usize << s.fold
                    } else {
                        3usize << s.fold
                    };
                    let leaf_perms = (lanes as f64 / 9.0).ceil();
                    bytes += 4.0 * q as f64;
                    bytes += words as f64
                        * (distinct(q, depth) * sym * (1u64 << s.fold) as f64
                            + 4.0
                            + 32.0 * siblings(q, depth, arity));
                    let path = if arity == 4 {
                        (depth / 2 + depth % 2) as f64
                    } else {
                        depth as f64
                    };
                    perms += words as f64 * q as f64 * (leaf_perms + path);
                }
                bytes += 24.0 * (1u64 << wc.final_vars) as f64;
                let s0 = wc.rounds[0];
                println!(
                    "1/{} {p} {k} | {:?} | {:.0} | {:.0} | {rom:.2} | {inter:.2} | {:.1} | {}",
                    1u64 << r,
                    qs,
                    bytes,
                    perms,
                    grind.log2(),
                    s0.log_domain
                );
            }
        }
    }
}

Homonyms

cyber/src/main.rs
cyb/cli/src/main.rs
soft3/nox/cli/main.rs
neural/trident/src/main.rs
cyb/optica/src/main.rs
soft3/glia/import/main.rs
cyberia/cyberia-my/src/main.rs
cyb/apps/src/main.rs
soft3/tru/cli/main.rs
neural/rune/cli/main.rs
warriors/trisha/cli/main.rs
warriors/joy/cli/main.rs
cyb/shell/src/main.rs
soft3/conformance/rs/src/main.rs
neural/eidos/cli/src/main.rs
soft3/radio/iroh-dns-server/src/main.rs
soft3/radio/iroh-relay/src/main.rs
soft3/radio/particle/src/main.rs
soft3/strata/cli/src/main.rs
soft3/zheng/cli/src/main.rs
neural/rs/pure-rust-check/src/main.rs
soft3/hemera/cli/src/main.rs
soft3/neuron/cli/src/main.rs
soft3/glia/run/cli/main.rs
neural/rs/link/src/main.rs
soft3/radio/radio-cli/src/main.rs
soft3/foculus/src/bin/main.rs
neural/rs/macho-linker/src/main.rs
soft3/bbg/cli/src/main.rs
neural/rs/rsc/src/main.rs
neural/rs/cli/src/main.rs
soft3/lens/cli/src/main.rs
soft3/cybergraph/cli/src/main.rs
warriors/erga/cli/src/main.rs
soft3/zheng/rs/examples/ivc_bench/main.rs
cyb/honeycrisp/acpu/src/probe/main.rs
soft3/strata/jali/cli/src/main.rs
soft3/zheng/rs/examples/wrap_keys/main.rs
soft3/mudra/audit/quantus-mldsa-crosscheck/src/main.rs
soft3/zheng/rs/examples/envelope_profiles/main.rs
soft3/zheng/specs/proto/zheng_spartan/main.rs
soft3/zheng/rs/examples/wrap_chain/main.rs
warriors/erga/rs/rtable-bench/src/main.rs
soft3/strata/kuro/cli/src/main.rs
soft3/strata/trop/cli/src/main.rs
soft3/zheng/rs/examples/wrap_flip/main.rs
soft3/zheng/rs/examples/wrap_bench/main.rs
warriors/trisha/tools/neptune-policy-oracle/src/main.rs
soft3/zheng/specs/proto/zheng_bug/main.rs
soft3/zheng/specs/proto/zheng_inner/main.rs
soft3/zheng/rs/examples/fast_path/main.rs
soft3/zheng/specs/proto/zheng_spartan_fixed/main.rs
warriors/erga/rs/mine-bench/src/main.rs
soft3/zheng/rs/examples/wrapped_sizes/main.rs
soft3/zheng/rs/examples/wrap_verify/main.rs
soft3/zheng/rs/examples/ivc_plan/main.rs
soft3/zheng/rs/examples/ivc_flip/main.rs
soft3/zheng/rs/examples/machine_bench/main.rs
soft3/zheng/rs/examples/succinct_bakeoff/main.rs
soft3/zheng/specs/proto/zheng_outer/main.rs
neural/inf/rs/cli/src/main.rs
cyb/wysm/crates/cli/src/main.rs
warriors/erga/rs/blake-bench/src/main.rs
soft3/strata/nebu/cli/src/main.rs
soft3/lytics/rs/agent/src/main.rs
cyb/honeycrisp/rane/src/probe/main.rs
neural/trident/silicon/src/bin/main.rs
soft3/strata/genies/cli/src/main.rs
soft3/lytics/rs/ingest/src/main.rs
soft3/radio/audit/2026-10-12-bao-bounded-proof/nostd/src/main.rs
soft3/radio/audit/2026-10-12-bao-proof-research/probe/src/main.rs
soft3/mudra/audit/signature-optimality/xnt-predicate-check/src/main.rs
cyb/honeycrisp/unimem/experiments/hyp_probe/src/main.rs
soft3/radio/audit/2026-10-12-bao-bounded-proof/fixture-probe/src/main.rs
soft3/radio/audit/2026-10-12-bao-bounded-proof/nostd-parent/src/main.rs
soft3/radio/audit/2026-10-12-bao-proof-research/primary-probe/src/main.rs
cyb/honeycrisp/unimem/experiments/iosurface_probe/src/main.rs
cyb/honeycrisp/unimem/experiments/dext_contiguous_alloc/client/src/main.rs
cyb/honeycrisp/unimem/experiments/dext_iosurface_pa/client/src/main.rs

Graph