证明复杂物体的不等式

时间:2019-04-07 17:15:12

标签: coq coq-tactic

我有一对不兼容的地图。我想知道什么是优雅/自动的方式来证明它。

AREA_X=1024; AREA_Y=576; OFFSET_X=110; OFFSET_Y=145

ffmpeg \
  -async 1 -vsync 1 \ 
  -loop 1 -i /home/helmi/Documents/Streaming.Chess.png \
  -thread_queue_size 512 -f x11grab -s ${AREA_X}x${AREA_Y} -framerate 25 -async 1 -vsync 1 -i :0.0+${OFFSET_X},${OFFSET_Y} \
  -thread_queue_size 512 -f v4l2 -framerate 25 -video_size 160x120 -i /dev/video0 \
  -thread_queue_size 512 -f pulse -ac 2 -ar 48000 -i default \
  -filter_complex \
  "color=0x336699cc:1024x64, drawtext=textfile=/home/helmi/Documents/Streaming.Chess.txt:fontfile=/home/helmi/.fonts/PersonalUse_Clipper_Script_fat.ttf:x=10:y=16:fontsize=40:fontcolor=white [bottom]; \
   [1:v]scale=960:-1,setpts=PTS-STARTPTS [a]; \
   [0:v]setpts=PTS-STARTPTS [0v]; \
   [0v][a]overlay=15:15 [b]; \
   [b][2:v]overlay=(W-w):0 [c]; \
   [c][bottom]overlay=0:H-64 [video]" \
   -map "[video]" -map "3:a" \
    -async 1 -vsync 1 \ 
    -c:v libx264 -b:v 500k -maxrate 500k -bufsize 1000k -framerate 25 -crf 17 -preset superfast -pix_fmt yuv420p -tune zerolatency \
      -force_key_frames "expr:gte(t,n_forced*2)" \
    -c:a aac -b:a 256k -ac 2 -af "aresample=async=1" \
  -f flv rtmp://live-vie.twitch.tv/app/...

2 个答案:

答案 0 :(得分:2)

要使其自动化,您需要对证明策略进行准确的描述。这是一种可能的证明策略:

要证明total_map的不等式:

  1. 首先介绍平等假设。
  2. 然后,对于添加到任一映射的每个键,添加以下假设:与该键关联的值在两个映射中都是相同的。
  3. 然后通过展开t_update,使用string_dec x x为真并查看是否有其他string_dec向下计算来简化所有这些等式假设。
  4. 最后,通过congruence解决目标。

我们可以自动执行每个步骤。总共变成:

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.

答案 1 :(得分:0)

基于Jason Gross的回答以及total_map是可判定类型的事实,我将一些自动化方法组合在一起来解决此问题。请注意,这个问题可能非常适合小规模反射。

(* TODO: don't bring trivial (n = n) or duplicated hypotheses into scope *)

(* Given two maps left and right, plus a lemma that they are equal, plus some key: assert that the values of the maps agree at the specified key *)
Ltac invert_total_map_equality_for_id lemma left right id :=
  let H := fresh "H" in
  assert (left id = right id) as H by (rewrite lemma; reflexivity); 
  cbv in H.

(* Recurse on the LHS map, extracting keys *)
Ltac invert_total_map_equality_left lemma left right left_remaining :=
  match left_remaining with
  | t_update ?left_remaining' ?id _ =>
    invert_total_map_equality_for_id lemma left right id;
    invert_total_map_equality_left lemma left right left_remaining'
  | _ => idtac
  end.

(* Recurse on the RHS map, extracting keys; move on to LHS once we've done all RHS keys *)
Ltac invert_total_map_equality_right lemma left right right_remaining :=
  match right_remaining with
  | t_update ?right_remaining' ?id _ =>
    invert_total_map_equality_for_id lemma left right id;
    invert_total_map_equality_right lemma left right right_remaining'
  | _ => invert_total_map_equality_left lemma left right left
  end.

(* Given a lemma that two total maps are equal, assert that their values agree at each defined key *)
Ltac invert_total_map_equality lem :=
  let T := type of lem in
    match T with
    | ?left = ?right =>
      match type of left with
      | string -> nat =>
        match type of right with
        | string -> nat =>
          invert_total_map_equality_right lem left right right
      end
    end
  end.

Goal forall n, (X !-> n; Y !-> n) <> (X !-> 1; Y !-> 2).
Proof.
  unfold not; intros.
  invert_total_map_equality H.
  congruence.
Qed.