code wiki / (root) / sketch_lossy_counting.nx

sketch_lossy_counting.nx

buildroot/runtime/sketch_lossy_counting.nx

7789 B231 linesdepth 4pulls 4 transitivereach 1 importersview sourcekind sketch/demotopic sketch
docsdependenciesstructsconstsfunctions

about

sketch_lossy_counting.nx -- Manku-Motwani 2002 Lossy Counting. THIRD major frequency-counting algorithm joining CMS / SpaceSaving / Misra-Gries / CountSketch. Distinct technique: BUCKET-PRUNING. ALGORITHM: Stream divided into "buckets" of size w = ceil(1/epsilon). For each item: - if tracked: increment frequency - else: insert with frequency=1, error=current_bucket-1 At each bucket boundary (every w items): - decrement EVERY tracked item's frequency by 1 - REMOVE items with frequency = 0 GUARANTEE: stored_freq <= true_freq (underestimate) stored_freq + error >= true_freq (upper bound) Items with true_freq > epsilon * N are NEVER missed No item has stored_freq > true_freq (NEVER overestimates) COMPARISON to other frequency algorithms: - CMS: random projection, overestimate-only, O(1) query - SpaceSaving: k-bounded counters, overestimate-only, top-K native - Misra-Gries: k-bounded counters, underestimate-only - CountSketch: median-based, UNBIASED, supports negative - Lossy Counting (THIS): bucket-pruning, underestimate + explicit error tracking per entry MEMORY: O((1/epsilon) log(epsilon * N)) -- bounded but data-dependent. We use a hash-set with linear probing; cap at NX_LC_MAX_ENTRIES.

dependencies 2 imports · 1 importers

syscalls.nx sketch_types.nx sketch_lossy_counting.nx sketch_lossy_counting_test.nx

imports: syscalls.nxsketch_types.nx

imported by: sketch_lossy_counting_test.nx

structs

39struct LcEntry {
45struct LossyCounting {

consts

35const NX_LC_MIN_EPS_PPM: i64 = 100 // epsilon >= 0.0001
36const NX_LC_MAX_EPS_PPM: i64 = 500000 // epsilon <= 0.5
37const NX_LC_MAX_ENTRIES: i64 = 100000
56const NX_LC_EMPTY_KEY: i64 = 0 // assume real keys != 0 by remapping

functions

60func nx_lc_is_pow2(n: i64) -> i64 {
called by 1: nx_lc_alloc
66func nx_lc_alloc(capacity: i64, epsilon_ppm: i64) -> *LossyCounting {
called by 1: main calls 1: nx_lc_is_pow2
95func nx_lc_hash(key: i64) -> i64 {
called by 1: nx_lc_probe
100func nx_lc_entry_at(lc: *LossyCounting, idx: i64) -> *LcEntry {
107func nx_lc_probe(lc: *LossyCounting, key: i64) -> i64 {
138func nx_lc_prune(lc: *LossyCounting) -> i64 {
called by 1: nx_lc_add calls 1: nx_lc_entry_at
158func nx_lc_add(lc: *LossyCounting, key: i64) -> i64 {
189func nx_lc_estimate(lc: *LossyCounting, key: i64) -> i64 {
198func nx_lc_upper_bound(lc: *LossyCounting, key: i64) -> i64 {
called by 1: main calls 2: nx_lc_probenx_lc_entry_at
207func nx_lc_max_undercount(lc: *LossyCounting) -> i64 {
called by 1: nx_lc_query
211func nx_lc_query(lc: *LossyCounting, key: i64) -> *ApproxI64 {
221func nx_lc_n_entries(lc: *LossyCounting) -> i64 {
called by 1: main
225func nx_lc_total_seen(lc: *LossyCounting) -> i64 {
229func nx_lc_memory_bytes(lc: *LossyCounting) -> i64 {