如何为less_eq操作生成代码

时间:2019-01-09 08:36:15

标签: isabelle

我需要生成一个代码,计算所有大于或等于某个值的值:

datatype ty = A | B | C

instantiation ty :: order
begin

fun less_ty where
  "A < x = (x = C)"
| "B < x = (x = C)"
| "C < x = False"

definition "(x :: ty) ≤ y ≡ x = y ∨ x < y"

instance
  apply intro_classes
  apply (metis less_eq_ty_def less_ty.elims(2) ty.distinct(3) ty.distinct(5))
  apply (simp add: less_eq_ty_def)
  apply (metis less_eq_ty_def less_ty.elims(2))
  using less_eq_ty_def less_ty.elims(2) by fastforce

end

instantiation ty :: enum
begin

definition [simp]: "enum_ty ≡ [A, B, C]"
definition [simp]: "enum_all_ty P ≡ P A ∧ P B ∧ P C"
definition [simp]: "enum_ex_ty P ≡ P A ∨ P B ∨ P C" 

instance
  apply intro_classes
  apply auto
  by (case_tac x, auto)+

end

lemma less_eq_code_predI [code_pred_intro]:
  "Predicate_Compile.contains {z. x ≤ z} y ⟹ x ≤ y"
(*  "Predicate_Compile.contains {z. z ≤ y} x ⟹ x ≤ y"*)
  by (simp_all add: Predicate_Compile.contains_def)

code_pred [show_modes] less_eq
  by (simp add: Predicate_Compile.containsI)

values "{x. A ≤ x}"
(* values "{x. x ≤ C}" *)

工作正常。但是该理论看起来过于复杂。我也不能计算小于或等于某个值的值。如果less_eq_code_predI引理的第二部分不存在,则less_eq将只有一种模式i => i => boolpos

有没有更简单,更通用的方法?

less_eq是否可以同时支持i => o => boolposo => i => boolpos

是否可以不将ty声明为enum类的实例?我可以声明一个函数,该函数返回一组大于或等于某个元素的元素:

fun ge_values where
  "ge_values A = {A, C}"
| "ge_values B = {B, C}"
| "ge_values C = {C}"

lemma ge_values_eq_less_eq_ty:
  "{y. x ≤ y} = ge_values x"
  by (cases x; auto simp add: dual_order.order_iff_strict)

这将允许我删除enumcode_pred的内容。但是在这种情况下,我将无法在其他谓词的定义中使用此函数。在以下定义中,如何用(≤)替换ge_values

inductive pred1 where
  "x ≤ y ⟹ pred1 x y"

code_pred [show_modes] pred1 .

我需要pred1才能拥有至少i => o => boolpos模式。

1 个答案:

答案 0 :(得分:1)

The predicate compiler has an option inductify that tries to convert functional definitions into inductive ones. It is somewhat experimental and does not work in every case, so use it with care. In the above example, the type classes make the whole situation a bit more complicated. Here's what I managed to get working:

case_of_simps less_ty_alt: less_ty.simps

definition less_ty' :: "ty ⇒ ty ⇒ bool" where "less_ty' = (<)"

declare less_ty_alt [folded less_ty'_def, code_pred_def]

code_pred [inductify, show_modes] "less_ty'" .

values "{x. less_ty' A x}"
  1. The first line convertes the pattern-matching equations into one with a case expression on the right. It uses the command case_of_simps from HOL-Library.Simps_Case_Conv.
  2. Unfortunately, the predicate compiler seems to have trouble with compiling type class operations. At least I could not get it to work. So the second line introduces a new constant for (<) on ty.
  3. The attribute code_pred_def tells the predicate compiler to use the given theorem (namely less_ty_alt with less_ty' instead of (<)) as the "defining equation".
  4. code_pred with the inductify option looks at the equation for less_ty' declared by code_pred_def and derives an inductive definition out of that. inductify usually works well with case expressions, constructors and quantifiers. Everything beyond that is at your own risk.

Alternatively, you could also manually implement the enumeration similar to ge_values and register the connection between (<) and ge_values with the predicate compiler. See the setup block at the end of the Predicate_Compile theory in the distribution for an example with Predicate.contains. Note however that the predicate compiler works best with predicates and not with sets. So you'd have to write ge_values in the predicate monad Predicate.pred.