Im trying to test the following tailrec function:
private tailrec fun findFixPoint(eps: Double = 5.0, x: Double = 1.0): Double = if (abs(x - cos(x)) < eps) x else findFixPoint(cos(x))
This is my test function:
#Test
fun testNewFeatures(){
TestCase.assertEquals(0.7390851332151611, findFixPoint())
}
The fix point is 0.7390851332151611 but the assertEquals returns me 1.0 as Actualvalue i can deduct the function is only being launch one time without recursion.
Any suggestion of how can be test a tailrec function properly?
Hope anyone can help me with this. Thank you all in advance.
EDIT
The real point of this post was a test of tailrec function for avoid a StackOverflowError so, i will post here two simple test, but sa1nt´s answer was correct for my question issue, and the tip of Benoit was great for simplifying the tailrec test
So, the following functions to test the StackOverflowError are this:
Not avoided
private fun testStackOverFlow(num : Double): Double = if (num == 10000000000.0) num else testStackOverFlow(num+1)
Avoided
private tailrec fun testNOTStackOverFlow(num : Double): Double = if (num == 10000000000.0) num else testNOTStackOverFlow(num+1)
Test function:
#Test
fun testNewFeatures(){
TestCase.assertEquals(10000000000.0, testStackOverFlow(1.0))
TestCase.assertEquals(10000000000.0, testNOTStackOverFlow(1.0))
}
Thank you all for the answers. Have a great day.
TLDR
Change your function to:
tailrec fun findFixPoint(eps: Double = 5.0, x: Double = 1.0): Double =
if (abs(x - cos(x)) < eps) x
else findFixPoint(eps, cos(x)) // eps argument added
And the test to:
#Test
fun testNewFeatures(){
TestCase.assertEquals(0.7390851332151611, findFixPoint(eps = 0.05)) // overriding default eps value
}
Details
Provide both arguments explicitly in the recursive call. Otherwise cos(x) will be used for the eps because it's the first argument:
private tailrec fun findFixPoint(eps: Double = 5.0, x: Double = 1.0): Double = if (abs(x - cos(x)) < eps) x else findFixPoint(eps, cos(x))
In the test you call the function like this findFixPoint() so default argument values are used. So, the condition if (abs(x - cos(x)) < eps) x else ... for eps = 5.0 and x = 1.0 will return x immediately after entering the function.
For this kind of method, Black-box testing seems to be the most appropriate. Basically you test the method without knowing the internal details. You must just check that the result is correct for the given input, i.e. what the method does. This is what you did. But there is no need to check how the method came to this result.
Now suppose you completely rewrite your method to use iteration instead of recursion: you don't need to rewrite the tests, they all remain valid.
Related
New to SML, trying to round up a real number to nth decimal, by declaring a function round(n,L), where L is a list of real numbers and n decide the nth decimal that can round up to.
My approach is to convert the real number to a string first, and then get the substring to the nth decimal and then parse the substring back to real number, this works fine if I only want to get the real number to nth decimal, but if I have a number like 0.3456 which I want to round to 0.35, my method won't really achieve that.
fun rd(_,[]) = []
|rd(a:int, x::y:real list) =
if x>0.0
then Option.getOpt(Real.fromString(String.substring(Real.toString(x),0,a+2)),0.0) :: rd(a,y)
else Option.getOpt(Real.fromString(String.substring(Real.toString(x),0,a+3)),0.0) :: rd(a,y)
The expected result is like this:
- rd (2, [0.1234, 0.2345, ~0.3456]);
val it = [0.12,0.23,~0.35] : real list`
But the actual output I got is
val it = [0.12,0.23,~0.34] : real list
If I want to round up the number, is there any good approach?
I've also tried this:
fun rd(_,[]) = []
|rd(a:int, x::y:real list) =
let
val n = real(round(x*Math.pow(10.0,real(a)))) / Math.pow(10.0,real(a))
in n::rd(a,y)
end;
but this solution will give me an uncaught exception overflow...
trying to round up a real number to nth decimal
declaring a function round(n,L), where L is a list of real numbers and n decide the nth decimal
Judging by your use of Math.pow(10.0,real(a)) in your second attempted solution, you seem to be on track. I don't understand where a list comes in; as Yawar points out, try and solve this for rounding a single real, and then apply that recursively (using map) to a list of reals.
So a function
fun roundN (x, n) = ...
fun roundManyN (xs, n) = map (fn x => roundN (x, n)) xs
Start by making some examples and encode them as tests. Since you can't compare real for equality in those tests, start by making (or copying) a custom equality operator.
fun nearlyEqual (a, b, eps) =
let val absA = Real.abs a
val absB = Real.abs b
val diff = Real.abs (a - b)
in Real.== (a, b) orelse
( if Real.== (a, 0.0) orelse
Real.== (b, 0.0) orelse
diff < Real.minNormalPos
then diff < eps * Real.minNormalPos
else diff / Real.min (absA + absB, Real.maxFinite) < eps )
end
val test_roundN_1 =
let val got = roundN (3.14159, 1)
val expected = 3.1
in nearlyEqual (got, expected, 0.1) end
val test_roundN_2 =
let val got = roundN (3.14159, 2)
val expected = 3.14
in nearlyEqual (got, expected, 0.01) end
(* rounding point *)
val test_roundN_3 =
let val got = roundN (3.14159, 3)
val expected = 3.142
in nearlyEqual (got, expected, 0.001) end
(* rounding point *)
val test_roundN_4 =
let val got = roundN (3.14159, 4)
val expected = 3.1416
in nearlyEqual (got, expected, 0.0001) end
val test_roundN_5 =
let val got = roundN (3.14159, 5)
val expected = 3.14159
in nearlyEqual (got, expected, 0.00001) end
You also have some edge cases that you eventually want to deal with:
When n is zero or negative, or when n is greater than the number of digits in the fraction.
When x is close to a rounding point, e.g. roundN (3.1451, 2) ~> 3.15.
When x·10ⁿ has a magnitude that exceeds the size of an int.
When n is so large that a magnitude change may affect the precision of a real.
For a better testing library, check out testlib.sml (and its use in test.sml) in this exercism exercise.
Extracting your second solution into a function, and giving Math.pow (10.0, real n) a temporary binding, you get the solution:
fun roundN (x, n) =
let val m = Math.pow(10.0, real n)
in real (round (x * m)) / m end
this solution will give me an uncaught exception overflow
On what input, I might ask.
One source could be that round : real -> int is a partial function: There are real values that cannot be expressed as int, such as Real.posInf, Real.negInf, 1e10 (on 32-bit SML) and 1e19 (on 64-bit SML). To avoid this, consider using Real.realRound : real -> real to avoid the int conversion.
One way to avoid errors related to x * Math.pow(10.0, real n) causing imprecision because the number grows too big, could be to strip the integer part before multiplying, and adding the integer part back after dividing.
Basically I have a recursive function, that I don't want to be recursive anymore.
But I can't figure out the logic of the existing code itself.
Here it is
float myRecursiveFunction(x, y, depth, divisor) {
if(depth == 0)
return result(x/divisor, y/divisor);
float displace = myRecursiveFunction(x, y, depth-1, divisor/2);
return result(displace+(x/divisor), displace+(y/divisor));
}
and here is how it is called :
float myresult = myRecursiveFunction(x, y, 5, 2);
it will ALWAYS be called with 5 and 2.
Any of you have an idea on how to proceed ? or if it's short enough, a code with no recursion ?
float result(float, float) isn't important here, it is just a function that returns a random float. The point here is to remove the recursion
divisor *= (1/2.0) ** depth
r = result(x/divisor, y/divisor)
for i in range(depth -1):
divisor *= 2
r = result(r + x/divisor, r+y/divisor)
return r
Be careful, you might be losing precision if you do it this way.
Hope I didn't forget some -1/+1 somewhere.
I have a programming function written for Eurler's approximations. Currently the function only takes 3 parameters.
step size
starting f(x)
endting f(x) which is what we are approximating
Each time I have to use Euler, I have to keep on changing my function's differential equation.
E.g.
euqation 1
f'(x) = 3x^{2} - 7
equation 2
f'(x) = f(x) + 2
I want to send differential equation as a paramter. How can I do so?
I am using C#, VBA. Don't have Matlab installed at the moment. But I am willing to try out in Python although I am new to it.
ps: I checked on this question. Quite hard to understand the case there...
perhaps this can help :
I use C# as an example
public static double equation(double x, Func<double, double> f)
{
return f(x);
}
static void Main(string[] args)
{
//f'(x) = 3x^{2} - 7
double result1 = equation(5, x => Math.Pow(3 * x, 1 / 2) - 7);
//f'(x) = f(x) + 2
double result2 = equation(5, x => x + 2);
Console.WriteLine(result1);
Console.WriteLine(result2);
}
I occasionally get a stackoverflow exception in this method.
double norm_cdf(const double x) {
double k = 1.0/(1.0 + 0.2316419*x);
double k_sum = k*(0.319381530 + k*(-0.356563782 + k*(1.781477937 + k*(-1.821255978 + 1.330274429*k))));
if (x >= 0.0) {
return (1.0 - (1.0/(pow(2*M_PI,0.5)))*exp(-0.5*x*x) * k_sum);
} else {
return 1.0 - norm_cdf(-x);
}
}
Any suggestions on why i might be getting it ? Any steps I can take to rectify the error ?
Your problem is when x is Not a Number. NAN >= 0.0 is false, -NAN >= 0.0 is also false.
You could check against NAN specially, as others have suggested, but I would suggest simplifying things:
static double norm_cdf_positive(const double x) {
double k = 1.0/(1.0 + 0.2316419*x);
double k_sum = k*(0.319381530 + k*(-0.356563782 + k*(1.781477937 + k*(-1.821255978 + 1.330274429*k))));
return (1.0 - (1.0/(pow(2*M_PI,0.5)))*exp(-0.5*x*x) * k_sum);
}
double norm_cdf(const double x) {
if (x >= 0.0) {
return norm_cdf_positive(x);
} else {
return 1.0 - norm_cdf_positive(-x);
}
}
This has the advantage that compilers can make smarter assumptions about its behaviour. Note that I've marked the "internal" function static (which will limit its scope to the current compilation unit). You could also use unnamed namespaces. (edit: actually Timothy Shields has a simpler way of removing the recursion, which keeps everything in one function)
Likely this method is just the straw that breaks the camel's back. This function will only call itself at most once, so it's not the problem. (Edit: Or it's the NAN issue others point to, which will result in infinite recursion.)
You can easily make the function not recursive anyway, which might be a simpler option.
double norm_cdf(double x) {
bool negative = x < 0;
x = abs(x);
double k = 1.0/(1.0 + 0.2316419*x);
double k_sum = k*(0.319381530 + k*(-0.356563782 + k*(1.781477937 + k*(-1.821255978 + 1.330274429*k))));
double result = (1.0/(pow(2*M_PI,0.5)))*exp(-0.5*x*x) * k_sum;
if (!negative)
result = 1.0 - result;
return result;
}
When x is NaN, the recursion will never terminate. Add a check: Either std::isnan in C++11, or the lazy x != x, or document-and-blame-user. If you choose to handle NaN, propagating it might be a sensible choice.
I am wondering if there is a C/C++ library or Matlab code technique to determine real and complex numbers using a minimization solver. Here is a code snippet showing what I would like to do. For example, suppose that I know Utilde, but not x and U variables. I want to use optimization (fminsearch) to determine x and U, given Utilde. Note that Utilde is a complex number.
x = 1.5;
U = 50 + 1i*25;
x0 = [1 20]; % starting values
Utilde = U * (1 / exp(2 * x)) * exp( 1i * 2 * x);
xout = fminsearch(#(v)optim(v, Utilde), x0);
function diff = optim(v, Utilde)
x = v(1);
U = v(2);
diff = abs( -(Utilde/U) + (1 / exp(2 * x)) * exp( 1i * 2 * x ) );
The code above does not converge to the proper values, and xout = 1.7318 88.8760. However, if U = 50, which is not a complex number, then xout = 1.5000 50.0000, which are the proper values.
Is there a way in Matlab or C/C++ to ensure proper convergence, given Utilde as a complex number? Maybe I have to change the code above?
If there isn't a way to do this natively in Matlab, then perhaps one
gist of the question is this: Is there a multivariate (i.e.
Nelder-Mead or similar algorithm) optimization library that is able
to work with real and complex inputs and outputs?
Yet another question is whether the function is convergent or not. I
don't know if it is the algorithm or the function. Might I need to change something in the Utilde = U * (1 / exp(2 * x)) * exp( 1i * 2 * x) expression to make it convergent?
The main problem here is that there is no unique solution to this optimization or parameter fitting problem. For example, looking at the expected and actual results above, Utilde is equivalent (ignoring round-off differences) for the two (x, U) pairs, i.e.
Utilde(x = 1.5, U = 50 + 25i) = Utilde(x = 1.7318, U = 88.8760)
Although I have not examined it in depth, I even suspect that for any value of x, you can find an U that computes to Utilde(x, U) = Utilde(x = 1.5, U = 50 + 25i).
The solution here would thus be to further constrain the parameter fitting problem so that the solver yields any solution that can be considered acceptable. Alternatively, reformulate Utilde to have a unique value for any (x, U) pair.
UPDATE, AUG 1
Given reasonable starting values, it actually seems like it is sufficient to restrict x to be real-valued. Performing unconstrained non-linear optimization using the diff function formulated above, I get the following result:
x = 1.50462926953244
U = 50.6977768845879 + 24.7676554234729i
diff = 3.18731710515855E-06
However, changing the starting guess to values more distant from the desired values does yield different solutions, so restricting x to be real-values does not alone provide a unique solution to the problem.
I have implemented this in C#, using the BOBYQA optimizer, but the numerics should be the same as above. If you want to try outside of Matlab, it should also be relatively simple to turn the C# code below into C++ code using the std::complex class and an (unconstrained) nonlinear C++ optimizer of your own choice. You could find some C++ compatible codes that do not require gradient computation here, and there is also various implementations available in Numerical Recipes. For example, you could access the C version of NR online here.
For reference, here are the relevant parts of my C# code:
class Program
{
private static readonly Complex Coeff = new Complex(-2.0, 2.0);
private static readonly Complex UTilde0 = GetUTilde(1.5, new Complex(50.0, 25.0));
static void Main(string[] args)
{
double[] vars = new[] {1.0, 25.0, 0.0}; // xstart = 1.0, Ustart = 25.0
BobyqaExitStatus status = Bobyqa.FindMinimum(GetObjfnValue, vars.Length, vars);
}
public static Complex GetUTilde(double x, Complex U)
{
return U * Complex.Exp(Coeff * x);
}
public static double GetObjfnValue(int n, double[] vars)
{
double x = vars[0];
Complex U = new Complex(vars[1], vars[2]);
return Complex.Abs(-UTilde0 / U + Complex.Exp(Coeff * x));
}
}
The documentation for fminsearch says how to deal with complex numbers in the limitations section:
fminsearch only minimizes over the real numbers, that is, x must only consist of real numbers and f(x) must only return real numbers. When x has complex variables, they must be split into real and imaginary parts.
You can use the functions real and imag to extract the real and imaginary parts, respectively.
It appears that there is no easy way to do this, even if both x and U are real numbers. The equation for Utilde is not well-posed for an optimization problem, and so it must be modified.
I've tried to code up my own version of the Nelder-Mead optimization algorithm, as well as tried Powell's method. Neither seem to work well for this problem, even when I attempted to modify these methods.