I have Nx2 matrix A and a function f of 2 variables.
A = [1,2;3,4;5,6;7,8;9,0];
func = '#(x1, x2) sin(x1+x2)*cos(x1*x2)/(x1-x2)';
func = str2func(func);
I can apply function to matrix in a way like this:
values = arrayfun(#(x1,x2) func(x1, x2), A(:,1), A(:,2));
It seems to be faster than by for-loop, but still to slow for my program.
I wonder if there is any other way to do it faster?
Edit. Functions are generated by the program. They are made by some simple functions like plus, minus, times, expl, ln. I don't know how to vectorize them.
The fastest approach is to vectorize your function, if that's possible. Vectorizing can sometimes be done by just changing *, /, ^ into their element-wise versions .*, ./, .^. In other cases it may require use of bsxfun.
For your example function, vectorization is straightforward:
A = [1,2;3,4;5,6;7,8;9,0];
x1 = A(:,1);
x2 = A(:,2);
values = sin(x1+x2).*cos(x1.*x2)./(x1-x2);
Related
I would like to approximate numerical data by a function:
f = #(a0,xdata) a0(1).*xdata + ... + a0(n) .* xdata.^n
How can I do that, since a for loop does not work in a function? I know there is an internal polynomial function, but since I might want to extend the sum to non-integer exponents, I want to write my own function.
f = #(a0,xdata) sum(a0 .* xdata.^(1:length(a0)));
If you insist on writing this as anonymous function, but I'd recommend writing this as a function on multiple lines with a function body:
function out = f(a0,xdata)
exponents = 1:length(a0);
out = sum(a0 .*xdata .^ exponents);
end
I have N functions in MATLAB and I can define them using strcat, num2str and eval in a for loop. So without defining by hand I am able to define N functions. Let N=4 and let them be given as follows:
f1=#(x) a1*x+1;
f2=#(x) a2*x+1;
f3=#(x) a3*x+1;
f4=#(x) a4*x+1;
Now I add these four functions and I can do this by hand as follows:
f=#(x)(f1(x)+f2(x)+f3(x)+f4(x));
Here I can do it by hand because I know that N=4. However, in general I never know how many functions I will have. For all cases I cannot write a new function.
Is there any way to do this automatically? I mean if I give N=6 I am expecting to see MATLAB giving me this:
f=#(x)(f1(x)+f2(x)+f3(x)+f4(x)+f5(x)+f6(x));
Whenever I give N=2 then I must have the function f, defined as follows:
f=#(x)(f1(x)+f2(x));
How can we do this?
First of all, you should read this answer that gives a series of reasons to avoid the use of eval. There are very few occasions where eval is necessary, in all other cases it just complicates things. In this case, you use to dynamically generate variable names, which is considered a very bad practice. As detailed in the linked answer and in further writings linked in that answer, dynamic variable names make the code harder to read, harder to maintain, and slower to execute in MATLAB.
So, instead of defining functions f1, f2, f3, ... fN, what you do is define functions f{1}, f{2}, f{3}, ... f{N}. That is, f is a cell array where each element is an anonymous function (or any other function handle).
For example, instead of
f1=#(x) a1*x+1;
f2=#(x) a2*x+1;
f3=#(x) a3*x+1;
f4=#(x) a4*x+1;
you do
N = 4;
a = [4.5, 3.4, 7.1, 2.1];
f = cell(N,1);
for ii=1:N
f{ii} = #(x) a(ii) * x + 1;
end
With these changes, we can easily answer the question. We can now write a function that outputs the sum of the functions in f:
function y = sum_of_functions(f,x)
y = 0;
for ii=1:numel(f)
y = y + f{ii}(x);
end
end
You can put this in a file called sum_of_functions.m, or you can put it at the end of your function file or script file, it doesn't matter. Now, in your code, when you want to evaluate y = f1(x) + f2(x) + f3(x)..., what you write is y = sum_of_functions(f,x).
let say that from given function f(t), we want to construct new function which is given from existed function by this way
where T is some constant let say T=3; of course k can't be from -infinity to infinity in reality because we can't do infinity summation using computer,so it is first my afford
first let us define our function
function y=f(t);
y=-1/(t^2);
end
and second program
k=-1000:1:999;
F=zeros(1,length(k));
T=3;
for t=1:length(k)
F(t)=sum(f(t+k*T));
end
but when i am running second program ,i am getting
>> program
Error using ^
Inputs must be a scalar and a square matrix.
To compute elementwise POWER, use POWER (.^) instead.
Error in f (line 2)
y=-1/(t^2);
Error in program (line 5)
F(t)=sum(f(t+k*T));
so i have two question related to this program :
1.first what is error why it shows me mistake
how can i do it in excel? can i simplify it somehow? thanks in advance
EDITED :
i have changed my code by this way
k=-1000:1:999;
F=zeros(1,length(k));
T=3;
for t=1:length(k)
result=0;
for l=1:length(k)
result=result+f(t+k(l)*T);
end
F(t)=result;
end
is it ok?
To solve your problem in a vectorized way, you'll have to change the function f such that it can be called with vectors as input. This is, as #patrik suggested, achieved by using the element-wise operators .* ./ .^ (Afaik, no .+ .- exist). Unfortunately the comment of #rayryeng is not entirely correct, which may have lead to confusion. The correct way is to use the element-wise operators for both the division ./ and the square .^:
function y = f(t)
y = -1 ./ (t.^2);
end
Your existing code (first version)
k = -1000:1:999;
F = zeros(1,length(k));
T = 3;
for t=1:length(k)
F(t) = sum(f(t+k*T));
end
then works as expected (and is much faster then the version you posted in the edit).
You can even eliminate the for loop and use arrayfun instead. For simple functions f, you can also use function handles instead of creating a separate file. This gives
f = #(t) -1 ./ (t.^2);
k = -1000:1:999;
t = 1:2000;
T = 3;
F = arrayfun(#(x)sum(f(x+k*T)), t);
and is even faster and a simple one-liner. arrayfun takes any function handle as first input. We create a function handle which takes an argument x and does the sum over all k: #(x) sum(f(x+k*T). The second argument, the vector t, contains all values for which the function handle is evaluated.
As proposed by #Divakar in comments, you can also use the bsxfun function:
f = #(t) -1 ./ (t.^2);
k = -1000:1:999;
t = 1:2000;
T = 3;
F = sum(f(bsxfun(#plus,k*T,t.')),2);
where bsxfun creates a matrix containing all combinations between t and k*T, they are all evaluated using f(...) and last, the sum along the second dimension sums over all k's.
Benchmarking
Lets compare these solutions:
Combination of for loop and sum (original question):
Elapsed time is 0.043969 seconds.
Go through all combinations in 2 for loops (edited question):
Elapsed time is 1.367181 seconds.
Vectorized approach with arrayfun:
Elapsed time is 0.063748 seconds.
Vectorized approach with bsxfun as proposed by #Divakar:
Elapsed time is 0.099399 seconds.
So (sadly) the first solution including a for loop beats both vectorized approaches. For larger k vectors (-10000:1:9999), this behavior can be reproduced. The conclusion seems to be that MATLAB has indeed learned how to optimize for loops.
I want to evaluate a double integral of the form
$$\int_{-\infty}^a \int_{-\infty}^b \sum_{i,j}^K a_ia_jx^iy^j\exp(-x^2 - y^2 + xy)dx dy $$
where $a_i$ and $a_j$ are constants. Since the integral is linear, I can interchange summation and integration, but in this case I have to evaluate $K^2$ integrals and it takes too long. In that case I do the following:
for i = 1:K
for j = 1:K
fun = #(x,y) x.^i.*y.^j.*exp(-2.*(x.^2 + y.^2 - 2.*x.*y))
part(i,j) = alpha(i)*alpha(j)*integral2(fun,-inf,a,-inf,b)
end
end
It takes too long, so I want to evaluate only one integral, but I don't know how to vectorize $\sum_{i,j}^K a_ia_jx^iy^j\exp(-x^2 - y^2 + xy)$, namely, how to supply it to integral2. I would be very grateful for any help.
It looks like you'll need to have i and j be third and fourth dimensions, in order for there to be a chance that the code will work.
I also don't have integral2 (I use octave, integral2 is a new matlab function that octave doesn't yet have), so I can't test it, but I'd think something like this might work:
alphaset=zeros(1,1,K,K);
alphaset(1,1,1:K,1:K)=alpha(1:K)'*alpha(1:K);
i_set=zeros(1,1,K,1);
j_set=zeros(1,1,1,K);
i_set(:)=1:K;
j_set(:)=1:K;
fun=#(x,y) x.^i_set.*y.^j_set.*exp(-2.*(x.^2 + y.^2 - 2.*x.*y));
part = squeeze(alphaset.*integral2(fun,-inf,a,-inf,b));
As I said, I can't promise that it'll work, because I don't know how integral2 works. But if you replace the integral2 with simply "sum(sum(fun([1,2,4],[3,-1,2])))", then it works as intended for that operation (that is, it sums over the x and y values, and the result is a matrix over the set of indices).
If you just want to improve speed, you may try parfor.
Let $X=(x,x^2,\cdots,x^K)$, $Y=(y,y^2,\cdots,y^K)$, $A=(a_{ij})$ be a matrix with $a_{ij}=a_{i}a_{j}$, then
$$\sum_{i,j}^K a_{i}a_{j}x^iy^j=XAY^{T}$$
I don't have integral2 function on my matlab, so I didn't test if it will improve the speed a lot.
Also, I think you need to use syms x and y, after you compute the $$XAY^{T}$$, then use matlabFunction to convert symbolic expression to function handle. Here it is my test code: syms x y; X=[x,x^2]; Y=[y,y^2]; Z=X*Y'; fun =matlabFunction(Z); ff=#(x,y) x^2+y^2; gg=fun(x,y).*ff(x,y);
I have a calculation that I want to perform element by element.
foreach i from i=1 to i=N
RES_i = det(A - V_i * I) // notice V_i and RES_i are SCALARS
where for example A is 3x3 , I is 3x3, V and RES are 1xN.
so basically what I do is
idx=1:81
res(idx) = det( A - V(idx)*I );
BUT, this get interperted as taking the whole of V and multiplying by I.
this seems like a simple example but I can't figure out how to vectorize it...
Thanks.
First, this isn't Matlab code...
Second: I think you confuse "vectorization" with an implicit loop. Vectorization means to apply an operation to a whole arrays at once, using vector/matrix/tensor notation and operations. What you want is however an implicit for-each type loop, and it makes total sense that Matlab complains about it.
There's no other way than to write it out explicitly:
res = zeros(81,1);
for ii = 1:numel(res)
res(ii) = det(A-V(ii)*I);
end
You perform element-by-element operation by using . together with the operator of choice. For example:
Element-by-element multiplication: .*
Element-by-element division: ./
and so on... is that what you mean?