1

Consider the following simple problem:

Goal forall (R : relation nat) (a b c d e f g h : nat), 
  (forall m n : nat, R m n -> False) -> (R a b) -> False.
Proof.
  intros ? a b c d e f g h H1 H2.
  saturate H1. (* <-- TODO implement this *)
  assumption.
Qed.

My current implementation of saturate instantiates H1 with every possible combination of nat hypotheses, leading to quadratic blowup in time and memory usage. Instead I would like it to inspect forall and see that it requires a R m n, so the only combination of parameters that makes sense in context is a and then b.

Is there a known solution to this? My intuition is to use evars, but if I could avoid them without sacrificing significant performance I would like to.

Carl Patenaude Poulin
  • 6,238
  • 5
  • 24
  • 46
  • I believe this is more-or-less what the `inster` tactic does in CPDT (http://adam.chlipala.net/cpdt/html/Match.html), and that tactic does use existentials... – Arthur Azevedo De Amorim Mar 18 '20 at 21:10
  • 1
    @ArthurAzevedoDeAmorim from the text: "For a given problem, we can consider all possible bounded-length sequences of quantifier instantiations, applying only propositional reasoning at the end. This is probably a bad idea for almost all goals, but it makes for a nice example of recursive proof search procedures in Ltac." So Adam's is the version that gives a quadratic blowup for this problem. I'm looking for one that does better. – Carl Patenaude Poulin Mar 18 '20 at 21:30

1 Answers1

1

This might be too simplistic, the idea is to try apply H1 on every hypothesis:

Ltac saturate H :=
  match goal with
    (* For any hypothesis I... *)
  | [ I : _ |- _ ] =>

    (* 1. Clone it (to not lose information). *)
    let J := fresh I in pose proof I as J;

    (* 2. apply H. *)
    apply H in J;

    (* 3. Abort if we already knew the resulting fact. *)
    let T := type of J in
    match goal with
    | [ I1 : T, I2 : T |- _ ] => fail 2
    end + idtac;

    (* 4. Keep going *)
    try (saturate H)
  end.

Example:

Require Setoid. (* To get [relation] in scope so the example compiles *)

(* Made the example a little less trivial to better test the backtracking logic. *)
Goal forall (R S : relation nat) (a b c d e f g h : nat), 
  (forall m n : nat, R m n -> S m n) -> (R a b) -> R c d -> S a b.
Proof.
  intros R S a b c d e f g h H1 H2 H3.

  (* --- BEFORE ---
     H2: R a b
     H3: R c d
   *)

  saturate H1.

  (* --- AFTER ---
     H2: R a b
     H3: R c d
     H0: S c d
     H4: S a b
   *)

  assumption.
Qed.
Li-yao Xia
  • 31,896
  • 2
  • 33
  • 56