Evaluating an integral numerically using Matlab - matlab

fun= #(x)exp(- a*(d+1).*(t-x)./(d-(t-x)) ) *b.*exp(-b*x);
int= integral(fun,0,t);
Since I did not find a closed form solution, I am using the above code in Matlab to numericaly evaluate the integral.
I am evaluating this integral for different values of d.
The problem is that when I take d<t I get inf. Any idea what is the problem ? and what approach can be used to evaluate the integral in this case ?
Note that a, b, d, and t are all positive. Ex: a=0.1, b=1, t=4.

If you look at the denominator of the first term of fun you see that it depends on t, x and d. So what happens if d == t and x == 0? The denominator goes to 0.0. If d > t there is no positive value for x that will cause the denominator to go to 0.0.
If we let d == t and plot that first term for values of x = 3:.001:5 we see this:
That discontinuity causes the values to be in the range [-Inf, Inf]. Now if we plot exp of these values we see this:

Related

Identify powers in an algebraic expression for a Buckingham Pi calculation in MatLab

This is a continuation of an earlier question I asked here.
If I create a symbolic expression in MatLab
syms L M T
F = M*L/T^2
I want to identify the powers of each dimension M, L, or T. In this case, the answer should be
for M, 1
for L, 1
for T, -2
There is a relatively easy way to do this if the expression F were a polynomial in MatLab employing the coeffs function. However, my expression is clearly not a polynomial as far as MatLab is concerned.
In the end, I will be working with at least two parameters so I will put them in a cell array since I anticipate cellfun will be useful.
V = L/T
param = {F,V};
The final output should be a table where the rows correspond to each dimension, L M and T and the columns are for each parameter F and V.
syms L M T
F = M*L/T^2
[C,T] = coeffs(expand(log(F),'IgnoreAnalyticConstraints',true))
[exp(T).' C.']
It returns the table:

Why does MATLAB give a negative value for this integration?

I'm trying do the following integration:
where d >= 0.
I try to get an explicit expression and I think the result should be a positive value since the integrand is greater or equal to 0, but the symbolic integration of MATLAB gave me this result:
syms y d
assume(d>=0)
int(y^2*sqrt(-y^2+d*y),y,0,d)
ans =
-(5*pi*d^4)/128
So I am wondering why a negative value appeared. Do you know how to interpret this result?
This is very clearly a bug, and I've already submitted a bug report with The MathWorks. You can confirm it by plotting the integrand and noting it is always positive over the range [0 d], thus assuring that the integral should yield a positive value:
h = [];
for d = 1:5,
y = linspace(0, d, 1000);
h = [h; plot(y, f(y, d))];
hold on;
end
legend(h, strcat({'d = '}, int2str((1:5).')));
xlabel('y');
ylabel('f(y)');
title('f(y) = y^2*sqrt(d*y - y^2)');
Update #1:
A response from The MathWorks suggest that this may be an issue with the MuPad command limit. Below is the indefinite integral found in MuPad:
Evaluating this at y=d gives the correct result, but evaluating it in the limit as y approaches 0 gives different results based on whether d is substituted before or after the limit calculation. Here's an example with d=1:
Note the change in sign of the first term. In this case, substituting for d before the limit calculation results in a positive (and correct) evaluation of the integral. MATLAB therefore appears to be substituting for d after the limit calculation, giving the erroneous negative result for the definite integral.
Update #2:
I received a follow-up response stating that this bug has now been addressed in the latest release, R2018b. I was able to confirm in the R2018b pre-release that the two limit calculations above produce the same result, and that the integration result now has the proper sign:
syms y d
assume(d >= 0)
int(y^2*sqrt(-y^2+d*y), y, 0, d)
ans =
(5*pi*d^4)/128

multipoint boundary value ode with varying coefficients in matlab

I have a second order differential equation given as:
d²u/dz²=a+bu, where a and b are constants that vary in different intervals and z∈[0,Zn]
Intervals are given as I1:z∈[0,Z1), I2:z∈[Z1, Z2), ..., I(n):z∈[Z(n-1), Z(n)] and {a,b} constants varies as {a1,b1} in I1, {a2,b2} in I2,...,{an,bn} in I(n).
Boundary condition is given as u(z=0)=U0, u(z=Zn)=Umax.
A continuous graph of u vs z is required.
I thought of using bvp5c in matlab but bvp5c can solve multipoint boundary value problems where a = a0 < a1 < a2 < ... < an = b in the interval [a,b]. The points a1,a2, ... ,an–1 represent interfaces that divide [a,b] into regions. The problem is my constants(a,b in above ode) is also varying in different intervals.
You can do it. If you read the bvp5c docs, you will see that it takes a function handle (odefun) which takes the z, and u arguments. Simply return the correct value for the RHS based on value of the argument z. Note that you have to convert your 2nd order equation to a 1st order one.
du/dz = v
dv/dz = a(z) + b(z)u
You need to return the vector [v, a(z) + b(z)u] from the two arguments z and [u,v] that your odefun will be called with.

matlab wrong modulo result when the divident is raised to a power

Just wondering... I tried doing by hand (with the multiply and square method) the operation (111^11)mod143 and I got the result 67. I also checked that this is correct, in many online tools. Yet, in matlab plugging:
mod(111^11,143)
gives 127! Is there any particular reason for this? I didn't find anything in the documentation...
The value of 111^11 (about 3.1518e+022) exceeds the maximum integer that is guaranteed to be represented exactly as a double, which is 2^53 (about 9.0072e+015). So the result is spoilt by insufficient numerical precision.
To achieve the correct result, use symbolic computation:
>> syms x y z
>> r = mod(x^y, z);
>> subs(r, [x y z], [111 11 143])
ans =
67
Alternatively, for this specific operation (modulo of a large number that is expressed as a product of small numbers), you can do the computation very easily using the following fact (where ∗ denotes product):
mod(a∗b, z) = mod(mod(a,z)∗mod(b,z), z)
That is, you can apply the modulo operation to factors of your large number and the final result is unchanged. If you choose factors sufficiently small so that they can be represented exactly as double, you can do the computation numerically without any loss of precision.
For example: using the decomposition 111^11 = 111^4*111^4*111^3, since all factors are small enough, gives the correct result:
>> mod((mod(111^4, 143))^2 * mod(111^3, 143), 143)
ans =
67
Similarly, using 111^2 and 111 as factors,
>> mod((mod(111^2, 143))^5 * mod(111, 143), 143)
ans =
67
from the matlab website they recommend using powermod(b, e, m) (b^e mod m)
"If b and m are numbers, the modular power b^e mod m can also be computed by the direct call b^e mod m. However, powermod(b, e, m) avoids the overhead of computing the intermediate result be and computes the modular power much more efficiently." ...
Another way is to use symfun
syms x y z
f = symfun(mod(x^y,z), [x y z])
f(111,11,143)

What is the Haskell / hmatrix equivalent of the MATLAB pos function?

I'm translating some MATLAB code to Haskell using the hmatrix library. It's going well, but
I'm stumbling on the pos function, because I don't know what it does or what it's Haskell equivalent will be.
The MATLAB code looks like this:
[U,S,V] = svd(Y,0);
diagS = diag(S);
...
A = U * diag(pos(diagS-tau)) * V';
E = sign(Y) .* pos( abs(Y) - lambda*tau );
M = D - A - E;
My Haskell translation so far:
(u,s,v) = svd y
diagS = diag s
a = u `multiply` (diagS - tau) `multiply` v
This actually type checks ok, but of course, I'm missing the "pos" call, and it throws the error:
inconsistent dimensions in matrix product (3,3) x (4,4)
So I'm guessing pos does something with matrix size? Googling "matlab pos function" didn't turn up anything useful, so any pointers are very much appreciated! (Obviously I don't know much MATLAB)
Incidentally this is for the TILT algorithm to recover low rank textures from a noisy, warped image. I'm very excited about it, even if the math is way beyond me!
Looks like the pos function is defined in a different MATLAB file:
function P = pos(A)
P = A .* double( A > 0 );
I can't quite decipher what this is doing. Assuming that boolean values cast to doubles where "True" == 1.0 and "False" == 0.0
In that case it turns negative values to zero and leaves positive numbers unchanged?
It looks as though pos finds the positive part of a matrix. You could implement this directly with mapMatrix
pos :: (Storable a, Num a) => Matrix a -> Matrix a
pos = mapMatrix go where
go x | x > 0 = x
| otherwise = 0
Though Matlab makes no distinction between Matrix and Vector unlike Haskell.
But it's worth analyzing that Matlab fragment more. Per http://www.mathworks.com/help/matlab/ref/svd.html the first line computes the "economy-sized" Singular Value Decomposition of Y, i.e. three matrices such that
U * S * V = Y
where, assuming Y is m x n then U is m x n, S is n x n and diagonal, and V is n x n. Further, both U and V should be orthonormal. In linear algebraic terms this separates the linear transformation Y into two "rotation" components and the central eigenvalue scaling component.
Since S is diagonal, we extract that diagonal as a vector using diag(S) and then subtract a term tau which must also be a vector. This might produce a diagonal containing negative values which cannot be properly interpreted as eigenvalues, so pos is there to trim out the negative eigenvalues, setting them to 0. We then use diag to convert the resulting vector back into a diagonal matrix and multiply the pieces back together to get A, a modified form of Y.
Note that we can skip some steps in Haskell as svd (and its "economy-sized" partner thinSVD) return vectors of eigenvalues instead of mostly 0'd diagonal matrices.
(u, s, v) = thinSVD y
-- note the trans here, that was the ' in Matlab
a = u `multiply` diag (fmap (max 0) s) `multiply` trans v
Above fmap maps max 0 over the Vector of eigenvalues s and then diag (from Numeric.Container) reinflates the Vector into a Matrix prior to the multiplys. With a little thought it's easy to see that max 0 is just pos applied to a single element.
(A>0) returns the positions of elements of A which are larger than zero,
so forexample, if you have
A = [ -1 2 -3 4
5 6 -7 -8 ]
then B = (A > 0) returns
B = [ 0 1 0 1
1 1 0 0]
Note that we have ones corresponding to an elemnt of A which is larger than zero, and 0 otherwise.
Now if you multiply this elementwise with A using the .* notation, then you are multipling each element of A that is larger than zero with 1, and with zero otherwise. That is, A .* B means
[ -1*0 2*1 -3*0 4*1
5*1 6*1 -7*0 -8*0 ]
giving finally,
[ 0 2 0 4
5 6 0 0 ]
So you need to write your own function that will return positive values intact, and negative values set to zero.
And also, u and v does not match in dimension, for a generall SVD decomposition, so you actually would need to REDIAGONALIZE pos(diagS - Tau), so that u* diagnonalized_(diagS -tau) agrres to v