ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Penrose Edgeworth 合成器 UI 解析:Substance 程序变异合成引擎与版本演进全指南

Penrose Edgeworth 合成器 UI 解析:Substance 程序变异合成引擎与版本演进全指南 开发工具数据可视化【免费下载链接】penroseCreate beautiful diagrams just by typing notation in plain text.项目地址https://gitcode.com/gh_mirrors/pe/penrose点击查看免费下载本文以仓库中 packages/edgeworth/CHANGELOG.md 为骨架结合 packages/edgeworth/README.md 与penrose/edgeworth包的源码实现合成器、变异算子、搜索算法与 UI 组件系统讲解 Penrose 项目中的“问题作者problem author工具”——Edgeworth 的定位、核心工作流、底层变异合成原理以及从 v2.0.0 到 v3.3.0 的功能演进脉络。读完本文你将掌握 Edgeworth 的配置结构SynthesizerSetting、三类变异操作与八种更新子类型的实现细节、基于观测等价observational equivalence的去重与路径搜索策略并能在仓库源码中快速定位对应实现。一、Edgeworth 是什么面向问题作者的合成器 UIEdgeworth包名penrose/edgeworth早期版本名为penrose/synthesizer-ui见 CHANGELOG v2.1.1 中的“Version bump only for package penrose/synthesizer-ui”是 Penrose 仓库中的一个 Web 应用包。它本身不负责绘制图形而是为 Penrose 的“问题作者”提供一个交互界面用于基于一个文件三元组domain / substance / style运行合成器批量生成多个经过变异的 Substance 程序允许作者编辑默认的 substance、domain 和 style 程序提供可调设置生成多少个程序、每个程序做多少次变异、可以对哪些类型的语句做变异每个变异程序会展示其CIEE编译并优化后的能量信息、变异操作记录以及变异后的 substance 程序通过勾选将喜欢的图 staged暂存点击Export将选中的图以 SVG 形式打包下载。从 README.md 看官方将其定位为“first pass”——首版覆盖了核心功能并预留了扩展空间。该包当前依赖penrose/core编译器与优化器、penrose/componentsSimple渲染组件、Listing编辑器等、penrose/examples几何、分子、图论等领域示例详见 packages/edgeworth/package.json。运行与构建在packages/edgeworth目录下可执行脚本定义见 package.json命令作用yarn start或yarn dev/yarn watch以 Vite 启动开发服务器README 说明浏览器访问http://localhost:4000实际端口以当前 Vite 配置与终端输出为准yarn build使用cross-env NODE_OPTIONS--max-old-space-size8192 vite build构建生产版本到dist目录yarn preview本地预览生产构建产物yarn typecheck运行tsc类型检查yarn test运行vitest run --no-threads执行单元测试yarn coverage运行测试并生成覆盖率报告构建/测试目标通过 Nx 配置了依赖顺序dependsOn: [^build, ^build-decls]即先构建依赖包再构建本包。应用入口 src/App.tsx 使用react-router-dom的createHashRouter定义了/主界面、/chemistry、/geometry、/graphs、/problems五个路由对应 src/problems 下的领域问题集合。二、核心工作流从三文件到批量变异程序Edgeworth 的完整工作流可以概括为选择领域与预设在左侧设置抽屉中选择 DomainMolecules / Geometry / Directed Graphs / Undirected Graphs见 src/examples.ts 中的domains与presets。编辑输入场景通过Listingsubstance 语言编辑器修改模板 substance 程序。生成变异点击 “Generate Variations” 或 “More Variations”前端调用generateProgs。浏览与筛选右侧 Grid 逐格渲染变异后的图展示每个程序对应的 substance 与变异操作记录。标注与导出勾选 checkbox staged 候选图用开关标记正确/错误最后 Export 打包为 zip。生成流程的源码实现生成入口在 src/components/Content.tsx 的generateProgs用compileDomain(dsl)编译 domain 得到domEnv若提供了模板 substance用compileSubstance(sub, domEnv)编译得到subEnv构造new Synthesizer(domEnv, subEnv, setting, subEnv undefined ? undefined : [subEnv, domEnv], seed)调用synth.generateSubstances(numPrograms)生成多个程序将模板程序作为第 0 号header 显示 “Original diagram”变异结果依次为 “Mutated diagram #1/#2/…”见 src/components/Content.tsx 对Grid的header回调。Settings 侧栏src/components/Settings.tsx默认numPrograms: 9、seed: test0。“More Variations” 按钮通过generateVariation()生成随机种子格式为颜色名 动物名 3~5 位数字例如BlueFox123然后以新种子重新生成从而在同一领域配置下获得不同的随机变异结果——这是seedrandom种子化随机数在 UI 层的直接体现。三、变异合成引擎Synthesizer 的配置与执行原理合成器核心在 src/synthesis/Synthesizer.ts。它接收一个已编译的 Domain 环境、一个可选的模板 Substance 环境、一个SynthesizerSetting配置和一个随机种子通过seedrandom(seed)派生确定性随机数生成器choice、weightedChoice、random因此同一 seed 下生成的变异序列可复现。3.1 配置结构 SynthesizerSettingSynthesizerSetting定义于 Synthesizer.ts#L97-L115是理解整个引擎的钥匙export interface SynthesizerSetting { mutationCount: [number, number]; // 每个程序变异次数的区间 [min, max]含端点 argOption: ArgOption; // existing | generated | mixed argReuse: ArgReuse; // distinct | repeated weights: { type: number; predicate: number; constructor: number }; opWeights: { [t in MutationType]: number }; // add / delete / edit add: DeclTypes; // 允许 add 的语句类型匹配* 或名称数组 delete: DeclTypes; edit: DeclTypes; }各字段含义mutationCountgenerateSubstance中通过this.random(...this.setting.mutationCount)取整随机数决定当前程序执行的变异步数Synthesizer.ts#L485。argOption生成新语句参数时的取值策略。generateArg中Synthesizer.ts#L1039-L1111existing从ctx.declaredIDs中按类型含子类型subTypesOf挑选已存在的标识符找不到时才降级为generatedgenerated按类型声明generateDecl生成新标识符如类型Set生成s0、s1…前缀取类型首字母小写见generateIDmixed对每个参数随机在existing与generated之间选择。argReusedistinct时同一组参数中不允许重复使用同一 ID通过usedIDs排除repeated则允许重复。weights选择新增/编辑哪种 Domain 声明type / predicate / constructor的权重。opWeightsmutateProgram中先用weightedChoice按权重选出add/delete/edit三种变异大类之一Synthesizer.ts#L533-L541。add/delete/edit每种操作可匹配的语句类型白名单值可为*通配全部或具体名称数组。filterContext会据此裁剪环境中的类型、函数、谓词、构造器声明Synthesizer.ts#L165-L233并可选地按模板程序中实际出现的类型进一步过滤。src/examples.ts 中给出了三套有代表性的预设参数可直接对照// 分子Lewis 结构只做 edit不增删 const lewisParams: SynthesizerSetting { mutationCount: [1, 4], argOption: existing, argReuse: distinct, weights: { type: 0.15, predicate: 0.5, constructor: 0.35 }, opWeights: { add: 0, delete: 0, edit: 1 }, add: { type: *, function: *, constructor: *, predicate: * }, delete: { type: *, function: *, constructor: *, predicate: * }, edit: { type: *, function: *, constructor: *, predicate: * }, }; // 几何add0, delete0.2, edit0.8以编辑为主、偶发删除 const geometryParams { ...lewisParams, opWeights: { add: 0, delete: 0.2, edit: 0.8 } }; // 图论add0.5, delete0.4, edit0.1增删为主 const graphParams { ...lewisParams, opWeights: { add: 0.5, delete: 0.4, edit: 0.1 } };3.2 三类变异操作与八种更新子类型变异操作类型定义在 src/synthesis/Mutation.tsMutation Add | Delete | UpdateMutationType add | delete | editUpdate是八种具体更新操作的联合SwapStmtArgs、SwapExprArgs、SwapInStmtArgs、SwapInExprArgs、ReplaceStmtName、ReplaceExprName、ChangeStmtType、ChangeExprType。每种变异都实现了统一的MutationBase接口{ tag, additionalMutations?, mutate(op, prog, ctx) }mutate返回WithContextSubProgA新程序 新的合成上下文这是“语句级操作 上下文同步”的关键抽象。例如Add在追加Decl语句时会调用addID把新标识符登记进ctx.declaredIDsDelete在删除Decl时会调用removeID同步移除Mutation.ts#L238-L262保证后续变异的候选 ID 集合始终与当前程序一致。八种更新的语义对应showMutation的字符串输出Mutation.ts#L143-L171变异语义SwapStmtArgs交换谓词语句中两个类型匹配的参数位置如Subset(A, B)→Subset(B, A)SwapExprArgs交换 Bind 表达式中两个类型匹配的参数SwapInStmtArgs/SwapInExprArgs将语句/表达式中的某个 ID 换成同类型的其他已声明 IDReplaceStmtName/ReplaceExprName将谓词/表达式名替换为签名匹配的其他声明matchSignaturesChangeStmtType/ChangeExprType将语句/表达式整体替换为参数兼容的其他声明并携带additionalMutations删除旧语句、新增依赖语句必要时触发cascadingDelete级联清理引用cascadingDelete是删除语义的关键当删除一个被其他语句引用的Bind/Decl时会递归删除所有引用它的语句Synthesizer.test.ts 的cascading delete测试验证了这一点删除Set A会连带删除Set C : Subset(B, A)与Set E : Intersection(D, C)仅剩Set B与Set D。3.3 单步变异的选择与执行Synthesizer.mutateProgramSynthesizer.ts#L518-L575是单步变异的主流程分别用filterContext得到 add / delete / edit 各自可用的上下文调用enumerateAdd、enumerateDelete、enumerateUpdate枚举出三类候选变异组MutationGroup[]用weightedChoice按opWeights选出本次变异的大类对选中的变异组执行executeMutations把结果写入currentProg并追加到currentMutations记录若某类候选为空则递归重试直到找到可行变异。enumerateAddSynthesizer.ts#L740-L807从nonEmptyDecls中随机选一种声明类型Type / Predicate / Function / Constructor再按类型生成一组Add变异——例如生成一个函数调用时除了Bind语句本身还会包含为参数和返回值生成的Decl语句作为一个不可分割的变异组返回。enumerateDeleteSynthesizer.ts#L813-L841则对选中声明执行级联删除并收集Delete组。3.4 结果收尾去重与语句规整generateSubstanceSynthesizer.ts#L484-L513在完成mutationCount步变异后对最终程序执行const prog sortStmts(dedupStmts(this.currentProg)); // 排序 去重避免编译错误 return { prog, ops: this.currentMutations, src: prettySubstance(prog) };generateSubstancesSynthesizer.ts#L457-L482更进一步通过dedupSynthesizedSubstances保证批量结果互不重复若去重后不足numProgs个则继续生成补齐——这正是 CHANGELOG v3.0.0 中 “deduplication of mutated Substance programs inedgeworth(#1481)” 落地为代码的直接证据。四、变异路径搜索从 diff 到可执行变异序列除随机合成外Edgeworth 还实现了反向搜索能力给定源程序与目标程序找出“如何用一组变异把源变成目标”。这部分集中在 src/synthesis/Search.ts对应 CHANGELOG v2.0.0 的 “enumerative search of Substance mutations (#638)”。4.1 AST 细粒度 diffdiffSubProgsSearch.ts#L93-L106用recursive-diff计算两棵 Substance AST 的精确差异并过滤掉所有与元属性metaProps相关的噪声 diffdiffSubStmtsSearch.ts#L115-L124先sortStmts归一化语句顺序再求 diff使结果与语句书写顺序无关subProgDiffsSearch.ts#L217-L244基于公共语句集合 similarNodes相似度映射将差异分类为DiffSet { add, delete, update }其中UpdateDiff携带source → result语句对。Search.test.ts 的 “Compute AST diff based on tree sets” 测试展示了典型输出把D : Union(A, B)改成E : Union(A, B)会得到一条Updatediff变量名变化而Equal(E, E)的移除被识别为Delete。4.2 单路径与全路径搜索findMutationPathsSearch.ts#L442-L489把 add/delete 打包为固定变异对每个 update 语句枚举候选变异仅保留执行后与目标语句完全一致的变异再用cartesianProduct组合出所有合法变异组enumerateAllPathsSearch.ts#L491-L526不做匹配过滤枚举全部可能的组合enumerateMutationPathsSearch.ts#L544-L610按maxDepth做广度优先搜索逐层把每个候选程序的所有可行变异执行一遍并用观测等价observational equivalence剪枝——_.uniqBy(candidates, (c) prettySubstance(c.prog))保证“产生相同输出程序的候选路径只保留一条”从而显著压缩搜索空间。这正是 CHANGELOG 中“enumerative search observational equivalence”的工程实现。对应测试见 Search.test.ts例如 “recognizing swap mutation” 验证Subset(A, B)→Subset(B, A)能被识别为SwapStmtArgs “recognizing multiple mutations on multiple stmts” 验证Subset(A,B)C : Intersection(A, B)到Equal(B, A)Intersecting(A, B)的最短路径恰好包含SwapStmtArgs、ChangeExprType、ReplaceStmtName三个变异。五、UI 组件与导出管线5.1 网格展示 Gridsrc/components/Grid.tsx 实现自定义网格每个Gridbox通过penrose/components的Simple组件渲染一张可交互的 Penrose 图并提供右上角Resample按钮更换随机variation布局随机种子重新优化同一程序Checkbox勾选后进入 staged 列表正确/错误开关CustomSwitchstaged 后用绿/红开关标记答案点击图可切换查看元信息Substance 程序文本 变异操作记录。网格通过onStateUpdate回调收集每张图的PenroseState当所有格子都完成优化isOptimized全为 true时触发onComplete。CHANGELOG v4.0.0-alpha 系列中的 “simplified sharedGridand customGridin Edgeworth (#1729)” 即指对该组件体系的简化共享网格在penrose/components自定义网格在本包。5.2 导出管线一个 zip 打包全部产物Content.exportDiagramsContent.tsx#L233-L261用jszipfile-saver打包 staged 图生成diagrams.zip内含anwser.jsonstaged 图的索引与正确/错误标记domain.domain、style.style当前使用的领域与样式源码每个图三个文件${idx}.svg由toSVG(state, resolver, diagram)生成、${idx}.substanceprettySubstance(prog)格式化、mutations_${idx}.txtshowMutations(ops)的人类可读变异记录。这意味着导出的 zip完整保留了问题作者出题所需的一切证据图形、程序文本与变异操作轨迹可直接用于生成多项选择题。5.3 多选题模式Content.problemContent.tsx#L263-L332把 staged 的“正确/错误”图组合成MultipleChoiceProblem来自penrose/components打乱选项后以全屏遮罩展示。顶部 “Show Problem” 按钮控制显隐prompt来自各预设见 examples.ts 中如In which of the following diagrams are points $B$, $D$, $E$ collinear?的题目文案。这一整套“生成→筛选→标注→组卷”流程正是 Edgeworth 作为问题作者工具的核心价值。六、版本演进解读CHANGELOG 对照源码CHANGELOG.md 记录了从 v2.0.02023-01到 v3.3.02025-09的完整演进。按时间线梳理如下v2.x从浏览器原型到成熟 UI2023-01 ~ 2023-03v2.0.0新增 synthesizer 浏览器#640、Substance 变异的枚举式搜索#638即 Search.ts 的前身、synthesizer-ui的预设加载#1133对应今天的 examples.tspresets、在Simple组件中显示错误#953、docusaurus 站点#771、统一 browser-ui 与 editor#1000。v2.2.0改进 registry schema 与加载#1212、支持更长文件扩展名#1280。v2.3.0editor 中网格展示多图实例#1287对应 Grid.tsx、修复 renderer 非确定性#1316呼应variation随机种子机制向 synthesizer-ui 补充 Lewis 结构示例#1334、图论示例#1336、扩展预设#1149。v3.0.0工程化整顿2023-07-14这是一次破坏性版本四个 BREAKING CHANGE 全部是仓库级重构Edgeworth 随之适配清理core导出与 synthesizer 模块#1367——从本包源码可见大量penrose/core/dist/...的深层导入合并automator与roger#1387更可读的core语言 API#1527每个 trio 独立 JSON 文件#1393——即packages/examples/src下大量*.trio.json的组织方式新增Edgeworth 中变异 Substance 程序的去重#1481即dedupSynthesizedSubstances内部TypeScript 升至 5.0#1395、抽出公共tsconfig.json#1392、从 jest 切换到 vitest#1406——当前 package.json 中test: vitest run --no-threads即此变更的延续。v3.1.0 / v3.2.0能力补全2023-07 ~ 2023-08v3.1.0在 edgeworth 中加入 LLM 程序生成 UI#1556。值得说明该项记录在 CHANGELOG 中属官方版本事实当前仓库源码中并未保留独立的 LLM 入口组件ContentState.prompt目前服务于多选题题干。v3.2.0Substance indexed sets#1572是 core 语言层新增能力为后续合成更丰富的程序提供类型系统支持。4.0.0-alpha 系列与 v3.3.02024-2025 的平行重构2024-05 ~ 2025-09CHANGELOG 在 v3.2.0 与 v3.3.0 之间插入了v4.0.0-alpha.0到v4.0.0-alpha.5六个预发布版本2024-05-07 至 2024-10-28随后在 2025-09-23 发布v3.3.0将 alpha 系列成果收敛回主线。核心变更包括BREAKING CHANGE分离 Substance environment 并移除未用功能#1677。对应源码中SubstanceEnv与DomainEnv的严格分离——initSubstanceEnv()、subEnv.objIds、subEnv.objs、subEnv.ast等字段在 Synthesizer.ts 中全面使用SynthesisContext同时携带subEnv与domEnv两个环境。新功能CodeMirror 迁移#1798editor 包从旧版 CodeMirror 迁移、未知变量的初始值#1638core 引擎可为未被约束赋值的变量提供初始值、Substance 字面量值#1682Substance 程序可直接书写字面量。Bug 修复edgeworth 的 UI 问题#1706。Polish简化共享Grid与 Edgeworth 自定义Grid#1729。内部将IsSubset、NotIntersecting改名简化#1724、简化 edgeworth 实现#1708、多轮版本号 bump。值得注意的是 v3.3.0 同时把 “4.0.0-alpha.4 (#1865)” 列为新功能说明 alpha.4 的产物被整体合入主线——这是该仓库“预发布分支 主线收敛”版本策略的直接体现。当前仓库packages/edgeworth/package.json版本号正是3.3.0与 CHANGELOG 顶部一致二者互相印证。七、测试体系如何验证合成器的正确性Edgeworth 的合成逻辑由两套 vitest 测试守护src/synthesis/Synthesizer.test.ts验证cascadingDelete的级联删除行为——删除Set A后依赖它的Set C : Subset(B, A)与Set E : Intersection(D, C)一并被删最终只剩Set B、Set D同时演示了initContext、executeMutations、removeStmtCtx的典型用法。src/synthesis/Search.test.ts覆盖 AST diff含语句顺序无关性、变异识别swap / replace / change-type、带噪声的路径搜索add delete update 混合路径、以及enumerateMutationPaths的观测等价剪枝两步路径唯一性。测试中使用seedrandom固定随机源、prettySubstance(sortStmts(...))作为语义等价性判据与生产代码的判定方式完全一致——测试即规范。八、结语与深入方向通过 CHANGELOG 与源码的对照可以清晰看到Edgeworth 不是简单的“图生成器”而是一套以随机化、可复现的 Substance 程序变异为核心、以观测等价剪枝为优化手段、以导出/组卷为出口的问题作者工具链。它的工程要点可归纳为可复现性一切随机决策由seedrandom(seed)驱动上下文一致性变异执行与SynthesisContext已声明 ID、生成名、环境同步更新结果质量sortStmtsdedupStmtsdedupSynthesizedSubstances三重规整保证产物可编译、不重复可解释性每次变异都留有人类可读的showMutations记录并随图导出。如需继续深入建议按以下路径阅读仓库源码合成主流程packages/edgeworth/src/synthesis/Synthesizer.ts变异算子全集packages/edgeworth/src/synthesis/Mutation.ts路径搜索与 diffpackages/edgeworth/src/synthesis/Search.tsUI 工作流packages/edgeworth/src/components/Content.tsx、packages/edgeworth/src/components/Settings.tsx、packages/edgeworth/src/components/Grid.tsx领域预设packages/edgeworth/src/examples.ts底层编译器/优化器packages/core/srccompileDomain、compileSubstance、toSVG等 API 均来自penrose/core赞分享开发工具数据可视化【免费下载链接】penroseCreate beautiful diagrams just by typing notation in plain text.项目地址https://gitcode.com/gh_mirrors/pe/penrose点击查看免费下载相关推荐Penrose Substance 程序合成器Synthesizer源码深度解析从 SynthesizerSettings 配置到 AST 变异引擎Penrose Substance 程序合成器Synthesizer源码深度解析从 SynthesizerSettings 配置到 AST 变异引擎 本文开发工具数据可视化fairseq S2T 实战在 MuST-C 上完成端到端语音翻译ST与语音识别ASR全流程fairseq S2T 实战在 MuST C 上完成端到端语音翻译ST与语音识别ASR全流程 导读 本文基于仓库 decoding/IAD/fairs开发工具数据可视化RapidOCR多推理引擎版本合并的技术演进RapidOCR多推理引擎版本合并的技术演进 在OCR技术领域RapidOCR作为一款优秀的开源OCR工具其发展历程中曾存在多个基于不同推理引擎的版本分支。人工智能计算机视觉OCR上一篇Minecraft 1.21终极指南如何轻松安装MASA模组全家桶中文汉化包下一篇终极开源字体解决方案Barlow 54款现代无衬线字体的深度应用指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表