whitepaper: 398/185 — wave6d (rails-0012..16, jsc-0001/2, vtk, sm-0002, redis/valkey-0003, helm-0002/3, k8s-0003)

This commit is contained in:
russell@unturf.com 2026-03-27 15:57:50 -04:00
parent eb9612e4bf
commit 3735145aa5
47 changed files with 3488 additions and 33 deletions

View file

@ -0,0 +1,200 @@
package unit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
/**
* JSC-0002: DFGGraph::handleSuccessor() O(E×P) predecessor dedup via Vector::contains.
*
* Models DFGGraph.cpp lines 738-746:
* - SlowGraph: predecessor dedup using List::contains — O(P) per edge
* - FastGraph: predecessor dedup using HashSet — O(1) per edge
*
* Compile: javac -d . *.java (from defects/jsc/unit/)
* Run: java -ea unit.JSCDFGGraphPredecessorTest
*/
public class JSCDFGGraphPredecessorTest {
static class Block {
final int id;
boolean isReachable = false;
final List<Integer> successors;
Block(int id, List<Integer> successors) {
this.id = id;
this.successors = successors;
}
}
// ---- slow path: List::contains O(P) per edge ----------------------------
static class SlowGraph {
static long opCount;
final List<Block> blocks;
final List<List<Integer>> predecessors; // per block
SlowGraph(List<Block> blocks) {
this.blocks = blocks;
predecessors = new ArrayList<>();
for (int i = 0; i < blocks.size(); i++)
predecessors.add(new ArrayList<>());
}
void handleSuccessor(Queue<Integer> worklist, int blockId, int succId) {
Block succ = blocks.get(succId);
if (!succ.isReachable) {
succ.isReachable = true;
worklist.add(succId);
}
List<Integer> preds = predecessors.get(succId);
// O(P) linear scan — the defect
boolean found = false;
for (int pred : preds) {
opCount++;
if (pred == blockId) { found = true; break; }
}
if (!found) preds.add(blockId);
}
void determineReachability() {
Queue<Integer> worklist = new LinkedList<>();
blocks.get(0).isReachable = true;
worklist.add(0);
while (!worklist.isEmpty()) {
int blockId = worklist.poll();
for (int succ : blocks.get(blockId).successors)
handleSuccessor(worklist, blockId, succ);
}
}
}
// ---- fast path: HashSet O(1) dedup --------------------------------------
static class FastGraph {
static long opCount;
final List<Block> blocks;
final List<List<Integer>> predecessors;
final List<HashSet<Integer>> predSeen; // dedup set
FastGraph(List<Block> blocks) {
this.blocks = blocks;
predecessors = new ArrayList<>();
predSeen = new ArrayList<>();
for (int i = 0; i < blocks.size(); i++) {
predecessors.add(new ArrayList<>());
predSeen.add(new HashSet<>());
}
}
void handleSuccessor(Queue<Integer> worklist, int blockId, int succId) {
Block succ = blocks.get(succId);
if (!succ.isReachable) {
succ.isReachable = true;
worklist.add(succId);
}
opCount++; // one hash lookup+insert
if (predSeen.get(succId).add(blockId)) {
predecessors.get(succId).add(blockId);
}
}
void determineReachability() {
Queue<Integer> worklist = new LinkedList<>();
blocks.get(0).isReachable = true;
worklist.add(0);
while (!worklist.isEmpty()) {
int blockId = worklist.poll();
for (int succ : blocks.get(blockId).successors)
handleSuccessor(worklist, blockId, succ);
}
}
}
// ---- graph builder: switch with N arms all targeting block N+1 ----------
// Block 0: entry, edges to blocks 1..N
// Blocks 1..N: arms, each edges to block N+1
// Block N+1: join/merge block
static List<Block> buildSwitchGraph(int N) {
List<Block> blocks = new ArrayList<>();
// block 0: switch, targets 1..N
List<Integer> arms = new ArrayList<>();
for (int i = 1; i <= N; i++) arms.add(i);
blocks.add(new Block(0, arms));
// blocks 1..N: each targets join block N+1
for (int i = 1; i <= N; i++) {
List<Integer> succ = new ArrayList<>();
succ.add(N + 1);
blocks.add(new Block(i, succ));
}
// block N+1: join (no successors)
blocks.add(new Block(N + 1, new ArrayList<>()));
return blocks;
}
// ---- tests --------------------------------------------------------------
static int passed = 0;
static int total = 0;
static void check(String name, boolean cond) {
total++;
if (cond) {
passed++;
} else {
System.out.println("FAIL: " + name);
}
}
public static void main(String[] args) {
// correctness: same predecessor list for small switch
{
int N = 5;
List<Block> slowBlocks = buildSwitchGraph(N);
List<Block> fastBlocks = buildSwitchGraph(N);
SlowGraph slow = new SlowGraph(slowBlocks);
FastGraph fast = new FastGraph(fastBlocks);
slow.determineReachability();
fast.determineReachability();
// join block (N+1) should have exactly N predecessors
check("slow: join preds == N", slow.predecessors.get(N + 1).size() == N);
check("fast: join preds == N", fast.predecessors.get(N + 1).size() == N);
}
// op-count scaling
int[] switchSizes = {10, 50, 100, 200, 500};
System.out.println();
System.out.printf("%-8s %12s %12s %8s%n", "N_arms", "slow_ops", "fast_ops", "ratio");
for (int N : switchSizes) {
List<Block> slowBlocks = buildSwitchGraph(N);
List<Block> fastBlocks = buildSwitchGraph(N);
SlowGraph.opCount = 0;
FastGraph.opCount = 0;
new SlowGraph(slowBlocks).determineReachability();
new FastGraph(fastBlocks).determineReachability();
long slow = SlowGraph.opCount;
long fast = FastGraph.opCount;
double ratio = (double) slow / fast;
System.out.printf("%-8d %12d %12d %8.1f%n", N, slow, fast, ratio);
check("slow > fast for N=" + N, slow > fast);
// slow O(N²) for the join block: sum 0..N-1 ~ N²/2
// fast O(N): exactly N lookups for join block
// ratio should grow with N; actual ratio ≈ N/2 - small constant
if (N >= 50) {
check("ratio >= N/5 for N=" + N, ratio >= (double) N / 5);
}
}
System.out.println();
System.out.printf("%d/%d PASS%n", passed, total);
if (passed != total) System.exit(1);
}
}