If I have a set of functions
f = #(x1,x2) ([x1 + x2; x1^2 + x2^2])
and I have a second matrix with
b = [x1,x2]
How do I evaluate f([b])? The only way I know how is to say f(b(1),b(2)) but I can't figure out how to automate that because the amount of variables could be up to n. I'm also wondering if there is a better way than going individually and plugging those in.
convertToAcceptArray.m:
function f = convertToAcceptArray(old_f)
function r = new_f(X)
X = num2cell(X);
r = old_f(X{:});
end
f = #new_f
end
usage.m:
f = #(x1,x2) ([x1 + x2; x1^2 + x2^2])
f2 = convertToAcceptArray(f);
f2([1 5])
You could rewrite your functions to take a vector as an input.
f = #(b)[b(1) + b(2); b(1)^2 + b(2)^2]
Then with, e.g., b=[2 3] the call f(b) gives [2+3; 2^2+3^2]=[5; 13].
Assuming that b is an N-by-2 matrix, you can invoke f for every pair of values in b as follows:
cell2mat(arrayfun(f, b(:, 1), b(:, 2), 'UniformOutput', 0)')'
The result would also be an N-by-2 matrix.
Alternatively, if you are allowed to modify f, you can redefine it to accept a vector as input so that you can obtain the entire result by simply calling f(b):
f = #(x)[sum(x, 2), sum(x .^ 2, 2)]
Related
For example, a matrix where each value at row r and column c is
a=[r^2+c^2]
like a=[1, 4; 4; 18]
or
A=[F(r,c)]
A=[F(1,1) F(1,2) F(1,3);
F(2,1) F(2,2) F(2,3);
F(3,1) F(3,2) F(3,3)]
or
A(r,c)=F(r,c)
Mehtod 1
You can do it manually. First, create two matrices for rows and columns indices (suppose the matrix is n x m):
R = repmat((1:n).',[1, m]);
C = repmat((1:m),[n, 1]);
Then, write the function base on these two:
result = R.^2 + C.^2; % F(x,y) = x^2 + y^2
Or define the function inline and apply it on those two:
F = #(x,y)(x.^2 + y.^2);
result = F(R,C);
Mehtod 2
By #Cris Luengo, you can do it the first part by the meshgird function as well. Hence, we can generate R and C like the following:
[C,R] = meshgrid(1:n, 1:m)
I have a simple row vector c with stepsize 0.5, from 10 to 100.(1x181)
Now I would like to get new row vector f which is equal to :
f = c(i) * (c(i)+5) + 1/c(i) + 2^c(i)
c(i) is the elements of c.
How can I implement this equation in MATLAB?
Matlab handles matrix operations like a peace of cake!
c = 10:0.5:100
f = (c.*(c+5))+ (1./c) + (2.^c)
can be done with a simple for loop
f = zeros(length(c),1);
for i = 1:length(c)
f(i) = c(i)*(c(i)+5) +1/(c(i)) + 2^(c(i));
end
I have two vectors, say A of size nx1, and B of size 1xm. I want to create a result matrix C (nxm) from a non-linear formula so that
C(i,j) = A(i)/(A(i)+B(j)).
I know I can do this with a loop such as:
for i=1:n,
C(i,1:m)=A(i)./(A(i)+B(1:m));
end
but is it possible in some way to do this without using a loop?
EDIT: Thanks for your answers! As a small addition, before I saw them a friend suggested the following solution:
C = A*ones(1,m)./(ones(n,1)*B+A*ones(1,m))
If you are on MATLAB R2016a or earlier you'll want to use bsxfun to accomplish this
result = bsxfun(#rdivide, A, bsxfun(#plus, A, B));
If you are on R2016b or newer, then there is implicit expansion which allows you to remove bsxfun and just apply the element-operators directly
result = A ./ (A + B);
Benchmark
Here is a real benchmark using timeit to compare the execution speed of using bsxfun, repmat, implicit broadcasting and a for loop. As you can see from the results, the bsxfun and implicit broadcasting methods yield the fastest execution time.
function comparision()
sz = round(linspace(10, 5000, 30));
times1 = nan(size(sz));
times2 = nan(size(sz));
times3 = nan(size(sz));
times4 = nan(size(sz));
for k = 1:numel(sz)
A = rand(sz(k), 1);
B = rand(1, sz(k));
times1(k) = timeit(#()option1(A,B));
A = rand(sz(k), 1);
B = rand(1, sz(k));
times2(k) = timeit(#()option2(A,B));
A = rand(sz(k), 1);
B = rand(1, sz(k));
times3(k) = timeit(#()option3(A,B));
A = rand(sz(k), 1);
B = rand(1, sz(k));
times4(k) = timeit(#()option4(A,B));
end
figure
p(1) = plot(sz, times1 * 1000, 'DisplayName', 'bsxfun');
hold on
p(2) = plot(sz, times2 * 1000, 'DisplayName', 'repmat');
p(3) = plot(sz, times3 * 1000, 'DisplayName', 'implicit');
p(4) = plot(sz, times4 * 1000, 'DisplayName', 'for loop');
ylabel('Execution time (ms)')
xlabel('Elements in A')
legend(p)
end
function C = option1(A,B)
C = bsxfun(#rdivide, A, bsxfun(#plus, A, B));
end
function C = option2(A,B)
m = numel(B);
n = numel(A);
C = repmat(A,1,m) ./ (repmat(A,1,m) + repmat(B,n,1));
end
function C = option3(A, B)
C = A ./ (A + B);
end
function C = option4(A, B)
m = numel(B);
n = numel(A);
C = zeros(n, m);
for i=1:n,
C(i,1:m)=A(i)./(A(i)+B(1:m));
end
end
See this answer for more information comparing implicit expansion and bsxfun.
Implicit expansion is the way to go if you have 2016b or newer, as mentioned by Suever. Another approach without that is to do element-wise operations after making A and B the same size as C, using repmat...
A1 = repmat(A,1,m);
B1 = repmat(B,n,1);
C = A1 ./ (A1 + B1);
Or in 1 line...
C = repmat(A,1,m) ./ (repmat(A,1,m) + repmat(B,n,1));
As a benchmark, I ran your loop method, the above repmat method, and Suever's bsxfun method for m = 1000, n = 100, averaging over 1,000 runs each:
Using for loop 0.00290520 sec
Using repmat 0.00014693 sec
Using bsxfun 0.00016402 sec
So for large matrices, repmat and bsxfun are comparable with repmat edging it. For small matrices though, just looping can be quicker than both, especially with a small n as that's your loop variable!
It's worth testing the given methods for your specific use case, as the timing results seem fairly variable depending on the inputs.
EDIT:
In regards to the linked question referenced above, I'm trying to describe a different computation than the one above. The one above is of form:
func1 >> func2 >> func3
where >> denotes continuation. Most importantly, func2 do not bind to any variable output by func1, and so on.
My function is of form:
func1 >>=# x func2(x) >>=# y func3(y)
where >>=# denotes continuation from func1 and func2, and func2 binds to the output of func1. So the key here is variable assignment needs to persist between function calls.
Question Proper.
I have this function declaration:
function[y] = distR3(x,c)
a = bsxfun(#minus, x, reshape(c, [1 1 3]));
b = a .* a;
c = b(:,:,1) + b(:,:,2) + b(:,:,3);
y = sqrt(c);
end
That I would like to convert to some anonymous function, perhaps like:
% Incorrect syntax
distRN = #(x,c)
a = bsxfun(#minus, x, reshape(c, [1 1 3]));
b = a .* a;
c = b(:,:,1) + b(:,:,2) + b(:,:,3);
y = sqrt(c);
return y
The key thing to note here is that there's multiple lines in the function, with variable assignment and possibly in-place update of variables.
Is such a thing possible?
EDIT EDIT:
I seem to have found an answer that uses "higher-order-functions". Here's the final code:
distRN = #(x,y) sqrt(c((b(a(x,y)))));
a = #(x,c) bsxfun(#minus, x, reshape(c, [1 1 3]));
b = #(a) a .* a;
c = #(b) b(:,:,1) + b(:,:,2) + b(:,:,3);
Note the indentations over a,b,and c are mine and have no effect.
I'm trying build a matlab function that will evaluate a function and vector that are sent in as parameters. I'm having a hard time trying to figure out how to send in the function so that it can be evaluated in the matlab function. I figured out how to do it without the function but I'm a little lost trying to evaluate it within a matlab function. Below is my code...
This is what I'm trying to do...
x = [x1 x2]';
f = x(x1)^2 + 2 * (x2)^2
x = [5 10];
f = (5)^2 + 2 * (10)^2 % which I would like to return 225, not a column vector
This is what I have and what I have tried...
x = [5 10]';
% without using a matlab function
% k = 1
% f = x(k)^2 + 2 * x(k + 1)^2; % returns the correct answer of 225
f = x^2 + 2 * x^2 % complains about the scalar 2
f = x.^2 + 2 * x.^2 % returns a column vector [75; 300]
function [value] = evalFunction(f,x)
value = f(x);
I've tried...
f = #(x) x.^2 + 2 * (x+1).^2;
value = evalFunction(#f,x) %Error: "f" was previously used as a variable
So I tried...
f = #(x) x.^2 + 2 * (x+1).^2;
value = evalFunction(f,x) %value = [97;342]
I'm new to matlab so any help is appreciated. I've been doing some research and found some stuff here on stackoverflow but can't seem to get it to work. I've seen there are other ways to do this, but I will eventually be adding more code to the matlab evalFunction function so I'd like to do it this way. Thanks!
Anonymous functions and function handles plus array indexing. Taking x as a 2-element vector, define and use your function like:
f = #(x) x(1).^2 + 2 * x(2).^2;
value = evalFunction(f,x) % but you can just do f(x) if that is all you need
However, if evalFunction does nothing other than evaluate f at x, then you don't need it at all. Just do f(x).
Alternately,
f = #(x1,x2) x1.^2 + 2*x2.^2;
value = evalFunction(f,x1,x2); % here your function will call it by f(x1,x2)
You are probably coming at this from a C background - in Matlab, x+1 is the entire vector x with 1 added - not the element offset by 1.
The function you need is
f = #(x)x(1).^2 + 2 * (x(2)).^2;
or, to be a little more "matlab-like":
f = #(x) [1 2] * x(1:2)'.^2;
Which performs the element-wise square of the first two elements of x as a column vector, and then does the matrix multiplication with [1 2], resulting in
1 * x(1) .^2 + 2 * x(2) .^2;
Which seems to be what you were asking for.
caveat: did not have opportunity to test this...