syms a12 a13
x=sym('x',[1,2]);
fun=a12+a13
fun=subs(fun,[a12 a13],[x(1) x(2)])
%fun=matlabFunction(fun)
fun = #(x) fun
I am pursuing the method to substitute all the symbols in a symbol expression by a variables vector and convert the symbol expression into a function #(x), so that I can use this function for optimization.
You were on the right path when choosing to employ matlabfunction. However, you probably missed out one of its optional parameters, signally Vars;
Order of input variables or vectors in a generated MATLAB function,
specified as a character vector, a vector of symbolic variables, or a
one-dimensional cell array of character vectors, symbolic variables,
or vectors of symbolic variables.
The number of specified input variables must equal or exceed the
number of free variables in f. Do not use the same names for the input
variables specified by Vars and the output variables specified by
Outputs.
By default, when you convert symbolic expressions, the order is
alphabetical. When you convert symbolic functions, their input
arguments appear in front of other variables, and all other variables
are sorted alphabetically.
See Specify Input Arguments for Generated Function
syms a12 a13;
x = sym('x',[1,2]);
fun = a12 + a13;
fun=subs(fun,[a12 a13],[x(1) x(2)]);
g = matlabFunction(fun,'Vars',{x})
g =
function_handle with value:
#(in1)in1(:,1)+in1(:,2)
For the sake of testing if it works:
k = [1 2];
g(k) % Output: 3
Related
matlabFunction() is a function that can convert symbolic to anonymous function. But how to specify what input arguments to be appeared on the anonymous function?
For example,
x = sym('x', [3, 1])
func = matlabFunction(x)
It returns a handle with:
func =
function_handle with value:
#(x1,x2,x3)[x1;x2;x3]
But how to make this to be returned:?
#(x) [x(1); x(2); x(3)]
that the whole x is the input arguments, not every element of it. This could be extremely useful when x has very long colums.
Instead of making that anonymous function, you can input the elements of x as a comma separated list to func by first converting x to a cell array.
xcell = num2cell(x);
func(xcell{:})
How to create symbolic function for matrices?
For example, I want to have matrix multiplication
A = sym('A',[5,1])
B = sym('B',[1,5])
f = symfun(A * B,[A, B])
But I have an error because A and B have different dimensions, and I can't use square brackets.
symfun only supports scalar arguments, thus you can only define a symbolic function with 10 scalar arguments:
f = symfun(A * B,[A(:); B(:)])
I recommend to work with the symbolic expression instead and use subs to evaluate:
f=A*B
Further you can also use a function handle:
f=#(a,b)(a*b);
f(A,B)
I have a cell array containing functions (with function handle) and I want to evaluate these inside a for-loop. I want to evaluate the differential equations:
x1'= x2,
x2' = ax2-bx1
My code is like this:
init = [0,0];
F = {#(x1,x2) x2,#(x1,x2)(a*x2-b*x1)};
X0 = init;
for i=1:10
X = X0 + c*F(init(1),init(2));
X0 = X;
init[1] = {X(1)};
init[2] = {X(2)};
end
The constants a,b and c are given.
I get the error:
Subscript indices must either be real positive integers or logicals.
Can someone help me with this?
F is a 1x2 cell array. To access elements (in your case, function handles) within this array you must use the curly braces {} to do so. For example, the first function is retrieved by F{1} and the second by F{2} using positive integer indices.
In your example, init is a 1x2 array of zeros so when the code evaluates
F(init(1),init(2));
it is trying to access something within F using indices that are not positive. Hence the error.
I suspect that you will need to do something like the following in your for loop and evaluate each function separately
for i=1:10
for j=1:2
% get the jth function handle
func = F{j};
% evaluate
X(j) = X0(j) + c*func(init(1),init(2));
% save
end
end
I've left the save* portion to be filled in by you because it isn't all that clear to me why there are the different init,X0 and X variables - could you consolidate them?
Note also your mixture of [] and () brackets when accessing arrays. In MATLAB, if the array is of type cell, then we use the {} to access elements. For all other arrays, we use the () brackets.
First of all, there are two other problems with your code: c is not defined and you are trying to index into init with []-brackets, which will throw:
Error: File: foo Line: 8 Column: 8
Unbalanced or unexpected parenthesis or bracket.
The subscript error occurs because you are trying to access F(0,0) because init(1) and init(2) are 0. Remember that the way you declared F, it is a cell array:
>> F = {#(x1,x2) x2,#(x1,x2)(a*x2-b*x1)};
>> whos F
Name Size Bytes Class Attributes
F 1x2 288 cell
Hence, F(0,0) is illegal because indexes in matlab start with 1. Your functions reside in F{1} and F{2}.
>> F{1}
ans =
#(x1,x2)x2
>> F{2}
ans =
#(x1,x2)(a*x2-b*x1)
>> f = F{1}
f =
#(x1,x2)x2
>> f(0,0)
ans =
0
I have a defined mathematical function: f =Inline('x1^2+x2^2+2*x1*x2','x1','x2')
and I have an array that represents the number value of x1 and x2. (e.g. the array is A=[1 2])
I want to automate the process of getting the f(x1,x2), but I couldn't figure out the right way that Matlab can take in the array and assign values to x1 and x2.
What can I do to pass in the array values to the mathematical model and get the function value?
You should be using anonymous functions instead of inline since inline will be removed in a future release of MATLAB.
Example (from the docs):
sqr = #(x) x.^2;
a = sqr(5)
a =
25
In your case:
f = #(x) x(1)^2+x(2)^2+2*x(1)*x(2);
Now it expects x to be a two (or more) value array.
A = [1 2];
f(A) =
9
Note:
I don't have MATLAB on my home computer so I haven't actually tested this but it should get you going in the right direction. Have a look over the docs and you'll be fine.
I need help figuring out how to code the following problem. Any help would be greatly appreciated!
Create a function that will take a vector/array input for x (1 by n) and a scalar input for a, and produce the output defined by the following equation:
y(x,a)=((xsin(ax-2))/(sqrt(1+(ax)^2)
-π ≤ x ≤ π
a={.5 1 1.5 2}
The equation must be vectorized in terms of x and the output from the function is the array y which has the same dimension as the array x.
Write a script that calls this function to compute y(x,a) for the range of x defined above and each value of the parameter a. Results should be stored in a solution matrix using a different row of the solution matrix for each value of a.
So far for my function I have:
function [y] = part1(a,x)
y=((x*sin(a*x-2))/(sqrt(1+(a*x).^2)));
end
I'm not sure how to output this into the solution matrix
For my script I have:
%%
clear,clc
a={0.5 1 1.5 2};
x=-pi:0.1:pi;
for
part1(x,a)
end
I'm getting the following errors when I run this now:
Undefined function 'mtimes' for input arguments of type 'cell'.
Error in part1 (line 4)
y=((x*sin(a*x-2))/(sqrt(1+(a*x).^2)));
Error in labtest2 (line 8)
y(i,:)=part1(x,a(i));
EDIT
I've made some changes and am still getting some errors that I cannot resolve.
Here is my full code for function followed by full code for script:
Function
function [y] = part1(x,a)
nx=numel(x);
na=numel(a);
y=((x.*sin(a.*x-2))./(sqrt(1+(a.*x).^2)));
size(y)=[nx na]
end
Script
%%
clear,clc
a={0.5 1 1.5 2};
x=-pi:0.1:pi;
for i = 1:length(a)
y(i,:)=part1(x,a(i));
end
Errors
Undefined function 'times' for input arguments of type 'cell'.
Error in part1 (line 6)
y=((x.*sin(a.*x-2))./(sqrt(1+(a.*x).^2)));
Error in labtest2 (line 8)
y(i,:)=part1(x,a(i));
The reason you're getting Undefined function 'times' for input arguments of type 'cell' is because your variable a is a cell array. You need to change your assignment of a from
a={0.5 1 1.5 2};
to
a=[0.5 1 1.5 2];
which will make it just a normal array. Alternatively, you need to reference it with cell array notation: a{i} instead of a(i).
You're almost there. Note that you've written
function [y] = part1(a,x)
but you call it in your script as
part1(x,a)
so you should probably correct that.
A few things jump out at me:
You never assign the output of part1(x,a) to anything. You're told that
Results should be stored in a solution matrix using a different row of the solution matrix for each value of a.
What I take this to mean is that the 1st row corresponds to part1() evaluated for the 1st element of a. Since we're operating on x which is a vector, that row will have multiple columns. Your output is indeed a matrix. In your case, length(-pi:0.1:pi) == 63, therefore size(y) == [4 63], where y is your output matrix.
Your for loop is backwards. You're told to accept scalar a and vector x. Therefore, your script should be something like:
a = 0.5:0.5:2;
x = -pi:0.1:pi;
for i = 1:length(a)
y(i,:) = part1(x, a(i));
end
Note the use of length and the : operator. I want to iterate between 1 to length(a) (in this case, length(a) == 4) so that I can use the current a(i) value as an index into my output matrix, y. The : operator in y(i,:) signifies "The ith row and all columns of y will take the value output by part1(x,a(i))."
Your function needs to be changed up for element-by-element operations. Notice that, for instance, x*sin(a*x-2) works for scalar x but not vectors. This is because x is a vector and sin(a*x-2) is also a vector (since the sin call will operate element-by-element and a is a scalar). Trying to multiply two vectors together will result in errors since MATLAB will try to perform a matrix multiplication. Resolve this by replacing * with .*. This way it is unambiguous that you are going to multiply these two vectors element-by-element. You'll also need to change / to ./.
On another note, thank you for attempting to do your homework before asking SO for help. We've been getting a huge influx of questions from students that have made no attempt to do their own work before dumping it on us, so it's refreshing that we regulars of the MATLAB tag get to actual help out instead of telling people to do their own work.
Finally got the whole thing worked out.
Function
function [y] = part1(x,a)
y=((x.*sin(a.*x - 2))./(sqrt(1 + (a.*x).^2)));
end
Script
%%
clear all;
clc;
close all;
x=[-pi:.1:pi];
a=[.5:.5:2];
for i=1:length(a)
y(i,:)=part1(x,a(i));
plot(x,y)
end
Sol=[y]