Hoare Logic for Repeat Until - hoare-logic

How can we prove a program in repeat until using Hoare Logic?
I've found a rule like this:
{P} S {R}, {R ^ ~B -> P}, {R ^ B -> Q}
For {P} repeat S until B {Q}
But I still can't find any explanatiom how I can use this rule
For example in this question:
{x > 0 ^ y > 0}
z:=0; u:=x; REPEAT
z:=z+y;
u:=u-1;
UNTIL u=0;
{z = x * y}
How I can use the rule to prove this program?

Related

Nesting n-sets of for loops - (Julia)

I am currently trying to create n-nested loops in order to compute a rather tricky sum.
Each term in the sum depends on the last, and therefore the nesting is required. Here is some Julia-written pseudo-code explaining what I'm trying to get:
# u,v are fixed integers
# m is a fixed, n-length array of integers
_
for i_1 in 0:min(m[1], u) |#Trio of Loops we want to repeat n times
for j_1 in 0:min(m[1], v) |
for t_1 in i_1:(i_1 + j_1) _|#1
_
for i_2 in 0:min(m[2], u - i_1) |
for j_2 in 0:min(m[2], v - j_1) |
for t_2 in i_2:(i_2 + j_2) _|#2
#... repeat until nth time...#
_
for i_n in 0:min(m[n],u - sum(#all i_'s up to n-1)) |
for j_n in 0:min(m[n],v - sum(#all j_'s up to n-1)) |
for t_n in i_n:(i_n + j_n) _|#n
#Sum over sum function which depends on i_'s and j_'s and t_'s
X += f(i_1,j_1,t_1)*f(i_2,j_2,t_2)*...*f(i_n,j_n,t_n)
I am completely unsure of how to properly code this for an arbitrary n-number of trios. If the number n is small then obviously this can be explicitly written, but if not, then we are stuck. I assume that there is a recursive way to employ this code, but I am unsure how to go about this.
Any and all help would be appreciated.
Here is a quick attempt at a slightly simplified version of your problem.
function inner(X, f, ms)
is = [Symbol(:i_, n) for n in 1:length(ms)]
js = [Symbol(:j_, n) for n in 1:length(ms)]
fs = [:($f($i, $j)) for (i,j) in zip(is, js)]
:($X += *($(fs...)))
end
inner(:X, :g, [3,4,5]) # :(X += g(i_1, j_1) * g(i_2, j_2) * g(i_3, j_3))
function looper(ex::Expr, ms, u)
isempty(ms) && return ex
n = length(ms)
m_n = ms[n]
i_n = Symbol(:i_,n)
j_n = Symbol(:j_,n)
out = :( for $i_n in 0:min($m_n, $u)
for $j_n in 0:min($m_n, $u)
$ex
end
end)
looper(out, ms[1:end-1], u)
end
looper(inner(:g, [4,5]), [4,5], 3)
# :(for i_1 = 0:min(4, 3)
# for j_1 = 0:min(4, 3)
# for i_2 = 0:min(5, 3)
# for j_2 = 0:min(5, 3)
# X += g(i_1, j_1) * g(i_2, j_2) ...
macro multi(X, f, ms, u)
ms isa Expr && ms.head == :vect || error("expected a literal vector like [1,2,3]")
looper(inner(esc(X), esc(f), ms.args), ms.args, esc(u))
end
#macroexpand #multi X f [4,5] u
# :(for var"#74#i_1" = 0:Main.min(4, u) ...
function multi(X, f, u)
#multi X f [4,5] u
X
end
multi(0.0, atan, 1)

Extract complete argument and function name(s) from the Expression, (standard mathematical functions only) MAPLE

For expressions like
a1 := sin(1+a/b);
a2 := log(1+ a*b);
a3 := abs(a^2+b);
how can I get expressions of respective functions. For example
someCommand(a1) # should get an output 1+a/b
someCommand(a2) # should get an output 1+a*b
someCommand(a3) # should get an output a^2+b
I have tried to get related topics from maple documentation but unfortunately am not able to get exactly.
edited: Also how is it possible to get list (in sequence)of functions used
let
a :=sin(log(abs(a+b)));# functions can be of more than two
someCommand(a) # have to return [{sin, log, abs}, a+b]
You can use the op() command, which breaks down expressions into their operands. For instance:
f := sin(1+a/b);
g := op(0,f); # sin
h := op(1,f); # 1+a/b
That's not complicated to construct. (More thoughts on that, below...)
restart;
W := (ee,nm::name) -> [op(map(`[]`#op,indets(ee,':-specfunc'(nm))))]:
And now to test it,
a1 := sin(1+a/b):
a2 := log(1+ a*b):
a3 := abs(a^2+b):
W( a1, sin );
[[ a]]
[[1 + -]]
[[ b]]
W( a2, ln );
[[a b + 1]]
W( a3, abs );
[[ 2 ]]
[[a + b]]
Now a slightly longer example,
foo := cos(1+a/b)/abs(a^2+b)
+log(1+ a*b)*cos(s-v)
+sin(c+d/r);
/ a\
cos|1 + -|
\ b/ / d\
foo := ---------- + ln(a b + 1) cos(s - v) + sin|c + -|
| 2 | \ r/
|a + b|
W( foo, sin );
[[ d]]
[[c + -]]
[[ r]]
W( foo, cos );
[[ a] ]
[[1 + -], [s - v]]
[[ b] ]
W( foo, abs );
[[ 2 ]]
[[a + b]]
W( foo, ln );
[[a b + 1]]
With no other context to judge by, I personally prefer to have the items above be returned within lists, to be able to handle them later more easily.
But it looks even simpler, if one leaves out the encapsulating lists,
Y := (ee,nm::name) -> op(map(op,indets(ee,':-specfunc'(nm)))):
Y( foo, cos );
a
1 + -, s - v
b
Now a few opinions. The reason that there is no dedicated command for doing precisely this is because there are so very many tasks in a similar vein. A programming language that is crammed full of hundreds of distinct commands to do too similar things can be awkward (or worse) to use.
To use Maple effectively it helps to learn the basic building blocks very well. Those include at least things like,
op, map, map[n], zip, select, remove, selectremove,
table, indices, entries, type, indets, subsindets,
normal, radnormal, simplify, evalc, evala, rationalize
In your followup comment to another Answer you gave the further example of sin(log(abs(a+b))). I suspect that you want to be able to slice and dice even more complicated examples.
You haven't really told use what your final goal is. Perhaps you're trying to build an expression tree. Or perhaps you're evenutally planning on doing something else with this analysis. It'd really help if you told us the final goal.
Having said that, the following might be of some use to you.
restart;
ee := "sin(log(abs(a+b))) + sin(s+t) + abs(log(v+w))":
P:=InertForm:-Parse(ee):
lprint(P);
`%+`(%sin(%log(%abs(`%+`(a,b)))),%sin(`%+`(s,t)),
%abs(%log(`%+`(v,w))))
It may be that the above inert form is something you can work with, for whatever your goal might be.
indets(P, specfunc(name,`%+`));
{a %+ b, s %+ t, v %+ w}
indets(P, specfunc(anything,%abs));
{%abs(a %+ b), %abs(%log(v %+ w))}
indets(P, specfunc(specfunc(name,`%+`),%abs));
{%abs(a %+ b)}
indets(P, specfunc(specfunc(name,`%+`),%log));
{%log(v %+ w)}
Using a routine limke from my earlier Answer,
W := (ee,nm) -> [op(map(`[]`#op,indets(ee,':-specfunc'(nm))))]:
W( indets(P, specfunc(specfunc(name,`%+`),%log)), `%+` );
[[v, w]]
W( indets(P, specfunc(specfunc(name,`%+`),%sin)), `%+` );
[[s, t]]
W( indets(P, specfunc(specfunc(name,`%+`),%abs)), `%+` );
[[a, b]]
There are other ways to get those last results (using something like W on an actual expression and not its inert form, say). I'm just trying to show you how you can do a bit more with it all.

Maxima: how to replace variables in equations

I'm trying to write down some notes of my work. The way Maxima would simplify my work is that once I write bunch of equations and I want to change the definition of a variable, I do it and re-evaluate the entire file.
Here is an example of what I'm trying to accomplish:
Question 1:
I have a system of equations and all I want from Maxima is just variables replacement.
eq1: x=a+b+c
eq2: y=d+e+f
eq3: x+y=0
How do I get Maxima to output
eq3: a+b+c+d+e+f = 0
So in the future if I want x to be a+b-c, I just change it and re-evaluate
Question 2:
Similar to before but a bit more complex
eq1: x=a+b+c
eq2: y=d+e+f
eq3: x=y
eq4: a+s+e=0
How do I get Maxima to output
eq3 a+b+c=d+e+f
How do I get Maxima to solve eq1 for a and solve eq2 for e and output
eq4: x-b-c+s+y-d-f = 0
Thank you in advance for your help,
Guido
I think subst and solve can handle the operations you want here.
(%i1) eq1: x=a+b+c;
(%o1) x = c + b + a
(%i2) eq2: y=d+e+f;
(%o2) y = f + e + d
(%i3) eq3: x+y=0;
(%o3) y + x = 0
(%i4) subst ([eq1, eq2], eq3);
(%o4) f + e + d + c + b + a = 0
OK, now here's your second example. Note that solve returns a list of equations.
(%i5) eq3: x=y;
(%o5) x = y
(%i6) eq4: a+s+e=0;
(%o6) s + e + a = 0
(%i7) subst ([eq1, eq2], eq3);
(%o7) c + b + a = f + e + d
(%i8) solve (eq1, a);
(%o8) [a = x - c - b]
(%i9) solve (eq2, e);
(%o9) [e = y - f - d]
(%i10) append (%o8, %o9);
(%o10) [a = x - c - b, e = y - f - d]
(%i11) subst (%o10, eq4);
(%o11) y + x + s - f - d - c - b = 0
Maxima's solve function is not too powerful; there are many kinds of equations it cannot solve. But it can solve linear equations.

Reflexivity on the gt relation in Coq

I want to prove that for any natural number n+1 is greater than 0.
Defining my own greater than function this works fine:
Fixpoint my_gt (n : nat) (m : nat) : bool
:= match n with
| O => false
| S n' => match m with
| O => true
| S m' => my_gt n' m'
end
end.
Lemma GT1: forall n, my_gt (S n) O = true. reflexivity. Qed.
But when I use the default ">"-relation Coq refuses with the message "Tactic failure: The relation gt is not a declared reflexive relation. Maybe you need to require the Setoid library". Because I do require the Setoid library I don't understand why Coq does not seem to find the gt definition?
Require Export Coq.Setoids.Setoid.
Lemma GT2: forall n, S n > O. reflexivity.
If you take a look at Coq's gt definition, you will this that it is just a notation over lt, which is a notation over le:
gt = fun n m : nat => m < n
: nat -> nat -> Prop
lt = fun n m : nat => S n <= m
: nat -> nat -> Prop
Inductive le (n : nat) : nat -> Prop :=
le_n : n <= n | le_S : forall m : nat, n <= m -> n <= S m
Now as you can see, it is not declared as a function, but as an inductive predicate, so you cannot simply "compute" to get the solution. To prove such a goal, you will have to use tactics such as constructor and induction to prove your goal.
Note that your relation is in bool whereas Coq's is in Prop (the general way to compare two elements of some type might no be decidable). For the particular case of natural numbers, you can find leb somewhere in the Arith module, which behaves as you except:
Require Import Arith.
Print leb.
Lemma GT2: forall n, leb O (S n) = true.
reflexivity.
Qed.
Best,
V.

R: Aggregate on Group 1 and NOT Group 2

I am trying to create two data sets, one which summarizes data by 2 groups which I have done using the following code:
x = rnorm(1:100)
g1 = sample(LETTERS[1:3], 100, replace = TRUE)
g2 = sample(LETTERS[24:26], 100, replace = TRUE)
aggregate(x, list(g1, g2), mean)
The second needs to summarize the data by the first group and NOT the second group.
If we consider the possible pairs from the previous example:
A - X B - X C - X
A - Y B - Y C - Y
A - Z B - Z C - Z
The second dataset should to summarize the data as the average of the outgroup.
A - not X
A - not Y
A - not Z etc.
Is there a way to manipulate aggregate functions in R to achieve this?
Or I also thought there could be dummy variable that could represent the data in this way, although I am unsure how it would look.
I have found this answer here:
R using aggregate to find a function (mean) for "all other"
I think this indicates that a dummy variable for each pairing is necessary. However if there is anyone who can offer a better or more efficient way that would be appreciated, as there are many pairings in the true data set.
Thanks in advance
First let us generate the data reproducibly (using set.seed):
# same as question but added set.seed for reproducibility
set.seed(123)
x = rnorm(1:100)
g1 = sample(LETTERS[1:3], 100, replace = TRUE)
g2 = sample(LETTERS[24:26], 100, replace = TRUE)
Now we have two solutions both of which use aggregate:
1) ave
# x equals the sums over the groups and n equals the counts
ag = cbind(aggregate(x, list(g1, g2), sum),
n = aggregate(x, list(g1, g2), length)[, 3])
ave.not <- function(x, g) ave(x, g, FUN = sum) - x
transform(ag,
x = NULL, # don't need x any more
n = NULL, # don't need n any more
mean = x/n,
mean.not = ave.not(x, Group.1) / ave.not(n, Group.1)
)
This gives:
Group.1 Group.2 mean mean.not
1 A X 0.3155084 -0.091898832
2 B X -0.1789730 0.332544353
3 C X 0.1976471 0.014282465
4 A Y -0.3644116 0.236706489
5 B Y 0.2452157 0.099240545
6 C Y -0.1630036 0.179833987
7 A Z 0.1579046 -0.009670734
8 B Z 0.4392794 0.033121335
9 C Z 0.1620209 0.033714943
To double check the first value under mean and under mean.not:
> mean(x[g1 == "A" & g2 == "X"])
[1] 0.3155084
> mean(x[g1 == "A" & g2 != "X"])
[1] -0.09189883
2) sapply Here is a second approach which gives the same answer:
ag <- aggregate(list(mean = x), list(g1, g2), mean)
f <- function(i) mean(x[g1 == ag$Group.1[i] & g2 != ag$Group.2[i]]))
ag$mean.not = sapply(1:nrow(ag), f)
ag
REVISED Revised based on comments by poster, added a second approach and also made some minor improvements.

Resources