Coq 复杂对象不等式的证明
我有一对完全不兼容的地图。我想知道什么是优雅的/自动化的方式来获得它的证明Coq 复杂对象不等式的证明,coq,coq-tactic,Coq,Coq Tactic,我有一对完全不兼容的地图。我想知道什么是优雅的/自动化的方式来获得它的证明 Require Import Coq.Strings.String. (* Prelude: the total_map data structure from Software Foundations, slightly modified *) Definition total_map := string -> nat. Definition empty_st : total_map := (fun _ =&g
Require Import Coq.Strings.String.
(* Prelude: the total_map data structure from Software Foundations, slightly modified *)
Definition total_map := string -> nat.
Definition empty_st : total_map := (fun _ => 0).
Definition t_update (m : total_map) k v := fun k' => if string_dec k k' then v else m k'.
Notation "a '!->' x" := (t_update empty_st a x) (at level 100).
Notation "x '!->' v ';' m" := (t_update m x v) (at level 100, v at next level, right associativity).
(* The actual goal I'm trying to solve *)
Definition X: string := "X".
Definition Y: string := "Y".
Goal forall n, (X !-> n; Y !-> n) <> (X !-> 1; Y !-> 2).
Proof.
intros n contra.
remember (X !-> n; Y !-> n) as st.
remember (st X) as n1.
assert (n1 = n). { rewrite Heqn1; rewrite Heqst; cbv; reflexivity. }
assert (n1 = 1). { rewrite Heqn1; rewrite contra; cbv; reflexivity. }
remember (st Y) as n2.
assert (n2 = n). { rewrite Heqn2; rewrite Heqst; cbv; reflexivity. }
assert (n2 = 2). { rewrite Heqn2; rewrite contra; cbv; reflexivity. }
congruence.
Qed.
需要导入Coq.Strings.String。
(*前奏曲:软件基础的总地图数据结构,稍作修改*)
定义总映射:=字符串->nat。
定义为空:总映射:=(乐趣=>0)。
定义t_更新(m:total_map)k v:=fun k'=>如果字符串为'u dec k'那么v else m k'。
符号“a”!->“x”:=(t\U更新为空\U st a x)(在级别100)。
符号“x”!->“v”;“m”:=(t_更新m x v)(在100级,v在下一级,右关联性)。
(*我试图解决的实际目标*)
定义X:string:=“X”。
定义Y:字符串:=“Y”。
所有n的目标,(X!->n;Y!->n)(X!->1;Y!->2)。
证明。
反面介绍。
记住(X!->n;Y!->n)是st。
记住(stx)是n1。
断言(n1=n)。{重写Heqn1;重写Heqst;cbv;自反性。}
断言(n1=1)。{重写Heqn1;重写contra;cbv;自反性。}
记住(sty)是n2。
断言(n2=n)。{重写Heqn2;重写Heqst;cbv;自反性。}
断言(n2=2)。{重写Heqn2;重写contra;cbv;自反性。}
相似
Qed。
为了实现自动化,您需要准确描述您的验证策略。以下是一种可能的证明策略:
要证明total\u map
s的不等式:
t\u update
,使用string\u dec x
为真,并查看是否有任何其他string\u dec
计算下来,简化所有这些等式假设Require Import Coq.Strings.String.
(* Prelude: the total_map data structure from Software Foundations, slightly modified *)
Definition total_map := string -> nat.
Definition empty_st : total_map := (fun _ => 0).
Definition t_update (m : total_map) k v := fun k' => if string_dec k k' then v else m k'.
Notation "a '!->' x" := (t_update empty_st a x) (at level 100).
Notation "x '!->' v ';' m" := (t_update m x v) (at level 100, v at next level, right associativity).
(* Automation *)
(* 1. First introduce the equality hypothesis. *)
Ltac start_proving_inequality H :=
intro H.
(* 2. Then, for every key that's been added to either map, add the hypothesis that the value associated to that key is the same in both maps. *)
(* To do this, we need a tactic that will pose a proof only if it does not already exist. *)
Ltac unique_pose_proof lem :=
let T := type of lem in
lazymatch goal with
| [ H : T |- _ ] => fail 0 "A hypothesis of type" T "already exists"
| _ => pose proof lem
end.
(* Maybe move this elsewhere? *)
Definition t_get (m : total_map) k := m k.
Ltac saturate_with_keys H :=
repeat match type of H with
| context[t_update _ ?k ?v]
=> unique_pose_proof (f_equal (fun m => t_get m k) H)
end.
(* 3. Then simplify all such equality hypotheses by unfolding `t_update`, using that `string_dec x x` is true, and seeing if any other `string_dec`s compute down. *)
Require Import Coq.Logic.Eqdep_dec.
Lemma string_dec_refl x : string_dec x x = left eq_refl.
Proof.
destruct (string_dec x x); [ apply f_equal | congruence ].
apply UIP_dec, string_dec.
Qed.
(* N.B. You can add more cases here to deal with other sorts of ways you might reduce [t_get] here *)
Ltac simplify_t_get_t_update_in H :=
repeat first [ progress cbv [t_get t_update empty_st] in H
| match type of H with
| context[string_dec ?x ?x] => rewrite (string_dec_refl x) in H
| context[string_dec ?x ?y]
=> let v := (eval cbv in (string_dec x y)) in
(* check that it fully reduces *)
lazymatch v with left _ => idtac | right _ => idtac end;
progress change (string_dec x y) with v in H
end ].
Ltac simplify_t_get_t_update :=
(* first we must change hypotheses of the form [(fun m => t_get m k) m = (fun m => t_get m k) m'] into [t_get _ _ = t_get _ _] *)
cbv beta in *;
repeat match goal with
| [ H : t_get _ _ = t_get _ _ |- _ ] => progress simplify_t_get_t_update_in H
end.
(* 4. Finally, solve the goal by `congruence`. *)
Ltac finish_proving_inequality := congruence.
(* Now we put it all together *)
Ltac prove_total_map_inequality :=
let H := fresh in
start_proving_inequality H;
saturate_with_keys H;
simplify_t_get_t_update;
finish_proving_inequality.
(* The actual goal I'm trying to solve *)
Definition X: string := "X".
Definition Y: string := "Y".
Goal forall n, (X !-> n; Y !-> n) <> (X !-> 1; Y !-> 2).
intros.
prove_total_map_inequality.
Qed.
需要导入Coq.Strings.String。
(*前奏曲:软件基础的总地图数据结构,稍作修改*)
定义总映射:=字符串->nat。
定义为空:总映射:=(乐趣=>0)。
定义t_更新(m:total_map)k v:=fun k'=>如果字符串为'u dec k'那么v else m k'。
符号“a”!->“x”:=(t\U更新为空\U st a x)(在级别100)。
符号“x”!->“v”;“m”:=(t_更新m x v)(在100级,v在下一级,右关联性)。
(*自动化*)
(*1.首先介绍平等假设。*)
Ltac启动证明不等式H:=
介绍H。
(*2.然后,对于添加到任一映射的每个键,添加与该键关联的值在两个映射中相同的假设。*)
(*要做到这一点,我们需要一种策略,只有在证据不存在的情况下才能提供证据。*)
Ltac独特的防姿态lem:=
设T:=中lem的类型
拉齐马特进球
|[H:T |-|]=>失败0“类型为“T”的假设已经存在”
|_uz=>防姿态lem
结束。
(*可能会将此移到其他地方?*)
定义t_get(m:总映射)k:=m k。
Ltac使用_键H饱和_:=
重复匹配H的类型
|上下文[t_更新?k?v]
=>独特的姿势证明(f_相等(乐趣m=>t_获得m k)H)
结束。
(*3.然后通过展开't_update',使用'string_dec x'为真,并查看是否有任何其他'string_dec'的计算结果,简化所有此类等式假设。*)
需要导入Coq.Logic.Eqdep\u dec。
引理string\u dec\u refl x:string\u dec x x=左等式\u refl。
证明。
自毁(字符串_dec x x);[应用f|u相等|同余]。
应用UIP_dec、字符串_dec。
Qed。
(*N.B.您可以在此处添加更多案例,以处理您可能会减少的其他类型的方法*)
Ltac在H中简化\u t\u获取\u t\u更新\u:=
在H中首先重复[progress cbv[t_get t_update empty_st]
|将H的类型与
|上下文[string_dec?x?x]=>在H中重写(string_dec_refl x)
|上下文[string_dec?x?y]
=>设v:=(计算cbv in(字符串x y))in
(*检查是否完全减少*)
lazymatch v带左=>idtac |右=>idtac端;
进度变化(字符串_dec x y)与H中的v
"完"。
Ltac简化\u t\u获取\u t\u更新:=
(*首先,我们必须将形式为[(fun m=>t_-get m k)m=(fun m=>t_-get m k)m']的假设更改为[t_-get=t_-get]
cbvβ-在*;
与对手重复比赛进球
|[H:t\U get\U=t\U get\U124;-\ U]=>在H中简化进度
结束。
(*4.最后,通过“一致性”解决目标。*)
Ltac完成证明不等式:=同余。
(*现在我们把它们放在一起*)
Ltac证明总映射不等式:=
设H:=新入
开始证明不等式H;
用_键H饱和_;
简化获取更新;
完成不等式的证明。
(*我试图解决的实际目标*)
定义X:string:=“X”。
定义Y:字符串:=“Y”。
所有n的目标,(X!->n;Y!->n)(X!->1;Y!->2)。
介绍。
证明全映射不等式。
Qed。
为了实现自动化,您需要准确描述您的验证策略。以下是一种可能的证明策略:
要证明total\u map
s的不等式:
t\u update
,使用string\u dec x
为真,并查看是否有任何其他string\u dec
计算下来,简化所有这些等式假设Require Import Coq.Strings.String.
(* Prelude: the total_map data structure from Software Foundations, slightly modified *)
Definition total_map := string -> nat.
Definition empty_st : total_map := (fun _ => 0).
Definition t_update (m : total_map) k v := fun k' => if string_dec k k' then v else m k'.
Notation "a '!->' x" := (t_update empty_st a x) (at level 100).
Notation "x '!->' v ';' m" := (t_update m x v) (at level 100, v at next level, right associativity).
(* Automation *)
(* 1. First introduce the equality hypothesis. *)
Ltac start_proving_inequality H :=
intro H.
(* 2. Then, for every key that's been added to either map, add the hypothesis that the value associated to that key is the same in both maps. *)
(* To do this, we need a tactic that will pose a proof only if it does not already exist. *)
Ltac unique_pose_proof lem :=
let T := type of lem in
lazymatch goal with
| [ H : T |- _ ] => fail 0 "A hypothesis of type" T "already exists"
| _ => pose proof lem
end.
(* Maybe move this elsewhere? *)
Definition t_get (m : total_map) k := m k.
Ltac saturate_with_keys H :=
repeat match type of H with
| context[t_update _ ?k ?v]
=> unique_pose_proof (f_equal (fun m => t_get m k) H)
end.
(* 3. Then simplify all such equality hypotheses by unfolding `t_update`, using that `string_dec x x` is true, and seeing if any other `string_dec`s compute down. *)
Require Import Coq.Logic.Eqdep_dec.
Lemma string_dec_refl x : string_dec x x = left eq_refl.
Proof.
destruct (string_dec x x); [ apply f_equal | congruence ].
apply UIP_dec, string_dec.
Qed.
(* N.B. You can add more cases here to deal with other sorts of ways you might reduce [t_get] here *)
Ltac simplify_t_get_t_update_in H :=
repeat first [ progress cbv [t_get t_update empty_st] in H
| match type of H with
| context[string_dec ?x ?x] => rewrite (string_dec_refl x) in H
| context[string_dec ?x ?y]
=> let v := (eval cbv in (string_dec x y)) in
(* check that it fully reduces *)
lazymatch v with left _ => idtac | right _ => idtac end;
progress change (string_dec x y) with v in H
end ].
Ltac simplify_t_get_t_update :=
(* first we must change hypotheses of the form [(fun m => t_get m k) m = (fun m => t_get m k) m'] into [t_get _ _ = t_get _ _] *)
cbv beta in *;
repeat match goal with
| [ H : t_get _ _ = t_get _ _ |- _ ] => progress simplify_t_get_t_update_in H
end.
(* 4. Finally, solve the goal by `congruence`. *)
Ltac finish_proving_inequality := congruence.
(* Now we put it all together *)
Ltac prove_total_map_inequality :=
let H := fresh in
start_proving_inequality H;
saturate_with_keys H;
simplify_t_get_t_update;
finish_proving_inequality.
(* The actual goal I'm trying to solve *)
Definition X: string := "X".
Definition Y: string := "Y".
Goal forall n, (X !-> n; Y !-> n) <> (X !-> 1; Y !-> 2).
intros.
prove_total_map_inequality.
Qed.
需要导入Coq.Strings.String。
(*前奏曲:软件基础的总地图数据结构,稍作修改*)
定义总映射:=字符串->nat。
定义为空:总映射:=(乐趣=>0)。
定义t_更新(m:总地图)k v:=fun