Coq: Equivalence, Induction & Waterproof Issues

by Admin 48 views
Coq: Equivalence, Induction & Waterproof Issues

Let's dive into some tricky issues encountered while working with equivalence and structural induction in Coq, especially when dealing with propositional formulas and the Waterproof library. We'll explore the challenges faced, understand the potential causes, and discuss possible solutions.

Problem Setup: Propositional Formulas in Coq

The user is formalizing results on propositional formulas in Coq. The foundation of this work lies in defining a data type for formulas and related functions for valuation, size, satisfiability, and tautology. Let's break down the code and the issues encountered.

Require Import Rbase.
Require Import Rfunctions.

Require Import Waterproof.Waterproof.
Require Import Waterproof.Notations.Common.
Require Import Waterproof.Notations.Reals.
Require Import Waterproof.Notations.Sets.
Require Import Waterproof.Chains.
Require Import Waterproof.Tactics.
Require Import Waterproof.Libs.Analysis.SupAndInf.
Require Import Waterproof.Automation.

Waterproof Enable Automation RealsAndIntegers.
Open Scope R_scope.
Open Scope subset_scope.
Set Default Goal Selector "!".

Require Import Bool.

Inductive formula : Set :=
  | True : formula
  | False : formula
  | Var : nat -> formula
  | Neg : formula -> formula -> formula
  | Or : formula -> formula -> formula
  | And : formula -> formula -> formula
  | Impl : formula -> formula -> formula
  | Equiv : formula -> formula -> formula.


Definition valuation := nat -> bool.

Fixpoint bool_val (phi : valuation) (f : formula) := 
    match f with
  | True => true
  | False => false
  | Var n => phi n
  | Neg G => negb (bool_val phi G)
  | Or G D => orb (bool_val phi G) (bool_val phi D)
  | And G D => andb (bool_val phi G) (bool_val phi D)
  | Impl G D => implb (bool_val phi G) (bool_val phi D)
  | Equiv G D => eqb (bool_val phi G) (bool_val phi D)
  end.

Definition tautologie (f : formula) := forall (phi : valuation), bool_val phi f = true.

Definition satisfiable (f : formula) := exists (phi : valuation), bool_val phi f = true.

Fixpoint size (f : formula) := 
    match f with
  | True => 1
  | False => 1
  | Var n => 1
  | Neg G => 1 + size G
  | Or G D | And G D | Impl G D | Equiv G D => 1 + size G + size D
end.

The First Hurdle: Tautology and Satisfiability

The primary challenge lies in proving the lemma tauto_ssi_neg_pas_sat. This lemma aims to establish the equivalence between a formula being a tautology and the negation of that formula not being satisfiable. Formally:

Lemma tauto_ssi_neg_pas_sat : forall f : formula, tautologie f <-> ~ satisfiable (Neg f).
Proof.
Take f : formula.
We show both directions.
++ We need to show that tautologie(f) ⇨ ¬ satisfiable(Neg(f)).

Admitted.

The "We show both directions." tactic is intended to split the proof into two subgoals, one for each direction of the equivalence. However, the user reports that this tactic fails even when following the software's hints. This usually happens when the context or goal is not in the expected format for the tactic to work correctly. Possible reasons include:

  • Implicit Arguments: The Waterproof library and its automation might be interfering with the expected behavior of standard tactics. Implicit arguments could be causing mismatches in unification.
  • Goal Simplification: The goal might not be simplified enough for the tactic to recognize the equivalence structure. Simplification tactics (like simpl, cbv, or lazy) might be needed before applying "We show both directions.".
  • Contextual Issues: The context might contain hypotheses that interfere with the tactic's ability to split the goal. Try clearing unnecessary hypotheses.

To debug this, you could try the following steps:

  1. Simplify the Goal: Use simpl. or cbv beta. to reduce the goal before attempting the "We show both directions." tactic. This will ensure the goal is in its simplest form.
  2. Explicit Tactics: Instead of relying on "We show both directions.", manually split the goal using split.. This gives you more control and insight into what's happening.
  3. Check the Context: Use Print Assumptions tauto_ssi_neg_pas_sat. to see the assumptions Coq is using. Look for any unexpected dependencies introduced by Waterproof. Then use clear tactic to clear unecessary hypothesis.
  4. Isolate the Problem: Try proving a simpler version of the lemma without the Waterproof library to see if the issue is related to the library's automation.

Let's look at a possible proof outline:

Lemma tauto_ssi_neg_pas_sat : forall f : formula, tautologie f <-> ~ satisfiable (Neg f).
Proof.
  intros f.
  split.
  - (* tautologie f -> ~ satisfiable (Neg f) *)
    intros H1 H2.
    unfold satisfiable in H2.
    destruct H2 as (phi, H3).
    unfold bool_val in H3.
    unfold tautologie in H1.
    specialize (H1 phi).
    unfold bool_val in H1.
    assert (bool_val phi f = true) by assumption.
    unfold Neg in H3.
    simpl in H3.
    apply H1 in H3.
    destruct H3.
    Admitted.
  - (* ~ satisfiable (Neg f) -> tautologie f *)
    intros H f0.
    unfold tautologie in H.
    unfold satisfiable in H0.
    unfold bool_val in H0.
    apply H in H0.
    Admitted.

The Second Challenge: Structural Induction

The second issue arises when attempting to prove that the size of any formula is positive. The user attempts a straightforward structural induction, but encounters difficulties.

Lemma size_pos : forall f : formula, 0 < size f.
Proof.
Take f : formula.
We use induction on f.

Admitted.

The problem here isn't necessarily a bug, but rather a misunderstanding of how structural induction works in Coq. When you use "induction on f.", Coq generates subgoals corresponding to each constructor of the formula inductive type. You need to prove that 0 < size f holds for each case.

Let's outline a complete proof:

Lemma size_pos : forall f : formula, 0 < size f.
Proof.
  intros f.
  induction f.
  - (* True *) simpl. lia. (* lia is a tactic for linear integer arithmetic *)
  - (* False *) simpl. lia.
  - (* Var n *) simpl. lia.
  - (* Neg G *) simpl. apply IHf. lia.
  - (* Or G D *) simpl. apply IHf1. apply IHf2. lia.
  - (* And G D *) simpl. apply IHf1. apply IHf2. lia.
  - (* Impl G D *) simpl. apply IHf1. apply IHf2. lia.
  - (* Equiv G D *) simpl. apply IHf1. apply IHf2. lia.
Qed.

Explanation:

  • intros f.: Introduces the formula f into the context.
  • induction f.: Starts the structural induction on f. Coq will generate a subgoal for each constructor of the formula type.
  • For each case (True, False, Var n, Neg G, Or G D, And G D, Impl G D, Equiv G D):
    • simpl.: Simplifies the goal by reducing the size function.
    • lia.: Solves the goal using linear integer arithmetic. This works because, after simplification, the goal becomes a simple inequality that lia can handle.
    • In the cases with inductive hypotheses (e.g., Neg G, Or G D), we use apply IHf. (or apply IHf1. apply IHf2.) to apply the inductive hypothesis to the subformulas.

The key to understanding this proof is recognizing that structural induction breaks down the problem into smaller, more manageable cases, each corresponding to a constructor of the inductive type. The inductive hypotheses allow you to assume the property holds for the subformulas, which is crucial for proving the property for the composite formulas.

Key Takeaways

  • Equivalence Proofs: When using tactics like "We show both directions.", ensure the goal is simplified and the context is clean. Explicitly splitting the goal with split. can provide more control.
  • Structural Induction: Understand that structural induction requires proving the property for each constructor of the inductive type. Utilize the inductive hypotheses appropriately.
  • Waterproof Library: Be aware that the Waterproof library and its automation might introduce complexities. If you encounter unexpected behavior, try isolating the problem and simplifying the code.
  • Simplification: Use simplification tactics (simpl, cbv, lazy) to reduce goals to a manageable form.
  • Linear Arithmetic: The lia tactic is invaluable for solving goals involving linear integer arithmetic.

By carefully considering these points, you'll be better equipped to tackle similar challenges when working with Coq and the Waterproof library. Remember to break down complex problems into smaller, more manageable steps, and don't hesitate to experiment with different tactics to find the most effective approach. Good luck, Coq enthusiasts!