Isabelle 如何通过求值简化归纳谓词?

Isabelle 如何通过求值简化归纳谓词?,isabelle,Isabelle,我定义了一个非常简单的面向对象模型。该模型定义了一组类和一组关联 nonterminal fmaplets and fmaplet syntax "_fmaplet" :: "['a, 'a] ⇒ fmaplet" ("_ /↦⇩f/ _") "_fmaplets" :: "['a, 'a] ⇒ fmaplet" ("_ /[↦⇩f]/ _") "" :: "fmaplet ⇒ fmaplets"

我定义了一个非常简单的面向对象模型。该模型定义了一组类和一组关联

nonterminal fmaplets and fmaplet

syntax
  "_fmaplet"  :: "['a, 'a] ⇒ fmaplet"              ("_ /↦⇩f/ _")
  "_fmaplets" :: "['a, 'a] ⇒ fmaplet"              ("_ /[↦⇩f]/ _")
  ""          :: "fmaplet ⇒ fmaplets"              ("_")
  "_FMaplets" :: "[fmaplet, fmaplets] ⇒ fmaplets"  ("_,/ _")
  "_FMapUpd"  :: "['a ⇀ 'b, fmaplets] ⇒ 'a ⇀ 'b" ("_/'(_')" [900, 0] 900)
  "_FMap"     :: "fmaplets ⇒ 'a ⇀ 'b"             ("(1[_])")

syntax (ASCII)
  "_fmaplet"  :: "['a, 'a] ⇒ fmaplet"              ("_ /|->f/ _")
  "_fmaplets" :: "['a, 'a] ⇒ fmaplet"              ("_ /[|->f]/ _")

translations
  "_FMapUpd m (_FMaplets xy ms)"      ⇌ "_FMapUpd (_FMapUpd m xy) ms"
  "_FMapUpd m (_fmaplet  x y)"        ⇌ "CONST fmupd x y m"
  "_FMap ms"                          ⇌ "_FMapUpd (CONST fmempty) ms"
  "_FMap (_FMaplets ms1 ms2)"         ↽ "_FMapUpd (_FMap ms1) ms2"
  "_FMaplets ms1 (_FMaplets ms2 ms3)" ↽ "_FMaplets (_FMaplets ms1 ms2) ms3"

datatype classes1 =
  Object | Person | Employee | Customer | Project | Task | Sprint

abbreviation "associations ≡ [
  STR ''ProjectManager'' ↦⇩f [
    STR ''projects'' ↦⇩f (Project, 0::nat, 100::nat),
    STR ''manager'' ↦⇩f (Employee, 1, 1)],
  STR ''ProjectMember'' ↦⇩f [
    STR ''member_of'' ↦⇩f (Project, 0, 100),
    STR ''members'' ↦⇩f (Employee, 1, 20)],
  STR ''ManagerEmployee'' ↦⇩f [
    STR ''line_manager'' ↦⇩f (Employee, 0, 1),
    STR ''project_manager'' ↦⇩f (Employee, 0, 100),
    STR ''employees'' ↦⇩f (Employee, 3, 7)],
  STR ''ProjectCustomer'' ↦⇩f [
    STR ''projects'' ↦⇩f (Project, 0, 100),
    STR ''customer'' ↦⇩f (Customer, 1, 1)],
  STR ''ProjectTask'' ↦⇩f [
    STR ''project'' ↦⇩f (Project, 1, 1),
    STR ''tasks'' ↦⇩f (Task, 0, 100)],
  STR ''SprintTaskAssignee'' ↦⇩f [
    STR ''sprint'' ↦⇩f (Sprint, 0, 10),
    STR ''tasks'' ↦⇩f (Task, 0, 5),
    STR ''assignee'' ↦⇩f (Employee, 0, 1)]]"
我还定义了一个
class\u roles
谓词,它将一个类与一组可从此类导航的关联端点关联起来:

lemma fmember_code_predI [code_pred_intro]:
  "x |∈| xs" if "Predicate_Compile.contains (fset xs) x"
  using that by (simp add: Predicate_Compile.contains_def fmember.rep_eq)

code_pred fmember
  by (simp add: Predicate_Compile.contains_def fmember.rep_eq)

definition "assoc_end_class ≡ fst"

inductive assoc_refer_class where
  "role |∈| fmdom ends ⟹
   fmlookup ends role = Some end ⟹
   assoc_end_class end = The 
code_pred
command generates equations for
class_roles
, one for each inferred mode, and
values
uses them. The theorem
class_roles.equation
shows them all. If you want to use them to prove your lemma, you must first transform goal or the lemma statement such that one of the generated
class_role_...
constants appears. Doing this manually is pretty cumbersome.

You get much better automation if you let the predicate compiler do this transformation for you. Since the lemma contains universally quantified variables (
assoc1
,
assoc2
,
from
, and
role
), I recommend that you define the negation of the lemma statement as an inductive predicate, as the negation turns the universal quantifier into an existential, which is modelled by a free variable in the assumptions. Then, you can use the proof method
eval
to do the heavy work:

inductive foo where
  "foo" if 
  "class_roles associations Employee assoc1 from role"
  "class_roles associations Employee assoc2 from role"
  "assoc1 ≠ assoc2"

code_pred foo .

lemma class_roles_unique:
  assumes "class_roles associations Employee assoc1 from role"
    and "class_roles associations Employee assoc2 from role"
  shows "assoc1 = assoc2"
proof -
  have "¬ foo" by eval
  with assms show ?thesis by(simp add: foo.simps)
qed
引理fmember\u code\u predI[code\u pred\u intro]: “x|∈| xs“if”谓词_Compile.contains(fset xs)x 使用该方法(simp add:Predicate_Compile.contains_def fmember.rep_eq) 前成员代码 by(simp add:Predicate_Compile.contains_def fmember.rep_eq) 定义“联合行动结束”类别≡ fst“ 感应assoc\u参考\u类别,其中 “作用|∈| fmdom结束⟹ fmlookup ends角色=某个结束⟹
assoc_end_class end=命令
code_pred
class_角色
生成等式,每个推断模式一个等式,值使用它们。定理
class_角色。等式
显示了所有等式。如果要使用它们来证明引理,必须首先转换目标或引理语句,使其中一个生成的
class\u role\u…
常量将出现。手动执行此操作相当麻烦

如果让谓词编译器为您执行此转换,您将获得更好的自动化。因为引理包含普遍量化的变量(
assoc1
assoc2
from
,以及
角色
),我建议您将引理语句的否定定义为归纳谓词,因为否定将通用量词转化为存在量词,由假设中的自由变量建模。然后,您可以使用证明方法
eval
来完成繁重的工作:

definition dup_bit :: "bool ⇒ integer ⇒ integer" where
 "dup_bit b i = i + i + (if b then 1 else 0)"

lemma dup_bit_code [code]:
  "dup_bit True 0 = 1"
  "dup_bit False 0 = 0"
  "dup_bit True (Code_Numeral.Pos n) = Code_Numeral.Pos (num.Bit1 n)"
  "dup_bit False (Code_Numeral.Pos n) = Code_Numeral.Pos (num.Bit0 n)"
  "dup_bit True (Code_Numeral.Neg n) = - Code_Numeral.sub (num.Bit0 n) Num.One"
  "dup_bit False (Code_Numeral.Neg n) = Code_Numeral.Neg (num.Bit0 n)"
  by(simp_all add: dup_bit_def Code_Numeral.sub_def nat_of_num_add num_eq_iff)
    (metis diff_numeral_special(1) numeral_Bit0 numeral_plus_numeral sub_num_simps(2))

fun integer_of_bits :: "bool list ⇒ integer" where
  "integer_of_bits [] = 0"
| "integer_of_bits (b # bs) = dup_bit b (integer_of_bits bs)"

lemma asciis_of_literal_code [code]: 
  "String.asciis_of_literal (STR '''') = []"
  "String.asciis_of_literal (String.Literal b0 b1 b2 b3 b4 b5 b6 s) =
     integer_of_bits [b0, b1, b2, b3, b4, b5, b6] # String.asciis_of_literal s"
  including literal.lifting by(transfer; simp add: dup_bit_def; fail)+
请注意,
eval
在PolyML中使用代码生成和求值,因此它计算结果而不是证明结果。也就是说,求值不是由Isabelle的内核检查的。相关的证明方法
code\u simp
通过内核,但在本例中它不起作用,因为代码设置为
字符串。Isabelle 2018中缺少一个或多个文本

下面的引理为文字字符串提供了缺少的代码表达式,但是
code\u simp
对于文字字符串的速度非常慢(
normalization
稍微快一点,但Isabelle的内核也没有检查)


非常感谢!但是我不明白为什么缺少代码设置。理论上有一个
字符串。explode\u code
引理。需要什么引理?它在开发版本中可用吗?问题是
String.asciis\u of_literal
没有附加代码定理。为配置了自定义序列化de>String.asci是理论
String.literal
中的_literal
,但这种序列化仅用于生成类似于
eval
的代码,而不用于使用
normalization
code\u simp
进行符号求值。因此无法比较两个
String.literal
值是否相同。开发版本也有同样的问题。要找到解决方案,您首先必须了解当前的代码设置。我使用适用于
String.asciis\u of_literal
的代码公式更新了答案。