Precision error with two mathematically identical expressions around zero - matlab

When plotting two mathematically equivalent expressions very close to zero we get two similar results, but one of the curve has steps instead of being smooth.
1-cosh(x) == -2*sinh(x/2)^2
Now a quick observation reveals that the height of the step is indeed equal to the precision of Matlab, i.e. the variable eps = 2.2204e-16 = 2^-52
This graph was introduced with the name "zero sum", obviously not referencing a zero sum game. But apparently this only occurs with results of additions (or substractions) being very close to zero.
However, to my knowledge calculations with floating point numbers (or doubles) are similar in precision regardless of the scale at which the calculations are being made. So I'd expect error to only creep when something really big is being operated on with something really small, in which case the smaller number gets rounded off.
Matlab code to reproduce this:
x = linspace(-5*10^-8, 5*10^-8, 1001);
y1 = #(x) 1 - cosh(x);
y2 = #(x) -2*(sinh(x/2)).^2;
plot(x,y1(x),'k',x,y2(x),'r')
legend('1-cosh(x)', '-2sinh(x/2)^2')
Can someone explain how this.. works?

The rounding happens in the cosh function. If you plot it and zoom in to the graph at the same scale, you'll see the same staircase-like effect, but centered around 1 on the y-axis.
That is because you cannot represent those intermediate values using doubles.

Related

MATLAB - negative values go to NaN in a symmetric function

Can someone please explain why the following symmetric function cannot pass a certain limit of negative values?
D = 0.1; l = 4;
c = #(x,v) (v/D).*exp(-v*x/D)./(1-exp(-v*l/D));
v_vec = -25:0.01:25;
figure(2)
hold on
plot(v_vec,c(l,v_vec),'b')
plot(v_vec,c(0,v_vec),'r')
Notice at the figure where the blue line chops, this is where I get inf/nan values.
It seems that Matlab is trying to compute a result that is too large, outputs +inf, and then operates on that, which yields +/- inf and NaNs.
For instance, at v=-25, part of the function computes exp(-(-25)*4/0.1), which is exp(1000), and that outputs +inf. (larger than the largest representable double precision float).
You can potentially solve that problem by rewriting your function to avoid operating of such very large (or very small) numbers, say by reorganising the fraction containing exp() functions.
I did encounter the same hurdle using exp() with arguments triggering overflow. Sometimes it is difficult to trace back numeric imprecision or convergence errors. In principle the function definition using exp() only create intermediate issues as your purpose as a transition function. The intention I guess was to provide a continuous function.
My solution to this problem is to divide the argument into regions and provide in each region an approximation function. In your case zero for negative x and proportional to x for positive x. In between you can use the orginal function. Care should be taken to match the approximation at the borders of the regions and the number of continuous differentiations which is important for convergence in loops.

Optimization algorithm in Matlab

I want to calculate maximum of the function CROSS-IN-TRAY which is
shown here:
So I have made this function in Matlab:
function f = CrossInTray2(x)
%the CrossInTray2 objective function
%
f = 0.0001 *(( abs(sin(x(:,1)).* sin(x(:,2)).*exp(abs(100 - sqrt(x(:,1).^2 + x(:,2).^2)/3.14159 )) )+1 ).^0.1);
end
I multiplied the whole formula by (-1) so the function is inverted so when I will be looking for the minimum of the inverted formula it will be actually the maximum of original one.
Then when I go to optimization tools and select the GA algorithm and define lower and upper bounds as -3 and 3 it shows me the result after about 60 iterations which is about 0.13 and the final point is something like [0, 9.34].
And how is this possible that the final point is not in the range defined by the bounds? And what is the actual maximum of this function?
The maximum is (0,0) (actually, when either input is 0, and periodically at multiples of pi). After you negate, you're looking for a minimum of a positive quantity. Just looking at the outer absolute value, it obviously can't get lower than 0. That trivially occurs when either value of sin(x) is 0.
Plugging in, you have f_min = f(0,0) = .0001(0 + 1)^0.1 = 1e-4
This expression is trivial to evaluate and plot over a 2d grid. Do that until you figure out what you're looking at, and what the approximate answer should be, and only then invoke an actual optimizer. GA does not sound like a good candidate for a relatively smooth expression like this. The reason you're getting strange answers is the fact that only one of the input parameters has to be 0. Once the optimizer finds one of those, the other input could be anything.

Matlab Bug in Sine function?

Has anyone tried plotting a sine function for large values in MATLAB?
For e.g.:
x = 0:1000:100000;
plot(x,sin(2*pi*x))
I was just wondering why the amplitude is changing for this periodic function? As per what I expect, for any value of x, the function has a period of 2*pi. Why is it not?
Does anyone know? Is there a way to get it right? Also, is this a bug and is it already known?
That's actually not the amplitude changing. That is due to the numerical imprecisions of floating point arithmetic. Bear in mind that you are specifying an integer sequence from 0 to 100000 in steps of 1000. If you recall from trigonometry, sin(n*x*pi) = 0 when x and n are integers, and so theoretically you should be obtaining an output of all zeroes. In your case, n = 2, and x is a number from 0 to 100000 that is a multiple of 1000.
However, this is what I get when I use the above code in your post:
Take a look at the scale of that graph. It's 10^{-11}. Do you know how small that is? As further evidence, here's what the max and min values are of that sequence:
>> min(sin(2*pi*x))
ans =
-7.8397e-11
>> max(sin(2*pi*x))
ans =
2.9190e-11
The values are so small that they might as well be zero. What you are visualizing in the graph is due to numerical imprecision. As I mentioned before, sin(n*x*pi) = 0 when n and x is are integers, under the assumption that we have all of the decimal places of pi available. However, because we only have 64-bits total to represent pi numerically, you will certainly not get the result to be exactly zero. In addition, be advised that the sin function is very likely to be using numerical approximation algorithms (Taylor / MacLaurin series for example), and so that could also contribute to the fact that the result may not be exactly 0.
There are, of course, workarounds, such as using the symbolic mathematics toolbox (see #yoh.lej's answer). In this case, you will get zero, but I won't focus on that here. Your post is questioning the accuracy of the sin function in MATLAB, that works on numeric type inputs. Theoretically with your input into sin, as it is an integer sequence, every value of x should make sin(n*x*pi) = 0.
BTW, this article is good reading. This is what every programmer needs to know about floating point arithmetic and functions: http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html. A more simple overview can be found here: http://floating-point-gui.de/
Because what is the exact value of pi?
This apparent error is due to the limit of floating point accuracy. If you really need/want to get around that you can do symbolic computation with matlab, see the difference between:
>> sin(2*pi*10)
ans =
-2.4493e-15
and
>> sin(sym(2*pi*10))
ans =
0

Solving equations involving dozens of ceil and floor functions in MATLAB?

I am tackling a problem which uses lots of equations in the form of:
where q_i(x) is the only unknown, c_i, C_j, P_j are always positive. We have two cases, the first when c_i, C_j, P_j are integers and the case when they are real. C_j < P_j for all j
How is this type of problems efficently solved in MATLAB especially when the number of iterations N is between 20 - 100?
What I was doing is q_i(x) - c_i(x) must be equal to the summation of integers. So i was doing an exhaustive search for q_i(x) which satisfies both ends of the equation. Clearly this is computationally exhaustive.
What if c_i(x) is a floating point number, this will even make the problem even more difficult to find a real q_i(x)?
MORE INFO: These equations are from the paper "Integrating Preemption Threshold to Fixed Priority DVS Scheduling Algorithms" by Yang and Lin.
Thanks
You can use bisection method to numerically find zeros of almost any well-behavior functions.
Convert your equation problem into a zero-finding problem, by moving all things to one side of the equal sign. Then find x: f(x)=0.
Apply bisection method equation solver.
That's it! Or may be....
If you have specific range(s) where the roots should fall in, then just perform bisection method for each range. If not, you still have to give a maximum estimation (you don't want to try some number larger than that), and make this as the range.
The problem of this method is for each given range it can only find one root, because it's always picking the left (or right) half of the range. That's OK if P_j is integer, as you can always find a minimum step of the function. Say P_j = 1, then only a change in q_i larger than 1 leads to another segment (and thus a possible different root). Otherwise, within each range shorter than 1 there will be at most one solution.
If P_j is an arbitrary number (such as 1e-10), unless you have a lower limit on P_j, most likely you are out of lucky, since you can't tell how fast the function will jump, which essentially means f(x) is not a well-behavior function, making it hard to solve.
The sum is a step function. You can discretize the problem by calculating where the floor function jumps for the next value; this is periodic for every j. Then you overlay the N ''rhythms'' (each has its own speed specified by the Pj) and get all the locations where the sum jumps. Each segment can have exactly 0 or 1 intersection with qi(x). You should visualize the problem for intuitive understanding like this:
f = #(q) 2 + (floor(q/3)*0.5 + floor(q/4)*3 + floor(q/2)*.3);
xx = -10:0.01:10;
plot(xx,f(xx),xx,xx)
For each step, it can be checked analytically if an intersection exists or not.
jumps = unique([0:3:10,0:4:10,0:2:10]); % Vector with position of jumps
lBounds = jumps(1:end-1); % Vector with lower bounds of stairs
uBounds = jumps(2:end); % Vector with upper bounds of stairs
middle = (lBounds+uBounds)/2; % center of each stair
fStep = f(middle); % height of the stairs
intersection = fStep; % Solution of linear function q=fStep
% Check if intersection is within the bounds of the specific step
solutions = intersection(intersection>=lBounds & intersection<uBounds)
2.3000 6.9000

why does log and exp matlab functions produce the inverse result?

Why does ais not the same as b in matlab??
a = signal;
b = exp(log(signal));
if I plot a and b, the signal is not the same, any help?
The logarithm of a negative number, -x, is y = log(x)+pi*1i. Thus when you apply the exponential function to y you will be left with a zero imaginary part (or something that looks like zero). Try this for example:
format long
x = -1;
y = exp(log(x))
abserr = abs(x-y)
Read more about the complex logarithm here.
There can also be inaccuracy due to floating point of course. The absolute error can be especially significant if your signal has values anywhere near to 1/eps (or -1/eps). Try
x = 1/eps;
y = exp(log(x));
abserr = abs(y-x)
relerr = abs(y-x)/abs(x)
which returns
abserr =
11.500000000000000
relerr =
2.553512956637860e-15
Note that the relative error is tiny. In floating point calculations relative error is generally what we wish to control.
horchler's answer is of course right – but I think it misses the plotting part which causes the OP's confusion. Since Matlab uses complex numbers when necessary, log is defined also for negative numbers, and exp should be the exact inverse of log – except for rounding errors. The numerical difference between signal and exp(log(signal)) should almost always be very small. An example:
>> signal = (-2:2)'
signal =
-2
-1
0
1
2
>> exp(log(signal))
ans =
-2 + 2.44929359829471e-16i
-1 + 1.22464679914735e-16i
0 + 0i
1 + 0i
2 + 0i
However, the behavior of plot differs depending on whether the argument is a real or a complex number:
subplot(1, 2, 1)
plot(signal, '.-')
subplot(1, 2, 2)
plot(exp(log(signal)), '.-')
results in
Though the two vectors have a negligible numerical difference, the plots look completely different.
That is because if called with a single real-valued vector as an argument, plot uses the given vector values for the vertical axis and the vector indices (1, 2, …) for the horizontal axis. However, if called with a single complex-valued vector, plot uses the real part for the horizontal axis and the imaginary part for the vertical axis. I.e., the two calls to plot in the above code are equivalent to
plot(1 : 5, signal, '.-')
and
plot(real(exp(log(signal))), imag(exp(log(signal))), '.-')
respectively.
If you use log with complex or negative values, Matlab calculates the complex logarithm. This will yield unexpected results.
a = abs(signal);
b = exp(log(a));
will work as you expect it to (although the signal's complex part and sign will be lost in the process).
b = log(exp(signal));
will also work because it doesn't need to handle complex logarithms.
In other words, you have to make sure to respect your functions' domains. The real (as in non-complex) log's domain is all positive(!) real numbers while real exp's domain is all numbers. On the other hand, log's image is all real numbers while real exp's is all positive real numbers. That's why it works one way, but not the other. You're trying to do something the real log can't do, so Matlab switches to the complex log. While exp still reverses it, you will get complex results which are handled differently and can look entirely different depending on what you do with them afterwards.