LeanDojo | 为 Lean 定理证明器搭建桥梁
简介
LeanDojo 是一个为 Lean 定理证明器设计的 Python 库,支持 Lean 3 和 Lean 4 版本。其主要提供以下两大功能:
- 数据提取:从 Lean 存储库中提取证明状态、策略、前提等关键信息。
- 环境交互:允许用户以编程方式与 Lean 环境进行交互。
LeanDojo 在解析 Lean 文件及与环境交互方面有很高的实用性。但项目只支持处理 GitHub 上的仓库,且这一问题一直没有修复。
最近给 LeanDojo 提交了一个更新 PR,增加对本地及非 GitHub 仓库的支持,借此机会写个简易教程。
项目浅析
LeanDojo 按照 仓库=>文件=>定理
的结构来解析文件,操作围绕 LeanGitRepo
类来进行:
该类基于 PyGithub
实现,因此频繁调用 GitHub API。
当前处理这个问题的 PR :Add Support for Local and Remote Repositories #179。使用 gitpython
作为补充,并对一些函数方法进行了重写。
相关链接
- 项目文档:LeanDojo: Machine Learning for Theorem Proving in Lean
- 项目仓库:lean-dojo/LeanDojo
- 社区帖子:Releasing LeanDojo
基本示例
准备工作
安装依赖,测试用 Python 3.10 版本:
1 | pip install lean-dojo |
使用官方示例仓库:yangky11/lean4-example。这是一个简洁的 Lean 包,文件结构如下:
1 | lean4-example/ |
其中,Lean4Example.lean
文件的内容:
1 | open Nat (add_assoc add_comm) |
从 Nat
命名空间导入了 add_assoc
和 add_comm
两个引理,然后定义了两个定理。
设置环境变量
环境变量只在首次 import lean_dojo
时生效,因此先设置:
1 | import os |
仓库对象
环境交互和数据提取都是围绕 LeanGitRepo
对象展开的。
首先导入 LeanGitRepo
类
1 | from lean_dojo import LeanGitRepo |
初始化仓库对象,可使用 commit hash 或 main 分支:
1 | repo = LeanGitRepo("https://github.com/PatrickMassot/GlimpseOfLean", "8d73d32d90ec2315616ad8e720754eeacfb96af6") |
查看仓库对象的基本属性:
1 | print("repo.url", repo.url) |
输出结果:
1 | repo.url https://github.com/PatrickMassot/GlimpseOfLean |
这里 lean_version
是一个 commit hash,而不是直观的版本字符串。
Trace 操作
对仓库进行 trace 操作:
1 | from lean_dojo import trace |
trace
主要执行以下步骤:
- 克隆仓库到
TMP_DIR
目录,并执行lake build
进行构建。 - 获取仓库的 Lean4 版本,将对应版本的 Lean4 文件复制到
.lake/packages
目录。 - 数据提取:将
ExtractData.lean
脚本拷贝到仓库,执行lake env lean --run ExtractData.lean
命令,提取 AST 树、状态和定理等信息,随后删除ExtractData.lean
文件。 - 环境交互:将
Lean4Repl.lean
脚本拷贝到仓库,并更新lakefile
以包含依赖信息,执行lake build Lean4Repl
命令进行构建。 - 获取仓库信息,并更新
.cache/leandojo
目录下的缓存。
此外,ExtractData.lean
和 Lean4Repl.lean
文件是整个项目的核心。如果只关心环境交互问题,可以重点关注 Lean4Repl.lean
文件。
数据提取
提取的文件位于 .lake/build
目录:
1 | .lake |
这里有两类比较重要的文件:
.ast.json
:包含带有语义信息的注释,例如策略状态和名称。.trace.xml
:结构化处理后的句法和语义信息。
项目按 仓库 => 文件 => 定理
的层次结构生成文件。示例中的例子比较简单,仅包含一个文件。
环境交互
示例仓库中包含两个定理。以下以 hello_world
定理为例,展示如何使用 Dojo
类进行环境交互。
1 | theorem hello_world (a b c : Nat) |
首先导入 Dojo
类和 Theorem
类:
1 | from lean_dojo import Theorem, Dojo |
获取定理对象,从 Lean4Example.lean
文件中提取 hello_world
定理:
1 | theorem = Theorem(repo, "Lean4Example.lean", "hello_world") |
获取初始状态:
1 | dojo, state_0 = Dojo(theorem).__enter__() |
对初始状态 state_0
执行策略,并获取更新后的状态:
1 | state_1 = dojo.run_tac(state_0, "rw [add_assoc]") |
继续对状态 state_1
执行策略,并获取最终状态:
1 | print(dojo.run_tac(state_1, "sorry")) |
小结
以上,我们演示了用 LeanDojo 进行数据提取和环境交互。
如果对 LeanDojo 的关键实现细节感兴趣,可以进一步阅读两个核心文件: