同形不同意图实验源码
研究总览 · 2026-09-20
附录 F:表示和修改语义的隔离实验。
附录 F:同形不同意图的表示再求值实验
Section titled “附录 F:同形不同意图的表示再求值实验”对应 §17.7。将下列完整源码保存为 TEMP 中的 aira-intent-representation-probe-20260920.mjs,使用 Node 运行。当前源文件 SHA-256 为 e6ce700fa8b6078776b736ce7d38aa427492813c010b406c8fcf8a7fc96d3f45。工作区路径按本机调整;HiGHS 使用附录 C 的同一隔离构件,不添加产品依赖。
实际环境为 Node 24.19.0、Windows x64、i7-13700F,HiGHS 报告核心 1.15.1 / 04024d7。OCCT WASM SHA-256 为 218e80a3fb69d62de4b44b613f64c0d99f3f8d2ad5cb5ce3aeea568805fcdcfa;HiGHS JS SHA-256 为 0bd23843c9795753f2276e9901eb2a1e66288547b6bcba84fa0665dc037b5c7c。脚本将完整输入、各候选结果、B-Rep 检查、状态及构件哈希写到 TEMP 的同名 JSON。summary.variables 仅指显式 LP 变量数,correct-reject 不代表已完成产品回滚或不可行证书核验;不可行单元没有构造几何。
这是有限构造域的隔离机制探针,不是产品执行器或 test/spec 套件。所有配方由研究者编写并携带相同政策逐输入再求值;没有模型持久化、真实编辑链和 AI 试用。诊断时长包含各自实际调用成本,但单格一次,不能用于方案性能排名。
import fs from 'node:fs';import os from 'node:os';import crypto from 'node:crypto';import { createRequire } from 'node:module';import { pathToFileURL } from 'node:url';const require = createRequire(import.meta.url);const root = '<workspace-root>';const runtime = root + '/packages/aira-geometry-kernel/runtime/feature-graph/aira_occt_feature_graph';const highPath = os.tmpdir() + '/aira-highs-standalone-research-20260920/highs.js';const hash = x => crypto.createHash('sha256').update(x).digest('hex');const t0 = performance.now();const { default: init } = await import(pathToFileURL(runtime + '.js'));const wasmBinary = fs.readFileSync(runtime + '.wasm');const oc = await init({ wasmBinary });const occtLoaded = performance.now();const high = await require(highPath)();const loaded = performance.now();const eps = 1e-7;const constants = { height: 30, thickness: 4, radius: 3, n: 4, edge: 7, web: 3, pitch: 20 };
// Feature recipes retain seed/pitch expressions, not just sampled coordinates.const featureRecipes = { edge: { origin: p => p.radius + p.edge, pitch: p => (p.width - 2 * (p.radius + p.edge)) / (p.n - 1) }, pitch: { origin: p => (p.width - (p.n - 1) * p.pitch) / 2, pitch: p => p.pitch },};function feature(p, intent) { const recipe = featureRecipes[intent], start = recipe.origin(p), step = recipe.pitch(p); return { x: Array.from({ length: p.n }, (_, i) => start + i * step) };}function program(p, intent) { const x = []; for (let i = 0; i < p.n; i++) x.push(intent === 'edge' ? p.radius + p.edge + i * (p.width - 2 * (p.radius + p.edge)) / (p.n - 1) : p.width / 2 + (i - (p.n - 1) / 2) * p.pitch); return { x };}function lp(n, rows) { const columns = Array.from({ length: n }, () => []); rows.forEach((r, i) => r.a.forEach(([j, a]) => columns[j].push([i, a]))); const starts = [], indices = [], values = []; for (const col of columns) { starts.push(indices.length); for (const [i, a] of col) { indices.push(i); values.push(a); } } starts.push(indices.length); const model = high.createModel({ numCols: n, numRows: rows.length, colCost: Array(n).fill(0), colLower: Array(n).fill(-high.infinity), colUpper: Array(n).fill(high.infinity), rowLower: rows.map(r => r.lo ?? -high.infinity), rowUpper: rows.map(r => r.hi ?? high.infinity), matrix: { format: 'csc', numRows: rows.length, numCols: n, starts, indices, values } }); try { model.options.set({ output_flag: false, solver: 'simplex' }); const status = model.run().modelStatus; if (status === 7) return { values: Array.from(model.getSolution().colValue), status, variables: n, constraints: rows.length }; return { status, variables: n, constraints: rows.length }; } finally { model.dispose(); }}function relation(p, intent) { const rows = [], last = p.n - 1, eq = (a, b) => rows.push({ a, lo: b, hi: b }); for (let i = 0; i < p.n; i++) rows.push({ a: [[i, 1]], lo: p.radius + p.edge, hi: p.width - p.radius - p.edge }); for (let i = 0; i < last; i++) rows.push({ a: [[i + 1, 1], [i, -1]], lo: 2 * p.radius + p.web }); if (intent === 'edge') { eq([[0, 1]], p.radius + p.edge); eq([[last, 1]], p.width - p.radius - p.edge); for (let i = 1; i < last; i++) eq([[i - 1, 1], [i, -2], [i + 1, 1]], 0); } else { for (let i = 0; i < last; i++) eq([[i + 1, 1], [i, -1]], p.pitch); eq([[0, 1], [last, 1]], p.width); } const r = lp(p.n, rows); return { ...r, x: r.values };}function hybrid(p, intent) { // Solve seed s and pitch q, then use the same procedural pattern x_i=s+i*q. const rows = [{ a: [[0, 1]], lo: p.radius + p.edge }, { a: [[0, 1], [1, p.n - 1]], hi: p.width - p.radius - p.edge }, { a: [[1, 1]], lo: 2 * p.radius + p.web }]; const eq = (a, b) => rows.push({ a, lo: b, hi: b }); if (intent === 'edge') { eq([[0, 1]], p.radius + p.edge); eq([[0, 1], [1, p.n - 1]], p.width - p.radius - p.edge); } else { eq([[1, 1]], p.pitch); eq([[0, 2], [1, p.n - 1]], p.width); } const r = lp(2, rows); return { ...r, x: r.values && Array.from({ length: p.n }, (_, i) => r.values[0] + i * r.values[1]) };}function requirements(p, intent, xs) { if (!xs || xs.length !== p.n || xs.some(x => !Number.isFinite(x))) return { pass: false, reason: 'missing-or-invalid-centres' }; const x = [...xs].sort((a, b) => a - b), gaps = x.slice(1).map((v, i) => v - x[i]); const margins = [x[0] - p.radius, p.width - x.at(-1) - p.radius]; const equalPitch = Math.max(...gaps) - Math.min(...gaps) <= eps; const inDomain = Math.min(...margins) >= p.edge - eps && Math.min(...gaps) >= 2 * p.radius + p.web - eps; const intentOK = intent === 'edge' ? margins.every(m => Math.abs(m - p.edge) <= eps) : gaps.every(g => Math.abs(g - p.pitch) <= eps) && Math.abs(x[0] + x.at(-1) - p.width) <= eps; return { pass: equalPitch && inDomain && intentOK, equalPitch, inDomain, intentOK, margins, gaps };}function scope(fn) { const held = [], take = x => (held.push(x), x); try { return fn(take); } finally { for (const x of held.reverse()) x.delete(); }}function build(p, xs) { return scope(h => { const point = (x, y, z) => h(new oc.gp_Pnt(x, y, z)); const polygon = h(new oc.BRepBuilderAPI_MakePolygon()); for (const [x, y] of [[0, 0], [p.width, 0], [p.width, p.height], [0, p.height]]) polygon.Add(point(x, y, 0)); polygon.Close(); const face = h(new oc.BRepBuilderAPI_MakeFace(h(polygon.Wire()), false)); for (const x of xs) { const axis = h(new oc.gp_Ax2(point(x, p.height / 2, 0), h(new oc.gp_Dir(0, 0, 1)))); const circle = h(new oc.gp_Circ(axis, p.radius)); const edge = h(new oc.BRepBuilderAPI_MakeEdge(circle)); const wireMaker = h(new oc.BRepBuilderAPI_MakeWire(h(edge.Edge()))); const wire = h(wireMaker.Wire()); wire.Reverse(); face.Add(wire); } if (!face.IsDone()) throw Error('face construction failed'); const prism = h(new oc.BRepPrimAPI_MakePrism(h(face.Face()), h(new oc.gp_Vec(0, 0, p.thickness)), false, true)); if (!prism.IsDone()) throw Error('prism construction failed'); return prism.Shape(); });}function inspect(shape, p, intent) { return scope(h => { const analyzer = h(new oc.BRepCheck_Analyzer(shape, true, false, true)); const props = h(new oc.GProp_GProps()); oc.BRepGProp.VolumeProperties(shape, props, true, false, false); const bounds = h(new oc.Bnd_Box()); oc.BRepBndLib.AddOptimal(shape, bounds, false, false); const collect = type => { const e = h(new oc.TopExp_Explorer(shape, type, oc.TopAbs_ShapeEnum.TopAbs_SHAPE)), items = []; while (e.More()) { const item = h(e.Current()); if (!items.some(x => x.IsSame(item))) items.push(item); e.Next(); } return items; }; const solids = collect(oc.TopAbs_ShapeEnum.TopAbs_SOLID).length, cylinders = []; for (const item of collect(oc.TopAbs_ShapeEnum.TopAbs_FACE)) { const a = h(new oc.BRepAdaptor_Surface(h(oc.TopoDS.Face(item)), true)); if (a.GetType() !== oc.GeomAbs_SurfaceType.GeomAbs_Cylinder) continue; const cyl = h(a.Cylinder()), loc = h(cyl.Location()), axis = h(cyl.Axis()), dir = h(axis.Direction()); cylinders.push({ x: loc.X(), y: loc.Y(), radius: cyl.Radius(), axisZ: dir.Z(), u: a.LastUParameter() - a.FirstUParameter(), v: a.LastVParameter() - a.FirstVParameter() }); } cylinders.sort((a, b) => a.x - b.x); const boundsVector = [bounds.GetXMin(), bounds.GetYMin(), bounds.GetZMin(), bounds.GetXMax(), bounds.GetYMax(), bounds.GetZMax()]; const expectedBounds = [0, 0, 0, p.width, p.height, p.thickness]; const volume = props.Mass(), expectedVolume = (p.width * p.height - p.n * Math.PI * p.radius ** 2) * p.thickness; const geometry = analyzer.IsValid() && solids === 1 && Math.abs(volume - expectedVolume) < eps && boundsVector.every((x, i) => Math.abs(x - expectedBounds[i]) < eps) && cylinders.length === p.n && cylinders.every(c => Math.abs(c.radius - p.radius) < eps && Math.abs(c.y - p.height / 2) < eps && Math.abs(Math.abs(c.axisZ) - 1) < eps && Math.abs(c.u - 2 * Math.PI) < eps && Math.abs(c.v - p.thickness) < eps); return { geometry, intent: requirements(p, intent, cylinders.map(c => c.x)), cylinders, volume, expectedVolume, boundsVector, solids }; });}const methods = { feature, program, relation, hybrid }, rows = [];const inputs = ['edge', 'pitch'].flatMap(intent => [80, 100, 60, 47, 46].map(width => ({ intent, width })));for (const input of inputs) { const p = { ...constants, width: input.width }; const necessaryWidth = input.intent === 'edge' ? 2 * (p.edge + p.radius) + (p.n - 1) * (2 * p.radius + p.web) : 2 * (p.edge + p.radius) + (p.n - 1) * p.pitch; const expectedFeasible = p.width >= necessaryWidth; for (const [method, predict] of Object.entries(methods)) { const start = performance.now(), result = predict(p, input.intent), predicted = performance.now(); const checked = requirements(p, input.intent, result.x); let measured; if (checked.pass) { const shape = build(p, result.x); try { measured = inspect(shape, p, input.intent); } finally { shape.delete(); } } const observedFeasible = Boolean(measured?.geometry && measured.intent.pass); const outcome = expectedFeasible ? observedFeasible ? 'pass' : 'fail' : !checked.pass && (method === 'feature' || method === 'program' || result.status === 8) ? 'correct-reject' : 'fail'; rows.push({ ...input, method, expectedFeasible, necessaryWidth, outcome, result, checked, measured, predictionMs: predicted - start, totalMs: performance.now() - start }); }}// Negative control: geometry only, identical stored initial coordinates for both intents.const negative = ['edge', 'pitch'].map(intent => { const p = { ...constants, width: 100 }, x = [10, 30, 50, 70], shape = build(p, x); try { return { intent, x, measured: inspect(shape, p, intent) }; } finally { shape.delete(); }});const summary = Object.fromEntries(Object.keys(methods).map(method => { const r = rows.filter(x => x.method === method); return [method, { pass: r.filter(x => x.outcome === 'pass').length, correctReject: r.filter(x => x.outcome === 'correct-reject').length, fail: r.filter(x => x.outcome === 'fail').length, variables: method === 'relation' ? 4 : method === 'hybrid' ? 2 : 0 }];}));const report = { kind: 'isolated-intent-representation-mechanism-probe', timestamp: new Date().toISOString(), node: process.version, platform: process.platform, cpu: os.cpus()[0].model, constants, tolerance: eps, environment: { root, runtime, highPath, highVersion: high.version, wasmSha256: hash(wasmBinary), occtJsSha256: hash(fs.readFileSync(runtime + '.js')), highJsSha256: hash(fs.readFileSync(highPath)), scriptSha256: hash(fs.readFileSync(new URL(import.meta.url))), initializationMs: { occt: occtLoaded - t0, highs: loaded - occtLoaded } }, protocol: 'Author-written recipes; fixed 10 inputs per candidate, no independent holdout; prediction time includes construction of LP and disposal; common OCCT geometry and independent requirement checks; no AI authoring or native product transactions; timings diagnostic only, one sample per cell; not an AI success-rate or performance benchmark.', summary, rows, negative };const output = os.tmpdir() + '/aira-intent-representation-probe-20260920.json';fs.writeFileSync(output, JSON.stringify(report, null, 2));console.log(JSON.stringify({ output, summary, negative: negative.map(r => ({ intent: r.intent, geometry: r.measured.geometry, intentPass: r.measured.intent.pass })), at100: rows.filter(r => r.width === 100).map(r => ({ method: r.method, intent: r.intent, x: r.result.x, outcome: r.outcome })) }, null, 2));if (rows.some(r => r.outcome === 'fail') || negative.some(r => !r.measured.geometry || r.measured.intent.pass)) process.exitCode = 1;