Isabelle 数据类型转换函数需要很长时间来证明

Isabelle 数据类型转换函数需要很长时间来证明,isabelle,formal-verification,Isabelle,Formal Verification,Isabelle需要很多时间来证明(在我看来)相当简单的数据类型转换函数的正确性。例如,我创建了数据类型来表示数学和布尔表达式,以及一个简化此类表达式的函数 datatype 'a math_expr = Num int | Add "'a math_expr" "'a math_expr" | Mul "'a math_expr" "'a math_expr" | Sub "'a math_expr" "'a math_expr" | Div "'a math_expr"

Isabelle需要很多时间来证明(在我看来)相当简单的数据类型转换函数的正确性。例如,我创建了数据类型来表示数学和布尔表达式,以及一个简化此类表达式的函数

datatype 'a math_expr =
  Num int |
  Add "'a math_expr" "'a math_expr" |
  Mul "'a math_expr" "'a math_expr" |
  Sub "'a math_expr" "'a math_expr" |
  Div "'a math_expr" "'a math_expr"

datatype 'a expr =
  True |
  False |
  And "'a expr" "'a expr" |
  Or "'a expr" "'a expr" |
  Eq "'a math_expr" "'a math_expr" |
  Ne "'a math_expr" "'a math_expr" |
  Lt "'a math_expr" "'a math_expr" |
  Le "'a math_expr" "'a math_expr" |
  Gt "'a math_expr" "'a math_expr" |
  Ge "'a math_expr" "'a math_expr" |
  If "'a expr" "'a expr" "'a expr"

function (sequential) simplify :: "'a expr ⇒ 'a expr" where
"simplify (And a True) = a" |
"simplify (And True b) = b" |
"simplify (Or a True) = True" |
"simplify (Or True b) = True" |
"simplify e = e"
by pat_completeness auto
termination by lexicographic_order
在我的笔记本上,Isabelle花了相当长的时间来证明函数(签名和正文突出显示),甚至花了更多的时间来证明函数的完整性(pat_Completion auto的
突出显示)。所需的计算时间在很大程度上取决于
expr
数据类型的复杂性和
simplify
中模式匹配规则的数量。数据类型中的构造函数越多,模式匹配规则越多,所需时间越长


这种行为的原因是什么?有没有办法使这样一个函数更容易证明?

顺序
选项使
函数
命令专门化重叠的方程,使它们不再重叠。但是,这只是实际内部构造的预处理器,它实际上支持重叠模式(前提是可以证明右侧表示重叠实例的相同HOL值,即它们是一致的)。此一致性证明表示为单个目标(如果使用
顺序
选项,则
自动
基本上总是解决,因为它足以证明它们不能重叠)。然而,在消歧方程的数量上有许多二次目标。因此,如果您添加更多的构造函数,重叠的方程将被分解为更多的情况,这些情况将转化为二次目标数

当函数不是递归函数时,有两种解决方法:

对于非递归函数,我建议将
定义
与右侧的
大小写
表达式一起使用。然后,您可以使用
HOL Library.simps\u case\u Conv
中的
simps\u of_case
来获取simp规则。不过,你没有一个很好的区分案例的规则

definition simplify :: "'a expr ⇒ 'a expr" where
  "simplify e = (case e of And a True => a | And True b => b | ... | _ => e)"

simps_of_case simplify_simps [simp]: simplify_def
如果您想获得好的区分大小写定理,可以将函数定义拆分为几个辅助函数:

fun simplify_add :: "'a expr => 'a expr => 'a expr" where
  "simplify_add a True = a"
| "simplify_add True b = b"
| "simplify_add a b = Add a b"

fun simplify_or (* similarly *)

fun simplify :: "'a expr => 'a expr" where
  "simplify (And a b) = simplify_and a b"
| "simplify (Or a b) = simplify_or a b"
| "simplify e = e"
对于递归函数,可以通过将一些大小写区分移到右侧来避免爆炸。例如:

fun simplify :: "'a expr ⇒ 'a expr" where
  "simplify (And a b) = (case b of True => a | _ => case a of True => b | _ => And a b)"
| ...
同样,在使方程不重叠后,这大大减少了方程的数量,但不再得到相同的区分规则(和归纳规则)