1

I am trying to prove a big case distinction in Isabelle for some (conceptually) simple arithmetic statement. During the proof, I stumbled upon the following subgoal.

 ⋀d l k. 0 < d ⟹
         ¬ 2 * k + 1 ≤ 2 * l ⟹
         2 * l ≠ 1 ⟹ - (2 * l) < 2 * k - 1 ⟹ k ≤ l ⟹ d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)

Mathematically, it is fairly simple: The two statements ¬ 2 * k + 1 ≤ 2 * l and k ≤ l imply that k=l, and therefore the last formula holds.

However, I just can't prove it in Isabelle. I figured it should be possible to construct a proof using my above reasoning in Isar, but I as I am still a beginner I struggle to find the right keywords. I get various frustrating errors. Here's (one of) my attempt(s):

lemma [simp]: "⋀ d k l :: int. 0 < d ⟶
         ¬ 2 * k + 1 ≤ 2 * l ⟶
         2 * l ≠ 1 ⟶ - (2 * l) < 2 * k - 1 ⟶ k ≤ l ⟶ d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)"
proof -
  fix d k l :: int
  assume "¬ 2 * k + 1 ≤ 2 * l" "k ≤ l"
  then have "k = l" by simp
  then have "d * (4 * l - 1) = d * (4 * k - 1) " by auto
  moreover have "d * (2 * l - 2) + d * (2 * l) + d = d * (4 * l - 1)" by algebra
  ultimately have "d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)" by auto
  from this show ?thesis
qed

I get a weird "Type unification failed" error.

Operator:  Trueprop :: bool ⇒ prop
Operand:   ?thesis :: int ⇒ int ⇒ int ⇒ bool

Anyone have some idea? Maybe how it is possible to overall prove this statement much simpler?

chris
  • 4,988
  • 20
  • 36
HdM
  • 169
  • 1
  • 11
  • Maybe helpful for future readers: I found that at the very beginning it helped to stick to the very basic keywords: `assume X:"..."` `from X Y have Z:"..."` and avoid `then`/`with`/`moreover`/`ultimately` etc – user253751 Aug 10 '22 at 18:48

2 Answers2

2

(Update: I start on these, and then someone else gives an answer after I've worked quite a bit up, so I go ahead and put up what I've done.

What I was wanting to know came in the other answer, which is the use of term ?thesis in the proof, to help match up the error message with where the problem is.

Maybe my answer here adds a little context for the other answer.)

Below, I use !! for meta-logic all, instead of \<And>.

You've entered into to the mysterious meta-logic-vs-object-logic-zone. A little understanding makes things a lot less mysterious.

Below, I give you a way to show the use of the hidden Trueprop function, which will take some of the mystery away.

  • explain a little about the 3 Pure meta-logic operators, and their relationship oto the HOL object-logic,
  • give 3 different forms of your lemma, starting with yours,
  • where the show ?thesis of the third form is finally acceptable to the proof engine.

I don't completely sort things out here. For myself, many times it's not important that I completely understand everything, but it is important that I'm not totally in the dark about the types of the meta-logic and object-logic functions that are being used, which is at the heart of all this.

HOL bool, Pure prop, and Trueprop :: (bool => prop), to tie HOL into Pure

The notation for the Trueprop function is normally hidden. You can define notation to see where it's applied in the output panel. I define notation here with some declares:

notation (output) Trueprop ("_:@T" [1000] 999)
declare[[show_brackets=false, show_types, show_sorts=false, show_consts]]

Here's the type of Trueprop:

term "Trueprop :: bool => prop"

In your lemma below, because you're using --> instead of ==>, the output shows that the series of implications is of type bool, and it's being coerced to prop by Trueprop, as shown by the notation :@T.

HOL logical connectives are of type bool. For example,

term "op --> :: (bool => bool => bool)"
term "A --> B :: bool"

3 main operators of Pure: eq (==), imp (==>), and all (!!)

Here, I confirm their types. CNTL-click on them to take you to them. A little awareness of the types involved, can make error messages less mysterious.

term "Pure.eq :: 'a => 'a => prop"
term "Pure.imp :: prop => prop => prop"
term "Pure.all :: ('a => prop) => prop"

There's too much to try and say about all this. Someone needs to write a textbook, for logic novices, like me, explaining the logic of Isabelle/HOL, starting with Pure.

prop vs bool

Free variables are implicitly, universally quantified, so I can get rid of the use of !!. The result is that the type of the term changes from prop to bool. Turning on type info can help make sense of type error messages.

term "(!! d k l :: int. 0 < d  --> ¬ 2 * k + 1 ≤ 2 * l --> 2 * l ≠ 1 
  --> -(2 * l) < 2 * k - 1 --> k ≤ l 
  --> d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)) :: prop"

term "(0 < (d::int)  --> ¬ 2 * k + 1 ≤ 2 * l --> 2 * l ≠ 1 
  --> -(2 * l) < 2 * k - 1 --> k ≤ l 
  --> d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)) :: bool"

Your original

You start out with ?thesis ::int => int => int => bool`.

declare[[show_types=false]]
lemma "!! d k l :: int. 0 < d  --> ¬ 2 * k + 1 ≤ 2 * l --> 2 * l ≠ 1 
  --> -(2 * l) < 2 * k - 1 --> k ≤ l 
  --> d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)" (*
1. !!d k l. (0 < d --> ¬ 2 * k + 1 ≤ 2 * l --> 2 * l ≠ 1 -->
    - (2 * l) < 2 * k - 1 --> k ≤ l -->
    d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)):@T *)
proof -
  fix d k l ::int
  assume " ¬ 2 * k + 1 ≤ 2 * l" "k ≤ l"
  then have "k = l" by simp
  then have "d * (4 * l - 1) = d * (4 * k - 1) " by auto
  moreover have "d * (2 * l - 2) + d * (2 * l) + d = d * (4 * l - 1)" by algebra
  ultimately have "d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)" by auto
    from this
    term "?thesis" (*
      "λd k l. 0 < d --> ¬ 2 * k + 1 ≤ 2 * l --> 2 * l ≠ 1 
      --> - (2 * l) < 2 * k - 1 
      --> k ≤ l --> d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)"
      :: "int => int => int => bool" *)
  show ?thesis (*
    Type unification failed: Clash of types "_ => _" and "bool"
    Type error in application: incompatible operand type
    Operator:  Trueprop :: bool => prop
    Operand:   ?thesis∷int => int => int => bool ::
      int => int => int => bool
    Coercion Inference:
    Local coercion insertion on the operand failed:
    No coercion known for type constructors: "fun" and "bool" *)
oops

Getting rid of the explicit use of !!

I get rid of !!, and now I get ?thesis :: bool, and the error message changes to a very common, frustrating error, "fails to refine any pending goal". It means somehow, I'm not matching up what I'm going to show, with what the proof engine sees as the goal (I guess).

lemma "0 < (d::int) 
       --> ¬ 2 * k + 1 ≤ 2 * l 
       --> 2 * l ≠ 1 
       --> - (2 * l) < 2 * k - 1 --> k ≤ l 
       --> d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)"
proof -
  fix d k l ::int
  assume " ¬ 2 * k + 1 ≤ 2 * l" "k ≤ l"
  then have "k=l" by simp
  then have "d * (4 * l - 1) = d * (4 * k - 1) " by auto
  moreover have "d * (2 * l - 2) + d * (2 * l) + d = d * (4 * l - 1)" by algebra
  ultimately have "d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)" by auto
    from this
    term "?thesis" (*
      "0 < d --> ¬ 2 * k + 1 ≤ 2 * l --> 2 * l ≠ 1 --> - (2 * l) < 2 * k - 1 
      --> k ≤ l --> d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)"
      :: "bool"        
    *)
  show ?thesis (*
  Failed to refine any pending goal 
  Local statement fails to refine any pending goal
  Failed attempt to solve goal by exported rule:
    ((¬ 2 * ?ka2 + 1 ≤ 2 * ?la2):@T) ==>
    ((?ka2 ≤ ?la2):@T) ==>
    (0 < d --> ¬ 2 * k + 1 ≤ 2 * l --> 2 * l ≠ 1 --> - (2 * l) < 2 * k - 1 
    --> k ≤ l --> d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)):@T *)
oops

Now ==> in place of -->, and a show ?thesis that gets accepted

And now I replace --> with ==>. The type of ?thesis is still bool, and it now accepts show ?thesis.

lemma "0 < (d::int) 
       ==> ¬ 2 * k + 1 ≤ 2 * l 
       ==> 2 * l ≠ 1 
       ==> - (2 * l) < 2 * k - 1  ==> k ≤ l 
       ==> d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)"
proof -
  fix d k l ::int
  assume " ¬ 2 * k + 1 ≤ 2 * l" "k ≤ l"
  then have "k=l" by simp
  then have "d * (4 * l - 1) = d * (4 * k - 1) " by auto
  moreover have "d * (2 * l - 2) + d * (2 * l) + d = d * (4 * l - 1)" by algebra
  ultimately have "d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)" by auto
    from this
    term "?thesis" (*
      "d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)" :: "bool"*)
  show ?thesis (*
goal (1 subgoal):
 1. (d * ((2::int) * k - (2::int)) + d * ((2::int) * l) + d =
     d * ((4::int) * k - (1::int))):@T *)
oops

No need to strain my brain any more today. There are subtleties in what we have to do, to give the proof the engine the facts it wants, in the way it wants them. I can look at the other answer and figure things out more.

1

The error is not weird at all. Just have a look at the term that is represented by ?thesis (via term "?thesis")

"λd k l.
    0 < d ⟶
    ¬ 2 * k + 1 ≤ 2 * l ⟶
    2 * l ≠ 1 ⟶
    - (2 * l) < 2 * k - 1 ⟶
    k ≤ l ⟶
    d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)"
  :: "int ⇒ int ⇒ int ⇒ bool"

You can see that the -bound variables have been turned into parameters for ?thesis (which thus has function type).

Additionally you used assume in your prove without first making the step from HOL implication --> to Pure implication ==>. Your lemma can be proved as follows:

lemma [simp]:
  "⋀ d k l ::int. 0 < d ⟶
  ¬ 2 * k + 1 ≤ 2 * l ⟶
  2 * l ≠ 1 ⟶
  - (2 * l) < 2 * k - 1 ⟶
  k ≤ l ⟶
  d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)"
proof -
  fix d k l :: int
  { assume "¬ 2 * k + 1 ≤ 2 * l" and "k ≤ l"
    then have "k = l" by simp
    then have "d * (4 * l - 1) = d * (4 * k - 1) " by auto
    moreover have "d * (2 * l - 2) + d * (2 * l) + d = d * (4 * l - 1)"     by algebra
    ultimately have "d * (2 * k - 2) + d * (2 * l) + d = d * (4 * k - 1)"     by auto }
  then show "?thesis d k l" by simp
qed

Here I use a raw proof block (inside curly braces) to prove a statement locally that is then used to obtain the final result.

More abstractly a block

{ fix x assume "A x" ... have "B x" ... }

results in the fact

!!x. A x ==> B x

This is described in more detail in Section 2.2 of the Isabelle/Isar Reference Manual.

chris
  • 4,988
  • 20
  • 36