简体   繁体   中英

Doing this proof automatically on Isabelle

I satarted to work with Isabelle a few weeks ago and it's hard to me to do some proves automatically. I've just use the rule "less_induct" to show a property on a list.

theorem cuenta_ordena_1:
"cuenta (ordena xs) y = cuenta xs y"

proof(induct "length xs" arbitrary: xs rule: less_induct)
case less
show ?case
proof(cases xs)
assume "xs=[]"
  then show ?thesis by simp
next
fix a list
assume "xs=a#list"
have "length(menores a list)<Suc(length list)" by simp
also have "... = length (a#list)" by simp
also have "... = length (xs)" using `xs=a#list` by simp
finally have 1:"length (menores a list)< length xs" by simp

have "length(mayores a list)<Suc(length list)" by simp
also have "... = length (a#list)" by simp
also have "... = length (xs)" using `xs=a#list` by simp
finally have 2:"length (mayores a list)< length xs" by simp

have " cuenta (ordena xs) y= cuenta (ordena (a#list)) y" using `xs=a#list` by simp
also have "...=  cuenta ((ordena (menores a list)) @ (a # (ordena (mayores a list)))) y " by simp
also have "... =  cuenta (ordena (menores a list)) y + cuenta (a # (ordena (mayores a list))) y " by (rule cuenta_append)
also have "... = cuenta (menores a list) y + cuenta (a # (ordena (mayores a list))) y " using less 1 by simp
finally have 3:"cuenta(ordena xs) y = cuenta (menores a list) y + cuenta (a # (ordena (mayores a list))) y" by simp
also have 4:"... = cuenta xs y"
  proof(cases "a=y")
  case False
    then have "cuenta (menores a list) y + cuenta (a # (ordena (mayores a list))) y 
              = cuenta (menores a list) y + cuenta (ordena (mayores a list)) y " by simp
    also have "... = cuenta (menores a list) y + cuenta (mayores a list) y " using less 2 by simp
    also have "... = cuenta xs y"
      proof (cases "y<a")
      case True
        hence "cuenta (menores a list) y + cuenta (mayores a list) y 
                = cuenta list y + cuenta (mayores a list) y" by (simp add: cuenta_menores)
        also have "... = cuenta list y" using "True" by (simp add: cuenta_mayores)
        also have "... = cuenta (a#list) y" using "False" by simp
        finally show ?thesis using `xs=a#list` by simp
      next
      case False
        hence "cuenta (menores a list) y + cuenta (mayores a list) y 
                =  cuenta (mayores a list) y" by (simp add: cuenta_menores)
        also have "... = cuenta list y" using "False" by (simp add: cuenta_mayores)
        also have "... = cuenta (a#list) y" using `¬(a=y)` by simp
        finally show ?thesis using `xs=a#list` by simp            
      qed
  finally show ?thesis by simp
  next
  case True
    hence "¬(y<a)" by simp
    have "cuenta (menores a list) y + cuenta (a # (ordena (mayores a list))) y 
              = cuenta (menores a list) y + Suc(cuenta (ordena (mayores a list)) y) " using "True" by simp 
    also have "... = cuenta (menores a list) y + Suc(cuenta (mayores a list) y) " using less 2 by simp
    also have "... = Suc(cuenta(mayores a list) y)" using `¬(y<a)` by (simp add: cuenta_menores) 
    also have "... = Suc(cuenta list y)" using `¬(y<a)` by (simp add: cuenta_mayores)
    also have "... = cuenta (a#list) y" using "True" by simp
    finally show ?thesis using `xs=a#list` by simp
  qed
  finally show ?thesis using 3 4 by simp   
 qed   
qed

To do the automatic proof I think I have to write something like this:

theorem cuenta_ordena:
  "cuenta (ordena xs) y = cuenta xs y"
apply (induction "length xs" arbitrary: xs rule: less_induct) 
apply (cases xs)
apply (auto simp add: cuenta_append cuenta_menores cuenta_mayores)

Can you help me?

Thank you!

Based upon your proof and my meagre knowledge of Spanish, I imagine your theory looks something like this:

fun mejores :: "('a :: linorder) ⇒ 'a list ⇒ 'a list" where
  "mejores y [] = []"
| "mejores y (x#xs) = (if x ≥ y then [x] else []) @ mejores y xs"

fun menores :: "('a :: linorder) ⇒ 'a list ⇒ 'a list" where
  "menores y [] = []"
| "menores y (x#xs) = (if x < y then [x] else []) @ menores y xs"

lemma length_mejores [simp]: "length (mejores y xs) ≤ length xs"
  by (induction xs) simp_all

lemma length_menores [simp]: "length (menores y xs) ≤ length xs"
  by (induction xs) simp_all

fun ordena where
  "ordena [] = []"
| "ordena (x#xs) = ordena (menores x xs) @ [x] @ ordena (mejores x xs)"

fun cuenta :: "_ list ⇒ _ ⇒ nat" where
  "cuenta [] y = 0"
| "cuenta (x#xs) y = (if y = x then 1 else 0) + cuenta xs y"

The automatic proof you suggested cannot work here, because when you write apply (cases xs) , xs is a variable that is universally quantified in the goal. If you want to do case distinction over such a variable, you should do an Isar proof (as you did before).

An easier approach requiring fewer auxiliary lemmas would be the following:

lemma cuenta_append [simp]: "cuenta (xs @ ys) y = cuenta xs y + cuenta ys y"
  by (induction xs) simp_all

lemma cuenta_mejores_menores: "cuenta (menores x xs) y + cuenta (mejores x xs) y = cuenta xs y"
  by (induction xs) auto

...and the proof is completely automatic:

lemma "cuenta (ordena xs) y = cuenta xs y"
  by (induction xs rule: ordena.induct) (auto simp: cuenta_mejores_menores)

Note that I used the induction rule for the ordena function. The induction on the list length that you did is more general, but that makes it more difficult to use automation. The rule ordena.induct looks like this:

P [] ⟹
(⋀x xs.
    P (menores x xs) ⟹
    P (mejores x xs) ⟹
    P (x # xs)) ⟹
P a0

That is precisely what you need here. Also, note that if you do want to do induction on list length, using the rule length_induct is much easier than natural-number induction on the list length itself, which is what you did.

Also, a simpler definition of ordena that does not require the auxiliary functions menores and mejores would be:

fun ordena :: "('a :: linorder) list ⇒ 'a list" where
  "ordena [] = []"
| "ordena (x#xs) = ordena [y ← xs. y < x] @ [x] @ ordena [y ← xs. y ≥  x]"

Note that [y ← xs. y < x] [y ← xs. y < x] is simply syntactic sugar for filter (λy. y < x) xs . Then you don't need cuenta_mejores_menores anymore and can use the following very general lemma on the interaction between cuenta and filter :

lemma cuenta_filter [simp]: "cuenta (filter P xs) y = (if P y then cuenta xs y else 0)"
  by (induction xs) simp_all

and the proof goes through automatically again:

lemma "cuenta (ordena xs) y = cuenta xs y"
  by (induction xs rule: ordena.induct) auto

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM