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
的代码公式更新了答案。