Say I have the following definition of a reflexive and transitive closure of a relation, where relations are represented by binary predicates:
inductive
closure :: "(['a, 'a] ⇒ bool) ⇒ (['a, 'a] ⇒ bool)"
for ℛ (infix "→" 50)
where
gen:
"x → y ⟹ closure (→) x y" |
refl:
"closure (→) x x" |
trans:
"⟦closure (→) x y; closure (→) y z⟧ ⟹ closure (→) x z"
I want to have a nicer syntax for applications of closure. Say I’d like to be able to write x *(→)* y for closure (→) x y. The problem is that the argument order in this notation doesn’t match the argument order of the function closure.
I thought that perhaps the use of \<index> could help. Unfortunately, the documentation of \<index> in the Isabelle/Isar Reference Manual is very terse, and I couldn’t really make sense of it. I played a bit with \<index> but didn’t find any workable solution.
What puzzled me was that apparently \<index> gets translated to ⇘some_index⇙, judging from some error messages I got. I tried to use ⇘ℛ⇙ to mark the position where the base relation should go, but this didn’t work either.
To switch the arguments, an abbreviation is the best choice. (syntax/translations works, too, but abbreviations should be preferred because they work in any context (locales, type classes, ...) and are type-checked.) Fortunately, inductive allows you to simultaneously declare abbreviations together with an inductive definition. The equations for the abbreviations have to come first. Here's how it works for your example:
inductive closure :: "(['a, 'a] ⇒ bool) ⇒ (['a, 'a] ⇒ bool)"
and closure_syntax :: "['a, ['a, 'a] ⇒ bool, 'a] ⇒ bool" ("(_ ⇧*(_)⇧* _)" [999,0,999] 100)
for ℛ (infix "→" 50)
where
"x ⇧*(→)⇧* y ≡ closure (→) x y"
| gen: "x → y ⟹ x ⇧*(→)⇧* y"
| refl: "x ⇧*(→)⇧* x"
| trans: "⟦x ⇧*(→)⇧* y; y ⇧*(→)⇧* z⟧ ⟹ x ⇧*(→)⇧* z"
The syntax element \<index> is rarely used nowadays, because locales achieve a similar effect and are usually more flexible. The point of \<index> is that you can declare a parameter as (structure) and this will then automatically be inserted whereever the parser sees \<index> in the syntax grammar. So it allows you to omit repeating the structure parameter, but locales usually work better.
You'd probably want to use syntax and translations, for example:
syntax "_closure" :: "['a, (['a, 'a] ⇒ bool), 'a] ⇒ (['a, 'a] ⇒ bool)" ("(_ *'(_')* _)")
translations "x *(ℛ)* y" ⇌ "CONST closure (ℛ) x y"
These are also documented in isar-ref.pdf, with some examples floating around in the source theory files (a hypersearch should turn these up).
Related
When I have a goal such as "∀x. P x" in Isabelle, I know that I can write
show "∀x. P x"
proof (rule allI)
However, when the goal is "∀x>0. P x", I cannot do that. Is there a similar rule/method that I can use after proof in order to simplify my goal? I would also be interested in one for the situation where you have a goal of the form "∃x>0. P x".
I'm looking for an Isar proof that uses the proof (rule something) style.
Universal quantifier
To expand on Lars's answer: ∀x>0. P x is just syntactic sugar for ∀x. x > 0 ⟶ P x. As a consequence, if you want to prove a statement like this, you first have to strip away the universal quantifier with allI and then strip away the implication with impI. You can do something like this:
lemma "∀x>0. P x"
proof (rule allI, rule impI)
Or using intro, which is more or less the same as applying rule until it is not possible anymore:
lemma "∀x>0. P x"
proof (intro allI impI)
Or you can use safe, which eagerly applies all introduction rules that are declared as ‘safe’, such as allI and impI:
lemma "∀x>0. P x"
proof safe
In any case, your new proof state is then
proof (state)
goal (1 subgoal):
1. ⋀x. 0 < x ⟹ P x
And you can proceed like this:
lemma "∀x>0. P (x :: nat)"
proof safe
fix x :: nat assume "x > 0"
show "P x"
Note that I added an annotation; I didn't know what type your P has, so I just used nat. When you fix a variable in Isar and the type is not clear from the assumptions, you will get a warning that a new free type variable was introduced, which is not what you want. When you get that warning, you should add a type annotation to the fix like I did above.
Existential quantifier
For an existential quantifier, safe will not work because the intro rule exI is not always safe due to technical reasons. The typical proof pattern for an ∃x>0. P x would be something like:
lemma "∃x>0. P (x :: nat)"
proof -
have "42 > (0 :: nat)" by simp
moreover have "P 42" sorry
ultimately show ?thesis by blast
qed
Or a little more explicitly:
lemma "∃x>0. P (x :: nat)"
proof -
have "42 > 0 ∧ P 42" sorry
thus ?thesis by (rule exI)
qed
In cases when the existential witness (i.e. the 42 in this example) does not depend on any variables that you got out of an obtain command, you can also do it more directly:
lemma "∃x>0. P (x :: nat)"
proof (intro exI conjI)
This leaves you with the goals ?x > 0 and P ?x. Note that the ?x is a schematic variable for which you can put it anything. So you can complete the proof like this:
lemma "∃x>0. P (x :: nat)"
proof (intro exI conjI)
show "42 > (0::nat)" by simp
show "P 42" sorry
qed
As I said, this does not work if your existential witness depends on some variable that you got from obtain due to technical restrictions. In that case, you have to fall back to the other solution I mentioned.
The following works in Isabelle2016-1-RC2:
lemma "∀ x>0. P x"
apply (rule allI)
In general, you can also just use apply rule, which will select the default introduction rule. Same is true for the existential quantifier.
I just cant find the syntax for removing a term from a set.
I have the following:
typedecl STUDENT
definition LeaveHall ::
"STUDENT set => STUDENT set => STUDENT set => STUDENT set => STUDENT =>
bool"
where
"LeaveHall badminton' badminton hall' hall leaver ==
(
(leaver \<in> hall) \<and> (hall' = hall \<setminus> {(leaver)})
<and>
(badminton' = badminton)
)"
What it doesnt like i the expression "(hall' = hall \ {(leaver)})
"
I'm trying to say is the set hall' is the set hall minus the term leaver.
But it just doesnt like it. Ive tried putting brackets and things and it
still doesnt work.
While the ∖ symbol exists in Isabelle under the name \<setminus>, it is not used at the moment. The proper syntax for set difference is quite simply -, so this works:
definition LeaveHall :: "STUDENT set ⇒ STUDENT set ⇒ STUDENT set ⇒ STUDENT set ⇒ STUDENT ⇒ bool"
where "LeaveHall badminton' badminton hall' hall leaver ⟷
leaver ∈ hall ∧ hall' = hall - {leaver} ∧ badminton' = badminton"
If you want to use \<setminus>, you can, of course, define an abbreviation with that syntax:
abbreviation setminus (infixl "∖" 65) where "setminus ≡ op -"
Or, to only allow this to input terms but not use it when printing terms:
abbreviation (input) setminus (infixl "∖" 65) where "setminus ≡ op -"
On an unrelated note: identifiers consisting of multiple words are typically written with underscores in Isabelle as opposed to Camel Case. Of course, you can call your identifiers whatever you want, but the convention is to use underscores instead of Camel Case.
Also, note that I used ⟷ in the definition of LeaveHall above, not the meta equality ≡ (as you did) or regular equality =. The use of the meta equality operator ≡ in definitions is discouraged (although it has no real disadvantages).
The Boolean equivalence operator ⟷ is simply an abbreviation for equality on Booleans (so it's exactly the same as writing =). So why use ⟷? Because it has lower precedence than =, which means you typically need fewer parentheses: P a = Q a ∧ R a is parsed as (P a = Q a) ∧ R a, whereas P a ⟷ Q a ∧ R a is parsed as P a = (Q a ∧ R a).
Given
notation
rtranclp ("(_^**)" [1000] 1000)
I can write, given an infix op ⇒
"op ⇒⇧*⇧* x x'"
but not the much more readable and prettier
"x ⇒⇧*⇧* x'"
I know that for every concrete relation (⇒ in this case), I can set up an abbreviation for this. But can I also solve this generally, i.e. for any infix relation?
If yes, can I extend that to multiple relations and other arguments? For example, given two infix relations ⇒ and ▹, and another term y I want to set it up so that I can write
x (⇒;▹)⇗y⇖ x'
(note the infix use) instead of
foo op ⇒ op ▹ y x x'
(where, in my case, has type foo :: ('a ⇒ 'a ⇒ bool) ⇒ ('a ⇒ 'b ⇒ bool) ⇒ 'b ⇒ 'a ⇒ 'a).
I believe that a general solution for all infix relations is not possible, because the parser does not know about the relation symbols in isolation. As can be seen from the implementation in mixfix.ML, an infix declaration with relation symbol < is equivalent to two mixfix declarations, namely "op <" and "(_ < _)" with appropriate precedences.
However, there is a more generic and elegant solution than to introduce abbreviations for all combinations of predicates and predicate transformers. First, introduce a syntactic category for relational symbols. To also get the right output, add a syntactic marker _infix
nonterminal rel
syntax (output) "_infix" :: "rel ⇒ logic" ("_")
Then, declare a syntax constant _rtranclp_rel for infix use with infix relations.
syntax "_rtranclp_rel" :: "logic ⇒ rel ⇒ logic ⇒ logic" ("(_ _⇧*⇧* _)")
translations "_rtranclp_rel x R y" ⇀ "CONST rtranclp R x y"
translations "_rtranclp_rel x (_infix R) y" ↽ "CONST rtranclp R x y"
Now, add a syntax translation to your relation rel that you want to use with _rtranclp_rel:
consts rel :: "nat ⇒ nat ⇒ bool" (infix "⇒" 100)
syntax "_rel_infix" :: rel ("⇒")
translations "_rel_infix" ⇀ "CONST rel"
translations "_rel_infix" ↽ "_infix (CONST rel)"
Then, Isabelle should be able to correctly parse and pretty-print x ⇒⇧*⇧* z. Note, however, that all fully applied instances of rtranclp are pretty-printed infix (e.g., rtranclp R x y, independent of whether the relation is an infix symbol.
This mechanism then also works for your function foo:
consts foo :: "('a ⇒ 'a ⇒ bool) ⇒ ('b ⇒ 'b ⇒ bool) ⇒ 'b ⇒ 'a ⇒ 'a ⇒ bool"
syntax "_foo_rel" :: "logic ⇒ rel ⇒ rel ⇒ logic ⇒ logic ⇒ logic" ("_ '(_;_')⇗_⇖ _")
translations "_foo_rel x R S y z" ⇀ "CONST foo R S x y z"
translations "_foo_rel x (_infix R) (_infix S) y z" ↽ "CONST foo R S x y z"
Of course, the precedences in the mixfix annotations should be adjusted to sensible ones. It is even possible to do this recursively. For example:
syntax "_rtranclp_rel2" :: "rel ⇒ rel" ("_⇧*⇧*")
translations "_rtranclp_rel2 R" ⇀ "CONST rtranclp R"
translations "_rtranclp_rel2 (_infix R)" ↽ "_infix (CONST rtranclp R)"
term "x (⇒⇧*⇧*;⇒)⇗y⇖ z"
I am attempting to generate a nice syntax for mapping a function over the values of an associative list, i.e. I want to write [x ↦ f y | (x ↦ y) ∈ l] for mapAList f l. I came up with
syntax
"_alist_map" :: "['b, pttrn, ('a × 'b) list] ⇒ ('a × 'b) list"
("[x ↦ _ | '(x ↦ _') ∈ _]")
which works, but causes term "(x,y)#[]" to tell me Inner syntax error at "(x , y ) # []" and the (x is shaded slightly different.
The reason seems that once x appears in a mixfix annotation, it now always a literal token to the grammer (a delimiter according to §7.4.1 of isar-ref) and no longer an identifier – just like the syntax for if ... then ... else ... prevents if from being a variable name
Can I somehow work around this problem?
Identifier names used in mixfix annotations cannot be used as identifiers any longer, and I don't know any way around that. Therefore, instead of using x as a variable name, you can pick a non-identifier symbol like \<xX> or \<mapAListvariable> and setup the LaTeX output to print this as x by adding \newcommand{\isasymmapAListvariable}{x} to your root.tex.
You can also add \<xX> or \<mapAListvariable> to the symbols file of Isabelle/JEdit (preferably in $ISABELLE_HOME_USER/etc/symbols) and assign it some Unicode point that will be used for display in Isabelle/JEdit.
I just made a small experiment with a function map_alist that hopefully corresponds to your mapAList and which is defined as follows:
fun map_alist :: "('b ⇒ 'c) ⇒ ('a × 'b) list ⇒ ('a × 'c) list"
where
"map_alist f [] = []" |
"map_alist f ((x, y) # xs) = (x, f y) # map_alist f xs"
Then existing syntax can be used which looks a little bit as you intended. Maybe this is an option?
lemma "map_alist f xs = [(x, f y). (x, y) ← xs]"
by (induct xs) auto
Is there an extensible, efficient way to write existential statements in Haskell without implementing an embedded logic programming language? Oftentimes when I'm implementing algorithms, I want to express existentially quantified first-order statements like
∃x.∃y.x,y ∈ xs ∧ x ≠ y ∧ p x y
where ∈ is overloaded on lists. If I'm in a hurry, I might write perspicuous code that looks like
find p [] = False
find p (x:xs) = any (\y -> x /= y && (p x y || p y x)) xs || find p xs
or
find p xs = or [ x /= y && (p x y || p y x) | x <- xs, y <- xs]
But this approach doesn't generalize well to queries returning values or predicates or functions of multiple arities. For instance, even a simple statement like
∃x.∃y.x,y,z ∈ xs ∧ x ≠ y ≠ z ∧ f x y z = g x y z
requires writing another search procedure. And this means a considerable amount of boilerplate code. Of course, languages like Curry or Prolog that implement narrowing or a resolution engine allow the programmer to write statements like:
find(p,xs,z) = x ∈ xs & y ∈ xs & x =/= y & f x y =:= g x y =:= z
to abuse the notation considerably, which performs both a search and returns a value. This problem arises often when implementing formally specified algorithms, and is often solved by combinations of functions like fmap, foldr, and mapAccum, but mostly explicit recursion. Is there a more general and efficient, or just general and expressive, way to write code like this in Haskell?
There's a standard transformation that allows you to convert
∃x ∈ xs : P
to
exists (\x -> P) xs
If you need to produce a witness you can use find instead of exists.
The real nuisance of doing this kind of abstraction in Haskell as opposed to a logic language is that you really must pass the "universe" set xs as a parameter. I believe this is what brings in the "fuss" to which you refer in your title.
Of course you can, if you prefer, stuff the universal set (through which you are searching) into a monad. Then you can define your own versions of exists or find to work with the monadic state. To make it efficient, you can try Control.Monad.Logic, but it may involve breaking your head against Oleg's papers.
Anyway, the classic encoding is to replace all binding constructs, including existential and universal quantifiers, with lambdas, and proceed with appropriate function calls. My experience is that this encoding works even for complex nested queries with a lot of structure, but that it always feels clunky.
Maybe I don't understand something, but what's wrong with list comprehensions? Your second example becomes:
[(x,y,z) | x <- xs, y <- xs, z <- xs
, x /= y && y /= z && x /= z
, (p1 x y z) == (p2 x y z)]
This allows you to return values; to check if the formula is satisfied, just use null (it won't evaluate more than needed because of laziness).