Spaces:
Running
Running
| /** | |
| * Pareto Finite Stabilization Gate | |
| * | |
| * @lean_theorem Lutar.Thesis.ParetoStabilization.th_v18_11_pareto_stabilization | |
| * @lean_file Lutar/Thesis/TH_V18_11_ParetoFiniteStabilization.lean | |
| * @lean_status GREEN — 0 sorries | |
| * @lean_commit see LEAN_COMMIT_SHA env var; pin at CI time from lutar-lean/lean-toolchain | |
| * | |
| * Theorem (Lynch 1996 Distributed Algorithms Ch.8; Sipser 2012 Intro to Theory of Computation): | |
| * For finite discrete multi-objective optimization over objectives O ⊂ ℝⁿ (finite set), | |
| * the Pareto frontier F* stabilizes in at most |O| steps. | |
| * Proof: Each update either adds a new non-dominated point (bounded by |O|) or removes | |
| * dominated points. Since |O| is finite, the frontier cannot oscillate indefinitely. | |
| * The governance optimizer reaches a fixed point in finite rounds. | |
| * | |
| * Applications: | |
| * - Multi-organ Ouroboros governance convergence guarantee | |
| * - Budget allocation convergence across 7 organs under discrete utility spaces | |
| * | |
| * References: | |
| * Lynch (1996) Distributed Algorithms Ch.8 — stabilization in finite systems | |
| * Sipser (2012) Introduction to the Theory of Computation §7 | |
| * Lutar/Thesis/TH_V18_11_ParetoFiniteStabilization.lean | |
| * | |
| * SPDX-License-Identifier: Apache-2.0 | |
| */ | |
| import * as crypto from "crypto"; | |
| // --------------------------------------------------------------------------- | |
| // Types | |
| // --------------------------------------------------------------------------- | |
| /** A multi-dimensional objective vector (maximize each dimension) */ | |
| export type ObjectiveVector = readonly number[]; | |
| export interface ParetoStabilizationResult { | |
| /** True iff the Pareto frontier stabilized before maxRounds */ | |
| stabilized: boolean; | |
| /** Round at which stabilization was detected (1-indexed) */ | |
| stabilizationRound: number; | |
| /** Final Pareto frontier */ | |
| paretoFrontier: ObjectiveVector[]; | |
| /** Total rounds processed */ | |
| roundsProcessed: number; | |
| /** DSSE receipt */ | |
| receipt: ParetoDsseReceipt; | |
| } | |
| export interface ParetoDsseReceipt { | |
| formula: string; | |
| lean_theorem: string; | |
| lean_file: string; | |
| lean_commit_sha: string; | |
| inputs_hash: string; | |
| output: { | |
| stabilized: boolean; | |
| stabilizationRound: number; | |
| frontierSize: number; | |
| roundsProcessed: number; | |
| }; | |
| ts: string; | |
| } | |
| // --------------------------------------------------------------------------- | |
| // Pareto dominance | |
| // --------------------------------------------------------------------------- | |
| /** | |
| * Returns true if `a` dominates `b` (a ≥ b in all dimensions, a > b in at least one). | |
| */ | |
| function dominates(a: ObjectiveVector, b: ObjectiveVector): boolean { | |
| if (a.length !== b.length) { | |
| throw new Error(`dominates: dimension mismatch ${a.length} vs ${b.length}`); | |
| } | |
| let strictlyBetter = false; | |
| for (let i = 0; i < a.length; i++) { | |
| if (a[i]! < b[i]!) return false; | |
| if (a[i]! > b[i]!) strictlyBetter = true; | |
| } | |
| return strictlyBetter; | |
| } | |
| /** | |
| * Compute Pareto frontier: non-dominated subset of `objectives`. | |
| */ | |
| function computeParetoFrontier( | |
| objectives: ObjectiveVector[] | |
| ): ObjectiveVector[] { | |
| const frontier: ObjectiveVector[] = []; | |
| for (const cand of objectives) { | |
| // Check if any existing frontier member dominates cand | |
| if (frontier.some((f) => dominates(f, cand))) continue; | |
| // Remove any frontier members dominated by cand | |
| const newFrontier = frontier.filter((f) => !dominates(cand, f)); | |
| newFrontier.push(cand); | |
| frontier.length = 0; | |
| frontier.push(...newFrontier); | |
| } | |
| return frontier; | |
| } | |
| /** | |
| * Frontier equality check (order-independent). | |
| */ | |
| function frontierEqual( | |
| a: ObjectiveVector[], | |
| b: ObjectiveVector[] | |
| ): boolean { | |
| if (a.length !== b.length) return false; | |
| const toStr = (v: ObjectiveVector) => v.join(","); | |
| const setA = new Set(a.map(toStr)); | |
| return b.every((v) => setA.has(toStr(v))); | |
| } | |
| // --------------------------------------------------------------------------- | |
| // Internal helpers | |
| // --------------------------------------------------------------------------- | |
| function sha256Hex(obj: unknown): string { | |
| return crypto.createHash("sha256").update(JSON.stringify(obj)).digest("hex"); | |
| } | |
| // --------------------------------------------------------------------------- | |
| // Public API | |
| // --------------------------------------------------------------------------- | |
| /** | |
| * Assert the Pareto finite stabilization theorem. | |
| * | |
| * Given a sequence of round-by-round candidate objective vectors, check that | |
| * the Pareto frontier stabilizes (does not change) within `maxRounds` rounds. | |
| * | |
| * @param candidateStream Array of rounds; each round is an array of new objective vectors. | |
| * Objectives accumulate across rounds. | |
| * @param maxRounds Maximum rounds before declaring non-stabilization (default 50) | |
| * | |
| * @returns ParetoStabilizationResult with stabilization round and DSSE receipt. | |
| * | |
| * By the Lean theorem, stabilization is guaranteed if the total objective space is finite. | |
| */ | |
| export function paretoStabilizationGate( | |
| candidateStream: ObjectiveVector[][], | |
| maxRounds = 50 | |
| ): ParetoStabilizationResult { | |
| let allObjectives: ObjectiveVector[] = []; | |
| let prevFrontier: ObjectiveVector[] = []; | |
| let stabilizationRound = -1; | |
| let roundsProcessed = 0; | |
| for (let r = 0; r < Math.min(candidateStream.length, maxRounds); r++) { | |
| allObjectives = allObjectives.concat(candidateStream[r]!); | |
| const newFrontier = computeParetoFrontier(allObjectives); | |
| roundsProcessed = r + 1; | |
| if (r > 0 && frontierEqual(prevFrontier, newFrontier)) { | |
| stabilizationRound = r + 1; | |
| prevFrontier = newFrontier; | |
| break; | |
| } | |
| prevFrontier = newFrontier; | |
| } | |
| const stabilized = stabilizationRound !== -1; | |
| const inputs_hash = sha256Hex({ candidateStream, maxRounds }); | |
| const lean_commit_sha = process.env["LEAN_COMMIT_SHA"] ?? "unknown"; | |
| const receipt: ParetoDsseReceipt = { | |
| formula: "th_v18_11_pareto_stabilization", | |
| lean_theorem: | |
| "Lutar.Thesis.ParetoStabilization.th_v18_11_pareto_stabilization", | |
| lean_file: "Lutar/Thesis/TH_V18_11_ParetoFiniteStabilization.lean", | |
| lean_commit_sha, | |
| inputs_hash, | |
| output: { | |
| stabilized, | |
| stabilizationRound, | |
| frontierSize: prevFrontier.length, | |
| roundsProcessed, | |
| }, | |
| ts: new Date().toISOString(), | |
| }; | |
| return { | |
| stabilized, | |
| stabilizationRound, | |
| paretoFrontier: prevFrontier, | |
| roundsProcessed, | |
| receipt, | |
| }; | |
| } | |
| /** | |
| * Build a candidate stream from a static pool of objectives. | |
| * Splits the pool across `rounds` batches evenly. | |
| * Convenience for testing stabilization under finite objective spaces. | |
| */ | |
| export function buildCandidateStream( | |
| objectives: ObjectiveVector[], | |
| rounds: number | |
| ): ObjectiveVector[][] { | |
| const batchSize = Math.ceil(objectives.length / rounds); | |
| const stream: ObjectiveVector[][] = []; | |
| for (let i = 0; i < objectives.length; i += batchSize) { | |
| stream.push(objectives.slice(i, i + batchSize)); | |
| } | |
| return stream; | |
| } | |