@@ -458,6 +458,7 @@ FUZZ_TARGET(clusterlin_ancestor_finder)
458
458
while (todo.Any ()) {
459
459
// Call the ancestor finder's FindCandidateSet for what remains of the graph.
460
460
assert (!anc_finder.AllDone ());
461
+ assert (todo.Count () == anc_finder.NumRemaining ());
461
462
auto best_anc = anc_finder.FindCandidateSet ();
462
463
// Sanity check the result.
463
464
assert (best_anc.transactions .Any ());
@@ -489,6 +490,7 @@ FUZZ_TARGET(clusterlin_ancestor_finder)
489
490
anc_finder.MarkDone (del_set);
490
491
}
491
492
assert (anc_finder.AllDone ());
493
+ assert (anc_finder.NumRemaining () == 0 );
492
494
}
493
495
494
496
static constexpr auto MAX_SIMPLE_ITERATIONS = 300000 ;
@@ -523,6 +525,7 @@ FUZZ_TARGET(clusterlin_search_finder)
523
525
assert (!smp_finder.AllDone ());
524
526
assert (!exh_finder.AllDone ());
525
527
assert (!anc_finder.AllDone ());
528
+ assert (anc_finder.NumRemaining () == todo.Count ());
526
529
527
530
// For each iteration, read an iteration count limit from the fuzz input.
528
531
uint64_t max_iterations = 1 ;
@@ -605,6 +608,7 @@ FUZZ_TARGET(clusterlin_search_finder)
605
608
assert (smp_finder.AllDone ());
606
609
assert (exh_finder.AllDone ());
607
610
assert (anc_finder.AllDone ());
611
+ assert (anc_finder.NumRemaining () == 0 );
608
612
}
609
613
610
614
FUZZ_TARGET (clusterlin_linearization_chunking)
@@ -775,11 +779,16 @@ FUZZ_TARGET(clusterlin_linearize)
775
779
if (n <= 19 && iter_count > (uint64_t {1 } << n)) {
776
780
assert (optimal);
777
781
}
778
- // Additionally, if the assumption of sqrt(2^k)+1 iterations per step holds, the maximum number
779
- // of iterations is also bounded by (2 + sqrt(2)) * (sqrt(2^n) - 1) + n, which is less than
780
- // (2 + sqrt(2)) * sqrt(2^n) + n. Subtracting n and squaring gives
781
- // (6 + 4 * sqrt(2)) * 2^n < 12 * 2^n.
782
- if (n <= 35 && iter_count > n && (iter_count - n) * (iter_count - n) >= uint64_t {12 } << n) {
782
+ // Additionally, if the assumption of sqrt(2^k)+1 iterations per step holds, plus ceil(k/4)
783
+ // start-up cost per step, plus ceil(n^2/64) start-up cost overall, we can compute the upper
784
+ // bound for a whole linearization (summing for k=1..n) using the Python expression
785
+ // [sum((k+3)//4 + int(math.sqrt(2**k)) + 1 for k in range(1, n + 1)) + (n**2 + 63) // 64 for n in range(0, 35)]:
786
+ static constexpr uint64_t MAX_OPTIMAL_ITERS[] = {
787
+ 0 , 4 , 8 , 12 , 18 , 26 , 37 , 51 , 70 , 97 , 133 , 182 , 251 , 346 , 480 , 666 , 927 , 1296 , 1815 , 2545 ,
788
+ 3576 , 5031 , 7087 , 9991 , 14094 , 19895 , 28096 , 39690 , 56083 , 79263 , 112041 , 158391 , 223936 ,
789
+ 316629 , 447712
790
+ };
791
+ if (n < std::size (MAX_OPTIMAL_ITERS) && iter_count >= MAX_OPTIMAL_ITERS[n]) {
783
792
Assume (optimal);
784
793
}
785
794
0 commit comments