diff --git a/playground/examples/uncertainty.affine b/playground/examples/uncertainty.affine index e0457db..423c2e1 100644 --- a/playground/examples/uncertainty.affine +++ b/playground/examples/uncertainty.affine @@ -1,11 +1,8 @@ // SPDX-License-Identifier: MPL-2.0 -// Ported via Harvard Engine mechanical processor +// Ported via Harvard Engine (Semantic pass) module uncertainty; -// TODO: Complete semantic implementation - -/* === ORIGINAL TYPESCRIPT CONTEXT === // SPDX-License-Identifier: MPL-2.0 // Copyright (c) Jonathan D.A. Jewell // SPDX-FileCopyrightText: 2025 hyperpolymath @@ -20,66 +17,66 @@ module uncertainty; import { type Tri } from '../src/ternary.ts'; /** Closed real interval [lo, hi]. */ -export interface Interval { +struct Interval { lo: number; hi: number; } -export const iv = (lo: number, hi: number): Interval => ({ +let iv = (lo: number, hi: number): Interval => ({ lo: Math.min(lo, hi), hi: Math.max(lo, hi), }); -export function addI(a: Interval, b: Interval): Interval { +fn addI(a: Interval, b: Interval): Interval { return iv(a.lo + b.lo, a.hi + b.hi); } -export function mulI(a: Interval, b: Interval): Interval { - const ps = [a.lo * b.lo, a.lo * b.hi, a.hi * b.lo, a.hi * b.hi]; +fn mulI(a: Interval, b: Interval): Interval { + let ps = [a.lo * b.lo, a.lo * b.hi, a.hi * b.lo, a.hi * b.hi]; return iv(Math.min(...ps), Math.max(...ps)); } /** Ternary comparison: definite when disjoint, Unknown when they overlap. */ -export function ltI(a: Interval, b: Interval): Tri { +fn ltI(a: Interval, b: Interval): Tri { if (a.hi < b.lo) return 'T'; if (a.lo > b.hi) return 'F'; return 'U'; } /** Gaussian number: mean with standard deviation. */ -export interface Gaussian { +struct Gaussian { mu: number; sd: number; } -export const gauss = (mu: number, sd: number): Gaussian => ({ mu, sd: Math.abs(sd) }); +let gauss = (mu: number, sd: number): Gaussian => ({ mu, sd: Math.abs(sd) }); /** First-order (uncorrelated) propagation through sum and product. */ -export function addG(a: Gaussian, b: Gaussian): Gaussian { +fn addG(a: Gaussian, b: Gaussian): Gaussian { return gauss(a.mu + b.mu, Math.hypot(a.sd, b.sd)); } -export function mulG(a: Gaussian, b: Gaussian): Gaussian { - const mu = a.mu * b.mu; - const rel = Math.hypot(a.sd / a.mu, b.sd / b.mu); +fn mulG(a: Gaussian, b: Gaussian): Gaussian { + let mu = a.mu * b.mu; + let rel = Math.hypot(a.sd / a.mu, b.sd / b.mu); return gauss(mu, Math.abs(mu) * rel); } -function main(): void { +fn main(): void { console.log('=== BetLang Uncertainty Modeling ===\n'); - const a = iv(2, 4); - const b = iv(3, 5); + let a = iv(2, 4); + let b = iv(3, 5); console.log(`Intervals: a=[${a.lo},${a.hi}] b=[${b.lo},${b.hi}]`); console.log(` a + b = [${addI(a, b).lo}, ${addI(a, b).hi}]`); console.log(` a * b = [${mulI(a, b).lo}, ${mulI(a, b).hi}]`); console.log(` a < b ? -> ${ltI(a, b)} (overlap => Unknown, not a false certainty)`); console.log(` [0,1] < [5,6] ? -> ${ltI(iv(0, 1), iv(5, 6))}`); - const g1 = gauss(10, 1); - const g2 = gauss(20, 2); - const s = addG(g1, g2); - const p = mulG(g1, g2); + let g1 = gauss(10, 1); + let g2 = gauss(20, 2); + let s = addG(g1, g2); + let p = mulG(g1, g2); console.log(`\nGaussians: g1=${g1.mu}±${g1.sd} g2=${g2.mu}±${g2.sd}`); console.log(` g1 + g2 = ${s.mu}±${s.sd.toFixed(4)}`); console.log(` g1 * g2 = ${p.mu}±${p.sd.toFixed(4)}`); @@ -89,4 +86,3 @@ if (import.meta.main) { main(); } -==================================== */ diff --git a/playground/src/main.affine b/playground/src/main.affine index e468799..34af339 100644 --- a/playground/src/main.affine +++ b/playground/src/main.affine @@ -1,11 +1,8 @@ // SPDX-License-Identifier: MPL-2.0 -// Ported via Harvard Engine mechanical processor +// Ported via Harvard Engine (Semantic pass) module main; -// TODO: Complete semantic implementation - -/* === ORIGINAL TYPESCRIPT CONTEXT === // SPDX-License-Identifier: MPL-2.0 // Copyright (c) Jonathan D.A. Jewell // SPDX-FileCopyrightText: 2025 hyperpolymath @@ -18,7 +15,7 @@ module main; import { main as ternaryDemo } from './ternary.ts'; import { main as probabilityDemo } from './probability.ts'; -function main(): void { +fn main(): void { console.log('BetLang Playground — Symbolic Probabilistic Metalanguage\n'); ternaryDemo(); console.log('\n' + '-'.repeat(60) + '\n'); @@ -30,4 +27,3 @@ if (import.meta.main) { main(); } -==================================== */ diff --git a/playground/src/probability.affine b/playground/src/probability.affine index 442c1cb..c5863b2 100644 --- a/playground/src/probability.affine +++ b/playground/src/probability.affine @@ -1,11 +1,8 @@ // SPDX-License-Identifier: MPL-2.0 -// Ported via Harvard Engine mechanical processor +// Ported via Harvard Engine (Semantic pass) module probability; -// TODO: Complete semantic implementation - -/* === ORIGINAL TYPESCRIPT CONTEXT === // SPDX-License-Identifier: MPL-2.0 // Copyright (c) Jonathan D.A. Jewell // SPDX-FileCopyrightText: 2025 hyperpolymath @@ -23,13 +20,13 @@ module probability; import { bet, type Tri } from './ternary.ts'; /** A lazy, weighted branch: a relative weight and a thunk producing a value. */ -export interface Branch { +struct Branch { weight: number; value: () => A; } /** Deterministic, seedable PRNG (mulberry32) so demos/tests are reproducible. */ -export function rng(seed: number): () => number { +fn rng(seed: number): () => number { let s = seed >>> 0; return () => { s = (s + 0x6d2b79f5) >>> 0; @@ -41,8 +38,8 @@ export function rng(seed: number): () => number { } /** Force exactly one branch, chosen with probability proportional to weight. */ -export function betWeighted(branches: Branch[], draw: () => number): A { - const total = branches.reduce((acc, b) => acc + b.weight, 0); +fn betWeighted(branches: Branch[], draw: () => number): A { + let total = branches.reduce((acc, b) => acc + b.weight, 0); if (total <= 0) throw new Error('betWeighted: weights must sum to a positive number'); let r = draw() * total; for (const b of branches) { @@ -56,7 +53,7 @@ export function betWeighted(branches: Branch[], draw: () => number): A { * Predicate-driven ternary selection. The predicate yields a Tri; a definite * answer takes the matching branch, Unknown defers to the `uncertain` branch. */ -export function betConditional( +fn betConditional( predicate: () => Tri, ifTrue: () => A, uncertain: () => A, @@ -66,13 +63,13 @@ export function betConditional( } /** Monte-Carlo expectation of a numeric weighted bet over `n` samples. */ -export function expectation(branches: Branch[], n: number, draw: () => number): number { +fn expectation(branches: Branch[], n: number, draw: () => number): number { let sum = 0; for (let i = 0; i < n; i++) sum += betWeighted(branches, draw); return sum / n; } -export function main(): void { +fn main(): void { console.log('=== BetLang Probabilistic Layer ===\n'); // A loaded three-sided "coin": 60% True, 30% Unknown, 10% False. @@ -81,9 +78,9 @@ export function main(): void { { weight: 0.3, value: () => 'U' as Tri }, { weight: 0.1, value: () => 'F' as Tri }, ]; - const draw = rng(42); + let draw = rng(42); const counts: Record = { T: 0, U: 0, F: 0 }; - const N = 100_000; + let N = 100_000; for (let i = 0; i < N; i++) counts[betWeighted(loaded, draw)]++; console.log(`Empirical distribution over ${N.toLocaleString()} draws (target 0.60/0.30/0.10):`); console.log( @@ -97,11 +94,11 @@ export function main(): void { { weight: 2, value: () => 10 }, { weight: 7, value: () => 0 }, ]; - const ev = expectation(payout, 200_000, rng(7)); + let ev = expectation(payout, 200_000, rng(7)); console.log(`\nExpected payout (analytic = 12.0): ${ev.toFixed(2)}`); // Conditional choice that stays total under Unknown. - const choice = betConditional( + let choice = betConditional( () => 'U' as Tri, () => 'committed', () => 'hedged (predicate was Unknown)', @@ -114,4 +111,3 @@ if (import.meta.main) { main(); } -==================================== */ diff --git a/playground/src/ternary.affine b/playground/src/ternary.affine index fb9ed4d..c141046 100644 --- a/playground/src/ternary.affine +++ b/playground/src/ternary.affine @@ -1,11 +1,8 @@ // SPDX-License-Identifier: MPL-2.0 -// Ported via Harvard Engine mechanical processor +// Ported via Harvard Engine (Semantic pass) module ternary; -// TODO: Complete semantic implementation - -/* === ORIGINAL TYPESCRIPT CONTEXT === // SPDX-License-Identifier: MPL-2.0 // Copyright (c) Jonathan D.A. Jewell // SPDX-FileCopyrightText: 2025 hyperpolymath @@ -22,30 +19,30 @@ module ternary; // under the order F < U < T. /** The three logical values of the BetLang core. */ -export type Tri = 'T' | 'F' | 'U'; +struct Tri { 'T' | 'F' | 'U'; const ORDER: Record = { F: 0, U: 1, T: 2 }; const BY_RANK: Tri[] = ['F', 'U', 'T']; /** Kleene negation: swaps T/F, fixes U. */ -export function not(a: Tri): Tri { +fn not(a: Tri): Tri { if (a === 'T') return 'F'; if (a === 'F') return 'T'; return 'U'; } /** Kleene conjunction = min under F < U < T. */ -export function and(a: Tri, b: Tri): Tri { +fn and(a: Tri, b: Tri): Tri { return BY_RANK[Math.min(ORDER[a], ORDER[b])]; } /** Kleene disjunction = max under F < U < T. */ -export function or(a: Tri, b: Tri): Tri { +fn or(a: Tri, b: Tri): Tri { return BY_RANK[Math.max(ORDER[a], ORDER[b])]; } /** Material implication, defined as `or(not(a), b)`. */ -export function implies(a: Tri, b: Tri): Tri { +fn implies(a: Tri, b: Tri): Tri { return or(not(a), b); } @@ -56,7 +53,7 @@ export function implies(a: Tri, b: Tri): Tri { * which branch wins — when it returns 'U' the middle branch is taken, which * is what makes the choice *total* even under uncertainty. */ -export function bet( +fn bet( selector: () => Tri, onTrue: () => A, onUnknown: () => A, @@ -73,13 +70,13 @@ export function bet( } /** Render a full binary truth table for a Tri operator. */ -function table(name: string, op: (a: Tri, b: Tri) => Tri): string { +fn table(name: string, op: (a: Tri, b: Tri) => Tri): string { const vals: Tri[] = ['T', 'U', 'F']; - const rows = vals.flatMap((a) => vals.map((b) => ` ${a} ${name} ${b} = ${op(a, b)}`)); + let rows = vals.flatMap((a) => vals.map((b) => ` ${a} ${name} ${b} = ${op(a, b)}`)); return [`${name} truth table:`, ...rows].join('\n'); } -export function main(): void { +fn main(): void { console.log('=== BetLang Ternary Core ==='); console.log('Values: True (T), False (F), Unknown (U)\n'); console.log(table('AND', and)); @@ -91,7 +88,7 @@ export function main(): void { // Laziness demonstration: only the selected thunk runs. let evaluated = ''; - const result = bet( + let result = bet( () => 'U', () => { evaluated = 'true-branch'; @@ -114,4 +111,3 @@ if (import.meta.main) { main(); } -==================================== */ diff --git a/playground/test/probability_test.affine b/playground/test/probability_test.affine index acd0037..73baa79 100644 --- a/playground/test/probability_test.affine +++ b/playground/test/probability_test.affine @@ -1,11 +1,8 @@ // SPDX-License-Identifier: MPL-2.0 -// Ported via Harvard Engine mechanical processor +// Ported via Harvard Engine (Semantic pass) module probability_test; -// TODO: Complete semantic implementation - -/* === ORIGINAL TYPESCRIPT CONTEXT === // SPDX-License-Identifier: MPL-2.0 // Copyright (c) Jonathan D.A. Jewell // SPDX-FileCopyrightText: 2025 hyperpolymath @@ -15,10 +12,10 @@ import { betConditional, betWeighted, type Branch, expectation, rng } from '../s import { type Tri } from '../src/ternary.ts'; Deno.test('rng is deterministic for a fixed seed and stays in [0,1)', () => { - const a = rng(123); - const b = rng(123); + let a = rng(123); + let b = rng(123); for (let i = 0; i < 50; i++) { - const x = a(); + let x = a(); assertEquals(x, b()); assert(x >= 0 && x < 1); } @@ -30,9 +27,9 @@ Deno.test('betWeighted respects weights within Monte-Carlo tolerance', () => { { weight: 0.3, value: () => 'U' }, { weight: 0.1, value: () => 'F' }, ]; - const draw = rng(42); + let draw = rng(42); const counts: Record = { T: 0, U: 0, F: 0 }; - const N = 50_000; + let N = 50_000; for (let i = 0; i < N; i++) counts[betWeighted(branches, draw)]++; assert(Math.abs(counts.T / N - 0.6) < 0.02); assert(Math.abs(counts.U / N - 0.3) < 0.02); @@ -64,4 +61,3 @@ Deno.test('betConditional defers to the uncertain branch on Unknown', () => { ); }); -==================================== */ diff --git a/playground/test/ternary_test.affine b/playground/test/ternary_test.affine index 2bd185d..50533d7 100644 --- a/playground/test/ternary_test.affine +++ b/playground/test/ternary_test.affine @@ -1,11 +1,8 @@ // SPDX-License-Identifier: MPL-2.0 -// Ported via Harvard Engine mechanical processor +// Ported via Harvard Engine (Semantic pass) module ternary_test; -// TODO: Complete semantic implementation - -/* === ORIGINAL TYPESCRIPT CONTEXT === // SPDX-License-Identifier: MPL-2.0 // Copyright (c) Jonathan D.A. Jewell // SPDX-FileCopyrightText: 2025 hyperpolymath @@ -49,7 +46,7 @@ Deno.test('implies(a,b) == or(not a, b)', () => { Deno.test('bet is lazy: only the selected branch is forced', () => { const forced: string[] = []; - const r = bet( + let r = bet( () => 'F', () => { forced.push('T'); @@ -68,4 +65,3 @@ Deno.test('bet is lazy: only the selected branch is forced', () => { assertEquals(forced, ['F']); }); -==================================== */