gp-lite
Version:
Tiny, zero-dependency GA/GP engine for TypeScript/JS with first-class types, deterministic RNG, and budget-aware runs.
1 lines • 22.8 kB
Source Map (JSON)
{"version":3,"sources":["../src/lib/defaults.ts","../src/lib/config.ts","../src/lib/estimate.ts","../src/cli.ts"],"names":["DEFAULT_ELITE","popSize","normalizeConfigBase","cfg","_a","_b","_c","_d","_e","_f","_g","_h","_i","_j","_k","_l","_m","_n","elite","maxWallMs","cxProb","mutProb","estimateRun","opts","c","expectedGenerations","immigrantsPerGen","childrenFromBreedingPerGen","pairsPerGen","selectionsPerGen","init","perGen","plannedTotal","expectedTotal","cappedByMaxEvaluations","perEvalMs","perGenOverheadMs","perRunOverheadMs","timeInit","timePerGen","timePlannedTotal","timeExpectedTotal","cappedByMaxWall","perEvalCost","monetary","parseArgs","argv","out","i","a","key","next","num","v","n","showHelp","main","__async","args","units","raw","json","e","maybe","k","maybeUnit","eg","est","lines"],"mappings":"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","file":"cli.cjs","sourcesContent":["export const DEFAULT_POP_SIZE = 100\nexport const DEFAULT_GENERATIONS = 1000\nexport const DEFAULT_ELITE = (popSize: number) =>\n Math.max(1, Math.floor(0.02 * popSize))\nexport const DEFAULT_CX_PROB = 0.8\nexport const DEFAULT_MUT_PROB = 0.2\nexport const DEFAULT_CROSSOVER_CHILDREN = 1\nexport const DEFAULT_IMMIGRATION = 0.02\nexport const DEFAULT_TOURNAMENT = 3\nexport const DEFAULT_STALL = 50\nexport const DEFAULT_TARGET_FITNESS = Infinity\nexport const DEFAULT_MAX_WALL_MS = Infinity\nexport const DEFAULT_MAX_EVALUATIONS = Infinity\nexport const DEFAULT_CONCURRENCY = 1\n\n","import type { GPConfig } from \"../types\"\nimport {\n DEFAULT_POP_SIZE,\n DEFAULT_GENERATIONS,\n DEFAULT_ELITE,\n DEFAULT_CX_PROB,\n DEFAULT_CROSSOVER_CHILDREN,\n DEFAULT_IMMIGRATION,\n DEFAULT_TOURNAMENT,\n DEFAULT_STALL,\n DEFAULT_TARGET_FITNESS,\n DEFAULT_MAX_WALL_MS,\n DEFAULT_MAX_EVALUATIONS,\n DEFAULT_CONCURRENCY,\n} from \"./defaults\"\n\n/**\n * Normalize GPConfig to shared defaults without instantiating the engine.\n *\n * Guidance:\n * - Breeding proportions: Pc + Pm = 1 (immigration is separate).\n * - If mutProb is omitted, we derive it as 1 - cxProb.\n * - timeLimitMs is a deprecated alias of maxWallMs (kept for back-compat).\n */\nexport function normalizeConfigBase<T>(\n cfg: GPConfig<T>,\n): Required<\n Pick<\n GPConfig<T>,\n | \"popSize\"\n | \"generations\"\n | \"elite\"\n | \"cxProb\"\n | \"mutProb\"\n | \"crossoverChildren\"\n | \"immigration\"\n | \"tournament\"\n | \"stall\"\n | \"targetFitness\"\n | \"timeLimitMs\"\n | \"maxWallMs\"\n | \"maxEvaluations\"\n | \"concurrency\"\n >\n> {\n const popSize = cfg.popSize ?? DEFAULT_POP_SIZE\n const elite = cfg.elite ?? DEFAULT_ELITE(popSize)\n const maxWallMs = cfg.maxWallMs ?? cfg.timeLimitMs ?? DEFAULT_MAX_WALL_MS\n const cxProb = cfg.cxProb ?? DEFAULT_CX_PROB\n // Ensure breeding operator simplex when caller omits mutProb\n const mutProb = cfg.mutProb ?? 1 - cxProb\n return {\n popSize,\n generations: cfg.generations ?? DEFAULT_GENERATIONS,\n elite,\n cxProb,\n mutProb,\n crossoverChildren: cfg.crossoverChildren ?? DEFAULT_CROSSOVER_CHILDREN,\n immigration: cfg.immigration ?? DEFAULT_IMMIGRATION,\n tournament: cfg.tournament ?? DEFAULT_TOURNAMENT,\n stall: cfg.stall ?? DEFAULT_STALL,\n targetFitness: cfg.targetFitness ?? DEFAULT_TARGET_FITNESS,\n timeLimitMs: maxWallMs,\n maxWallMs,\n maxEvaluations: cfg.maxEvaluations ?? DEFAULT_MAX_EVALUATIONS,\n concurrency: cfg.concurrency ?? DEFAULT_CONCURRENCY,\n }\n}\n","import type { GPConfig, GPMetrics } from \"../types\"\nimport { normalizeConfigBase } from \"./config\"\n\nexport interface CostModel {\n /** Estimated milliseconds per fitness evaluation (defaults to 0). */\n perEvaluationMs?: number\n /** Optional monetary cost per fitness evaluation (generic units). */\n perEvaluationCost?: number\n /** Fixed overhead per generation in milliseconds (loop bookkeeping). */\n perGenerationOverheadMs?: number\n /** One-time overhead per run in milliseconds (setup/teardown). */\n perRunOverheadMs?: number\n}\n\nexport interface RunEstimate {\n evaluations: {\n init: number\n perGen: number\n plannedTotal: number\n expectedTotal: number\n cappedByMaxEvaluations?: number\n }\n timeMs?: {\n init: number\n perGen: number\n plannedTotal: number\n expectedTotal: number\n cappedByMaxWall?: number\n }\n monetary?: {\n perEval: number\n plannedTotal: number\n expectedTotal: number\n }\n operations: {\n immigrantsPerGen: number\n childrenFromBreedingPerGen: number\n pairsPerGen: number\n selectionsPerGen: number\n expectedCrossoversPerGen: number\n expectedMutationsPerGen: number\n }\n notes: string[]\n}\n\n/**\n * Normalize GPConfig to mirror GPLite defaults without instantiating the engine.\n */\n// uses shared normalization from config.ts\n\n/**\n * Estimate planned and expected costs for a run given a config.\n * - Generic: uses counts of fitness evaluations + optional unit costs.\n * - Time and budget caps are applied to provide \"capped\" views.\n */\nexport function estimateRun<T>(\n cfg: GPConfig<T> = {},\n opts: {\n /** If provided, overrides `cfg.generations` for expected scenario. */\n expectedGenerations?: number\n /** Generic cost and time units. */\n units?: CostModel\n } = {},\n): RunEstimate {\n const c = normalizeConfigBase(cfg)\n const expectedGenerations = opts.expectedGenerations ?? c.generations\n const immigrantsPerGen = Math.floor(c.popSize * c.immigration)\n const childrenFromBreedingPerGen = Math.max(\n 0,\n c.popSize - c.elite - immigrantsPerGen,\n )\n const pairsPerGen = Math.ceil(childrenFromBreedingPerGen / 2)\n const selectionsPerGen = pairsPerGen * 2\n\n const init = c.popSize\n // Each full generation evaluates exactly popSize - elite new individuals\n const perGen = Math.max(0, c.popSize - c.elite)\n const plannedTotal = init + c.generations * perGen\n const expectedTotal = init + expectedGenerations * perGen\n const cappedByMaxEvaluations = Math.min(expectedTotal, c.maxEvaluations)\n\n const perEvalMs = opts.units?.perEvaluationMs ?? 0\n const perGenOverheadMs = opts.units?.perGenerationOverheadMs ?? 0\n const perRunOverheadMs = opts.units?.perRunOverheadMs ?? 0\n\n const timeInit = init * perEvalMs + perRunOverheadMs\n const timePerGen = perGen * perEvalMs + perGenOverheadMs\n const timePlannedTotal = timeInit + c.generations * timePerGen\n const timeExpectedTotal = timeInit + expectedGenerations * timePerGen\n const cappedByMaxWall = Math.min(timeExpectedTotal, c.maxWallMs)\n\n const perEvalCost = opts.units?.perEvaluationCost\n const monetary =\n perEvalCost !== undefined\n ? {\n perEval: perEvalCost,\n plannedTotal: plannedTotal * perEvalCost,\n expectedTotal: expectedTotal * perEvalCost,\n }\n : undefined\n\n return {\n evaluations: {\n init,\n perGen,\n plannedTotal,\n expectedTotal,\n cappedByMaxEvaluations: Number.isFinite(c.maxEvaluations)\n ? cappedByMaxEvaluations\n : undefined,\n },\n timeMs:\n perEvalMs || perGenOverheadMs || perRunOverheadMs\n ? {\n init: timeInit,\n perGen: timePerGen,\n plannedTotal: timePlannedTotal,\n expectedTotal: timeExpectedTotal,\n cappedByMaxWall: Number.isFinite(c.maxWallMs)\n ? cappedByMaxWall\n : undefined,\n }\n : undefined,\n monetary,\n operations: {\n immigrantsPerGen,\n childrenFromBreedingPerGen,\n pairsPerGen,\n selectionsPerGen,\n expectedCrossoversPerGen: pairsPerGen * c.cxProb,\n expectedMutationsPerGen: childrenFromBreedingPerGen * c.mutProb,\n },\n notes: [\n \"Estimates assume no early stop (target/stall/time/evaluations).\",\n \"Per-generation evaluations equal popSize - elite by construction.\",\n \"Crossovers are counted per parent-pair; mutations per child genome.\",\n ],\n }\n}\n\n/**\n * Compute realized cost from a completed run's metrics (post‑hoc).\n */\nexport function estimateFromMetrics(m: GPMetrics, units: CostModel = {}) {\n const evals = m.evaluations\n const timeMs = (units.perEvaluationMs ?? 0) * evals\n const cost =\n units.perEvaluationCost !== undefined\n ? units.perEvaluationCost * evals\n : undefined\n return {\n evaluations: evals,\n timeMs: units.perEvaluationMs !== undefined ? timeMs : undefined,\n monetary:\n cost !== undefined\n ? { total: cost, perEval: units.perEvaluationCost! }\n : undefined,\n }\n}\n","#!/usr/bin/env node\nimport { estimateRun, type CostModel } from \"./lib/estimate\"\nimport type { GPConfig } from \"./types\"\n\ntype ArgMap = Record<string, string | true>\n\nfunction parseArgs(argv: string[]): ArgMap {\n const out: ArgMap = {}\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i]\n if (a.startsWith(\"--\")) {\n const key = a.slice(2)\n const next = argv[i + 1]\n if (next && !next.startsWith(\"--\")) {\n out[key] = next\n i++\n } else {\n out[key] = true\n }\n }\n }\n return out\n}\n\nfunction num(v: unknown): number | undefined {\n if (v === undefined || v === true) return undefined\n const n = Number(v)\n return Number.isFinite(n) ? n : undefined\n}\n\nfunction showHelp() {\n const h = `gp-lite-estimate\n\nUsage:\n gp-lite-estimate [--config path.json] [flags]\n\nConfig flags (override JSON when present):\n --popSize N --generations N --elite N\n --cxProb F --mutProb F --immigration F\n --tournament N --stall N --targetFitness F\n --maxWallMs N --maxEvaluations N --expectedGenerations N\n\nUnits (generic):\n --perEvaluationMs F --perGenerationOverheadMs F\n --perRunOverheadMs F --perEvaluationCost F\n\nOutput:\n --json print machine-readable JSON\n --help show this help\n`\n console.log(h)\n}\n\nasync function main() {\n const argv = process.argv.slice(2)\n const args = parseArgs(argv)\n if (args.help) return showHelp()\n\n type AllowedCfgKey =\n | \"popSize\"\n | \"generations\"\n | \"elite\"\n | \"cxProb\"\n | \"mutProb\"\n | \"immigration\"\n | \"tournament\"\n | \"stall\"\n | \"targetFitness\"\n | \"maxWallMs\"\n | \"maxEvaluations\"\n let cfg: Partial<Pick<GPConfig<unknown>, AllowedCfgKey>> = {}\n type AllowedUnitKey =\n | \"perEvaluationMs\"\n | \"perGenerationOverheadMs\"\n | \"perRunOverheadMs\"\n | \"perEvaluationCost\"\n let units: Partial<Pick<CostModel, AllowedUnitKey>> = {}\n let expectedGenerations: number | undefined\n\n if (args.config && typeof args.config === \"string\") {\n try {\n const fs = await import(\"node:fs/promises\")\n const raw = await fs.readFile(args.config, \"utf8\")\n const json = JSON.parse(raw)\n cfg = json.config ?? json\n units = json.units ?? {}\n expectedGenerations = json.expectedGenerations ?? undefined\n } catch (e) {\n console.error(`Failed to read config: ${args.config}`, e)\n process.exit(2)\n }\n }\n\n // Apply flag overrides (numbers only when provided)\n const maybe = (k: AllowedCfgKey) => {\n const v = num(args[k])\n if (v !== undefined) cfg[k] = v as never\n }\n ;(\n [\n \"popSize\",\n \"generations\",\n \"elite\",\n \"cxProb\",\n \"mutProb\",\n \"immigration\",\n \"tournament\",\n \"stall\",\n \"targetFitness\",\n \"maxWallMs\",\n \"maxEvaluations\",\n ] as const\n ).forEach((k) => maybe(k))\n\n const maybeUnit = (k: AllowedUnitKey) => {\n const v = num(args[k])\n if (v !== undefined) units[k] = v as never\n }\n ;(\n [\n \"perEvaluationMs\",\n \"perGenerationOverheadMs\",\n \"perRunOverheadMs\",\n \"perEvaluationCost\",\n ] as const\n ).forEach((k) => maybeUnit(k))\n\n const eg = num(args.expectedGenerations)\n if (eg !== undefined) expectedGenerations = eg\n\n const est = estimateRun(cfg, { expectedGenerations, units })\n\n if (args.json) {\n console.log(JSON.stringify(est, null, 2))\n return\n }\n\n const lines: string[] = []\n lines.push(\"gp-lite estimate\")\n lines.push(\"\")\n lines.push(\"Evaluations:\")\n lines.push(\n ` init=${est.evaluations.init} perGen=${est.evaluations.perGen} planned=${est.evaluations.plannedTotal} expected=${est.evaluations.expectedTotal}`,\n )\n if (est.evaluations.cappedByMaxEvaluations !== undefined)\n lines.push(\n ` cappedByMaxEvaluations=${est.evaluations.cappedByMaxEvaluations}`,\n )\n if (est.timeMs) {\n lines.push(\"Time (ms):\")\n lines.push(\n ` init=${est.timeMs.init} perGen=${est.timeMs.perGen} planned=${est.timeMs.plannedTotal} expected=${est.timeMs.expectedTotal}`,\n )\n if (est.timeMs.cappedByMaxWall !== undefined)\n lines.push(` cappedByMaxWall=${est.timeMs.cappedByMaxWall}`)\n }\n if (est.monetary) {\n lines.push(\"Monetary:\")\n lines.push(\n ` perEval=${est.monetary.perEval} planned=${est.monetary.plannedTotal} expected=${est.monetary.expectedTotal}`,\n )\n }\n lines.push(\"Operations (per gen):\")\n lines.push(\n ` selections=${est.operations.selectionsPerGen} pairs=${est.operations.pairsPerGen} crossovers~= ${est.operations.expectedCrossoversPerGen.toFixed(2)} mutations~= ${est.operations.expectedMutationsPerGen.toFixed(2)}`,\n )\n if (est.notes.length) {\n lines.push(\"Notes:\")\n est.notes.forEach((n) => lines.push(` - ${n}`))\n }\n console.log(lines.join(\"\\n\"))\n}\n\nmain().catch((e) => {\n // For GP-specific errors, show clean message without stack trace\n if (\n e.name === \"ConfigError\" ||\n e.name === \"ProblemError\" ||\n e.name === \"EvolutionError\" ||\n e.name === \"UserFunctionError\"\n ) {\n console.error(`${e.name}: ${e.message}`)\n if (e.code) {\n console.error(` code: \"${e.code}\"`)\n }\n } else {\n // For unexpected errors, show full details\n console.error(e)\n }\n process.exit(1)\n})\n"]}