Why is this seemingly incorrect proof OK with Isabelle? - isabelle

While copying the following proof from the PDF tutorial of Isabelle 2020 into the IDE (about Cantor’s theorem that a function from a set to its powerset cannot be surjective), I made a typo on the "from 1 have 2" line.
lemma "¬ surj (f :: 'a ⇒ 'a set)"
proof
assume 0: "surj f"
from 0 have 1: "∀ A. ∃ a. A = f a" by(simp add: surj_def )
from 1 have 2: "∃ a. {x. x ∉ f x} = f a" by blast
from 2 show "False" by blast
qed
, so that the line now reads (with a wrong forall quantifier)
from 1 have 2: "∀ a. {x. x ∉ f x} = f a" by blast
Strangely, both the original proof in the example and this changed version work. But the changed version is incorrect, isn't it?
Am I missing something or can someone explain how the changed version (below) is correct?
lemma "¬ surj (f :: 'a ⇒ 'a set)"
proof
assume 0: "surj f"
from 0 have 1: "∀ A. ∃ a. A = f a" by(simp add: surj_def )
from 1 have 2: "∀ a. {x. x ∉ f x} = f a" by blast
from 2 show "False" by blast
qed
--- Update ---
To help diagnose the problem, below is the output when I place the mouse on the "from 2 show ..." line. It mentions an exported rule, which seems to be the theorem to be proven. (I don't remember exporting the rule myself, other than maybe accidentally getting the quantifier right in a few trials.)
show False
Successful attempt to solve goal by exported rule:
(surj f) ⟹ False
proof (state)
this:
False
goal:
No subgoals!
I just tried closing Isabelle and reopening the same .thy file, and got the same result. (As you can see, I am new to the Isabelle environment). Did I just save the theorem somewhere when I entered the right text?

Which Isabelle version are you using? On mine the blast call does not terminate (within a few seconds), as highlighted by the background:
However, Isabelle is optimistic: it assumes that blast will eventually terminate (it won't). Hence the next step is checked (and that one holds because types are not empty: "∀ a. P a", then "∃ a. P a"). That might give you the impression that the proof is going through, but it is not the case.

Related

How can I use proved goals of locale interpretation to prove the remaining ones

I define a strict order locale as follows:
locale strict_order =
fixes ls::"'a set ⇒ 'a set ⇒ bool"
assumes
irrefl:"¬ ls a a" and
trans:"ls a c ∧ ls c g ⟹ ls a g" and
asym:"ls a c ⟹ ¬ ls c a"
Then, I declare a type as interpretation of strict_order
interpretation nest:strict_order "op ≪"
proof
fix a
show "¬ a ≪ a"
proof (rule contra, auto)
....
qed
next
fix a c g
assume a:"a ≪ c ∧ c ≪ g"
show " a ≪ g"
proof -
(* uses the fact that ¬ a<<a *)
The proof "trans" property for type nest needs at some point "irrefl" property which has been successfully proved inside the interpretation block. How can I label and use it? Or there is no way but moving it outside the interpretation block?
Thanks.
If you state a fact with show, you can name it just like with have, e.g., show irrefl: "¬ a ≪ a". However, next drops everything that you have proven so far, so you have to avoid next. Conceptually, next corresponds to closing a block and opening a new one, i.e., next essentially means } {.
Hence, you could write something like the following:
proof
{ fix a
show "¬ a ≪ a"
proof (rule contra, auto) .... qed }
note irrefl = this
{ fix a c g
assume a: "a ≪ c ∧ c ≪ g"
show "a ≪ g"
proof - ... (* can reference irrefl *) qed }
qed
Note that you can name the irreflexivity law only after closing the block, because you want the fixed a being generalised, which only happens upon export from the block. If you are using Isabelle2016 or later, you can write the cases more concisely using for and if clauses. This saves you all the boilerplate with } and {.
proof
show irrefl: "¬ a ≪ a" for a
proof (rule contra, auto) .... qed
show "a ≪ g" if a: "a ≪ c ∧ c ≪ g" for a c g
proof - ... (* can reference irrefl *) qed
qed

Failed to apply initial proof method. Proving an empty trace contains no messages

I am trying to prove that in a trace of a protocol run a message will not be in an empty trace. The eventual goal is to prove that no host will send a message to itself. This seems intuitively simple so I'm not actually sure what is happening. The error I receive is
Failed to apply initial proof method⌂:
using this:
[] ∈ ns_public
goal (1 subgoal):
1. ∀A B X. Says A B X ∉ set_of_list []
Here is the code in question.
inductive_set ns_public :: "event list set"
where
Nil[intro!,simp] : "[] ∈ ns_public" |
....
<snip>
....
lemma "∀ A B X. [] ∈ ns_public ⟶ Says A B X ∉ set_of_list []"
proof
assume "[] ∈ ns_public"
from this have "∀ A B X. Says A B X ∉ set_of_list []"
from this show "True" by blast
oops

Isabelle - Nitpick counterexample usage

I would like to complete this proof.
How can I easily/elegantly use the values found by nitpick? (What to write at the ... part?)
Alternatively, how can I use the fact that nitpick found a counterexample to finish the proof?
lemma Nitpick_test: "¬(((a+b) = 5) ∧ ((a-b) = (1::int)))" (is "?P")
proof (rule ccontr)
assume "¬ ?P"
nitpick
(* Nitpicking formula...
Nitpick found a counterexample:
Free variables:
a = 3
b = 2
*)
show "False" by ...
qed
The theorem does not hold as stated, because if a = 3 and b = 2, the statement evaluates to False. For other values of a and b, however, the statement does hold. Thus, as a and b are implicitly universally quantified, you cannot prove the theorem as stated.
If you want to instead prove
theorem "EX a b. a + b = 5 & a - b = (1 :: int)"
you can use rule exI[where x="..."] to provide the witness ... for the existential quantifier, so 3 and 2 in this case.

how to get isabelle to recognize an obvious conclusion

I'm trying to prove that the frontier, interior and exterior of a set are disjoint in isabelle. On the line I have marked '***', the fact that c \<inter> d = {} clearly follows from the previous line given the assumption at the start of the block, so how would I get isabelle to understand this?
theory Scratch
imports
"~~/src/HOL/Multivariate_Analysis/Topology_Euclidean_Space"
"~~/src/HOL/Probability/Sigma_Algebra"
begin
lemma boundary_disjoint: "disjoint {frontier S, interior S, interior (-S)}"
proof (rule disjointI)
fix c d assume sets:
"c \<in> {frontier S, interior S, interior (-S)}"
"d \<in> {frontier S, interior S, interior (-S)}"
and "c \<noteq> d"
show "c \<inter> d = {}"
proof cases
assume "c = frontier S \<and> d = interior S"
then show ?thesis using frontier_def by auto
next
assume "c = frontier S \<and> d = interior (-S)"
have "closure S \<inter> interior (-S) = {}" by (simp add: closure_interior)
hence "frontier S \<inter> interior (-S) = {}" using frontier_def by auto
*** then show ?thesis by auto
next
qed
qed
end
In Isar, you have to explicitly reference the facts you want to use. If you say that your goal follows from the previous line and the local assumption you made, you should give the assumption a name by writing assume A: "c = frontier S ∧ d = interior (-S)", and then you can prove your goal by with A have ?thesis by auto.
Why did I write have and not show? Well, there is another problem. You did a proof cases, but that uses the rule (P ⟹ Q) ⟹ (¬P ⟹ Q) ⟹ Q, i.e. it does a case distinction of the kind ‘Is P true or false?’. That is not what you want here.
One way to do your case distiction is by something like this:
from sets show "c ∩ d = {}"
proof (elim singletonE insertE)
insertE is an elimination rule for facts of the form x ∈ insert y A, and since {a,b,c} is just syntactic sugar for insert a (insert b (insert c A)), this is what you want. singletonE is similar, but specifically for x ∈ {y}; using singletonE instead of insertE means you do not get trivial cases with assumptions like x ∈ {}.
This gives you 9 cases, of which 3 are trivially solved by simp_all. The rest you have to prove yourself in Isar if you want to, but they can be solved quite easily by auto as well:
from sets and `c ≠ d` show "c ∩ d = {}"
by (auto simp: frontier_def closure_def interior_closure)

Express that a function is constant on a set

I’m trying to express that a function f is constant on a set S, with value r My first idea was
f ` S = {r}
but that does not work, as S can be empty. So I am currently working with
f ` S ⊆ {r}
and it works okish, but I have the impression that this is still not ideal for the standard automation. In particular, auto would fail leaving this goal (irrelevant facts erased)
2. ⋀xa. thunks (delete x Γ) ⊆ thunks Γ ⟹
ae ` thunks Γ ⊆ {up⋅0} ⟹
xa ∈ thunks (delete x Γ) ⟹
ae xa = up⋅0
Sledgehammer of course has no problem (metis image_eqI singletonD subsetCE), but there are a few occurrences of this. (In general, ⊆ does not seem to work with auto as good as I’d expect).
There there a better way to express this, i.e. one that can be used by auto more easily when occurring as an assumption?
I didn't try it, since I didn't have any examples handy. But you might try the following setup.
definition "const f S r ≡ ∀x ∈ S. f x = r"
Which is equivalent to your definition:
lemma
"const f S r ⟷ f ` S ⊆ {r}"
by (auto simp: const_def)
Then employ the following simp rule:
lemma [simp]:
"const f S r ⟹ x ∈ S ⟹ f x = r"
by (simp add: const_def)
The Analysis library defines
definition constant_on (infixl "(constant'_on)" 50)
where "f constant_on A \<equiv> \<exists>y. \<forall>x\<in>A. f x = y"

Resources