Iterating through an array/vector Matlab - matlab

First off, I do have to apologize, because I'm very sure that I'm simply making a simple mistake. I am making my first program in MatLab, and have been reading up on the relevant documentation, but simply still can't seem to solve my problem.
I am trying to implement the equation for information entropy in MatLab (I'm sure it probably already exists, but that's beside the point), but I am having issues with arrayfun as it seems to be calling entropySingle with no arguments.
I have the following functions in appropriately named files
function y = entropySingle(x)
y = x * log2(x);
end
and
function y = entropy(x)
if ~isvector(x)
error('Input must be a vector');
end
x = arrayfun(entropySingle, x);
y = sum(x);
end
and I'm calling entropy([1/3 1/4 1/6 1/8 1/12 1/24]). The error occurs on line 2 of entropySingle, but why is it being called with a null pointer? Thanks in advance,

You need to use element wise multiplication:
y = x .* log2(x);
Not using that small . before the multiplication tell matlab this is about matrix multiplication where it is not.
Also, don't use the name entropy. You are overwriting a built-in matlab function, and this just invites more trouble to your code and life in general.

Related

Matlab SOR Method Implementation

Using an initial approximation of a zero vector and not considering tolerance I have shorten the code to only require 4 arguments. Such that x1 always equals c, and so on by the equation x(k+1)=x(k)T+c.
However the code doesn't seem to produce the correct approximations that you would expect. Does anyone notice where I messed up? Assuming DLU_decomposition(A) returns the correct matrices.
function x = sor2(A,b,omega,kmax)
[D,L,U] = DLU_decomposition(A);
T=inv(D-omega*L)*(((1-omega)*D)+(omega*U));
c= (omega*inv(D-omega*L))*b;
for k=1:kmax,
if(k==1),
x=c;
end
x=T*x+c;
end
norm(A*x-b)
end
Well I can guess all the confusion comes maybe from the multiplications. You need to calculate the matrices elementwise --> use .* instead of the normal *. Would that deliver the correct approximations?

Obtaining the constant that makes the integral equal to zero in Matlab

I'm trying to code a MATLAB program and I have arrived at a point where I need to do the following. I have this equation:
I must find the value of the constant "Xcp" (greater than zero), that is the value that makes the integral equal to zero.
In order to do so, I have coded a loop in which the the value of Xcp advances with small increments on each iteration and the integral is performed and checked if it's zero, if it reaches zero the loop finishes and the Xcp is stored with this value.
However, I think this is not an efficient way to do this task. The running time increases a lot, because this loop is long and has the to perform the integral and the integration limits substitution every time.
Is there a smarter way to do this in Matlab to obtain a better code efficiency?
P.S.: I have used conv() to multiply both polynomials. Since cl(x) and (x-Xcp) are both polynomials.
EDIT: Piece of code.
p = [1 -Xcp]; % polynomial (x-Xcp)
Xcp=0.001;
i=1;
found=false;
while(i<=x_te && found~=true) % Xcp is upper bounded by x_te
int_cl_p = polyint(conv(cl,p));
Cm_cp=(-1/c^2)*diff(polyval(int_cl_p,[x_le,x_te]));
if(Cm_cp==0)
found=true;
else
Xcp=Xcp+0.001;
end
end
This is the code I used to run this section. Another problem is that I have to do it for different cases (different cl functions), for this reason the code is even more slow.
As far as I understood, you need to solve the equation for X_CP.
I suggest using symbolic solver for this. This is not the most efficient way for large polynomials, but for polynomials of degree 20 it takes less than 1 second. I do not claim that this solution is fastest, but this provides generic solution to the problem. If your polynomial does not change every iteration, then you can use this generic solution many times and not spend time for calculating integral.
So, generic symbolic solution in terms of xLE and xTE is obtained using this:
syms xLE xTE c x xCP
a = 1:20;
%//arbitrary polynomial of degree 20
cl = sum(x.^a.*randi([-100,100],1,20));
tic
eqn = -1/c^2 * int(cl * (x-xCP), x, xLE, xTE) == 0;
xCP = solve(eqn,xCP);
pretty(xCP)
toc
Elapsed time is 0.550371 seconds.
You can further use matlabFunction for finding the numerical solutions:
xCP_numerical = matlabFunction(xCP);
%// we then just plug xLE = 10 and xTE = 20 values into function
answer = xCP_numerical(10,20)
answer =
19.8038
The slight modification of the code can allow you to use this for generic coefficients.
Hope that helps
If you multiply by -1/c^2, then you can rearrange as
and integrate however you fancy. Since c_l is a polynomial order N, if it's defined in MATLAB using the usual notation for polyval, where coefficients are stored in a vector a such that
then integration is straightforward:
MATLAB code might look something like this
int_cl_p = polyint(cl);
int_cl_x_p = polyint([cl 0]);
X_CP = diff(polyval(int_cl_x_p,[x_le,x_te]))/diff(polyval(int_cl_p,[x_le,x_te]));

How to solve an equation with piecewise defined function in Matlab?

I have been working on solving some equation in a more complicated context. However, I want to illustrate my question through the following simple example.
Consider the following two functions:
function y=f1(x)
y=1-x;
end
function y=f2(x)
if x<0
y=0;
else
y=x;
end
end
I want to solve the following equation: f1(x)=f2(x). The code I used is:
syms x;
x=solve(f1(x)-f2(x));
And I got the following error:
??? Error using ==> sym.sym>notimplemented at 2621
Function 'lt' is not implemented for MuPAD symbolic objects.
Error in ==> sym.sym>sym.lt at 812
notimplemented('lt');
Error in ==> f2 at 3
if x<0
I know the error is because x is a symbolic variable and therefore I could not compare x with 0 in the piecewise function f2(x).
Is there a way to fix this and solve the equation?
First, make sure symbolic math is even the appropriate solution method for your problem. In many cases it isn't. Look at fzero and fsolve amongst many others. A symbolic method is only needed if, for example, you want a formula or if you need to ensure precision.
In such an old version of Matlab, you may want to break up your piecewise function into separate continuous functions and solve them separately:
syms x;
s1 = solve(1-x^2,x) % For x >= 0
s2 = solve(1-x,x) % For x < 0
Then you can either manually examine or numerically compare the outputs to determine if any or all of the solutions are valid for the chosen regime – something like this:
s = [s1(double(s1) >= 0);s2(double(s2) < 0)]
You can also take advantage of the heaviside function, which is available in much older versions.
syms x;
f1 = 1-x;
f2 = x*heaviside(x);
s = solve(f1-f2,x)
Yes, the Heaviside function is 0.5 at zero – this gives it the appropriate mathematical properties. You can shift it to compare values other than zero. This is a standard technique.
In Matlab R2012a+, you can take advantage of assumptions in addition to the normal relational operators. To add to #AlexB's comment, you should convert the output of any logical comparison to symbolic before using isAlways:
isAlways(sym(x<0))
In your case, x is obviously not "always" on one side or the other of zero, but you may still find this useful in other cases.
If you want to get deep into Matlab's symbolic math, you can create piecewise functions using MuPAD, which are accessible from Matlab – e.g., see my example here.

Matlab Finding the Zeros of a Symbolic Function

I have a symbolic function, whose zeros I am particular interested in knowing. I have searched through google, trying to find something related to my query, but was unsuccessful.
Could someone please help me?
EDIT:
T(x,t) = 72/((2*n+1)^2*pi^3)*(1 - (2*n+1)^2*pi^2*t/45 + (2*n+1)^4*pi^4*t^2/(2*45^2) - (2*n+1)^6*pi^6*t^3/(6*45^3))*(2*n+1)*pi*x/3;
for i=1:1:1000
T_new = 72/((2*i+1)^2*pi^3)*(1 - (2*i+1)^2*pi^2*t/45 + (2*i+1)^4*pi^4*t^2/(2*45^2) - (2*i+1)^6*pi^6*t^3/(6*45^3))*(2*i+1)*pi*x/3;
T = T + T_new;
end
T = T - 72/((2*n+1)^2*pi^3)*(1 - (2*n+1)^2*pi^2*t/45 + (2*n+1)^4*pi^4*t^2/(2*45^2) - (2*n+1)^6*pi^6*t^3/(6*45^3))*(2*n+1)*pi*x/3;
T = T(1.5,t);
T_EQ = 0.00001
S = solve(T - T_EQ == 0,t);
The problem that I get is that S is an a vector which contains imaginary numbers. I expected a real number, because I am trying to calculate a time.
Here is a little background as to what I am trying to do:
http://hans.math.upenn.edu/~deturck/m241/solving_the_heat_eqn.pdf
In the given link is the heat equation solved for a particular one-dimensional case. The temperature distribution, that satisfies the prescribed boundary and initial conditions, is given on page 50, I believe.
What I would like to do is find the time at which the one-dimensional object equilibrates with the environment, which is held at a constant temperature of T=0. As far as I know, the easiest way to do this would be to use the Taylor expansion of the exponential function, using only the first few terms, because I expect the equilibrium time to be relatively short; and then use the small angle approximation for the sine function, because the rod has a relatively small length. Doing just this, I made a for loop to generate terms just as the summation function would--as you can see, I used 1000 terms.
Does what I am doing seem wrong to anyone? If there is a better method, could someone please recommend it?
You shouldn't be surprised to see imaginary roots provided that at least one root is real and positive, corresponding to your time. The question is if the time makes any sense due to the approximations that you're making. Have you plotted the the actual function to get a rough approximation for where the zero is?
I can't really comment on the particular problem you're trying to solve. You need to make sure that you're using enough Taylor expansion terms an that they are accurate for the domain. Have you tried this leaving in the exp and/or sin? Is there any reason that you can't just use zero? And have you checked that your summation has converged after 1,000 terms? Or does it converge much sooner or not at all?
The main question is why are you using symbolic math at all to solve this? This seems like a numeric problem unless you're experiencing overflow/underflow issues in your summation. You can find the zero using fzero in this case:
N = 32; % Number of terms in summation
x = 1.5;
T_EQ = 1e-5;
n = (2*(0:N)+1)*pi;
T = #(t)sum((72./n.^3).*exp(-n.^2*t/45).*sin(n*x/3))-T_EQ;
S = fzero(T,[0 1e3]) % Bounds around a root guarantees solution if function monotonic
which returns
S =
56.333877640358708
If you're going to use solve, I'd do something like the following to avoid for loops:
syms t
N = 32;
x = 1.5;
T_EQ = 1e-5;
n = (2*sym(0:N)+1)*sym(pi);
T(t) = sum((72./n.^3).*exp(-n.^2*t/45).*sin(n*x/3));
S = double(solve(T-T_EQ==0,t))
or, using symsum:
syms n t
N = 32;
x = 1.5;
T_EQ = 1e-5;
T(t) = symsum((72/(pi*(2*n+1))^3)*exp(-(pi*(2*n+1))^2*t/45)*sin(pi*(2*n+1)*x/3),n,0,N);
S = double(solve(T-T_EQ==0,t))
Lastly, your symbolic solutions are not even exact as some your pi variables are being converted to rational approximations. pi is floating point. Things like pi*t are generally safe if t is symbolic, because pi will be recognized as such. However, pi^2 is calculated in floating-point before being converted to symbolic due to order of operations. In general your should use sym('pi') or sym(pi) in symbolic expressions.
Assuming you have a polynomial or trigonometric function of x or y, and what you mean by "zeros" is the values where the function crosses the axis, i.e., either x or y is zero, you can call the value of the function when a variable is 0. An example:
syms x y
f=-cos(x)*exp(-(x^2)/40);
ezsurf(f,[-10,10])
F=matlabFunction(f,'vars',{[x]});
F([0])
The ezsurf just visualizes the plot. If you want a function of both x and y, you do something like the following:
syms x y
f=-cos(x)*cos(y)*exp(-(x^2+y^2)/40);
ezsurf(f,[-10,10])
F=matlabFunction(f,'vars',{[x,y]});
for y=0
solve(f)
end
This will give you the value of the function for which integer multiples of x correspond to zero points for y (values of the function that are on the y=0 plane).

vector valued limits in matlab integral

Is it possible to use vector limits for any matlab function of integration? I have to avoid from for loops because of the speed of my program. Can you please give me a clue on do
k=0:5
f=#(x)x^2
quad(f,k,k+1)
If somebody need, I found the answer of my question:quad with vector limit
I will try giving you an answer, based on my experience with quad function.
Starting from this:
k=0:5;
f=#(x) x.^2;
Notice the difference in your f definition (incorrect) and mine (correct).
If you only mean to integrate f within the range (0,5) you can easily call
quad(f,k(1),k(end))
Without handle function, you may reach the same results in a different way, by making use of trapz:
x = 0:5;
y = x.^2;
trapz(x,y)
If, instead, you mean to perform a step-by-step integration in the small range [k(i),k(i+1)] you may type
arrayfun(#(ii) quad(f,k(ii),k(ii+1)),1:numel(k)-1)
For a sake of convenince, notice that
sum(arrayfun(#(ii) quad(f,k(ii),k(ii+1)),1:numel(k)-1)) == quad(f,k(1),k(end))
I hope this helps.