I'm kinda lost in a problem where I need to (dynamically) create an anonymous function handle from huge matrices and 192 variables.
I'll try to give you an (easier) example of what I have to do and what I have in mind to achieve it (but without a clue how to do it in MATLAB ):
syms x1 x2 x3 x4 real
X = [x1 x2 x3 x4]'
F = [1 2 3 4; 1 2 3 4]
Y = [9 8]'
my_fun = (F*X + Y)' * (F*X + Y)
%solve my_fun to min for X
So, this is what I want to have (my_fun).
The thing is, that there will be x1 to x192, F will be like 10000x192 and Y like 10000x1. Using symbolic tb is very slow and since I later have to calculate the Hessian it is superdupser slow.
I now found a way to numerically calculate the Hessian (from MATLAB file exchange) but have no clue, how to calculate my_fun as an (anonymous) function. I simply lack the skills of MATLAB + function handles. I already tried several things.
So, I think what I need to know is how to create X dynamically with x(1) to x(192) and then calculate my_fun = #(x) ...
EDIT: Thanks for the edit :)
The only thing that I can think of to solve this is by using a couple of loops to create the anonymous function handle as a string and then use str2fun, but I feel like this isn't the easiest way to get what I need :)
First of all: Delete your first two lines containing stuff from the symbolic toolbox. You won't need any of this.
You have two options:
Using a function-file:
These would be the contents of the file my_fun.m:
function result = my_fun(X)
F = [1 2 3 4; 1 2 3 4];
Y = [9 8]';
result = (F*X + Y)' * (F*X + Y);
You would then pass this function as an argument using #my_fun.
Using an anonymous function
You could define a function handle using an anonymous function using:
F = [1 2 3 4; 1 2 3 4];
Y = [9 8]';
my_fun = #(X) (F*X + Y)' * (F*X + Y);
This will capture the current contents of your local variables Fand Y. So changing F or Y afterwards won't change my_fun.
In contrast to the above version you will pass this using my_fun.
Related
I need some help iterating over a function that depends on two variables.
So let's say I have a function that depends on two variables.
Let's call it f = x + y
Now, I have a two lists, one of x variables and one of y variables. For example,
xlist = [1 2 3] and
ylist = [4 5 6]
And I want to go through each element of the lists and plug it into f. For example, set x=1 and then evaluate f for y=4, then y=5, then y=6... and repeat for x=2 and x=3.
Finally, I want to return a matrix of the calculated values. For the example above, the answer should be
[5 6 7];[6 7 8];[7 8 9]
How would I go about doing this?
Assuming the function can't be vectorized and thus you really need to iterate, a simple way is via ndgrid (to create x, y values that describe all possible pairs) and arrayfun (to iterate over the two x, y values at the same time):
f = #(x,y) x+y; % Or f = #fun, if fun is a function defined elsewhere
xlist = [1 2 3];
ylist = [4 5 6];
[xx, yy] = ndgrid(xlist, ylist); % all pairs
result = arrayfun(f, xx, yy);
In many cases the function can be vectorized, which results in faster code. For the example function this would be done defining f as
f = #(x,y) bsxfun(#plus, x(:), y(:).');
or in recent Matlab versions you can exploit implicit singleton expansion and just write
f = #(x,y) x(:)+y(:).';
In either case, note that the two arguments of addition are forced to be a column vector (x(:)) and a row vector (y(:).'), so that singleton expansion will automatically create all pairs:
xlist = [1 2 3];
ylist = [4 5 6];
result = f(xlist, ylist);
Another way to do it would be to use two for loops:
x_values=[2,4,6,8];
y_values=[1,3,5,7];
%initialize a matrix with zeros
output_matrix=zeros(length(x_values),length(y_values));
for i=1:length(x_values)
for j=1:length(y_values)
output_matrix(i,j)=x_values(i)+y_values(j);
end
end
output_matrix
how can I differentiate a function in matlab? I tried with:
syms x;
f = 3x^2 + 2;
A = diff(f);
disp(A);
My problem is now I want to give x a value after (for example A(x = 1) and I don't know how.
First, there's an error in your code, you can't imply multiplication, you need to write 3*x^2 rather than 3x^2.
Also, in case you feed the function a vector rather than scalar, you should use element-wise operations (including a . before powers, multiplication etc.) so this becomes 3*x.^2.
Other than that, 2 options:
syms x;
f = 3*x.^2 + 2;
1) define A like you did and use subs to substitute x for, say, 1.
A = diff(f);
subs(A,x,1);
2) define A as an anonymous function and call it more easily.
A = #(y) subs(diff(f),x,y)
Now A can be easily called with different values
A(1)
ans = 6
A(2)
ans = 12
Links to documentation on element-wise ops, subs and anonymous functions:
https://uk.mathworks.com/help/matlab/matlab_prog/array-vs-matrix-operations.html
https://uk.mathworks.com/help/symbolic/subs.html
https://uk.mathworks.com/help/matlab/matlab_prog/anonymous-functions.html
Modify your code like this:
syms x;
f = 3*x^2 + 2; % You missed a * here
A(x) = diff(f); % This creates a symfun
A(1) % This gives the value of A at x=1
You need the matlabfunction function.
matlabFunction Generate a MATLAB file or anonymous function from a sym
I've already searched it here but I couldn't found it the way I was looking for.
I kind managed to do it using Symbolic Math but I don't understand it quite well. For exemple, after doing that
syms y x
ezplot(-y + x + 1 == 0)
i get a nice graph, but can I use this expression later to calculate its value? like, first I want to plot -y + x + 1 == 0 and at another moment I want to solve f(3) for exemple, where f(x) = x + 1 (same equation).
I know I can write a function to do that, but as a function I don't know how to plot it. In the other way, I know how to plot using symbolic math, but I don't know how to calculate it after.
I'm writing a PLA algorithm and them I need to generate the 'a', 'b' 'c' for the equation, that why I need to know how to plot and solve in a "systematic code" way, and not typing one by one.
Thanks in advance!
The equation you gave us is a straight line, so a polynomial. The coefficients are y= -b/a*x -c/a.
% ay + bx + c = 0 reads y = -b/a*x - c/a*1
a = -1;
b = 1;
c = 1;
p = [-b/a, -c/a]; % polynomial representing your equation
% plot like this
x = linspace(-2,2, 50);
figure
plot(x, polyval(p,x)) % evaluate polynomial p at the positions x
% find the solution
roots(p) # -1
If you need or want to use ezplot, you can put the polyval-expression in an inline function and you can call ezplot with that handle:
f = #(x) polyval(p, x); % the function
ezplot(f)
Just define f to be a function of the symbolic variable x:
>> syms x
>> f = x+1;
Then you can use f as the input to ezplot:
>> ezplot(f)
which produces the graph
On the other hand, to solve the equation f(x)=0 use solve as follows:
>> solve(f)
ans =
-1
ezplot and solve can be used with string inputs as well, but the string has to be different in either case. To plot the graph:
>> ezplot('x+1');
To solve the equation:
>> solve('x+1=0')
ans =
-1
Is it possible to use the size (s) of the points to 'weight' the line of best fit?
x = [1 2 3 4 5];
y = [2 4 5 3 4];
s = [10 15 20 2 5];
scatter(x,y,s)
hold on
weight = s;
p = polyfit(x,y,1); %how do I take into account the size of the points?
f = polyval(p,x);
plot(x,f,'-r')
Using Marcin's suggestion, you can incorporate lscov into polyfit. As the documentation explains, polynomial fitting is done by computing the Vandermonde matrix V of x, and then executing p = V\y. This is the standard formalism of any least-squares solution, and lends itself to weighted-least-squares in MATLAB through lscov.
Taking your x, y and weight vectors, instead of calling polyfit(x,y,n) you can do the following:
% Construct Vandermonde matrix. This code is taken from polyfit.m
V(:,n+1) = ones(length(x),1,class(x));
for j = n:-1:1
V(:,j) = x.*V(:,j+1);
end
% Solve using weighted-least-squares
p = lscov(V,y,weight);
You can even go one step further, and modify polyfit.m itself to include this functionality, or add another function polyfitw.m if you are not inclined to modify original MATLAB functions. Note however that polyfit has some more optional outputs for structure, computed using QR decomposition as detailed in the documentation. Generalization of these outputs to the weighted case will require some more work.
x = (1:10)';
y = (3 * x + 5) + rand(length(x),1)*5;
w = ones(1,length(y));
A = [x ones(length(x),1)];
p = lscov(A,y,w);
plot(x,y,'.');
hold on
plot(x,p(1)*x + p(2),'-r');
I am thinking of recast a double for loop into something I can use with parallel computing. Specifically, I have
for i = 1 : N
x = x0+i*dx;
for j = 1 : N
y = y0+j*dy;
end
end
and the main program calls functions that require x and y as input arguments. In my problem the variables x and y are independent and so the two for loops should be able to recast into something simpler that can be run more efficiently taking advantage of matlab's matrix computations.
I'm thinking of creating a nested 2D array like (symbolically):
A = [{x0,y0},{x0,y1},{x0,y2},...,{x0,yN};
{x1,y0},{x1,y1},{x1,y2},...,{x1,yN};
...
{xN,y0},{xN,y1},{xN,y2},...,{xN,yN}]
i.e. each element in a 2D array is a 2-tuple {xi,yi} formed from the elements of the vectors x and y. Can I create such an object in matlab? If so, how can I call each individual element within each tuple? I need to have a way to call each element, e.g. x2 in {x2,y1}, in this array.
I am thinking of doing this so as to have the program run in parallel with input arguments given by each set of tuple {xi,yi} simultaneously, using the parallel processing toolbox on a GPU.
Many thanks in advance for your help.
James
I think what you are actually looking for is either meshgrid or ndgrid
>> [x y] = meshgrid( 1:N, 1:N )
For N=3 you'll get
>> [x y] = meshgrid( 1:3, 1:3 )
x =
1 2 3
1 2 3
1 2 3
y =
1 1 1
2 2 2
3 3 3
Now if you want to access a pair you can access its x and y coordinate for each matrix.
For example accessing the coordinates of ii=1, jj=2
>> ii=1; jj=2;
>> [x(ii,jj) y(ii,jj)]
Several comments
If you want both x and y to assume the same range of values (like in this example 1:N), you can skip the second arguemnt of meshgrid
>> [x y] = meshgrid( 1:N );
You can modify the inputs of meshgrid to capture the exact pattern you want for x and y, using dx and dy:
>> [x y] = meshgrid( x0 + (1:N)*dx, y0 + (1:N)*dy );
It is best not to use i and j as variable names in Matlab.