Matlab symbolic matrix as argument of function instead of individual components variables - matlab

I want to export to file a symbolic expression that involves a matrix:
% M is a 2x2 symbolic matrix composed by M_1_1, M_1_2, M_2_1, M_2_2
M = sym('M_%d_%d', [2 2], 'real');
% s1 and s2 are scalar variables
syms('s1', 's2');
% Expression with M, s1 and s2
myExpr = M*[s1;s2];
% Store expression as matlab code in a function file
matlabFunction(myExpr, 'file', 'myExprFunc.m');
However, since the expanded expression is:
myExpr =
M_1_1*s1 + M_1_2*s2
M_2_1*s1 + M_2_2*s2
This creates a function with expanded input arguments (one per free variable):
function myExpr = myExprFunc(M_1_1, M_1_2, M_2_1, M_2_2, s1, s2)
...
With 20x20 matrices, this is nightmare. It would be nice to have a signature like
function myExpr = myExprFunc(M, s1, s2)
But nothing seem to work. The straigthforward approach matlabFunction(myExpr, 'file', 'myExprFunc.m', 'Vars', {'M', 's1', 's2'}); returns an error because the free variables M_x_y must appear as arguments.
My current solution involves creating a wrapper function that assigns individual variables as M_x_y = M(x,y);, but it would be much better to get it done "the pretty way".
Do anybody knows a solution?

Don't use strings, e.g., {'M', 's1', 's2'}, when working with symbolic math. This has been deprecated and direct support for such usage is disappearing with each Matlab version. To achieve what you want, you can use:
M = sym('M_%d_%d', [2 2], 'real');
syms s1 s2;
myExpr = M*[s1;s2];
matlabFunction(myExpr, 'Vars', {M,s1,s2}, 'file', 'myExprFunc.m');

Related

Problem of creating function handle from the result of symbolic differentiation

Suppose I have a simple function handle defined as
Eq.1 F = #(t,A) A(1) + A(2)*t + A(3)*t^2;
And I'd like to define another function handle from the differentiation of F, such as
Eq.2: dF = #(t,A) diff( F(t,A), t );
But, it seems forbidden to evaluate dF at some specific t, such as dF(0,A), and an error occurs as
"The second argument must either be variables or a variable"
Then I tried to use the expression shown below:
Eq.3 dF(t,A) = diff( F(t,A), t );
This way, it allows direct evaluation at t=0
However, it must be in the form of dF( 0, A(1), A(2), A(3) ) to evaluate Eq.3 rather than dF(0,A)
My question is:
Is there a simpler way to make this direct evaluation work using the direct form dF(0,A) rather than dF(0, A(1), ... )
To save the effort of typing, ony-by-one, A(...) in dF( 0, A(1), A(2), ..., A(100) ), suppose there are 100 parameters
PS:
Without using matlabFunction
The testing codes are as follows:
syms t A a0 a1 a2
A = [a0,a1,a2];
F = #(t,A) A(1) + A(2)*t + A(3)*t^2;
dF1 = #(t,A) diff( F(t,A), t );
dF2(t,A) = diff( F(t,A), t ); % Same as using symfun
dF3 = matlabFunction( diff( F(t,A), t ), 'Vars', {t,A} );
Now, type in the command window,
>> dF1(t,A)
>> ans = a1 + 2*a2*t
>> dF1(0,A)
>> ans = a0 % This is wrong
>> dF3(t,A)
>> ans = a1 + 2*a2*t
>> dF3(0,A)
>> ans = a1 % This is correct
>> dF2(t,A)
Error using symfun/subsref (line 141)
Symbolic function expected 4 inputs and received 2.
>> dF2(t,a0,a1,a2)
>> ans = a1 + 2*a2*t
>> dF2(0,a0,a1,a2)
>> ans = a1 % This is correct
It is obvious that only dF2 is a symbolic function.
However, the form of inputs seems not so friendly.
The matlabFunction runs much slower than symfun, and #(x,A) diff(...) can't admit numerical results. This is why I want to use symfun to define a function that has too many parameters. Yet the form of inputs of symbolic function seems not so direct nor friendly.
Your question is answered over at MATLAB Answers. In short: this cannot be done.
You cannot create a symbolic function that uses an array as input:
This all reflects a fundamental internal limitation in the symbolic engine: the very insides of the symbolic engine have no provision for describing or operating on an "array" whose contents will be filled in later.
The linked post goes in great detail explaining why and how the symbolic engine in MATLAB works. I recommend that you read it.
Your code shows some misconceptions around symbolic functions and anonymous functions. When you do
F = #(t,A) A(1) + A(2)*t + A(3)*t^2;
you are creating a function handle to an anonymous function. It is completely unrelated to the symbolic variables t and A, and it is not a symbolic function. Here, t and A are just the input arguments, and can be filled in by anything.
Next,
dF1 = #(t,A) diff( F(t,A), t );
creates another function handle to an anonymous function, this time the function will evaluate x=F(t,A), then call diff(x,t), where diff is the normal function, not the one in the symbolic toolbox. It computes the difference between subsequent array elements, t times.
To create a symbolic function, you can do:
clear
syms t
A = sym('a', [1,3]); % A = [a1, a2, a3]
F = symfun(A(1) + A(2)*t + A(3)*t^2, [t, A]);
dF = diff(F, t);
dF(0, A(1), A(2), A(3)) % returns a2
However, this creates a symbolic function where each of the elements of A is a separate input argument, which is not what you want. There is no way around this, except, as suggested in an answer to the post I linked at the top, to create an anonymous function that evaluates your symbolic expression:
clear
syms t
A = sym('a', [1,3]);
F = symfun(A(1) + A(2)*t + A(3)*t^2, [t, A]);
dF_sym = diff(F, t);
dF = #(t,A)dF_sym(t, A(1), A(2), A(3));
dF(0, A) % returns a2
PS: Note that the symfun call above is identical to:
clear
syms t F(t,a1,a2,a3)
F(t,a1,a2,a3) = a1 + a2*t + a3*t^2;
and this is how you would normally create a symbolic function. I used symfun above to be able to use A instead of a1, a2 and a3.
It seems that you have just mixed up a few things.
You anonymous function definitions are fine, but I don't think that they represent your intended use.
The function diff calculates the difference in a vector or does this n-times The second argument specifies the latter:
Y = diff(X,n) calculates the nth difference by applying the diff(X)
operator recursively n times. In practice, this means diff(X,2) is the
same as diff(diff(X)).
So it is obvious that diff(...,0) raises an error ("calculate the 0th difference of something").
I can't help thinking that this is not what you want (because there wouldn't be a point in using t in the original function F ...). I assume that t is a time (vector)
Perhaps this suits more your problem:
F = #(t,A) A(:,1) + A(:,2).*t + A(:,3).*t.^2; % vector-wise
dF = #(t,A) diff(F(t,A),[],1)./diff(t,[],1); % row-wise difference
So you can do
t = (1:10).'; % 10 rows = 10 time steps
A = rand(length(t),3);
% call dF: approximating the 1st derivative as finite difference (row-wise)
dF(t,A)
PS: those are no symbolic functions but just anonymous function handles, i.e. pointers to functions (there is a separate Symbolic Math Toolbox and to get a symbolic math function to a function handle, you can use the matlabFunction function)

How can vector elements with indexing be used in a MATLAB symbolic expression?

I would like to create a MATLAB function with vector inputs. The problem is that the inputs of a function created by matlabFunction() has only scalar inputs.
x = sym('x',[2 1]);
y = sym('y',[2 1]);
f=x(1)+x(2)+y(1)+y(2);
matlabFunction(f,'file','testFunction.m');
matlabFunction(f,'file','testFunction.m','vars',[x,y]); % tried with different options but doesn't work
This is the result (with x1,x2,y1,y2 inputs instead of x,y):
function f = testFunction(x1,x2,y1,y2)
%TESTFUNCTION
% F = TESTFUNCTION(X1,X2,Y1,Y2)
% This function was generated by the Symbolic Math Toolbox version 8.2.
% 10-Apr-2019 21:28:40
f = x1+x2+y1+y2;
Is there a solution to this problem within MATLAB? Or do I need to write a program opening the file as txt and replacing the words...
Update: I managed to solve the problem. For me, the best solution is the odeToVectorField() function.
Manually it is more difficult to give vector inputs to a function created by matlabFunction(). One way is the following:
syms y;
f=str2sym('y(1)+y(2)');
matlabFunction(f,'File','fFunction','Vars',y);
With this method, you need to manipulate the equation as a string (which is possible but not practical...), then re-convert it to symbolic expression.
If you check the result of f=x(1)+x(2)+y(1)+y(2) you will see that it is also scalar. Do simple test:
x = sym('x',[2 1]);
y = sym('y',[2 1]);
f=x(1)+x(2)+y(1)+y(2);
disp(f)
The results is x1 + x2 + y1 + y2. So there's nothing wrong with your matlabFunction expression, it just save what you give. If you need it to be stored in the form x(1)+x(2)+y(1)+y(2) you need to rewrite your f expression so it will be stored in vector form, until passing it to matlabFunction. Or alternatively you can create your file structure manualy using fprintf, look docs.

Implicit differentiation - Second derivative using Matlab

The equation is 4*x^2-2*y^2==9. Using implicit differentiation, I can find that the second derivative of y with respect to x is -9/y^3, which requires a substitution in the final step.
I am trying to duplicate this answer using Matlab's symbolic toolbox. I did find some support for the first derivative here, and was successful finding the first derivative.
clear all
syms x y f
f=4*x^2-2*y^2-9
sol1=-diff(f,x)/diff(f,y)
But I am unable to continue onward to find the second derivative with the final simplification (replacing 4*x^2-2*y^2 with 9).
Can someone show me how to do this in Matlab?
To my knowledge there is no direct way to obtain an implicit second derivative in Matlab. And working with implicit functions in Matlab can be fairly tricky. As a start, your variable y is implicitly a function of x s you should define it as such:
clear all
syms y(x) % defines both x and y
f = 4*x^2-2*y^2-9
Here y(x) is now what is called an arbitrary or abstract symbolic function, i.e., one with no explicit formula. Then take the derivative of f with respect to x:
s1 = diff(f,x)
This returns a function in terms of the implicit derivative of y(x) with respect to x, diff(y(x), x) (in this case diff(y) is shorthand). You can solve this function for diff(y) algebraically with subs and solve:
syms dydx % arbitrary variable
s2 = subs(s1,diff(y),dydx)
s3 = solve(s2,dydx)
This yields the first implicit derivative. You can then take another derivative of this expression to obtain the second implicit derivative as a function of the first:
s4 = diff(s3,x)
Finally, substitute the expression for the first implicit derivative into this and simplify to obtain the final form:
s5 = simplify(subs(s4,diff(y),s3))
This yields (2*(y(x)^2 - 2*x^2))/y(x)^3. And then you can eliminate x using the original expression for f with further substitution and solving:
syms x2
f2 = subs(f,x^2,x2)
x2 = solve(f2,x2)
s6 = subs(s5,x^2,x2)
Finally, you can turn this back into an explicit algebraic expression with a final substitution, if desired:
s7 = subs(s6,y,'y')
This yields your solution of -9/y^3.
This whole process can be written more concisely (but very unclearly) as:
clear all
syms y(x) dydx x2
f = 4*x^2-2*y^2-9;
s1 = solve(subs(diff(f,x),diff(y),dydx),dydx)
s2 = simplify(subs(subs(subs(diff(s1,x),diff(y),s1),x^2,solve(subs(f,x^2,x2),x2)),y,'y'))
There are many other ways to achieve the same result. See also these two tutorials: [1], [2].
It's been almost four years since I asked this question, and got brilliant help from horchler, but I've discovered another method using the chain rule.
syms x y
f=4*x^2-2*y^2-9
dydx=-diff(f,x)/diff(f,y)
d2ydx2=diff(dydx,x)+diff(dydx,y)*dydx
d2ydx2=simplifyFraction(d2ydx2,'Expand',true)
s1=solve(f,x)
subs(d2ydx2,x,s1(2))

Use symbolic matlab for flexible number of arguments and functions

I have a function F which takes as an input a vector a. Both the output of the function and a are vectors of length N, where N is arbitrary. Each component Fn is of the form g(a(n),a(n-k)), where g is the same for each component.
I want to implement this function in matlab using its symbolic functionality and calculate its Jacobian (and then store both the function and its jacobian as a regular .m file using matlabFunction). I know how to do this for a function where each input is a scalar that can be handled manually. But here I want a script that is capable of producing these files for any N. Is there a nice way to do this?
One solution I came up with is to generate an array of strings "a0","a1", ..., "aN" and define each component of the output using eval. But this is messy and I was wondering if there is a better way.
Thank you!
[EDIT]
Here is a minimal working example of my current solution:
function F = F_symbolically(N)
%generate symbols
for n = 1:N
syms(['a',num2str(n)]);
end
%define output
F(1) = a1;
for n = 2:N
F(n) = eval(sprintf('a%i + a%i',n,n-1));
end
Try this:
function F = F_symbolically(N)
a = sym('a',[1 N]);
F = a(1);
for i=2:N
F(i) = a(i) + a(i-1);
end
end
Note the use of sym function (not syms) to create an array of symbolic variables.

In Matlab why does cellfun(#size, x) not require UniformOutput False for non scalar values?

In Matlab you can do the following
x = {1:4, rand(3,3,3), 3};
[a, b, c] = cellfun(#size, x);
The above though not scalar output, does not require UniformOutput to be false.
If instead I have
x = {1:4, rand(3,3,3), 3};
[a,b,c] = cellfun(#(my_dummy_fun) [1, 2, 3], x); % GIVES ERROR
I get an error. How is this different than #size? Is there a way to get the same behavior for the custom function as for size?
thanks!
You where confused by size. Size allows a single output (vector) or multiple output arguments.
%three outputs
[a,b,c]=size(rand(3,3,3))
%one output
[x]=size(rand(3,3,3))
where x =[a,b,c]
You are successfully using size with three output arguments, but your function handle has only one output argument (which is a vector).
I don't know any possible syntax to directly define a anonymous function with multiple output arguments. To work around this, I wrote this small wrapper function:
function varargout=vec2nargout(in)
varargout=mat2cell(in(:),ones(1,nargout));
end
It allows:
[a,b,c] = cellfun(#(my_dummy_fun)vec2nargout([1,2,3]), x);