MarkovJunior是一种概率性编程语言,程序是重写规则的组合,推理通过约束传播执行。MarkovJunior以数学家Andrey Andreyevich Markov命名,他定义并研究了现在被称为马尔可夫算法的内容。
<p align="center"> <img src="https://yellow-cdn.veclightyear.com/ab5030c0/c7b02639-30de-4e97-9669-1b7a279018af.gif"/> <img src="https://yellow-cdn.veclightyear.com/ab5030c0/ab1d6cae-abbb-4cbf-bfd4-f1c7dec70af7.gif"/> </p>在基本形式中,一个MarkovJunior程序是一个有序的重写规则列表。例如,MazeBacktracker(左下动画)是一个包含2条重写规则的列表:
RBB=GGR
或"用绿绿红替换红黑黑"。RGG=WWR
或"用白白红替换红绿绿"。在每个执行步骤中,MJ解释器都会找到列表中第一个在网格上有匹配的规则,找到该规则的所有匹配项并随机应用该规则。在迷宫回溯示例中,解释器首先应用一系列 RBB=GGR
规则。但最终绿色自避免行走会陷入困境。此时第一个规则没有匹配,所以解释器应用第二个规则RGG=WWR
直到行走摆脱困境。然后它可以再次应用第一个规则,依此类推。当没有任何规则有匹配时,解释器停止。
MarkovJunior中的概率推理允许对未来状态施加约束,并仅生成满足约束的 运行。例如,在Sokoban规则{RWB=BRW RB=BR}
的推理中,一组(红色)智能体会将(白色)箱子组织成指定的形状。
利用这些思想,我们构建了许多概率生成器,生成地牢、建筑、谜题和有趣的模拟。
<p align="center"><a href="images/top-1764.png"/><img src="https://yellow-cdn.veclightyear.com/ab5030c0/82635135-a0a5-42e3-b815-54748410b84c.png"/></a></p>附加资料:
在字母表 A 上的马尔可夫算法是一个有序的规则列表。每条规则都是 x=y 的形式,其中 x 和 y 是 A 中的词,某些规则可能被标记为终止规则。将马尔可夫算法应用于单词 w 的过程如下:
例如,考虑此字母表 {0, 1, x} 上的马尔可夫算法(ε 是空词):
1=0x
x0=0xx
0=ε
如果我们将其应用于字符串 110,我们会得到以下字符串序列:
110 -> 0x10 -> 0x0x0 -> 00xxx0 -> 00xx0xx -> 00x0xxxx -> 000xxxxxx -> 00xxxxxx -> 0xxxxxx -> xxxxxx
总的来说,该算法将数字的二进制表示转换为其单元表示。
马尔可夫的学生Vilnis Detlovs证明对于任何图灵机,都存在一个马尔可夫算法计算相同的函数。相比之下,语法是无序的重写规则集,L-系统是并行应用的重写规则。要了解更多有趣的马尔可夫算法示例,请查看马尔可夫的著作或在评论区中看到最大公约数示例,或参见维基百科上的乘法示例。
如何将马尔可夫算法推广到多维?首先,在多维中没有自然的方法将一个字符串插入到另一个字符串中,所以我们的重写规则的左右应该具有相同的大小。其次,没有自然的方法选择"最左边的"匹配。可能的选项有:
我们失去了图灵完备性,因为我们的新过程不是确定性的,但实践表明,这种形式仍然允许描述大范围有趣的随机过程。
最简单的MarkovJunior程序可能是(B=W)
。它包含一条单一规则B=W
。在每一次执行中,该程序将一个随机的黑色方块转换为白色方块。
Growth模型(WB=WW)
更有趣。在每一次执行中,它将相邻的黑白单元格对BW
替换为白白单元格对WW
。换句话说,在每一次执行中,它选择一个随机的黑色单元格,如果它相邻到一个白色单元格,就将其涂成白色。这个模型几乎与Eden生长模型相同:在每一次执行中,两个模型都选择相同集合中的黑色单元格。它们唯一的区别在于概率分布:一个是在相邻的黑白单元格对上的均匀分布,另一个是在黑色单元格上的均匀分布。
模型(WBB=WAW)
以一行代码生成一个迷宫!将其与传统语言中的实现进行比较。任何MarkovJunior模型都可以在任意数量的维度上运行而不需要任何更改。在右侧,您可以看到MazeGrowth在3D中的最终结果,使用MagicaVoxel渲染。默认情况下,我们使用PICO-8调色板:
我们可以把多条规则放在一个规则节点中。例如,(RBB=WWR RBW=GWP PWG=PBU UWW=BBU UWP=BBR)
就是一种删除环路的随机行走。轨迹模型(RB=WR RW=WR)
会生成不错的连通洞穴。
模型(RBB=WWR R*W=W*R)
被称为Aldous-Broder迷宫生成算法。输入中的通配符符号*
表示该方格可以是任意颜色。输出中的通配符表示该颜色在规则应用后不会改变。Aldous-Broder算法平均需要更多步骤来生成迷宫,但它有一个MazeGrowth没有的好特性:每个迷宫都有相同的概率被生成。换句话说,MazeTrail是一种无偏的迷宫生成算法,或者说它以均匀分布采样迷宫(或生成树)。Wilson算法是一种更高效的无偏迷宫生成算法。将其MarkovJunior实现[(models/Wilson.xml)]与常规语言的实现进行比较吧!
我们可以把多个规则节点放在一个序列节点中,依次运行。在River模型中,我们首先构建一个随机Voronoi图,有2个源点,并将形成区域的边界作为河流的基础。然后我们生成一些额外的Voronoi种子来生长森林,同时从河流生长草地。最终我们得到了随机的河谷!
<p align="center"> <a href="models/River.xml"><img src="https://yellow-cdn.veclightyear.com/ab5030c0/17453bc3-f85d-46c5-a237-516448194385.gif"/></a> <a href="models/Apartemazements.xml"><img src="https://yellow-cdn.veclightyear.com/ab5030c0/a00448ec-2314-4eb8-9e5c-124841ed4238.gif"/></a> </p>在Apartemazements中,我们从一个WFC节点开始,然后用规则节点进行构造性后处理:
结合节点的更有趣方式是将它们放入一个马尔可夫节点。马尔可夫节点大大扩展了我们的能力,因为它们允许返回到过去的节点。当一个马尔可夫节点处于活跃状态时,解释器会找到它的第一个匹配的子节点并应用它。在下一轮中,它会再次在列表中找到第一个匹配的节点,依此类推。马尔可夫节点 使用的最简单例子是MazeBacktracker,在前面部分已经解释过了。
<p align="center"> <a href="models/NystromDungeon.xml"><img src="https://yellow-cdn.veclightyear.com/ab5030c0/824a11dc-2d64-44ba-ad67-1fee2b9298ab.gif"/></a> <a href="models/Flowers.xml"><img src="https://yellow-cdn.veclightyear.com/ab5030c0/7bc76da8-08c2-4338-bd6b-be0f9c25c43a.gif"/></a> </p>我最喜欢的例子之一,也是促使开发MarkovJunior的一个例子,是Bob Nystrom的地牢生成算法。它的步骤如下:
{PBB=**P}
.(room.png)
.({GWW=**G}(GBW=*WG))
.(GBG=*W* #5)
,使最终的地牢有循环。没有循环的地牢很无聊,因为玩家必须通过已经探索的区域返回。{BBB/BWB=BBB/BBB}
.与REFAL一样,马尔可夫节点也可以嵌套:一旦进入子节点,我们就会忽略外部节点,直到子分支完成。
MarkovJunior中的概率推理允许我们对未 来状态施加约束,并只生成满足约束的运行。换句话说,推理将两个给定状态(或部分观察状态)用一系列重写规则连接起来。
使用推理的最简单例子是用路径连接两个点。在自回避行走模型(RBB=WWR)
中,我们可以观察网格上的某个方格变为红色R
。然后解释器只会生成导致该方格的行走。我们可以通过调节温度参数来更严格或更宽松地遵循目标。默认情况下,温度设置为0。
我们还可以观察所有奇数格子变为白色或红色。然后解释器会生成覆盖整个网格的自回避行走。
<p align="center"> <a href="models/CompleteSAW.xml"><img src="https://yellow-cdn.veclightyear.com/ab5030c0/a0156789-4b67-4eea-88ff-7501214365f1.gif"/></a> <a href="models/SokobanLevel1.xml"><img src="https://yellow-cdn.veclightyear.com/ab5030c0/a26a864c-52af-450b-9649-13b09909a831.gif"/></a> </p>我们可以对任何重写规则进行推理。例如,对绘制楼梯规则进行推理可以连接两点并生成楼梯路径。对规则R**/**B=B**/**R
进行推理会生成国际象棋马可以走的路径。在CrossCountry模型中的推理连接两点并考虑地形成本。对Sokoban规则集{RB=BR RWB=BRW}
进行推理可以解决Sokoban谜题,甚至多智能体Sokoban谜题!
如果约束传播完成,这并不一定意味着目标状态是可实现的。但如果传播失败,我们就知道目标肯定是不可实现的。这使我们能够捕捉到在 Sokoban 中推箱子到错误的墙壁上,或者网格遍历路径将网格分成两个不连通部分的情况。除了这个布尔启发式外,我们也需要关注约束传播完成所需的最小步数。这个基于整数值的启发式是可接受的,我们在 A* 搜索中使用它来采样两个给定状态之间的重写规则路径。
过程生成的程序合成。William Chyr 的演讲"Level Design in Impossible Geometry"并不是关于过程生成的,但我发现一张幻灯片非常能代表 pcg 实践。William 比较了他之前和后来的关卡设计方法。前者产生了混乱的关卡,而后者基于一个核心思想产生了更有结构、更有目的性的关卡。后来的关卡并不比之前简单,但更有记忆性,对玩家也更易感知。在我看来,左边的关卡就像是用过程生成的!它和我的过程体素拼图有着非常相似的感觉。我们能否制造出生成像右边那样关卡的生成器?这个问题似乎 AI 完备。但我认为它和经典的遗传编程问题,如 Koza 的割草机问题非常相似。例如,考虑一个简单的过程生成任务,就是在网格上生成 Hamiltonian 路径。即使对于像 29x29 这样小的网格尺寸,这个任务也是计算密集型的。但是,我们真的需要从所有可能的路径中采样吗?如果我们把这个任务交给一个人,他们可能会画一个螺旋形或者之字形曲线 - 这些设计比随机的 Hamiltonian 路径更有记忆性和目的性,而且可以推广到任意网格尺寸。总之,我们可以要求系统要么找到一条随机的 Hamiltonian 路径,要么找到一个生成 Hamiltonian 路径的短程序。在第一种情况下,结果会像幻灯片左边的关卡,在第二种情况下会像右边的关卡。解决后一个程序合成问题将创造出更有记忆性和目的性的生成器。
从样本合成模型。Markov 算法似乎是进行程序/模型合成的完美环境:没有变量、if 或 while,节点可以轻松移动而不破坏正确性,模型也很容易微分。随机 MJ 程序常常很有趣,能产生人性化的结果和行为。
在波动空间运行的自定义算法。结合构造式和约束式过程生成的优点。相关:带有 Ising 能量或 ConvChain 能量等自定义能量函数的自定义算法(MJ 重写规则)。
概括模式的概念。
研究在其他(可能是非正则的)网格或任意图上的 MJ 类过程。
探索 Markov 算法的交互式扩展。可以将任何 MJ 模型转化为游戏,将特定的重写规则或节点分配给按键。
推进网格基础过程生成的前沿。ModernHouse还没有达到像Sims 2 的房屋这样人类设计房屋的结构多样性。使用更细微的约束。
与图灵机和λ演算相比,Markov 算法可能是最简短、最简单的严格定义算法的方式。
练习:证明以下 Markov 算法可以找到用单元表示的两个数的最大公约数。例如,如果我们应用它到 111111*1111111111
上,我们得到11
。
1a=a1
1*1=a*
1*=*b
b=1
a=c
c=1
*=ε (halt)
快速模式匹配。MarkovJunior 解释器均匀地采样匹配,但它不会在每个回合扫描整个网格。为了保持模式匹配的快速,解释器记住之前找到的匹配,并只在被改变的地方进行搜索。当第一次遇到一个规则节点时,MJ 解释器使用Boyer-Moore 算法的多维版本。
随机放松。Markov 节点有一个很好的表示形式,它们是可微分节点的极限。考虑一个无序的重写规则集,每 个规则 r
被赋予一个权重 w(r)
。在每一步,解释器找到所有规则的所有匹配,并根据玻尔兹曼分布 p(r) ~ exp(-w(r)/t)
随机选择一个匹配。然后在冻结极限 t->0
下,我们得到一个由权重排序的 Markov 节点。这种构造的好处在于,对于任何 t>0
和一个典型的得分函数,多次运行的得分平均值将是权重的连续(对于实际应用来说也是平滑)函数。这意味着我们可以通过梯度下降找到最优权重,然后冻结系统以获得最终的离散程序。
请阅读Boris Kushner关于 A. A. Markov 及其构造数学工作的论文。
主要参考文献:
相关工作:
示例来源:
体素场景使用ephtracy开发的MagicaVoxel渲染。特别感谢Brian Bucklew向我展示了在roguelike关卡生成中Dijkstra场的威力,以及Kevin Chapelier给出的很多好的建议。GUI中使用的字体是Tamzen。
MarkovJunior解释器是一个仅依赖于标准库的控制台应用程序。请下载.NET Core在Windows、Linux或macOS上运行:
dotnet run --configuration Release MarkovJunior.csproj
或者,下载并运行最新的发行版用于Windows。
生成的结果会放在output
文件夹中。编辑models.xml
来更改模型参数。使用MagicaVoxel打开.vox
文件。
MarkovJunior的开发得到了以下方的资助:
AI辅助编程,代码自动修复
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。
AI小说写作助手,一站式润色、改写、扩写
蛙蛙写作—国内先进的AI写作平台,涵盖小说、学术、社交媒体等多场景。提供续写、改写、润色等功能,助力创作者高效优化写作流程。界面简洁,功能全面,适合各类写作者提升内容品质和工作效率。
全能AI智能助手,随时解答生活与工作的多样问题
问小白,由元石科技研发的AI智能助手,快速准确地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮助用户在日常生活中提高效率,轻松管理个人事务。
实时语音翻译/同声传译工具
Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。
一键生成PPT和Word,让学习生活更轻松
讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。
深度推理能力全新升级,全面对标OpenAI o1
科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。
一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型
Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合 成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。
AI助力,做PPT更简单!
咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支持多种文档格式导入生成 PPT,提供海量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。
选题、配图、成文,一站式创作,让内容运营更高效
讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。
专业的AI公文写作平台,公文写作神器
AI 材料星,专业的 AI 公文写作辅助平台,为体制内工作人员提供高效的公文写作解决方案。拥有海量公文文库、9 大核心 AI 功能,支持 30 + 文稿类型生成,助力快速完成领导讲话、工作总结、述职报告等材料,提升办公效率,是体制打工人的得力写作神器。
最新AI工具、AI资讯
独家AI资源、AI项目落地
微信扫一扫关注公众号