I have the following minimal code:
N=30;
P=200;
a = lpc(signal,N);
y = zeros(1, P);
y(1:N) = x(1:N);
for ii=(N+1):P
y(ii) = -sum(a(2:end) .* y((ii-1):-1:(ii-N)));
end
the for loop in y is not efficient, is the a way to vectorize this? maybe a matlab related function ?
EDIT:
some more context to the question - I am trying to predict a known periodic signal efficiently using lpc. For a=lpc(signal,3) I found in matlab documentation that y=filter([0 -a(2:end)],1,x) would do, how do I generalize it to lpc(signal,N)?
I used the symbolic toolbox to print out the formula for any later y values. These formulas are very long and require about (ii-N)*N multiplications for step ii to calculate y directly. A vectorised solution would have to do all these multiplications, it will be slower.
Optimizing your loop is everything that can be done:
b=a(end:-1:2);
for ii=(N+1):P
y(ii) = -sum(b .* y((ii-N):(ii-1)));
end
Indexing backwards is slow.
I don't see an easily feasible way, as each position in y depends on its precedessors. So they have to be calculated step by step.
Related
I am attempting to write a MATLAB program that allows me to give it a differential equation and then ultimately produce a numerical solution.
In particular, I am looking to solve this equation:
The steps involved to create such a program would be, as I see it:
1st: Discretizing the domain of the ODE into n-intervals of equivalent length
2nd: Replace the differential operators write finite difference operators.
3rd: Somehow get MATLAB to construct a system of linear equations that approximates the ODE
4th: Solve the system of linear algebraic equations with MATLAB
5th: Plot the results.
And, on that conceptual level, that all makes sense to me. Attempting to carry out the steps using code is what is proving difficult.
Thus far, I have the program split into two parts. The first one is my attempt at graphing the function, while the second part attempts to perform the integration.
First Part:
function [y] = ODEs (n,a, b)
x= 0:(1/n):1;
A= zeros(n+1,n+1);
A(1,1)= -2;
A(1,2)= 1;
A(n+1, n+1)= -2;
A(n+1, n)=1;
for i= 2:n;
A(i,i)=-2;
A(i,i-1)=1;
A(i,i-1)=1;
end
for i=1:n+1;
b(i,1)=(x(1,i)).* (1/n);
end
y=inv(A)*b;
plot (x,y)
hold all
plot (x,(x(:).^3./6) +(b-a-(1/6)).*x(:) +a)
Second Part:
clear all;
clc;
prompt='How many times do you want to integrate the function y=x: ';
y = input(prompt);
syms ('x');
i = 1;
j = 1;
b = 1;
den_num = 1;
while i <= y
while j <= y
den_num = j*den_num;
j = j+1;
end
b = x.^y /den_num;
i = i+1;
end
pretty(b)
At this point, both parts are riddled with errors (the 2nd part doesn't even provide a graph like I would like), but hopefully what I'm attempting to do is clear. I'm not looking for a solution to all my problems to be handed to me: I know that would prove immense. However, it would be nice to know if I'm heading in the right direction? Or is there a more efficient way of going about things that I'm missing? Hopefully this all makes some sense.
I'm writing a Matlab code that needs to calculate distances of vectors and I execute
X = norm(A(:,i)-B(:,j));
%do something with X
%loop over i and j
quite often. It is a relatively small computation so it is not really suitable for parfor, so I thought the best idea would be to implement it with the gpu functions.
I found that pagefun and arrayfun do something like what I want, but they execute element-wise operations and not on vectors.
So my question is, is there a more clever way of calculating norms without for loops? Or if I actually need to use gpu, what is the best way to do it?
If you need the norm between all the elements of A and B, the fastest way is probably this:
N = 1000; % number of elements
dim = 3; % number of dimensions
A = rand(dim,N, 'gpuArray');
B = rand(dim,1,N, 'gpuArray');
C = sqrt(squeeze(sum(bsxfun(#minus, A, B).^2))); % C(i,j) norm
I get the execution time of 0.16 seconds on CPU and 0.13 seconds on the GPU.
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]));
Here is the code I am using -
mu = mean(X);
sigma = std(X);
for iter = 1:size(X, 1)
X_norm(iter,:)=((X(iter,:)-mu)./sigma)
end
I was wondering if there was a way to do this without using a loop and using only the basic operators, something by which I could add each row in X by mu and divide each by sigma.
X and X_norm are matrices.
One way I found out is - (Although it uses the function ones )
one= ones(size(X, 1), 1);
X_norm = (X - one*(mean(X)))./(one*std(X));
Please note that I want to know more about using the basic operators so don't suggest any libraries or toolkits .
If you are going to post a function, post its implementation as well
Use bsxfun -
X_norm = bsxfun(#rdivide,bsxfun(#minus,X,mu),sigma)
You can also use ones() with your beloved operator : for replication as stated in Loren's blog and then perform the stated operations, like so -
M = size(X,1);
X_norm = (X - mu(ones(M,1),:))./sigma(ones(M,1),:)
For performance, I would go with bsxfun any day!
Note: #Divakar posted a very elegant answer using bsxfun, and I'd suggest to use that approach. Still, I am posting this answer (as I already wrote most of it when the other answer was posted), so you can see what was wrong with your existing code.
As your goal is to normalize every row of the matrix X to zero mean and variance 1, then your version doesn't work as expected. As #Dan remarked in a comment, by using / to divide, you do a matrix division between two row vectors, which creates a scalar as result. The output of the loop is therefore a n x 1 column vector (of which I don't know what it actually contains...).
First, realize that mean returns a row vector, where each entry contains the mean of the corresponding column. To normalize row-wise, you have to get the mean of each row, which can be done by mean(X,2). The same goes for std, i.e. use std(X,[],2).
mu = mean(X,2);
sigma = std(X,[],2);
A version using for loops would now be
X_norm = zeros(size(X));
for k= 1:size(X, 1)
X_norm(k,:) = (X(k,:)-mu(k)) ./ sigma(k);
end
i.e. go through all rows and subtract the mean of the row, and divide by the standard deviation.
By using mu(k), you use the correct mean/std dev for every row.
Also, don't forget to preallocate the matrix X_norm for performance reasons.
Another solution for you using repmat is
(X - repmat(mu, length(X), 1)) ./ repmat(sigma, length(X), 1)
This is possibly a little easier to understand than bsxfun. I have posted this solution to demonstrate that to carry out the operation you want you need to replicate your vectors, mu and sigma. repmat can be used for that, : cant.
Additional Reading: Colon Operator in MATLAB
Although, I would recommend going with bsxfun.
If you have the Statistics Toolbox, you can use the built-in function zscore()
X_norm = zscore(X);
I have the following differential equation which I'm not able to solve.
We know the following about the equation:
D(r) is a third grade polynom
D'(1)=D'(2)=0
D(2)=2D(1)
u(1)=450
u'(2)=-K * (u(2)-Te)
Where K and Te are constants.
I want to approximate the problem using a matrix and I managed to solve
the similiar equation: with the same limit conditions for u(1) and u'(2).
On this equation I approximated u' and u'' with central differences and used a finite difference method between r=1 to r=2. I then placed the results in a matrix A in matlab and the limit conditions in the vector Y in matlab and ran u=A\Y to get how the u value changes. Heres my matlab code for the equation I managed to solve:
clear
a=1;
b=2;
N=100;
h = (b-a)/N;
K=3.20;
Ti=450;
Te=20;
A = zeros(N+2);
A(1,1)=1;
A(end,end)=1/(2*h*K);
A(end,end-1)=1;
A(end,end-2)=-1/(2*h*K);
r=a+h:h:b;
%y(i)
for i=1:1:length(r)
yi(i)=-r(i)*(2/(h^2));
end
A(2:end-1,2:end-1)=A(2:end-1,2:end-1)+diag(yi);
%y(i-1)
for i=1:1:length(r)-1
ymin(i)=r(i+1)*(1/(h^2))-1/(2*h);
end
A(3:end-1,2:end-2) = A(3:end-1,2:end-2)+diag(ymin);
%y(i+1)
for i=1:1:length(r)
ymax(i)=r(i)*(1/(h^2))+1/(2*h);
end
A(2:end-1,3:end)=A(2:end-1,3:end)+diag(ymax);
Y=zeros(N+2,1);
Y(1) =Ti;
Y(2)=-(Ti*(r(1)/(h^2)-(1/(2*h))));
Y(end) = Te;
r=[1,r];
u=A\Y;
plot(r,u(1:end-1));
My question is, how do I solve the first differential equation?
As TroyHaskin pointed out in comments, one can determine D up to a constant factor, and that constant factor cancels out in D'/D anyway. Put another way: we can assume that D(1)=1 (a convenient number), since D can be multiplied by any constant. Now it's easy to find the coefficients (done with Wolfram Alpha), and the polynomial turns out to be
D(r) = -2r^3+9r^2-12r+6
with derivative D'(r) = -6r^2+18r-12. (There is also a smarter way to find the polynomial by starting with D', which is quadratic with known roots.)
I would probably use this information right away, computing the coefficient k of the first derivative:
r = a+h:h:b;
k = 1+r.*(-6*r.^2+18*r-12)./(-2*r.^3+9*r.^2-12*r+6);
It seems that k is always positive on the interval [1,2], so if you want to minimize the changes to existing code, just replace r(i) by r(i)/k(i) in it.
By the way, instead of loops like
for i=1:1:length(r)
yi(i)=-r(i)*(2/(h^2));
end
one usually does simply
yi=-r*(2/(h^2));
This vectorization makes the code more compact and can benefit the performance too (not so much in your example, where solving the linear system is the bottleneck). Another benefit is that yi is properly initialized, while with your loop construction, if yi happened to already exist and have length greater than length(r), the resulting array would have extraneous entries. (This is a potential source of hard-to-track bugs.)