Is there anything like a subst_tac rule in Isabelle? - substitution

I have the lemma
lemma ex1_variable: "(∃x. ∀z. x = y z) = (∃!x. ∀z. x = y z)"
and I have an intermediate statement in a proof
"∀a. ∃P. ∀z. P = Q z a"
I would like to show
"∀a. ∃!P. ∀z. P = Q z a".
I cannot use by (rule ex1_variable) directly because of the ∀a. However, I feel like it should be possible to use something like the subst method e.g.
from `∀a. ∃P. ∀z. P = Q z a` have "∀a. ∃!P. ∀z. P = Q z a"
by (subst_tac ?x="P" and ?y="λx. Q x a" and ?z="z" in ex1_variable)
so that ex1_variable is substituted in the present goal but only after having been instantiated. This particular example doesn't work, but is there anything along similar lines?

There is no need to explicitly instantiate the lemma ex1_variable, higher-order unification will do that for you. And since ex1_variable is an equality statement, you can actually use plain subst to prove replace the instance of the left-hand side with the instantiated right-hand side. But you have to tell subst to look in the assumptions since this is where the left-hand side instance occurs in your subgoal. So the following should work:
lemma ex1_variable: "(∃x. ∀z. x = y z) = (∃!x. ∀z. x = y z)" sorry
notepad begin
fix Q
have "∀a. ∃P. ∀z. P = Q z a" sorry
then have "∀a. ∃!P. ∀z. P = Q z a"
by(subst (asm) ex1_variable)
end
Alternatively, you can flip the sides of the theorem around and apply subst to the conclusion:
by(subst ex1_variable[symmetric])

Related

infinitely recursive type in OCaml

I'm reading this OCaml file and it contains the following:
type z = Z of z
This looks like z is infinitely recursive. How is it useful and how can I even construct such a type?
I don't think this type is particularly useful, except possibly as a test case in type theory.
You can construct values of the type like this:
# let rec x = Z x;;
val x : z = Z <cycle>
# let rec q = Z (Z q);;
val q : z = Z (Z <cycle>)
Once you have a value of the type you can readily construct other values of course:
# let y = Z (Z x);;
val y : z = Z (Z (Z <cycle>))

finding depth of object without use of arithmetics

Without using arithmetics (=< , =>, etc.)!
I have a few separate piles of blocks, for example two piles.
I need a way to figure out if block A sits Higher on any pile than block B.
For example:
is_on_top(Block1,Pile,Block2). %relations of blocks in a particular pile
for example:
is_bellow(a,1,b). % a is bellow b in pile number 1
is_bellow(r,2,e).
is_bellow(f,2,null). % is at top.
....
and so on.
I'm trying to figure out how to write the predicate:
is_higher(Block1,Block2):- %block1 is higher than block2 in Any line.
% to check for the same line if a block is higher than another I'm this
% is Block1 higher than Block2 in THE SAME pile.
taller(Block1, Block2) :-
is_bellow(Block2,_,Block1).
taller(Block1, Block2) :-
is_bellow(Y, I,Block1),
taller(Y, Block2).
is it possible to do it without using arithmetics?
I think I have the terminating condition.
is_higher(Block1,Block2):-
is_bellow(Block1,_,null), is_bellow(Block2,_,X).
X \= null.
is_higher(Block1,Block2):- % don't know how to continue.
From the comments:
I thought something along the lines of digging deeper on both blocks till block one is paired with null, but I cant quite get my head around it.
You are thinking along the correct lines, but your representation of the world seems to confuse you a bit. It becomes easier if we define a cleaner language for talking about blocks and their relationships.
It would have been good if you had posted a complete example. Here is the one I will be using:
is_below(a, 1, b).
is_below(b, 1, null). % topmost on pile
is_below(c, 2, d).
is_below(d, 2, e).
is_below(e, 2, f).
is_below(f, 2, null). % topmost on pile
I understand this to model the following world:
f
e
b d
a c
-----------------
pile 1 pile 2
Now let's talk about concepts related to this world. First... what even is a block? The representation is implicit, but it appears that a block is something that is on a pile. Being "on a pile" is somewhat implicit too, but it means being below something -- another block, or the special non-block atom null.
So this is a block:
% block(X): X is a block
block(X) :-
is_below(X, _Pile, _BlockOrNull).
Prolog can now enumerate blocks:
?- block(X).
X = a ;
X = b ;
X = c ;
X = d ;
X = e ;
X = f.
Note that null is not included, which is good since it is not a block.
Now, is_below complicates things because it talks about non-blocks (namely, null) and also about the numbers of piles, which we don't always need. Let's define a simpler notion of a block being directly on top of another block:
% block_on(X, Y): X is a block directly on top of block Y
block_on(X, Y) :-
is_below(Y, _Pile, X),
block(X).
Note that we use block(X) to make sure we only talk about blocks. Let's test:
?- block_on(X, Y).
X = b,
Y = a ;
X = d,
Y = c ;
X = e,
Y = d ;
X = f,
Y = e ;
false.
Good. Now, let's define notions for being the topmost and the bottommost block on a pile:
% top(X): X is a block that is topmost on its pile
top(X) :-
block(X),
\+ block_on(_OtherBlock, X). % no other block is on X
% bottom(X): X is a block that is bottommost on its pile
bottom(X) :-
block(X),
\+ block_on(X, _OtherBlock). % X is not on any other block
This behaves like this:
?- top(X).
X = b ;
X = f.
?- bottom(X).
X = a ;
X = c ;
false.
And now we can return to your comment:
I thought something along the lines of digging deeper on both blocks till block one is paired with null, but I cant quite get my head around it.
You were talking about digging (upwards?) until you arrive at a topmost block, but in fact what you should be doing is to dig downwards until you arrive at a bottommost block! Hopefully you can see that it's easier to talk about these concepts now that we have given them clearer names, rather than descriptions like being "paired with null".
Let's start with a non-recursive rule for expressing "higher than". Any non-bottom block is definitely "higher than" any bottom block:
% higher_than(X, Y): X is a block higher on any pile than Y
higher_than(X, Y) :-
bottom(Y),
block(X),
\+ bottom(X).
This already captures a lot of relationships:
?- higher_than(X, Y).
X = b,
Y = a ;
X = d,
Y = a ;
X = e,
Y = a ;
X = f,
Y = a ;
X = b,
Y = c ;
X = d,
Y = c ;
X = e,
Y = c ;
X = f,
Y = c ;
false.
Any non-bottom block (b, d, e, f) is higher than any bottom block (a, c).
Now let's do the "digging" part to express that, for example, f is higher than b. Your idea is correct: If we're at some blocks X and Y, and X is directly on top of some block V and Y is directly on top of some block W, and we can somehow establish that V is higher than W, then X is higher than Y! Here's the same idea expressed in Prolog code:
higher_than(X, Y) :-
block_on(X, V),
block_on(Y, W),
higher_than(V, W).
So is f higher than b?
?- higher_than(f, b).
true ;
false.
Nice. And enumerating all "higher than" pairs:
?- higher_than(X, Y).
X = b,
Y = a ;
X = d,
Y = a ;
X = e,
Y = a ;
X = f,
Y = a ;
X = b,
Y = c ;
X = d,
Y = c ;
X = e,
Y = c ;
X = f,
Y = c ;
X = e,
Y = b ;
X = e,
Y = d ;
X = f,
Y = b ;
X = f,
Y = d ;
X = f,
Y = e ;
false.
Most of these are as before, but we got some new pairs as well: e is higher than b and d, f is higher than b, d, and e. And that is all!
Final remark: I'm not an expert on blocks worlds, but my impression was that it is more usual to model the table top as a special "location" rather than having a special marker for "there is nothing above this".
So I would have represented the same world more like this:
pile_on(1, a, table).
pile_on(1, b, a).
pile_on(2, c, table).
pile_on(2, d, c).
pile_on(2, e, d).
pile_on(2, f, e).
You could switch your code to this representation, maybe it would make your life easier. You could also keep the same higher_than definition -- if you adjust the definitions of block and block_on, all the rest can remain the same.
Assuming is_below( A, P, B) means block A is immediately below block B in some pile P, or is topmost in that pile, with B = null, we can code the is_higher( A, B) predicate exactly as you wanted:
we either have one more step to go down the piles and recurse, or we've reached the bottom of the B pile and judge the situation accordingly:
is_higher( A, B) :- % A is higher than B, if
is_below( A2, _, A), % A is atop one
is_below( B2, _, B), % which is _higher_ than that
A \== B, % which B is atop of
is_higher( A2, B2). % (determined _recursively_)
is_higher( A, B) :- % or,
is_below( _, _, A), % A is not bottommost
is_below( B, _, _), % while B is, because
\+ is_below( _, _, B). % there is nothing below B
%% the world: c
%% b e
%% a d
is_below(a,1,b).
is_below(b,1,c).
is_below(c,1,null).
is_below(d,2,e).
is_below(e,2,null).
Testing:
36 ?- findall( A-B, (is_higher(A,B), A\==null), X).
X = [c-b, c-e, b-a, b-d, c-a, c-d, e-a, e-d].

Definition without recursion, by cases, in Isabelle

I'm trying to define a unary operation on a set stalk x, whose typical elements are of the form germ x U s. In this case, there is no way to define an operation on general things of the same type as germ x U s in a way that reduces to what I want, so it seems like I really do have to resort to a definition by cases. I attempted the following
definition stalk_mop2 :: "'a ⇒( ('a set × 'a) set ⇒ ('a set × 'a) set ) " where
"stalk_mop2 x y = ( (λ z . if (∃ U s. y= germ x U s ) then
(germ x U ( -⇩a ⇘objectsmap U⇙ s ) ) else undefined) z ) " ,
and got the error message that U s are extra variables on the RHS. It seems like by using this syntax Isabelle does not make the connection between the if hypothesis and the following term, so that although I did bind U and s in the conditional statement, it apparently interprets the next occurrences of U and s (after then) as free variables.
What I really want is just a function that takes x and something of the form germ x U s and returns germ x U ( -⇩a ⇘objectsmap U⇙ s ). Nothing here is recursive.
Is there a way around this problem, or maybe a better way to make definitions by cases that will allow me to define what I want?
Be aware that this is nothing strange about Isabelle's syntax but, there just is no connection between the if-condition and the then- and else-branches. The scope of the existential quantifier naturally ends with then.
If you want to obtain a witness for something you know exists, you can use Hilbert's choice operator, e.g., SOME (U, s). y = germ x U s) gives you a pair (U, s) that satisfies y = germ x U s if such a pair exists (which you made sure by your if-condition), and is undefined otherwise.
So how about:
definition stalk_mop2 :: "'a ⇒(('a set × 'a) set ⇒ ('a set × 'a) set)"
where
"stalk_mop2 x y = ((λz .
if ∃U s. y = germ x U s then
let (U, s) = (SOME (U, s). y = germ x U s) in
germ x U (-⇩a ⇘objectsmap U⇙ s)
else undefined) z)"
Update: You can use multiple lets in one of the following ways
let x1 = e1 in let x2 = e2 in ...
or
let x1 = e1; x2 = e2; ... in ...

When exactly do we use let rec?

I know that let rec is used when I want recursive.
For example,
let rec power i x = if i = 0 then 1.0 else x *. (power (i-1) x);;
Ok, I understand that.
But how about this one:
let x y = y + y in x 2?
Should I use rec inside?
I think I should, because it has x 2 inside, loading itself, but it seems it is fine with compiler.
So when I should use let rec and shouldn't?
Also, what is the difference between
let (-) x y = y - x in 1-2-3;;
and
let rec (-) x y = y - x in 1-2-3;;
Are they both legal?
You need to understand the scoping rules of OCaml first.
When you write let f XXX = YYY in ZZZ, if you use f in YYY then you need rec. In both cases (ie with or without rec),f will be defined in ZZZ.
So:
let x y = y + y in
x 2
is perfectly valid.
For you second question: no it is not equivalent, if you try it on the toplevel, the second statement loop for ever and is equivalent to let rec loop x y = loop y x in (). To understand why it is looping for ever, you can understand the application of loop as an expansion where the identifier is replaced by its body. so:
So loop body is function x y -> loop y x, which can be expanded to
function x y -> (function a b -> loop b a) y x (I've renamed the parameter names to avoid ambiguity), which is equivalent to function x y -> loop x y when you apply the body and so on and so on. So this function never does anything, it just loops forever by trying to expand/apply its body and swapping its arguments.

How can I prove this statement of big o notation?

How to prove this:
x^7 = O(x^10)
x^10 = O(x^7)?
I couldn't prove this statement.
Let's take a look at the definition of big-O notation.
f ∈ O(g) <=> (∃ x) (∃ c > 0) (∀ y > x) (|f(y)| <= c⋅|g(y)|)
The right hand side can be formulated "the quotient f/g is bounded for sufficiently large x".
So to prove that f ∈ O(g), look at the quotient, choose a (largish) x and try to find a bound.
For the first case, the quotient is
x⁷ / x¹⁰ = 1/x³
A bound for x ≥ 1 is obvious.
To refute f ∈ O(g), look at the quotient and prove that it assumes values of arbitrarily large modulus on each interval [x, ∞). Assume an arbitrary c > 0, and prove that for any x, there is an y > x with |f(y)/g(y)| > c.
That should give enough of a hint.
If not: x³ > c for x ≥ c+1.

Resources