zBit is an experimental bits-to-Karnaugh-map circuits compression algorithm.
Its central peculiarity is that it does not only look at a file as a linear sequence of bytes. It also tries to treat the file as a Boolean landscape: bits, positions, symbols, chunks, frame payloads, corrections, and transformed ranges can become cells in a Karnaugh-like map. When regions of that map can be grouped, simplified, linked, or represented as circuits with less metadata than the original bytes, zBit can store the circuit/structure instead of storing the data literally.
In a classic compressor, the main question is often: "which previous byte sequence or symbol distribution can describe this sequence cheaply?" In zBit, the deeper question is: "which Boolean/circuit structure explains these bits cheaply, and is the explanation smaller than the raw data plus corrections?"
This makes zBit closer to an adaptive structural compressor than to a single fixed codec. The current Rust implementation combines exact Boolean minimization, heuristic cover refinement, SAT-assisted local pruning, canonical circuit DAGs, adaptive byte packing, recursive transform topology, and chunked stream grouping. The packer is intentionally conservative: circuit modeling is used only when the model, dictionary, references, and residual corrections beat simpler representations.
The conceptual model is:
file bytes -> bit/position/context map -> Karnaugh-like groups -> simplified circuits -> encoded structure + residual corrections
A Karnaugh map groups adjacent equal Boolean outputs so they can be represented by fewer literals. zBit generalizes that idea beyond the small classroom grid:
- cells can be individual bits, byte-symbol rows, chunk ranges, transformed positions, framed payload bytes, correction bytes, or stream pieces;
- ON/OFF/DC sets describe what must evaluate to
1, what must remain0, and what may be ignored or corrected elsewhere; - cubes / implicants are generalized K-map groups over many dimensions;
- circuits are executable descriptions of these groups and relations;
- compression wins only when the structural explanation is smaller than the literal bytes.
The algorithm is therefore not simply "find repeated bytes". A useful pattern may be a Boolean relation, a reusable circuit slice, a transformed residual, a monotonic integer stream, a framed-data reconstruction plan, a global stream slice, or a conventional entropy/codec candidate if that is actually smaller.
| Classic compression tendency | zBit structural/circuit tendency |
|---|---|
| Search repeated substrings, dictionaries, or symbol probabilities. | Search Boolean regions, circuit covers, transform topology, reusable slices, and candidate pack structures. |
| Treat data mainly as a byte stream. | Treat data as bytes and as bit-level maps over positions, contexts, chunks, and reversible transforms. |
| A match is usually a previous sequence or statistical code. | A match can be a simplified circuit, a cube cover, a frame reconstruction rule, a correction plan, or a stream/global slice. |
| One dominant codec strategy is applied to the whole input or block. | Many reversible representations compete; the smallest validated candidate is selected. |
| Good entropy coding can hide local redundancy. | zBit tries to expose deeper logical structure before choosing how to encode it. |
This is why the project should be read as a bits-to-Karnaugh-map-to-circuits compressor: the Boolean/circuit view is the distinctive research direction, while the adaptive packer makes the approach usable on real files without forcing circuits where they are not economical.
At a high level, zBit works like a structural search engine for reversible explanations of data:
- Map the data into candidate spaces. The same input may be seen as raw bytes, indexed symbols, small truth tables, frame payloads, transformed ranges, stream chunks, or correction streams.
- Find compressible Boolean regions. For bounded truth-table problems, exact minimization builds implicants like K-map groups. For larger inputs, heuristic and SAT-assisted passes try cheaper local improvements.
- Build or reuse circuit-like descriptions. Canonical nodes, recursive transform nodes, group nodes, and global slices represent structure that can be serialized and later decoded deterministically.
- Estimate total cost, not elegance. A beautiful circuit is rejected if its metadata is larger than raw bytes or a conventional codec candidate.
- Validate roundtrip reconstruction. Every selected representation must decode back to the exact original bytes.
The long-term development direction is a stronger Circuit Atlas: a cacheable dictionary of reusable circuits/slices that can link distant and apparently unrelated parts of a file or stream when they share hidden Boolean structure. The current code already contains foundations for that direction through canonical models, adaptive candidates, recursive topology metadata, stream grouping, and global-slice references.
This repository currently contains:
zbit-rs/: the active Rust cratepapers/: theory and implementation-guidance documents
The implementation is intentionally aligned with the paper guidance that exact methods are valuable for bounded local problems, while practical compression needs representation-aware heuristics and strict validation.
Paper guidance: exact minimization is strongest on small support functions and should be bounded.
Implemented:
- Quine-McCluskey style prime implicant generation
- exact minimum cover selection with branch-and-bound search
- don't-care support in minimization
- hard exact limit:
ZBIT_MAX_INPUTS_EXACT = 16 - hierarchical Shannon-cofactor decomposition above the 16-input exact bound (ROADMAP IMMED-2): functions over more than 16 inputs split on a chosen variable, recurse on each cofactor, and combine via mux nodes; probe-based essential-input pruning detects variables the function does not actually depend on so e.g. a 32-input stride function with 4 active bits collapses to a small leaf instead of a deep Shannon tree
Code:
zbit-rs/src/minimizer.rszbit-rs/src/hierarchical.rszbit-rs/src/model.rs
Paper guidance: representation choice matters.
Implemented:
- canonical node interning (
Pin,Not,And,Or,Xor) - commutative normalization and simplification rules
- deterministic serialized model format (
.zbit) - advanced rewrite flow with:
- graph-style resubstitution (absorbed-term elimination)
- AIG-like consensus merges (local rewriting)
- balancing-aware objective estimation
Code:
zbit-rs/src/model.rszbit-rs/src/advanced.rs
Paper guidance: large search spaces need iterative heuristic improvements in addition to exact bounded methods.
Implemented:
- iterative expand/select loop inspired by Espresso-style cover refinement
- legal expansion under ON+DC constraints
- greedy objective-aware cube selection and irredundancy cleanup
Code:
zbit-rs/src/advanced.rs
Paper guidance: SAT is useful as a bounded local oracle inside larger heuristic flows.
Implemented:
- lightweight CNF SAT solver (DPLL with unit propagation)
- SAT-driven local redundancy pruning for cubes in a candidate cover
- bounded SAT window control (
sat_local_exact_inputs)
Code:
zbit-rs/src/sat.rszbit-rs/src/advanced.rs
Paper guidance: objective function must match target technology, not just literal count.
Implemented:
- objective-aware scoring for:
- literal minimization
- ASIC area proxy
- ASIC delay proxy
- FPGA LUT4/LUT6 proxies
- advanced model entrypoints with explicit objective selection
Code:
zbit-rs/src/advanced.rszbit-rs/src/model.rs
Paper guidance: choose method by objective/cost, avoid one fixed algorithm worldview.
Implemented:
- adaptive selection among:
raw-copyindexed-rawindexed-circuitindexed-huffmanraw-deflateraw-zstdraw-xz/raw-brotli/framed-raw/recursive-circuit-xz/monotonic-delta/adaptive-transformed-xz
- rule-based gating for circuit-dictionary evaluation
- size-based final method choice, never worse than raw baseline by design
- strict
.zbpkparser validation - bit-stream interning primitive (ROADMAP IMMED-1):
CircuitBitStreamwrites the first occurrence of any circuit-level definition (transform plan, topology node, etc.) inline and re-references it atceil(log2(N))bits cost; in-tree primitive plus acceptance tests for cross-region sharing (ROADMAP IMMED-3) of distant byte ranges with identical structure - profile-bounded parallelism (ROADMAP IMMED-5):
rayon::ThreadPoolBuilder::installwraps the encoder entry points, sized byCompressionBudgets::max_parallel_codec_threads(2 forfast; unbounded forbalanced/deep/research)
Code:
zbit-rs/src/pack/zbit-rs/src/pack/bitstream.rszbit-rs/src/pack_rules.rs
Implemented:
.zbpschunk-stream container with key-piece intervals for restartable decode- per-chunk/per-group adaptive selection with configurable multi-level grouping depth
- deterministic block boundaries so receivers can start decode from key pieces without replaying full history
- optional grouping-history hints in block headers for sharing generalized grouping strategy over time
- optional shared-grouping payload layer in non-wide realtime mode, so blocks can reference global generalized circuits/slices when local piece compression is weaker
Code:
zbit-rs/src/pack/zbit-rs/src/bin/benchmark_stream_real_file.rs
Paper guidance: implementation quality requires verification + measurement loops.
Implemented:
- unit + integration tests for:
- exact minimization
- Espresso-style heuristic optimization
- SAT local pruning
- objective-aware advanced compression
- model and pack roundtrip validation
- benchmark binary with method rationale, candidate sizes, timings, throughput, ratio, and output validation
Code:
zbit-rs/tests/zbit-rs/src/bin/benchmark_real_file.rs
README.md: this fileLICENSE: PolyForm Noncommercial License 1.0.0papers/zbit-algorithmsResearch.md: theory and architecture recommendationszbit-rs/: Rust crate
Inside zbit-rs/:
src/lib.rs: public APIsrc/model.rs: exact Boolean model +.zbitserializationsrc/minimizer.rs: exact minimization enginesrc/hierarchical.rs: Shannon-cofactor decomposition above the 16-input exact boundsrc/advanced.rs: heuristic/rewrite/SAT/objective optimization flowsrc/sat.rs: internal SAT solver used by local exactness pruningsrc/pack/: adaptive.zbpk+ streaming.zbpscompression/decompressionsrc/pack/bitstream.rs:CircuitBitStreambit-level interning primitive (ROADMAP IMMED-1)src/pack_rules.rs: method-selection rulessrc/bin/benchmark_real_file.rs: real-file benchmark binarysrc/bin/benchmark_stream_real_file.rs: real-file stream benchmark binarytests/: integration tests
From repository root:
cargo test --manifest-path zbit-rs/Cargo.tomlRun the model validation demo:
cargo run --manifest-path zbit-rs/Cargo.toml --bin zbit-rsRun the real-file benchmark (defaults already target papers/zbit-algorithmsResearch.md):
cargo run --manifest-path zbit-rs/Cargo.toml --bin zbit-benchmark -- \
papers/zbit-algorithmsResearch.md \
zbit-rs/benchmark_algorithmsResearch.zbpk \
zbit-rs/benchmark_latest.txtRun the cat challenge benchmark with auto-download (if missing in assets/):
bash zbit-rs/scripts/benchmark_cat_challenge.shRun the streaming benchmark (chunked/key-piece mode):
cargo run --manifest-path zbit-rs/Cargo.toml --bin zbit-benchmark-stream -- \
assets/cat_challenge.png \
zbit-rs/benchmark_cat_challenge_stream.zbps \
zbit-rs/benchmark_cat_challenge_stream_latest.txt \
262144 8 2 8Optional trailing flags: realtime_mode, wide_overfitting_circuits, carry_grouping_history
as boolean values (true/false or 1/0).
Compression profile control is available for both real-file and stream paths via
ZBIT_COMPRESSION_PROFILE (fast, balanced, deep, research), defaulting to balanced.
Run the cat challenge streaming benchmark script (auto-download if missing):
bash zbit-rs/scripts/benchmark_cat_challenge_stream.shRun the cat challenge multilevel streaming benchmark matrix (multiple profiles):
bash zbit-rs/scripts/benchmark_cat_challenge_stream_multilevel.shCurrent snapshot (short reports refreshed on 2026-05-26; long cat/depth reports kept from 2026-05-23):
| Test | Input | Selected method/profile | Original -> Compressed (bytes) | Ratio | Savings | Compression ms | Decompression ms | Validation |
|---|---|---|---|---|---|---|---|---|
| Paper benchmark | papers/zbit-algorithmsResearch.md |
raw-brotli |
62015 -> 18573 |
0.299492 |
70.05% |
820.075 |
8.575 |
PASS |
| Primary binary benchmark | assets/primary.3b.bin |
monotonic-delta |
3233613 -> 562799 |
0.174046 |
82.60% |
9803.097 |
133.500 |
PASS |
| Cat challenge benchmark | assets/cat_challenge.png |
recursive-circuit-xz |
2969404 -> 2670571 |
0.899363 |
10.07% |
58945.348 |
481.421 |
PASS |
| Cat challenge stream benchmark | assets/cat_challenge.png |
wide-overfit stream |
2969404 -> 2670846 |
0.899455 |
10.05% |
112964.407 |
8186.741 |
PASS |
| Depth Anything model benchmark | assets/depth_anything_v2_vits.pth |
adaptive-transformed-xz |
99218434 -> 83380762 |
0.840376 |
15.96% |
628278.163 |
236.317 |
PASS |
raw-brotli is now available for bounded text-like inputs and moves the paper benchmark from 20561 bytes (raw-xz, ratio 0.331549) to 18573 bytes (ratio 0.299492). The candidate is gated by a cheap text-likeness check so binary corpora such as primary.3b, cat, and depth_anything do not pay the q11 Brotli search cost. Outer recompression of .zbpk artifacts was also probed: it lost on paper/primary and saved only 58 bytes on the 83 MB depth artifact with zstd, so it is documented but not promoted into the live format yet.
Compression times remain substantially lower than the 2026-05-07 snapshot on the structural paths: primary 16 635 ms -> 9 803 ms, cat 112 500 ms -> 60 747 ms, and depth_anything 5 429 743 ms -> 628 278 ms. Cat ratio improved slightly (0.899412 -> 0.899361, 151 bytes saved cumulatively across the v3 dictionary compaction). The structural-speed improvements come from (a) a cheap XZ-3 ranking pass before the expensive choose_best_codec evaluation, (b) a leaner per-plan winner-refinement tuning matrix, (c) a bounded framed-payload analyzer, (d) a tuned-XZ cache, and (e) a runtime gate that skips the full raw-xz tuning matrix when a cheap XZ-3 estimate plus adaptive-transformed-xz prove raw-xz cannot win.
Several new tail-only reversible transforms have been added without changing tracked ratios: periodic-head-tail-tail-row-delta / row-xor / row-up (PNG-style Sub / XOR / Up predictors applied only to the row-data tail), periodic-head-tail-tail-bit-plane-transpose (with and without follow-up unary delta), plus deep-search XZ tunings (depth=2000/4000) gated to the deep / research profiles. They lose the XZ-3 ranking on the already-filtered cat PNG IDAT plain (where the simple periodic-head-tail still wins by ~23 KB on XZ-9) but stay available for unfiltered raster payloads where they should win cleanly.
The N3 multi-block recursive-circuit path is also landed (deep/research only): the inflated plain is optionally split into 2, 4, or 8 consecutive blocks, each block picks its own best transform plan, and the concatenated transformed bytes go through a single codec pass. The on-disk format extension uses a backward-compatible top-bit flag on the topology count so legacy single-plan dictionaries decode unchanged. For cat (uniformly-structured PNG IDAT) the multi-block path's best candidate is ~106 KB larger than the single-plan one — the rearrangement breaks XZ cross-block matches — so single-plan still wins and is selected. Multi-block is ready to win cleanly on heterogeneous inputs where per-region best plans differ substantially.
A new top-level pack method adaptive-transformed-xz brings the same reversible-transform search to inputs that are not framed deflate (e.g. PyTorch .pth model files, raw float-tensor dumps). It runs choose_adaptive_transform_plan on the raw input, encodes the best transformed payload with the full codec/tuned-XZ selection, and stores a small 18-byte dictionary (transform_kind, period, head, codec, plain_len) so the decoder can invert the transform deterministically. Two cost gates keep it bounded: skip when recursive-circuit-xz already covers the same search; skip when raw-xz already compresses to ≤ 0.30 of the input (already-strong corpora like primary.3b.bin). A 128 KiB size threshold keeps small text files out of the plan search. On the new depth_anything_v2_vits.pth corpus it wins by ~7 MB (~7.8 %) vs raw-xz alone: raw-xz 90 414 940 → 83 380 790 adaptive-transformed-xz, final ratio 0.840376 on 99 218 434 input bytes.
The on-disk format is now ZBPK v4. v3 rebuilt every dictionary section under the same rule the topology bit-packing introduced: spend only the bits each enumeration value or magnitude actually needs, never a whole byte for a single bit of state. v4 keeps that layout and uses another reserved 4-bit method slot for raw-brotli, a no-dictionary payload method for text-heavy inputs:
- ZBPK header.
method(≤ 16 values) andbits_per_symbol(0..=15) are packed into one byte (4 bits each).unique_count,original_size,dict_size, andpayload_sizeare varints instead of fixedu16/u64. The header on a 62 KB text file shrinks from 36 B to 17 B. - Framed-payload dictionary. The six u32 size fields (prefix_len, suffix_len, base_chunk_len, full_chunk_count, tail_chunk_len, total_chunks) are varints; the fixed section drops from 28 B to ~12 B.
- Recursive-circuit fixed section. The four u64 sizes are varints. A single
u16carries(transformed_codec:2 | correction_codec:2 | transform_kind_index:6 | reserved:6)instead of three separateu8s.periodandheadare varints. Together this drops the fixed section from 51 B to ~25 B. - Multi-block plan trailer.
block_count,block_size, and each plan'speriod/headare varints; the plan's kind index is one byte (6 bits used). Per-plan slot goes from 9 B to 3-5 B. - Adaptive-transformed-xz dictionary. One packed byte
(codec:2 | kind_index:6)plus varintperiod/head/plain_len. Drops from 18 B to ~9 B. - Monotonic-delta dictionary. One packed byte
(width-1:3 | mode:3 | codec:2), thentrailing_zero_shift(6 bits used out of its byte), then varintcount/first_value/transformed_plain_len. Drops from 28 B to ~12 B. - Raw-brotli payload. No dictionary; the payload is a Brotli q11 stream. It is evaluated only for bounded text-like inputs and selected only when it beats the other total packed sizes.
All five share the same dense kind_to_compact_index table the topology bit-packing introduced, so the 49 distinct CircuitTransformKind-derived values fit in exactly 6 bits everywhere they appear. Measured wins on the existing corpus (all PASS):
| Corpus | Before v3 | After v3 | Δ bytes |
|---|---|---|---|
| paper | 20 580 | 20 561 | −19 B |
| primary.3b | 562 836 | 562 799 | −37 B |
| cat | 2 670 624 | 2 670 571 | −53 B (cumulative −147 B vs the original v2) |
The absolute byte counts are small because the payload dominates, but the format no longer carries any bits the enumerations themselves don't need — every bit on the wire is principled.
Circuit-topology nodes used to be serialised in a fixed 28-byte-per-node layout: id u32 + parent_id u32 + relation u8 + order u16 + kind u8 + param_a u32 + param_b u32 + a per-node 8-byte FNV-style hash. With only 2 valid relation values, an order that builders never push above 3, and ~49 distinct kind values in use, that layout left several bits per field unused for every node written. The new bit-packed form, signalled by the 0x4000 RECURSIVE_TOPOLOGY_COMPACT_FLAG bit on the on-disk topology-count u16, writes the entire topology as a single MSB-first bit stream where every field consumes only the bits it actually needs:
- relation — 1 bit
- order — 2 bits (0..3 covers every builder)
- kind_index — 6 bits (49 in-use kinds mapped to a dense 0..48 range; 0..26 = normal topology kinds, 27..49 = embedded correction-plan kinds)
- is_root — 1 bit
- parent_index —
ceil(log2(prev_node_count))bits when not root: 0 bits for the very first child (only one possible parent), 1 bit for nodes #2..#3, 2 bits for nodes #4..#5, … - param_a / param_b — nibble varints (3 value bits + 1 continuation bit per nibble; small values cost 4 bits each, PNG-stride 6401 costs 20 bits)
- id — implicit (=
position + 1), 0 bits on the wire - hash64 — removed; overall decode correctness already validates the topology end-to-end through the inverse-transform pipeline
A trivial root node spends 18 bits (was 224 bits of fixed slot); a child node carrying a PNG-stride 6401 period spends 34 bits (was 224). The whole 5-node topology for the cat-challenge PNG goes from 140 bytes to 18 bytes — roughly an 8× compaction on the topology itself. The compact flag is independent of the existing 0x8000 MULTI_BLOCK_FLAG so both extensions compose. Legacy single-plan dictionaries (neither flag set) continue to decode with the fixed-width path and full per-node hash verification, so older .zbpk files keep working unchanged. Cat ratio measured win: 0.899412 -> 0.899380 (94 bytes saved across the 5-node topology). The number is small in absolute terms because the topology was tiny vs the payload, but it is principled: the wire no longer carries any bits for combinations the enumerations never use.
| Profile | Ratio | Savings | Original -> Compressed (bytes) | Compression ms | Decompression ms | Compression MiB/s | Decompression MiB/s | Validation | Resume |
|---|---|---|---|---|---|---|---|---|---|
realtime-fast |
0.999011 |
0.10% |
2969404 -> 2966468 |
1021.660 |
6.007 |
2.772 |
471.450 |
PASS |
PASS |
realtime-balanced |
0.998602 |
0.14% |
2969404 -> 2965252 |
3501.634 |
6.831 |
0.809 |
414.583 |
PASS |
PASS |
realtime-deep |
0.899455 |
10.05% |
2969404 -> 2670846 |
193723.466 |
8251.937 |
0.015 |
0.343 |
PASS |
PASS |
wide-overfit |
0.899455 |
10.05% |
2969404 -> 2670846 |
302112.453 |
10152.587 |
0.009 |
0.279 |
PASS |
PASS |
Latest outputs for the tracked tests are written to:
zbit-rs/benchmark_latest.txt: paper benchmark (papers/zbit-algorithmsResearch.md)zbit-rs/benchmark_primary.3b_latest.txt: primary binary benchmark (assets/primary.3b.bin)zbit-rs/benchmark_cat_challenge_latest.txt: cat challenge benchmark (assets/cat_challenge.png)zbit-rs/benchmark_cat_challenge_stream_latest.txt: cat challenge stream benchmark (assets/cat_challenge.png, 256 KiB chunks)zbit-rs/benchmark_cat_challenge_stream_multilevel_latest.txt: cat challenge multilevel stream profile matrixzbit-rs/benchmark_depth_anything_latest.txt: PyTorch model benchmark (assets/depth_anything_v2_vits.pth)
use zbit_rs::{
ZbitModel, StreamPackOptions, compress_adaptive_stream_to_file, compress_adaptive_to_file,
decompress_file, decompress_stream_file,
};
// 2-input XOR truth table
let outputs = [0u8, 1, 1, 0];
let mut model = ZbitModel::new(2)?;
model.compress_from_table(&outputs, None)?;
model.validate_against_table(&outputs)?;
// Advanced flow with technology-aware objective
let report = model.compress_from_table_with_objective(
&outputs,
None,
zbit_rs::MappingObjective::FpgaLut6,
)?;
assert!(report.selected.estimated_luts > 0);
// Pack/unpack bytes
let input = b"abcabcabc";
let _stats = compress_adaptive_to_file(input, "example.zbpk")?;
let output = decompress_file("example.zbpk")?;
assert_eq!(output, input);
let stream_options = StreamPackOptions::default();
let _stream_stats = compress_adaptive_stream_to_file(input, "example.zbps", &stream_options)?;
let stream_output = decompress_stream_file("example.zbps")?;
assert_eq!(stream_output, input);
# Ok::<(), zbit_rs::ZbitError>(())- magic:
ZBIT(0x5A42_4954) - version:
1 - stores canonical node DAG and root id
- magic:
ZBPK(0x5A42_504B) - version:
4 - variable header + dictionary + payload
- adaptive methods include
raw-copy,indexed-raw,indexed-circuit,indexed-huffman,raw-deflate,raw-zstd,raw-xz,raw-brotli,framed-raw,recursive-circuit-xz,monotonic-delta, andadaptive-transformed-xz - method selection is cost-based: circuit/structural candidates are accepted only when they beat safer raw or codec-backed candidates
- magic:
ZBPS(0x5A42_5053) - version:
1 - fixed stream header + independent key-piece blocks
- each block stores a multi-level piece/group topology and embedded
.zbpkpayloads - key-piece interval enables restartable decode from block boundaries
- Main theory and recommendations:
papers/zbit-algorithmsResearch.md - Crate internals and API:
zbit-rs/src/
PolyForm Noncommercial License 1.0.0. See LICENSE.