Standard ML: How to compute x to the power of i? - sml

I am new to Standard ML. I am trying to compute x squared i, where x is a real and i is an non-negative integer. The function should take two parameters, x and i
Here is what I have so far:
fun square x i = if (i<0) then 1 else x*i;
The error that I am getting is that the case object and rules do not agree

The unary negation operator in SML is not - as it is in most languages, but instead ~. That is likely what is causing the specific error you cite.
That said, there are some other issues with this code. L is not bound in the example you post for instance.
I think you may want your function to look more like
fun square (x : real) 0 = 1
| square x i = x * (square x (i - 1))
You'll want to recurse in order to compute the square.

Related

Power function using multiplication and iteration in Standard ML

I am having trouble understanding a method to implement a power function in SML using only iteration and multiplication.
my iteration is the following:
fun iterate 0 f x = x
| iterate n f x = iterate (n-1) f (f x);
while my multiplication is basically iterating recursively
fun multiply 0 f = 0
| multiply f x = iterate x (fn x => x + 1) (multiply x (f-1));
Power function would basically be an iteration of the multiplication of the same base but I don't know which value to decrement
power n f = iterate (mult n n) (fn x => x + 1) (power (n) (f-1))
which is definately wrong
power n f = iterate (mult n n) (fn x => x + 1) (power (n) (f-1))
So, when it comes to naming, I might definitely write power x y or power i j or power x n or some such, since x, y, i, j or n look like they're numbers or integers, whereas f looks like it's a function. So right off the bat you have:
fun power x y = iterate (...a...) (...b...) (...c...)
As for what goes into each of these three parts, ...a..., ...b... and ...c...:
a. The thing iterate calls n, which is the number of times to iterate.
b. The thing iterate calls f, which is the function to apply each time.
c. The thing iterate calls x, which is what is applied each time.
As elaborated on in How to make a multiplication function using just addition function and iterate function in SML, there is no point in making power call itself; the point of using iterate is to hand over recursion to this list-combinator rather than use explicit recursion (where power has a reference to itself somewhere in its definition).

Modifying a value on a logarithmic curve

I have one value that is a floating point percentage from 0-100, x, and another value that is a floating point from 0-1, y. As y gets closer to zero, it should reduce the value of x on a logarithmic curve.
So for example, say x = 28.0f and y = 0.8f. Since 0.8f isn't that far from 1.0f it should only reduce the value of x by a small amount, say bringing it down to x = 25.0f or something like that. As y gets closer to zero it should more and more drastically reduce the value of x. The only way I can think of doing this is with a logarithmic curve. I know what I want it to do, but I cannot for the life of me figure out how to implement this in C++. What would this algorithm look like in C++?
It sounds like you want this:
new_x = x * ln((e - 1) * y + 1)
I'm assuming you have the natural log function ln and the constant e. The number multiplied by x is a logarithmic function of y which is 0 when y = 0 and 1 when y = 1.
Here's the logic behind that function (this is basically a math problem, not a programming problem). You want something that looks like the ln function, rising steeply at first and then leveling off. But you want it to start at (0, 0) and then pass through (1, 1), and ln starts at (1, 0) and passes through (e, 1). That suggests that before you do the ln, you do a simple linear shift that takes 0 to 1 and 1 to e: ((e - 1) * y + 1.
We can try with the following assumption: we need a function f(y) so that f(0)=0 and f(1)=1 which follows some logarithmic curve, may be something like f(y)=Alog(B+Cy), with A, B and C constants to be determined.
f(0)=0, so B=1
f(1)=1, so A=1/log(1+C)
So now, just need to find a C value so that f(0.8) is roughly equal to 25/28. A few experiment shows that C=4 is rather close. You can find closer if you want.
So one possibility would be: f(y) = log(1.0 + 4.0*y) / log(5.0)

Linear Programming - variable that equals the sign of an expression

I am trying to write a linear program and need a variable z that equals the sign of x-c, where x is another variable, and c is a constant.
I considered z = (x-c)/|x-c|. Unfortunately, if x=c, then this creates division by 0.
I cannot use z=x-c, because I don't want to weight it by the magnitude of the difference between x and c.
Does anyone know of a good way to express z so that it is the sign of x-c?
Thank you for any help and suggestions!
You can't model z = sign(x-c) exactly with a linear program (because the constraints in an LP are restricted to linear combinations of variables).
However, you can model sign if you are willing to convert your linear program into a mixed integer program, you can model this with the following two constraints:
L*b <= x - c <= U*(1-b)
z = 1 - 2*b
Where b is a binary variable, and L and U are lower and upper bounds on the quantity x-c. If b = 0, we have 0 <= x - c <= U and z = 1. If b = 1, we have L <= x - c <= 0 and z = 1 - 2*1 = -1.
You can use a solver like Gurobi to solve mixed integer programs.
For k » 1 this is a smooth approximation of the sign function:
Also
when ε → 0
These two approximations haven't the division by 0 issue but now you must tune a parameter.
In some languages (e.g. C++ / C) you can simply write something like this:
double sgn(double x)
{
return (x > 0.0) - (x < 0.0);
}
Anyway consider that many environments / languages already have a sign function, e.g.
Sign[x] in Mathematica
sign(x) in Matlab
Math.signum(x) in Java
sign(1, x) in Fortran
sign(x) in R
Pay close attention to what happens when x is equal to 0 (e.g. the Fortran function will return 1, with other languages you'll get 0).

i was solving a sequence of large numbers, but python shell stop responding

I am a python newbie
How to deal with large numbers in python?
If i need to calculate the value of n*(2**(n-1))%m
where,
n=1000000000000000009 m=1000000007
when i was dealing with small value of n up to
n=1000009
it works but python shell stops responding for higher values
You should use a modular exponentiation method. Python builtin pow does that for you:
pow(x, y[, z]) -> number
With two arguments, equivalent to x**y. With three arguments,
equivalent to (x**y) % z, but may be more efficient (e.g. for longs).
Here is a non builtin implementation (copied from here):
def f(x,e,m):
X = x
E = e
Y = 1
while E > 0:
if E % 2 == 0:
X = (X * X) % m
E = E/2
else:
Y = (X * Y) % m
E = E - 1
return Y
Finally, what you need is
>>> n=1000000000000000009
>>> m=1000000007
>>> n*pow(2,n-1, m) % m
783433706L
n*(2**(n-1)) will be huge, so computing this the naive way will fail. Instead, you should try to split this up into reasonably sized chunks of work, and compute the modulo operation after each such chunk. A common technique here is binarization: you compute 2%m, 4%m=((2%m)*(2%m))%m, 16%m=((4%m)*(4%m))%m, 256%m=((16%m)*(16%m))%m and so on, and then multiply those values for which (n-1) has a bit set.
I think the lag may just be Python taking time to calculate the massive numbers you're dealing with.

Probability density function from a paper, implemented using C++, not working as intended

So i'm implementing a heuristic algorithm, and i've come across this function.
I have an array of 1 to n (0 to n-1 on C, w/e). I want to choose a number of elements i'll copy to another array. Given a parameter y, (0 < y <= 1), i want to have a distribution of numbers whose average is (y * n). That means that whenever i call this function, it gives me a number, between 0 and n, and the average of these numbers is y*n.
According to the author, "l" is a random number: 0 < l < n . On my test code its currently generating 0 <= l <= n. And i had the right code, but i'm messing with this for hours now, and i'm lazy to code it back.
So i coded the first part of the function, for y <= 0.5
I set y to 0.2, and n to 100. That means it had to return a number between 0 and 99, with average 20.
And the results aren't between 0 and n, but some floats. And the bigger n is, smaller this float is.
This is the C test code. "x" is the "l" parameter.
//hate how code tag works, it's not even working now
int n = 100;
float y = 0.2;
float n_copy;
for(int i = 0 ; i < 20 ; i++)
{
float x = (float) (rand()/(float)RAND_MAX); // 0 <= x <= 1
x = x * n; // 0 <= x <= n
float p1 = (1 - y) / (n*y);
float p2 = (1 - ( x / n ));
float exp = (1 - (2*y)) / y;
p2 = pow(p2, exp);
n_copy = p1 * p2;
printf("%.5f\n", n_copy);
}
And here are some results (5 decimals truncated):
0.03354
0.00484
0.00003
0.00029
0.00020
0.00028
0.00263
0.01619
0.00032
0.00000
0.03598
0.03975
0.00704
0.00176
0.00001
0.01333
0.03396
0.02795
0.00005
0.00860
The article is:
http://www.scribd.com/doc/3097936/cAS-The-Cunning-Ant-System
pages 6 and 7.
or search "cAS: cunning ant system" on google.
So what am i doing wrong? i don't believe the author is wrong, because there are more than 5 papers describing this same function.
all my internets to whoever helps me. This is important to my work.
Thanks :)
You may misunderstand what is expected of you.
Given a (properly normalized) PDF, and wanting to throw a random distribution consistent with it, you form the Cumulative Probability Distribution (CDF) by integrating the PDF, then invert the CDF, and use a uniform random predicate as the argument of the inverted function.
A little more detail.
f_s(l) is the PDF, and has been normalized on [0,n).
Now you integrate it to form the CDF
g_s(l') = \int_0^{l'} dl f_s(l)
Note that this is a definite integral to an unspecified endpoint which I have called l'. The CDF is accordingly a function of l'. Assuming we have the normalization right, g_s(N) = 1.0. If this is not so we apply a simple coefficient to fix it.
Next invert the CDF and call the result G^{-1}(x). For this you'll probably want to choose a particular value of gamma.
Then throw uniform random number on [0,n), and use those as the argument, x, to G^{-1}. The result should lie between [0,1), and should be distributed according to f_s.
Like Justin said, you can use a computer algebra system for the math.
dmckee is actually correct, but I thought that I would elaborate more and try to explain away some of the confusion here. I could definitely fail. f_s(l), the function you have in your pretty formula above, is the probability distribution function. It tells you, for a given input l between 0 and n, the probability that l is the segment length. The sum (integral) for all values between 0 and n should be equal to 1.
The graph at the top of page 7 confuses this point. It plots l vs. f_s(l), but you have to watch out for the stray factors it puts on the side. You notice that the values on the bottom go from 0 to 1, but there is a factor of x n on the side, which means that the l values actually go from 0 to n. Also, on the y-axis there is a x 1/n which means these values don't actually go up to about 3, they go to 3/n.
So what do you do now? Well, you need to solve for the cumulative distribution function by integrating the probability distribution function over l which actually turns out to be not too bad (I did it with the Wolfram Mathematica Online Integrator by using x for l and using only the equation for y <= .5). That however was using an indefinite integral and you are really integration along x from 0 to l. If we set the resulting equation equal to some variable (z for instance), the goal now is to solve for l as a function of z. z here is a random number between 0 and 1. You can try using a symbolic solver for this part if you would like (I would). Then you have not only achieved your goal of being able to pick random ls from this distribution, you have also achieved nirvana.
A little more work done
I'll help a little bit more. I tried doing what I said about for y <= .5, but the symbolic algebra system I was using wasn't able to do the inversion (some other system might be able to). However, then I decided to try using the equation for .5 < y <= 1. This turns out to be much easier. If I change l to x in f_s(l) I get
y / n / (1 - y) * (x / n)^((2 * y - 1) / (1 - y))
Integrating this over x from 0 to l I got (using Mathematica's Online Integrator):
(l / n)^(y / (1 - y))
It doesn't get much nicer than that with this sort of thing. If I set this equal to z and solve for l I get:
l = n * z^(1 / y - 1) for .5 < y <= 1
One quick check is for y = 1. In this case, we get l = n no matter what z is. So far so good. Now, you just generate z (a random number between 0 and 1) and you get an l that is distributed as you desired for .5 < y <= 1. But wait, looking at the graph on page 7 you notice that the probability distribution function is symmetric. That means that we can use the above result to find the value for 0 < y <= .5. We just change l -> n-l and y -> 1-y and get
n - l = n * z^(1 / (1 - y) - 1)
l = n * (1 - z^(1 / (1 - y) - 1)) for 0 < y <= .5
Anyway, that should solve your problem unless I made some error somewhere. Good luck.
Given that for any values l, y, n as described, the terms you call p1 and p2 are both in [0,1) and exp is in [1,..) making pow(p2, exp) also in [0,1) thus I don't see how you'd ever get an output with the range [0,n)