Sequence points in a language with left to right evaluation order? - side-effects

When evaluation order is specified as "left to right" and language is a (pseudo) C-like, which are the sequence points in the following examples?
int x = 1;
int z = x-- + x; // z = 1 + 0 or z = 1 + 1?
my_func(x++); // x incremented before or after my_func execution?
my_func(x++ + --x); // combining those above

A sequence point is what the language standard defines to be a sequence point. The answers I'm about to give apply to C, but another "C-like" language might very well define different sequence points and thus have different answers to those questions.
int z = x-- + x; // z = 1 + 0 or z = 1 + 1?
Since + is not a sequence point in C, the result of the above statement is undefined.
my_func(x++); // x incremented before or after my_func execution?
x is incremented before my_func runs, but my_func is called with the old value of x as an argument.
my_func(x++ + --x); // combining those above
Undefined for the same reason as the first one.

Related

How to convert the following if conditions to Linear integer programming constraints?

These are the conditions:
if(x > 0)
{
y >= a;
z <= b;
}
It is quite easy to convert the conditions into Linear Programming constraints if x were binary variable. But I am not finding a way to do this.
You can do this in 2 steps
Step 1: Introduce a binary dummy variable
Since x is continuous, we can introduce a binary 0/1 dummy variable. Let's call it x_positive
if x>0 then we want x_positive =1. We can achieve that via the following constraint, where M is a very large number.
x < x_positive * M
Note that this forces x_positive to become 1, if x is itself positive. If x is negative, x_positive can be anything. (We can force it to be zero by adding it to the objective function with a tiny penalty of the appropriate sign.)
Step 2: Use the dummy variable to implement the next 2 constraints
In English: if x_positive = 1, then y >= a
However, if x_positive = 0, y can be anything (y > -inf)
y > a - M (1 - x_positive)
Similarly,
if x_positive = 1, then z <= b
z <= b + M * (1 - x_positive)
Both the linear constraints above will kick in if x>0 and will be trivially satisfied if x <=0.

How do you calculate combined orders of growth?

Suppose I have a recursive procedure with a formal parameter p. This procedure
wraps the recursive call in a Θ(1) (deferred) operation
and executes a Θ(g(k)) operation before that call.
k is dependent upon the value of p. [1]
The procedure calls itself with the argument p/b where b is a constant (assume it terminates at some point in the range between 1 and 0).
Question 1.
If n is the value of the argument to p in the initial call to the procedure, what are the orders of growth of the space and the number of steps executed, in terms of n, for the process this procedure generates
if k = p? [2]
if k = f(p)? [3]
Footnotes
[1] i.e., upon the value of the argument passed into p.
[2] i.e., the size of the input to the nested operation is same as that for our procedure.
[3] i.e., the size of the input to the nested operation is some function of the input size of our procedure.
Sample procedure
(define (* a b)
(cond ((= b 0) 0)
((even? b) (double (* a (halve b))))
(else (+ a (* a (- b 1))))))
This procedure performs integer multiplication as repeated additions based on the rules
a * b = double (a * (b / 2)) if b is even
a * b = a + (a * (b - 1)) if b is odd
a * b = 0 if b is zero
Pseudo-code:
define *(a, b) as
{
if (b is 0) return 0
if (b is even) return double of *(a, halve (b))
else return a + *(a, b - 1)
}
Here
the formal parameter is b.
argument to the recursive call is b/2.
double x is a Θ(1) operation like return x + x.
halve k is Θ(g(k)) with k = b i.e., it is Θ(g(b)).
Question 2.
What will be the orders of growth, in terms of n, when *(a, n) is evaluated?
Before You Answer
Please note that the primary questions are the two parts of question 1.
Question 2 can be answered as the first part. For the second part, you can assume f(p) to be any function you like: log p, p/2, p^2 etc.
I saw someone has already answered question 2, so I'll answer question 1 only.
First thing is to notice is that the two parts of the question are equivalent. In the first question, k=p so we execute a Θ(g(p)) operation for some function g. In the second one, k=f(p) and we execute a Θ(g(f(p))) = Θ((g∘f)(p)). replace g from the first question by g∘f and the second question is solved.
Thus, let's consider the first case only, i.e. k=p. Denote the time complexity of the recursive procedure by T(n) and we have that:
T(n) = T(n/b) + g(n) [The free term should be multiplied by a constant c, but we can talk about complexity in "amount of c's" and the theta bound will obviously remain the same]
The solution of the recursive formula is T(n) = g(n) + g(n/b) + ... + g(n/b^i) + ... + g(1)
We cannot further simplify it unless given additional information about g. For example, if g is a polynomial, g(n) = n^k, we get that
T(n) = n^k * (1 + b^-k + b^-2k + b^-4k + ... + b^-log(n)*k) <= n^k * (1 + b^-1 + b^-2 + ....) <= n^k * c for a constant c, thus T(n) = Θ(n^k).
But, if g(n) = log_b(n), [from now on I ommit the base of the log] we get that T(n) = log(n) + log(n/b) + ... + log(n/(b^log_b(n))) = log(n^log(n) * 1/b^(1 + 2 + ... log(n))) = log(n)^2 - log(n)^2 / 2 - log(n) / 2 = Θ(log(n) ^ 2) = Θ(g(n)^2).
You can easily prove, using a similar proof to the one where g is a polynomial that when g = Ω(n), i.e., at least linear, then the complexity is g(n). But when g is sublinear the complexity may be well bigger than g(n), as g(n/b) may be much bigger then g(n) / b.
You need to apply the wort case analysis.
First,
you can approximate the solution by using powers of two:
If then clearly the algorithm takes: (where ).
If it is an odd number then after applying -1 you get an even number and you divide by 2, you can repeat this only times, and the number of steps is also , the case of b being an odd number is clearly the worst case and this gives you the answer.
(I think you need an additional base case for: b=1)

Loop Invariant for Proving Partial Correctness

I'm trying to find a loop invariant so that we can prove this program partially-correct:
{ n >= 1 } pre-condition
i = 1;
z = 1;
while (i != n) {
i = i + 1;
z = z + i*i;
}
{ z = n*(n+1)*(2*n + 1)/6 } post-condition
I am really stuck. Some of the invariants I've tried so far are:
z <= n*(n+1)*(2*n + 1)/6 ^ i <= n
and
z = i*(i+1)*(2*i + 1)/6 ^ i <= n
I would really appreciate some advice.
To find an appropriate invariant you have to have an intuition what the investigated function actually does. In your example the value i^2 is successively added to the accumulator z. So the function computes (just going through the first few iterations of the while-loop by hand and then generalizing):
1^2 + 2^2 + 3^2 + 4^2 + 5^2 + ... + n^2
or written a bit more formally
SUM_{i=1}^{n} i^2
i.e., the sum of all squares of i ranging from 1 to n.
On first sight this might not look similar to your post-condition. However, it can be shown by induction on n that the above sum is equal to
(n*(n+1)*(2*n + 1))/6
which I guess is the intended post-condition. Since we now know that the post-condition is equal to this sum, it should be easy to read off the invariant from the sum.

Lua - Two local variables with the same name

I have been learning Lua and I was wondering if it is allowed to reference two local variables of the same name.
For example, in the following code segment, is the syntax legal (without undefined behavior)?
I ask because it does run, but I cannot seem to figure out what is happening behind the scenes. Is this simply referencing the same x local? Or are there now two local x variables that mess things up behind the scenes. I'd like to know what exactly is happening here and why it is the case.
local x = 5 + 3; -- = 8
local x = 3 - 2; -- = 1
print("x = " .. x); -- x = 1
There are two variables. The second shadows (but does not remove or overwrite) the first.
Sometimes you can still access the earlier definition via a closure.
local x = 5 + 3
local function getX1()
return x
end
local x = 3 - 2
local function getX2()
return x
end
print("x = " .. x); -- x = 1
print("x = " .. getX1()); -- x = 8
print("x = " .. getX2()); -- x = 1
All your local variables have been remembered by Lua :-)
local x = 5 + 3; -- = 8
local x = 3 - 2; -- = 1
local i = 0
repeat
i = i + 1
local name, value = debug.getlocal(1, i)
if name == 'x' then
print(name..' = '..value)
end
until not name
Yes, it is legal. Lua handles local-variable declarations as statements.
Here's an interesting example from the Lua Reference Manual:
Notice that each execution of a local statement defines new local variables. Consider the following example:
a = {}
local x = 20
for i=1,10 do
local y = 0
a[i] = function () y=y+1; return x+y end
end
The loop creates ten closures (that is, ten instances of the anonymous function). Each of these closures uses a different y variable, while all of them share the same x.
In this example, if ignore the returning closure part, there are 10 local variables named y in the same for block.

How to get random numbers with the wrong generator

Question: Suppose you have a random number generator randn() that returns a uniformly distributed random number between 0 and n-1. Given any number m, write a random number generator that returns a uniformly distributed random number between 0 and m-1.
My answer:
-(int)randm() {
int k=1;
while (k*n < m) {
++k;
}
int x = 0;
for (int i=0; i<k; ++i) {
x += randn();
}
if (x < m) {
return x;
} else {
return randm();
}
}
Is this correct?
You're close, but the problem with your answer is that there is more than one way to write a number as a sum of two other numbers.
If m<n, then this works because the numbers 0,1,...,m-1 appear each with equal probability, and the algorithm terminates almost surely.
This answer does not work in general because there is more than one way to write a number as a sum of two other numbers. For instance, there is only one way to get 0 but there are many many ways to get m/2, so the probabilities will not be equal.
Example: n = 2 and m=3
0 = 0+0
1 = 1+0 or 0+1
2 = 1+1
so the probability distribution from your method is
P(0)=1/4
P(1)=1/2
P(2)=1/4
which is not uniform.
To fix this, you can use unique factorization. Write m in base n, keeping track of the largest needed exponent, say e. Then, find the biggest multiple of m that is smaller than n^e, call it k. Finally, generate e numbers with randn(), take them as the base n expansion of some number x, if x < k*m, return x, otherwise try again.
Assuming that m < n^2, then
int randm() {
// find largest power of n needed to write m in base n
int e=0;
while (m > n^e) {
++e;
}
// find largest multiple of m less than n^e
int k=1;
while (k*m < n^2) {
++k
}
--k; // we went one too far
while (1) {
// generate a random number in base n
int x = 0;
for (int i=0; i<e; ++i) {
x = x*n + randn();
}
// if x isn't too large, return it x modulo m
if (x < m*k)
return (x % m);
}
}
It is not correct.
You are adding uniform random numbers, which does not produce a uniformly random result. Say n=2 and m = 3, then the possible values for x are 0+0, 0+1, 1+0, 1+1. So you're twice as likely to get 1 than you are to get 0 or 2.
What you need to do is write m in base n, and then generate 'digits' of the base-n representation of the random number. When you have the complete number, you have to check if it is less than m. If it is, then you're done. If it is not, then you need to start over.
The sum of two uniform random number generators is not uniformly generated. For instance, the sum of two dice is more likely to be 7 than 12, because to get 12 you need to throw two sixes, whereas you can get 7 as 1 + 6 or 6 + 1 or 2 + 5 or 5 + 2 or ...
Assuming that randn() returns an integer between 0 and n - 1, n * randn() + randn() is uniformly distributed between 0 and n * n - 1, so you can increase its range. If randn() returns an integer between 0 and k * m + j - 1, then call it repeatedly until you get a number <= k * m - 1, and then divide the result by k to get a number uniformly distributed between 0 and m -1.
Assuming both n and m are positive integers, wouldn't the standard algorithm of scaling work?
return (int)((float)randn() * m / n);