Logic of SML recursive functions - recursion

Hi I'm trying to learn SML. I'm having trouble understanding the some of the recursive functions I'm coming across , for example
fun Square (x:int, y:int)=
if y=0
then 1
else x * Square(x,y-1);
I understand that in the else bracket the x is being multiplied by the value of the Square function taking x and y-1 as arguments and this process will continue until y hits 0 . I'm just not clear in each step of the recursion what is x being multiplied by? Furthermore once y hits 0 why doesn't the function return 1?
Thank you

The function does return 1 when y = 0, but this value is returned to the caller - Square(x,1) - which returns a value to its caller, Square(x,2), and so on.
(The big secret of recursive function is that they work exactly like non-recursive functions.)
I think one of the best ways towards understanding is to use the substitution method.
Look at Square (3,2). Replacing x and y in the function definition with their values gives
if 2 = 0 then 1 else 3 * Square (3, 2-1)
2 is clearly not 0, so we need to figure out what Square (3, 1) is before we can continue with the multiplication.
Repeat the same process:
if 1 = 0 then 1 else 3 * Square (3, 1-1)
The condition is still false, so continue with Square (3,0).
if 0 = 0 then 1 else 3 * Square (3, 0-1)
Now the condition is true, so we know that Square (3,0) is 1.
Move back one level and substitute:
if 1 = 0 then 1 else 3 * 1
So, Square (3,1) is 3. Substitute again:
if 2 = 0 then 1 else 3 * 3
which makes 9, which is what you would expect.
You could also consider this (endless) sequence of non-recursive functions:
...
fun Square_3 (x, y) = if y = 0 then 1 else x * Square_2 (x, y-1)
fun Square_2 (x, y) = if y = 0 then 1 else x * Square_1 (x, y-1)
fun Square_1 (x, y) = if y = 0 then 1 else x * Square_0 (x, y-1)
fun Square_0 (x, y) = if y = 0 then 1 else x * Square_minus1(x, y-1)
fun Square_minus1 (x, y) = ...
and then think about how Square_2(3, 2) works. Square(3,2) works in exactly the same way.
(By the way, your function has a pretty odd name. You might want to rename it.)

Related

CVXPY violates constraints when it solves SDP

Let's say that I want to solve the following problem.
minimize Tr(CY)
s.t. Y = xxT
x is 0 or 1.
where xxT indicates an outer product of n-1 dimension vector x. C is a n-1 by n-1 square matrix. To convert this problem to a problem with a single matrix variable, I can write down the code as follows by using cvxpy.
import cvxpy as cp
import numpy as np
n = 8
np.random.seed(1)
S = np.zeros(shape=(int(n), int(n)))
S[int(n-1), int(n-1)] = 1
C = np.zeros(shape=(n,n))
C[:n-1, :n-1] = np.random.randn(n-1, n-1)
X = cp.Variable((n,n), PSD=True)
constraints=[]
constraints.append(cp.trace(S # X) == 1)
for i in range(n-1):
Q = np.zeros(shape=(n,n))
Q[i,i] = 1
Q[-1,i] = -0.5
Q[i,-1] = -0.5
const = cp.trace(Q # X) == 0
constraints.append(const)
prob = cp.Problem(cp.Minimize(cp.trace(C # X)),constraints)
prob.solve(solver=cp.MOSEK)
print("X is")
print(X.value)
print("C is")
print(C)
To satisfy the binary constraint that the entries of the vector x should be one or zero, I added some constraints for the matrix variable X.
X = [Y x; xT 1]
Tr(QX) == 0
There are n-1 Q matrices which are forcing the vector x's entries to be 0 or 1.
However, when I ran this simple code, the constraints are violated severely.
Looking forward to see any suggestion or comments on this.

How to generate random points within an octahedron without discarding?

I need random points within an octahedron, uniformly distributed. I am defining an octahedron as the volume where all points satisfy abs(x) + abs(y) + abs(z) <= 1 where abs gives absolute value. IE: each of the six vertices would be on an axis, 1 away from 0,0,0. Maybe you could call it a unit octahedron.
With the definition in mind, I can naively generate a point like so:
val x: Double = nextDouble() // 0-1 range
val y = nextDouble(1.0 -x) // 1-x is upper bound, probably <1
val z = nextDouble(1.0 -(x+y))
The problem is that this leans toward small y values, and smaller z values. Clearly not an even distribution. Also clearly, all these points are in just one of eight quadrants.
I'm avoiding the discard method because this function will be called a lot, and it just seems like I should be able to do better than throwing out the majority of points.
Note that the dual of the octahedron is the cube. Because of this, I have an inkling that there might exist a simple function to translate any point within a cube to be within the octahedron, but that's just an intuition I'm still exploring.
Here is the idea - sample points from Dirichlet distribution in D+1, select D points such that you're uniform in the simplex
x0+x1+x2 <= 1, xi >= 0
To make octahedron, randomly select octant to put your point.
Code in Python
import math
import random
def Dirichlet():
"""sample 4d Dirichlet"""
x0 = -math.log(1.0 - random.random()) # exponential
x1 = -math.log(1.0 - random.random()) # exponential
x2 = -math.log(1.0 - random.random()) # exponential
x3 = -math.log(1.0 - random.random()) # exponential
s = 1.0/(x0+x1+x2+x3) # scaling
return (x0*s, x1*s, x2*s, x3*s)
def OctahedronSampling():
x0, x1, x2, _ = Dirichlet()
octant = random.randint(0, 7)
if octant == 0:
return (x0, x1, x2)
elif octant == 1:
return (x0, -x1, x2)
elif octant == 2:
return (x0, x1, -x2)
elif octant == 3:
return (x0, -x1, -x2)
elif octant == 4:
return (-x0, x1, x2)
elif octant == 5:
return (-x0, -x1, x2)
elif octant == 6:
return (-x0, x1, -x2)
elif octant == 7:
return (-x0, -x1, -x2)
return None
for _ in range(0, 2000):
x0, x1, x2 = OctahedronSampling()
print(f"{x0} {x1} {x2}")
And here is quick graph with 2K points
You know how to choose points in a cube with uniform distribution, and a cube can be dissected into eight square pyramids. (Sorry I can't provide graphics.)
I'd start with a cube: abs(x) <= 1; abs(y) <= 1; abs(z) <= 1
Pick a point in it (a column vector, (x, y, z)), then reflect to bring it into the "top and bottom" pyramids:
if abs(x) > abs(z), swap x and z. Equivalently, multiply by
0 0 1
0 1 0
1 0 0
if abs(y) > abs(z), swap y and z. Equivalently, multiply by
1 0 0
0 0 1
0 1 0
Then invert the two pyramids to make an octahedron:
if z>0
z = 1-z
if z<0
z = -1-z
Then rotate and scale:
multiply by
1/2 -1/2 0
1/2 1/2 0
0 0 1

Subtraction operation using only increment, loop, assign, zero

I am trying to build up subtraction, addition, division, multiplication and other operations using only following ones:
incr(x) - Once this function is called it will assign x + 1 to x
assign(x, y) - This function will assign the value of y to x (x = y)
zero(x) - This function will assign 0 to x (x = 0)
loop X { } - operations written within brackets will be executed X times
Using following rules it is straight forward to implement addition (add) like this:
ADD (x, y) {
loop X {
y = incr (y)
}
return y
}
However, I'm struggling to implement subtraction. I think that all the other needed operations could be completed using subtraction.
Any hint will be very appreciated.
Stephen Cole Kleene devised a way to perform integer subtraction using integer addition. However, it assumes that you cannot have negative integers. For example:
0 - 1 = 0
1 - 1 = 0
2 - 1 = 1
3 - 1 = 2
4 - 1 = 3
5 - 2 = 3
6 - 3 = 3
6 - 4 = 2
6 - 5 = 1
6 - 6 = 0
6 - 7 = 0
In your question, you implemented the addition operation using the increment operation.
Similarly, you can implement the subtraction operation using the decrement operation as follows:
sub(x, y) {
loop y
{ x = decr(x) }
return x
}
Now, all we need to do is implement the decrement operation.
This is where the genuis of Kleene shines:
decr(x) {
y = 0
z = 0
loop x {
y = z
z = incr(z)
}
return y
}
Here we've used all the four operations. This is how it works:
We have two base cases, y (the base case for 0) and z (the base case for 1):
y = 0 - 1 = 0
z = 1 - 1 = 0
Hence, we initialize them both to 0.
When x is 0 we run the loop 0 times (i.e. never) and then we simply return y = 0.
When x is 1 then we run the loop once, assign y = z and then simply return y = z = 0.
Notice that every time we run the loop y holds the result of the current iteration while z holds the result of the next iteration. This is the reason why we require two base cases. The decrement function is not a continuous function. It is a piecewise function:
decr(0) = 0
decr(n + 1) = n
Kleene realized this when he went to the dentist and the dentist extracted two of his teeth. He was frustrated while trying to solve this very problem and when the dentist extracted two of his teeth he realized that he required two base cases.

Maxima: Recursively taking derivatives

I am trying to write some code that recursively finds Taylor coefficients by taking derivatives of a function and then once at the base case evaluates the derivatives at x=0. Here's the code I have so far:
test(f, n) := block([df],
define(df(x), diff(f(x), x)),
print(n, "|", df(x), "|", f(x)),
if n = 0
then f(0)
else test(df, n-1)
);
test_func(x) := x^2;
test(test_func, 2);
The trouble is that this is what I get:
(%i4) test(test_func,2)
2
2 | 2 x | x
1 | 2 | 2
0 | 0 | 0
(%o4) 0
As you can see, the first time through everything looks good, f(x) is x^2, df(x) is 2x. However, the second time through f(x) is 2, even though df(x) was 2x the last time through the function. I'm somewhat new to Maxima so it's quite possible that I'm simply missing something obvious (i.e. don't assume I'm not making a stupid mistake).
My advice is to work with expressions instead of named functions. Something like this:
test(e, n) := block([e1 : diff(e, x)],
print(n, "|", e, "|", e1),
if n = 0
then ev(e, x = 0)
else test(e1, n - 1));

How can I show that a function is always not commutative

I have the following vexing problem.
I have implemented the following function:
function bool less(nat x, nat y) {
if (y<>0) then
if (x<>0) then
return less(x-1,y-1);
else
return true;
end;
else
return false;
end;
end;
How can I show that for all x,y the following
less(x,y) and less(y,x) are not possible at the
same time?
Bye
Well, first of all I would ask you to consider the case of less(-1, -2), so we will have to define the function to be on the bounds of n ≥ 0. Also when the first input is equal to the second it will return true for both orderings, so we will have to assume that x ≠ y.
I would use Proof by Contradiction.
Assume that for some x and some y where x and y are both ≥ 0 and x≠y, that less(x,y) and less(y,x) are both true.
This would imply that while x and y are both nonzero, you subtract one from them n times until one of them is zero, checking x first. The function returns true when the first operand reaches zero, false when the second operand reaches zero while the first is nonzero.
There are two cases for this:
x reaches zero first. In this case n = x, because 0 = x - n(1).
y reaches zero first. In this case n = y, because 0 = y - n(1).
By our assumption, less(x,y) returned true, meaning that the function iterated x times, after which x - x(1) = 0 and y - x(1) > 0 (because y ≠ x, and the function didn't return false before hand).
Similarly, less(y,x) returned true, meaning that the function iterated y times, after which y- y(1) = 0 and x - y(1) > 0 (same reasons as before).
This gives us two useful relations: y - x > 0 and x - y > 0. rearranged: y > x and x > y (the semantic meaning of the function, but we have achieved this from the definition of how the function works and we have reduced it to the pure mathematics which we can work with certain axioms for).
From y > x and x > y, you can rearrange as x > x and y > y (If x is greater than y, then it is greater than all things y is greater than. y is greater than x, therefore x is greater than x).
This is a logical contradiction, and therefore our assumption (that they were both true) is incorrect.
Therefore, by Proof by Contradiction, when x ≠ y, and x,y ≥ 0, the function less cannot return true for both less(x,y) and less(y,x).
(it's been a while since I had to do a proof (though I'm going to have to do some coming up so it is good practice) so I might be a bit rusty. If any one sees an error, please point it out and I will try to fix it)

Resources