Search code examples
coqsymmetricinversion

Inversion on symmetrical relation becomes circular in Coq


One possible way to say that n m : nat are adjacent even numbers in Coq is to define that relation inductively, beginning with 0 and 2.

Inductive adj_ev : nat -> nat -> Prop :=
| ae_0 : adj_ev 0 2
| ae_1 : forall ( n m : nat ), adj_ev n m -> adj_ev m ( S ( S m ) )
| ae_2 : forall ( n m : nat ), adj_ev n m -> adj_ev m n.

ae_0 states that 0 and 2 are adjacent even numbers. ae_1 states that if some n m : nat are adjacent even numbers, so are m and m + 2. With these two constructors we can cover all pairs of adjacent even numbers up to infinity. But wait! This works for n and m if and only if n < m. So we need the last constructor ae_2 that flips any given number pair in the relation.

Now that I've defined the relation, I want to do some sanity checks on it to make sure it works. For instance, I know that 1 and 3 are not adjacent even numbers, and I also know that adj_ev 1 3 can never be obtained from the way I defined adj_ev. So I can surely prove that ~ ( adj_ev 1 3 ), right?

Theorem test' : ~ ( adj_ev 1 3 ).
unfold not. intros H.
inversion H. inversion H0.

After a few inversions I quickly get stuck in an infinite loop. It's like I'm asking Coq, "How can n and m be adjacent and even?" Coq answers "well, perhaps m and n are adjacent and even..." Then I ask, "How are m and n adjacent and even?" Coq says "well, perhaps n and m are adjacent and even..." ad infinitum.

The general problem is that, when you have some inductively defined symmetrical relation R, it is easy to show that R holds where it really does hold, but difficult to show that it doesn't where it doesn't. Perhaps there is a better tactic than inversion for extracting a contradiction in such cases, but I'm not sure what it might be.

Any thoughts?


Solution

  • First I tried induction with some extra equations, but that wasn't enough.

    Goal forall n1 n2, adj_ev n1 n2 -> n1 = 1 -> n2 = 3 -> False.
    Proof. induction 1. Abort.
    

    I managed to prove your theorem by first proving that two adjacent even numbers are even.

    Enable rewriting with equivalence relations.

    Require Import Coq.Setoids.Setoid.
    

    Turn off proof search when using firstorder. Allow only simplification.

    Set Firstorder Depth 0.
    

    Create a hint database Hints for use with auto, autorewrite, or autounfold.

    Create HintDb Hints.
    

    Shorthand for commonly used tactics.

    Ltac simplify := repeat (firstorder || subst || autorewrite with Hints in *).
    
    Inductive even : nat -> Prop :=
      | even_0 : even 0
      | even_S : forall n1, even n1 -> even (S (S n1)).
    

    Simple enough.

    Conjecture C1 : even 0 <-> True.
    Conjecture C2 : even 1 <-> False.
    Conjecture C3 : forall n1, even (S (S n1)) <-> even n1.
    
    Hint Rewrite C1 C2 C3 : Hints.
    
    Theorem T1 : forall n1 n2, adj_ev n1 n2 -> even n1 /\ even n2.
    Proof. induction 1; simplify. Qed.
    
    Goal ~ adj_ev 1 3. Proof. intro H1. apply T1 in H1. simplify. Qed.
    

    You could have also defined

    Definition least : (nat -> Prop) -> nat -> Prop := fun p1 n1 => p1 n1 /\ (forall n2, p1 n2 -> n2 >= n1).
    
    Definition greatest : (nat -> Prop) -> nat -> Prop := fun p1 n1 => p1 n1 /\ (forall n2, p1 n2 -> n2 <= n1).
    
    Definition even : nat -> Prop := fun n1 => exists n2, n1 = 2 * n2.
    
    Definition least_greater_even : nat -> nat -> Prop := fun n1 => least (fun n2 => n2 > n1 /\ even n2).
    
    Definition greatest_less_even : nat -> nat -> Prop := fun n1 => greatest (fun n2 => n2 < n1 /\ even n2).
    
    Definition adjacent_even : nat -> nat -> Prop := fun n1 n2 => least_greater_even n1 n2 /\ greatest_less_even n2 n1 \/ greatest_less_even n1 n2 /\ least_greater_even n2 n1.
    

    and worked from there. And there are other ways of defining your predicate.

    Inductive adj_ev : nat -> nat -> Prop :=
      | adj_ev_0_2 : adj_ev 0 2
      | adj_ev_2_0 : adj_ev 2 0
      | adj_ev_S_S : forall n1 n2, adj_ev n1 n2 -> adj_ev (S (S n1)) (S (S n2)).
    
    Goal ~ adj_ev 1 3. Proof. inversion 1. Qed.