简体   繁体   中英

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 , ie 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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM