/** * llmindex.io — math item templates (compositional chains, distractors, counterfactual bases) * Author: Simon-Pierre Boucher * Contact: contact@spboucher.ai * License: Proprietary — © Simon-Pierre Boucher, all rights reserved * * Hardened for frontier discrimination: multi-step composition (errors * compound multiplicatively), provably-inert distractor clauses, value * re-randomization every run, and counterfactual-rule variants (base-k * arithmetic) that separate reasoning from retrieval. */ import { ANSWER_FORMAT_INSTRUCTIONS } from '../answer'; import type { Rng } from '../rng'; import type { ItemTemplate } from '../types'; const LEADS = [ 'Compute the value of the following expression.', 'Evaluate the expression below and give the result.', 'Work out the exact value of this expression.', 'Calculate the following. Show your reasoning, then answer.', ]; export const mathArithChain: ItemTemplate = { id: 'math.arith.chain-v2', domain: 'math', description: 'Deep integer arithmetic chain (6-8 dependent operations, 2-4 digit operands) — errors compound multiplicatively.', paramSpace: 999 ** 6 * 4 ** 6, render(rng: Rng, perturbSeed: string) { // Build a dependent chain: v0 = a·b − c; v1 = v0·d + e; v2 = v1 − f·g; … const a = rng.int(23, 97); const b = rng.int(23, 97); const c = rng.int(101, 999); const d = rng.int(3, 9); const e = rng.int(1001, 9999); const f = rng.int(11, 99); const g = rng.int(11, 99); const h = rng.int(2, 7); const v0 = a * b - c; const v1 = v0 * d + e; const v2 = v1 - f * g; const value = v2 * h; const expr = `(((${a} × ${b} − ${c}) × ${d} + ${e}) − ${f} × ${g}) × ${h}`; return { templateId: this.id, domain: this.domain, prompt: `${rng.pick(LEADS)}\n\n${expr}\n\n${ANSWER_FORMAT_INSTRUCTIONS}`, answerKey: String(value), grading: 'numeric', perturbSeed, }; }, }; export const mathLinearSolve: ItemTemplate = { id: 'math.algebra.system-v2', domain: 'math', description: 'Two-variable integer linear system solved for a derived quantity (not x or y directly).', paramSpace: 20 ** 4 * 200 ** 2, render(rng: Rng, perturbSeed: string) { const x = rng.int(-40, 40); const y = rng.int(-40, 40); const a1 = rng.int(2, 9); const b1 = rng.int(2, 9); const a2 = rng.int(2, 9); let b2 = rng.int(2, 9); if (a1 * b2 === a2 * b1) b2 += 1; // keep the system non-degenerate const c1 = a1 * x + b1 * y; const c2 = a2 * x - b2 * y; const p = rng.int(2, 6); const q = rng.int(2, 6); const derived = p * x - q * y; return { templateId: this.id, domain: this.domain, prompt: `Solve the system, then answer the derived question.\n\n` + `${a1}x + ${b1}y = ${c1}\n${a2}x − ${b2}y = ${c2}\n\n` + `What is the value of ${p}x − ${q}y?\n\n${ANSWER_FORMAT_INSTRUCTIONS}`, answerKey: String(derived), grading: 'numeric', perturbSeed, }; }, }; const DISTRACTOR_FACTS = [ 'The warehouse was painted {N} years ago.', 'A rival firm shipped {N} unrelated parcels the same week.', 'The delivery van has a {N}-liter fuel tank.', 'The company was founded {N} kilometers from the port.', 'Each pallet weighs about {N} grams more when wet.', ]; export const mathPercentChain: ItemTemplate = { id: 'math.percent.chain-v2', domain: 'math', description: 'Three successive percentage changes on a base quantity with provably-inert distractor clauses injected.', paramSpace: 99 * 40 ** 3 * 5 ** 2 * 200, render(rng: Rng, perturbSeed: string) { // base multiple of 1000 ⇒ result exact at 3 decimals for the chosen rates const base = rng.int(2, 99) * 1000; const up1 = rng.int(5, 45); const down = rng.int(5, 45); const up2 = rng.int(5, 45); const value = (((base * (100 + up1)) / 100) * (100 - down)) / 100; const final = (value * (100 + up2)) / 100; const rounded = Math.round(final * 100) / 100; // Inert distractors: quantities that never enter the computation. const d1 = rng.pick(DISTRACTOR_FACTS).replace('{N}', String(rng.int(3, 180))); const d2 = rng.pick(DISTRACTOR_FACTS).replace('{N}', String(rng.int(3, 180))); return { templateId: this.id, domain: this.domain, prompt: `An inventory starts at ${base} units. ${d1} In the first month the inventory grows by ${up1}%. ` + `${d2} The next month it shrinks by ${down}%, and the month after it grows by ${up2}%. ` + `How many units remain (exact value, round to 2 decimals only if needed)?\n\n${ANSWER_FORMAT_INSTRUCTIONS}`, answerKey: String(rounded), grading: 'numeric', perturbSeed, }; }, }; /** Digits of n in base b (b ≤ 13, digits as letters beyond 9 avoided: b ≤ 13 uses 0-9+A-C but we cap at 13 and exclude ambiguity by using b ≤ 13 with A,B,C). */ function toBase(n: number, b: number): string { return n.toString(b).toUpperCase(); } export const mathCounterfactualBase: ItemTemplate = { id: 'math.counterfactual.base-v1', domain: 'math', description: 'Counterfactual-rule arithmetic: add/multiply numbers written in base k (k ∈ {7,8,9,11,13}) — separates rule-following computation from memorized decimal arithmetic.', paramSpace: 5 * 2 * 3000 ** 2, render(rng: Rng, perturbSeed: string) { const b = rng.pick([7, 8, 9, 11, 13] as const); const op = rng.pick(['add', 'multiply'] as const); const x = op === 'add' ? rng.int(200, 3000) : rng.int(12, 90); const y = op === 'add' ? rng.int(200, 3000) : rng.int(12, 90); const result = op === 'add' ? x + y : x * y; return { templateId: this.id, domain: this.domain, prompt: `Work strictly in base ${b}. ${op === 'add' ? 'Add' : 'Multiply'} the base-${b} numbers ` + `${toBase(x, b)} and ${toBase(y, b)}. Give the result IN BASE ${b}` + `${b > 10 ? ' (digits beyond 9 are A, B, C)' : ''}.\n\n${ANSWER_FORMAT_INSTRUCTIONS}`, answerKey: toBase(result, b), grading: 'exact', perturbSeed, }; }, }; export const mathChained: ItemTemplate = { id: 'math.chained.pipeline-v1', domain: 'math', description: 'Three linked sub-problems where each answer feeds the next (R-Horizon-style chaining) — per-step accuracy compounds, amplifying discrimination.', paramSpace: 90 ** 4 * 9 ** 3, render(rng: Rng, perturbSeed: string) { const a = rng.int(12, 89); const b = rng.int(12, 89); const s1 = a * b; // step 1 const m = rng.int(3, 9); const c = rng.int(100, 999); const s2 = s1 * m - c; // step 2 const dsor = rng.int(3, 9); const s3 = Math.floor(s2 / dsor) + (s2 % dsor); // step 3: quotient + remainder return { templateId: this.id, domain: this.domain, prompt: `Solve the following linked steps; each step uses the previous result.\n\n` + `Step 1: P = ${a} × ${b}.\n` + `Step 2: Q = P × ${m} − ${c}.\n` + `Step 3: divide Q by ${dsor}: let q be the integer quotient and r the remainder. The final answer is q + r.\n\n` + `${ANSWER_FORMAT_INSTRUCTIONS}`, answerKey: String(s3), grading: 'numeric', perturbSeed, }; }, };