Again, transitive closure and identity - isabelle

I have another theorem that I am not being able to prove in Isabelle, involving identity and transitive closure.
It is the following:
lemma "r ⊆ Id ⟹ r^* = Id"
Update: Using apply-style I have the following:
lemma "r ⊆ Id ⟹r^* = Id"
apply (rule equalityI)
apply (rule subrelI)
apply (erule rtrancl_induct)
apply (blast+)
done
How can the same be done in Isar?

It seems that your question is more about transforming apply-style proofs into proper Isar. For the specific example you have this can be done as follows. As you mentioned yourself in
lemma "r ⊆ Id ⟹ r^* = Id"
there are difficulties to refer to the assumption r ⊆ Id. The canonical Isar way of structuring this proof is as follows. We start a proof via
proof -
where the - indicates that no initial rule should be used. This just serves the purpose to be able to state assumptions explicitly.
assume *: "r ⊆ Id"
show "r^* = Id"
In addition we give the name * to the assumption. Alternatively we could have stated the whole lemma differently as
lemma
assumes *: "r ⊆ Id"
shows "r^* = Id"
which saves one level of nesting. Anyway, having this, as you said, equality of sets is again canonical, namely:
proof
show "r^* ⊆ Id"
proof (rule subrelI)
fix x y
assume "(x, y) ∈ r^*"
then show "(x, y) ∈ Id"
using * by (induct) blast+
The above line is where we use the assumption (alternatively, we could refer to the assumption literally via ‹r ⊆ Id› or via the implicit name assms that is introduced for the facts following assumes). And we finish by:
qed
next
show "Id ⊆ r^*" by blast
qed

Related

How do you print local variables and ?thesis in an Isabelle proof (debugging in Isabelle)?

I sometimes find it hard to use Isabelle because I cannot have a "print command" like in normal programming.
For example, I want to see what ?thesis. The concrete semantics book says:
The unknown ?thesis is implicitly matched against any goal stated by lemma or show. Here is a typical example:
My silly sample FOL proof is:
lemma
assumes "(∃ x. ∀ y. x ≤ y)"
shows "(∀x. ∃ y. y ≤ x)"
proof (rule allI)
show ?thesis
but I get the error:
proof (state)
goal (1 subgoal):
1. ⋀x. ∃y. y ≤ x
Failed to refine any pending goal
Local statement fails to refine any pending goal
Failed attempt to solve goal by exported rule:
∀x. ∃y. y ≤ x
but I do know why.
I expected
?thesis === ⋀x. ∃y. y ≤ x
since my proof state is:
proof (state)
goal (1 subgoal):
1. ⋀x. ∃y. y ≤ x
Why can't I print ?thesis?
It's really annoying to have to write the statement I'm trying to proof if it's obvious. Perhaps it's meant to be explicit but in the examples in chapter 5 they get away with using ?thesis in:
lemma fixes a b :: int assumes "b dvd (a+b)" shows "b dvd a" proof −
have "∃k′. a = b∗k′" if asm: "a+b = b∗k" for k proof
show "a = b∗(k − 1)" using asm by(simp add: algebra_simps) qed
then show ?thesis using assms by(auto simp add: dvd_def ) qed
but whenever I try to use ?thesis I always fail.
Why is it?
Note that this does work:
lemma
assumes "(∃ x. ∀ y. x ≤ y)"
shows "(∀x. ∃ y. y ≤ x)"
proof (rule allI)
show "⋀x. ∃y. y ≤ x" proof -
but I thought ?thesis was there to avoid this.
Also, thm ?thesis didn't work either.
Another example is when I use:
let ?ys = take k1 xs
but I can't print ?ys value.
TODO:
why doesn't:
lemma "length(tl xs) = length xs - 1"
thm (cases xs)
show anything? (same if your replaces cases with induction).
You can find ?theorem and others in the print context window:
As for why ?thesis doesn't work, by applying the introduction rule proof (rule allI) you are changing the goal, so it no longer matches ?thesis. The example in the book uses proof- which prevents Isabelle from applying any introduction rule.
It seems I asked a very similar question worth pointing to: What is the best way to search through general definitions, theorems, functions, etc for Isabelle?
But here is a list of thing's I've learned so far:
thm: seems to work for definition, lemmas and functions. For definition do name_def for a definition with name name. For functions do thm f.simps for all definitions in the function. For a single one do thm f.simps(1) for the first one. For lemmas do thm lemma_name or thm impI or HOL.mp etc.
term: for terms do term term_name e.g. in isar term ?thesis or term this
print_theorems: if you place this after a definition or a function it shows all the theorems defined for those! It's amazing.
print... I just noticed in jedit if you let the auto complete show you the rest for print it has a bunch of options! Probably useful!
Search engine for Isabelle: https://search.isabelle.in.tum.de/
You can use Query (TODO: improve this)
TODO: how to find good way to display stuff about tactics.
I plan to update this as I learn all the ways to debug in Isabelle.

How to prove this simple theorem in Isabelle?

I define a very simple function replace which replaces 1 with 0 while preserving other input values. I want to prove that the output of the function cannot be 1. How to achieve this?
Here's the code.
theory Question
imports Main
begin
fun replace :: "nat ⇒ nat" where
"replace (Suc 0) = 0" |
"replace x = x"
theorem no1: "replace x ≠ (Suc 0)"
sorry
end
Thanks!
There exist several approaches for proving the statement that you are trying to prove.
You can make an attempt to use sledgehammer to find the proof automatically, e.g.
theorem no1: "replace x ≠ (Suc 0)"
by sledgehammer
(*using replace.elims by blast*)
Once the proof is found, you can delete the explicit invocation of the command sledgehammer.
Perhaps, a slightly better way to state the proof found by the sledgehammer would be
theorem no1': "replace x ≠ (Suc 0)"
by (auto elim: replace.elims)
You can also try to provide a more specialized proof. For example,
theorem no1: "replace x ≠ (Suc 0)"
by (cases x rule: replace.cases) simp_all
This proof looks at the different cases the value of x can have and then uses simplifier (in conjunction with the simp rules provided by the command fun during the definition of your function) to finish the proof. You can see all theorems that are generated by the command fun by typing print_theorems immediately after the specification of replace, e.g.
fun replace :: "nat ⇒ nat" where
"replace (Suc 0) = 0" |
"replace x = x"
print_theorems
Of course, there are other ways to prove the result that you are trying to prove. One good way to improve your ability to find such proofs is by reading the documentation and tutorials on Isabelle. My own starting point for learning Isabelle was the book "Concrete Semantics" by Tobias Nipkow and Gerwin Klein.

Isabelle/HOL restrict codomain

I am sorry for asking so many Isabelle questions lately. Right now I have a type problem.
I want to use a type_synonym introduced in a AFP-theory.
type_synonym my_fun = "nat ⇒ real"
I have a locale in my own theory where:
fixes n :: nat
and f :: "my_fun"
and A :: "nat set"
defines A: "A ≡ {0..n}"
However, in my use case the output of the function f is always a natural number in the set {0..n}. I want to impose this as a condition (or is there a better way to do it?). The only way I found was to:
assumes "∀v. ∃ i. f v = i ∧ i ∈ A"
since
assumes "∀v. f v ∈ A"
does not work.
If I let Isabelle show me the involved types it seems alright to me:
∀v::nat. ∃i::nat. (f::nat ⇒ real) v = real i ∧ i ∈ (A::nat set)
But of course now I cannot type something like this:
have "f ` {0..10} ⊆ A"
But I have to prove this. I understand where this problem comes from. However, I do not know how to proceed in a case like this. What is the normal way to deal with it? I would like to use my_fun as it has the same meaning as in my theory.
Thank you (again).
If you look closely at ∀v::nat. ∃i::nat. (f::nat ⇒ real) v = real i ∧ i ∈ (A::nat set), you will be able to see the mechanism that was used for making the implicit type conversion between nat and real: it is the abbreviation real (this invokes of_nat defined for semiring_1 in Nat.thy) that appears in the statement of the assumption in the context of the locale.
Of course, you can use the same mechanism explicitly. For example, you can define A::real set as A ≡ image real {0..n} instead of A::nat set as A ≡ {0..n}. Then you can use range f ⊆ A instead of assumes "∀v. ∃ i. f v = i ∧ i ∈ A”. However, I doubt that there is a universally accepted correct way to do it: it depends on what exactly you are trying to achieve. Nonetheless, for the sake of the argument, your locale could look like this:
type_synonym my_fun = "nat ⇒ real"
locale myloc_basis =
fixes n :: nat
abbreviation (in myloc_basis) A where "A ≡ image real {0..n}"
locale myloc = myloc_basis +
fixes f :: "my_fun"
assumes range: "range f ⊆ A"
lemma (in myloc) "f ` {0..10} ⊆ A"
using range by auto
I want to impose this as a condition (or is there a better way to do
it?).
The answer depends on what is known about f. If only a condition on the range of f is known, as the statement of your question seems to suggest, then, I guess, you can only state is as an assumption.
As a side note, to the best of my knowledge, defines is considered to be obsolete and it is best to avoid using it in the specifications of a locale: stackoverflow.com/questions/56497678.

Isabelle FOL partial Rule application

Let's assume we have such variant of Modus Ponens
lemma invDed: ‹(A-->B)==>(A==>B)›
apply(rule mp)
apply assumption
apply assumption
done
Can it be applied for proving the theorem? (I mean A:=A, B:=A, and A-->A we use as if it was previously proved)
lemma myid2: "A==>A"
If not, why? I know several other ways to prove this theorem("apply assumption" or 5-step proof from Frege's propositional calculus axioms.), but I interested in this nuance of proof mechanics.
i have one rule, now I want obtain an another [admissible] rule, what's problem?
Application with rule only applies to the formula after the rightmost meta implication (==>). So you would get something like the following, which is not very helpful:
lemma myid2: "A==>A"
proof (rule invDed[where A=A and B=A])
show "A ⟹ A ⟶ A"
by (rule imp_refl)
show "A ⟹ A"
by assumption
qed
If you rotate your premises (done below with the [rotated] modifier) to have A==>(A-->B)==>(B), then you can apply it with erule:
lemma myid2: "A==>A"
apply (erule invDed[rotated])
apply (rule imp_refl)
done

Instantiating a class from a concrete object?

I'm attempting to formalize a series of proofs about topology from a book [1] in Isabelle.
I want to encode the idea that a topological space (X,T) consists of a set X of "points" (elements of some arbitrary type 'a), and a set of subsets of X, called T, such that:
A1. if an element p is in X, then there exists at least one set N in T that also contains p.
A2. if sets U and V are in T, and if p∈(U∩V), then there must exist at a set N in T where N⊆(U∩V) and x∈N. (If two sets intersect, then there must be a neighborhood that covers the intersection.).
Currently I have the following definition:
class topspace =
fixes X :: "'a set"
fixes T :: "('a set) set"
assumes A1: "p∈X ≡ ∃N∈T. p∈N"
assumes A2: "U∈T ∧ V∈T ∧ x∈(U∩V) ⟹ ∃N∈T. x∈N ∧ N⊆(U∩V)"
begin
(* ... *)
end
So far, so good. I'm able to add various definitions and prove various lemmas and theorems about hypothetical topspace instances.
But how do I actually create one? Unless I'm misinterpreting things, the examples I've seen so far for the instance and instantiate keywords all seem to be been about declaring that one particular abstract class (or type or locale) is an instance of another.
How do I tell Isabelle that a particular pair of sets (e.g. X={1::int, 2, 3}, T={X,{}}) form a topspace?
Likewise, how can I use my definition to prove that X={1::int, 2, 3}, T={} does not fit the requirements?
Finally, once I show that a particular concrete object X meets the definition of a topspace, how do I tell Isabelle to now make use of all the definitions and theorems I've proven about topspace when proving things about X?
BTW, I'm using class because I don't know any better. If it's not the right tool for the job, I'm happy to do something else.
[1]: A Bridge to Advanced Mathematics by Dennis Sentilles
I've made some progress here: a class is a special type of locale, but it isn't necessary for this sort of usage, and using the locale keyword directly simplifies the situation a bit. Every locale has an associated theorem that you can use to instantiate it:
locale topspace =
fixes X :: "'a set"
fixes T :: "('a set) set"
assumes A1 [simp]: "x∈X ≡ ∃N∈T. x∈N"
assumes A2 [simp]: "U∈T ∧ V∈T ∧ x∈(U∩V) ⟹ ∃N∈T. x∈N ∧ N⊆(U∩V)"
theorem
assumes "X⇩A={1,2,3::int}" and "T⇩A={{}, {1,2,3::int}}"
shows "topspace X⇩A T⇩A"
proof
show "⋀U V x. U∈T⇩A ∧ V∈T⇩A ∧ x∈U∩V ⟹ ∃N∈T⇩A. x∈N ∧ N⊆U∩V"
and "⋀x. x∈X⇩A ≡ ∃N∈T⇩A. x∈N" using assms by auto
qed
If we want to use definition for declarations, the proof goal becomes a bit more complex, and we need to use the unfolding keyword. (The locales.pdf that comes with isabelle covers this, but I'm not sure I'm not yet able to explain it in my own words). Anyway, this works:
experiment
begin
definition X⇩B where "X⇩B={1,2,3::int}"
definition T⇩B where "T⇩B={{}, {1,2,3::int}}"
lemma istop0: "topspace X⇩B T⇩B" proof
show "⋀U V x. U∈T⇩B ∧ V∈T⇩B ∧ x∈U∩V ⟹ ∃N∈T⇩B. x∈N ∧ N⊆U∩V"
and "⋀x. x∈X⇩B ≡ ∃N∈T⇩B. x∈N" unfolding X⇩B_def T⇩B_def by auto
qed
end
I believe it's also possible, and possibly preferable, to do all this work inside of a sub-locale, but I haven't quite worked out the syntax for this.
Although locales are implemented in the calculus itself and hence their predicates can be used in any regular proposition, this is usually not recommended. Instead, you should instantiate locales using e.g. interpretation, as in the following example.
locale topspace =
fixes X :: "'a set"
fixes T :: "('a set) set"
assumes A1 [simp]: "x∈X ⟷ (∃N∈T. x∈N)"
assumes A2 [simp]: "U∈T ∧ V∈T ∧ x∈(U∩V) ⟹ ∃N∈T. x∈N ∧ N⊆(U∩V)"
context
fixes X⇩A T⇩A
assumes X⇩A_eq: "X⇩A = {1, 2, 3 :: int}"
and T⇩A_eq: "T⇩A = {{}, {1, 2, 3 :: int}}"
begin
interpretation example: topspace X⇩A T⇩A
by standard (auto simp add: X⇩A_eq T⇩A_eq)
lemmas facts = example.A1 example.A2
end
thm facts
Whether this pattern really fits for your needs depends on your application; if you just want to have a predicate, it is better to define it directly without using locale at all.
Note: there is really need to the Pure equality »≡«; prefer HOL equality »=«, or its syntactic variant »⟷«.

Resources