How to find the proof method chosen by the "proof" command - isabelle

Take the statement P ⟹ Q ⟹ P ∧ Q as an example. You may prove it with:
lemma dummy: "P ⟹ Q ⟹ P ∧ Q"
proof
assume "P" "Q"
show "P" by fact
show "Q" by fact
qed
Here the proof command chooses some proof method, which generates two subtasks, a proof of P, followed by a proof of Q.
Is there a way for me to find out which method was chosen by proof?
Note: I know the proof method chosen here was rule conjI, my question is for the general case.

As #NieDzejkob already mentioned, the proof method chosen by proof is standard. I'm not an expert in Isabelle/ML, but the following ML snippet traverses the proof term and prints the list of used theorems, which may be helpful in trying to find out the specific theorem used by standard:
ML_command ‹
val thm = #{thm dummy};
val body = Proofterm.strip_thm_body (Thm.proof_body_of thm);
val all_thms = Proofterm.fold_body_thms (fn {name, ...} => insert (op =) name) [body] [];
writeln (commas_quote all_thms);
›

Related

Isabelle Code Generation and Linear Order

I am trying to use the export_code tool for the following definition:
definition set_to_list :: "('a×'a) set ⇒ ('a×'a) list"
where "set_to_list A = (SOME L. set L = A)"
This is not working due to missing code equations for Eps. Now I discovered that there is also a definition:
definition sorted_list_of_set :: "'a set ⇒ 'a list" where
"sorted_list_of_set = folding.F insort []"
However, I am not capable of asserting that ('a ×'a) is a linear order (which would be fine for me, e.g. first comparing the first element and then the second). Can someone help me to either fix my own definition or using the existing one?
To use sorted_list_of_set you can implement the type class linorder for product types:
instantiation prod :: (linorder,linorder) linorder begin
definition "less_eq_prod ≡ λ(x1,x2) (y1,y2). x1<y1 ∨ x1=y1 ∧ x2≤y2"
definition "less_prod ≡ λ(x1,x2) (y1,y2). x1<y1 ∨ x1=y1 ∧ x2<y2"
instance by standard (auto simp add: less_eq_prod_def less_prod_def)
end
You can also import "HOL-Library.Product_Lexorder" from the standard library, which includes a similar definition.
Then you can define set_to_list if you restrict the type parameter to implement linorder:
definition set_to_list :: "('a::linorder×'a) set ⇒ ('a×'a) list"
where "set_to_list A = sorted_list_of_set A"

Isabelle CONST meaning (in relation to THE)

What is the meaning of CONST in Isabelle/Pure? In HOL.thy, we have the following code blocks:
translations "∃!x. P" ⇌ "CONST Ex1 (λx. P)"
translations "THE x. P" ⇌ "CONST The (λx. P)"
translations
"_Let (_binds b bs) e" ⇌ "_Let b (_Let bs e)"
"let x = a in e" ⇌ "CONST Let a (λx. e)"
I was trying to understand what "THE" meant, and found this in HOL.thy. "THE" is explained somewhat here, but I don't really get what's going fundamentally, since supposing P :: 'a ==> a' ==> bool
definition test :: "'a ==> 'a" where
"test y = (THE x. (P x y))"
How can "test y" be type "'a" if there doesn't exists x s.t. P x y? Somehow this has to be hiding in CONST and The (which I also don't really understand as it's just given axiomatically as something of type "('a ==> bool) ==> 'a" without any properties).
Perhaps most importantly, where is there a reference for all of this?? It's not in the Isabelle/Isar reference manual, the Isabelle HOL tutorial, the Isabelle/Isar Implementation pdf, in comments of the theory files, or anywhere I've been able to find.

How to define an inductive predicate inside locale?

Here is an example of a simple locale:
locale test =
fixes test_less_eq :: "'a ⇒ 'a ⇒ bool"
begin
inductive test_eq where
"test_less_eq x y ⟹ test_less_eq y x ⟹ test_eq x y"
end
It defines inductive test_eq. It can be defined using definition, but I need it to be an inductive predicate.
Then I define a trivial interpretation of the locale and try to use it:
interpretation interp: test "op <" .
inductive some_pred where
"interp.test_eq x y ⟹
some_pred x y"
code_pred [show_modes] some_pred .
The problem is that I get the following error for code_pred:
Type mismatch of predicate test.test_eq (trying to match ?'a
⇒ ?'a ⇒ bool and ('a ⇒ 'a ⇒ bool)
⇒ 'a ⇒ 'a ⇒ bool) in ?x1 < ?y1 ⟹
?y1 < ?x1 ⟹ interp.test_eq ?x1 ?y1
What is a cause of the error and how to fix it?
The predicate compiler has never been localized, i.e., it cannot directly deal with predicates that are defined inside a locale. There are two ways to make this work nevertheless.
Either, use global_interpretation with a defines clause to introduce a new constant for the predicate (plain interpretation only introduces an abbreviation). Then, you also have to re-declare the introduction rules to code_pred and prove the corresponding elimination rule.
global_interpretation interp: test "op <"
defines interp_test_eq = interp.test_eq .
declare interp.test_eq.intros[code_pred_intro]
code_pred interp_test_eq by(rule interp.test_eq.cases)
Or, leave the interpretation as is and re-declare the introduction rules of the internal constant to which the definition in the locale is mapped. This is <locale_name>.<predicate_name>, i.e., test.test_eq in your case. This works only if your locale has no assumption.
declare test.test_eq.intros[code_pred_intro]
code_pred test.test_eq by(rule test.test_eq.cases)

Working with generic definitions in Isabelle

I am working with limits and I am unable to prove the following
definition func :: "real ⇒ real"
where "func = real"
lemma "(λh. (func (x+h))) -- 0 --> (func (x))"
unfolding func_def
apply (auto intro!: tendsto_eq_intros)
However if I replace the definition of func to
definition func :: "real ⇒ real"
where "func x = x"
the lemma is solved.
How can I solve this lemma when working with generic definitions?
I believe, here the problem is that the function real has just a generic (overloaded) syntax, i.e., real :: 'a => real, but it is not necessarily defined for all possible types 'a. This is easily seen when using find_theorems: when searching for lemmas on real :: nat => real, you get plenty of results whereas searching for real :: real => real doesn't give you a single result.
find_theorems "real :: real => real"
find_theorems "real :: nat => real"
Consequently, you can not even prove a simple lemma like func x = x, since it is not specified that real :: real => real really is the identity function.

How do I abstractly work with theorems and terms using locale assumptions and variables in ML?

Consider the following locale definition:
locale my_locale =
fixes a :: nat
assumes "a > 0"
begin
definition "f n ≡ a + n"
lemma f_pos: "f x > 0"
sorry
end
In Isar, if I attempt to work with the definition of f or the lemma f_pos, the locale assumptions and fixed variables are hidden from me. For example, thm f_def f_pos returns:
f ?n ≡ a + ?n
0 < f ?x
as expected.
If, however, I try to reason about these terms in ML, the "hidden" fixed variables are suddenly exposed. ML {* #{thm f_def} |> prop_of *}, for instance, returns:
Const ("==", "nat ⇒ nat ⇒ prop") $
(Const ("TestSimple.my_locale.f", "nat ⇒ nat ⇒ nat") $
Free ("a", "nat") $ Var (("n", 0), "nat")) $
(Const ("Groups.plus_class.plus", "nat ⇒ nat ⇒ nat") $
Free ("a", "nat") $ Var (("n", 0), "nat"))
where the fixed variable a becomes a parameter to the function f.
Is there a way to be able to work inside a locales in ML so that I am not exposed to such locale variables?
It appears that the version of f which doesn't have the parameter a is simply an abbreviation generated by the locale command. In particular, typing print_abbrevs shows:
local.f ≡ My_Theory.my_locale.f a
This means that from the user's perspective, f doesn't appear to have any locale parameters, as they are hidden behind the abbreviation. Behind the scenes, however, f will always have the locale parameter attached to it, and thus ML code must be coded to explicitly handle it.

Resources