Problem with function fsolve
3 visualizzazioni (ultimi 30 giorni)
Mostra commenti meno recenti
Ivan Khomich
il 9 Ott 2020
Commentato: Walter Roberson
il 10 Ott 2020
Hello everyone!
I have a problem with fsolve, whick probably depends on my misunderstanding of how the anonymous functions work.
The code is following:
JordanNormalForm=[0 0;0 -1];
Bp=[1;-1];
MatrixExp=@(t) expm(JordanNormalForm.*t);
MatrixUnderIntegral=@(t) expm(-JordanNormalForm.*t)*Bp;
IntExp1=@(t1) integral( MatrixUnderIntegral,0,t1,'ArrayValued',true);
X01=@(t1) feval(MatrixExp, t1)*(feval(IntExp1,t1)+x0');
IntExp2=@(t2) integral( MatrixUnderIntegral,0,t2,'ArrayValued',true);
IntPlusX01=@(t1,t2) -feval(IntExp2,t2)+feval(X01,t1);
X02=@(varargin) feval(MatrixExp, varargin{1})*feval(IntPlusX01,varargin{1:2});
fsolve(X02,[1,0.5])
So, when i run this code I get this error
Not enough input arguments.
Error in MatrixExponentOfLinearParallelSys>@(t1,t2)feval(MatrixExp,t2)*feval(IntPlusX01,t1,t2) (line 287)
X02=@(t1,t2) feval(MatrixExp, t2)*feval(IntPlusX01,t1,t2);
Error in fsolve (line 242)
fuser = feval(funfcn{3},x,varargin{:});
Error in MatrixExponentOfLinearParallelSys (line 289)
fsolve(X02,[1,0.5])
Caused by:
Failure in initial objective function evaluation. FSOLVE cannot continue.
I just don't understand what can cause this problem. Because other operations like feval works correctly.
And even more than that i don't understand why this works then:
MatrixExp=@(t) expm(JordanNormalForm.*t);
MatrixUnderIntegral=@(t) expm(-JordanNormalForm.*t)*Bp;
IntExp1=@(t1) integral( MatrixUnderIntegral,0,t1,'ArrayValued',true);
X01=@(t1) feval(MatrixExp, t1)*(feval(IntExp1,t1)+x0');
IntExp2=@(t2) integral( MatrixUnderIntegral,0,t2,'ArrayValued',true);
IntPlusX01=@(t1,t2) -feval(IntExp2,t2)+feval(X01,t1);
X02=@(t) feval(MatrixExp, t(2))*feval(IntPlusX01,t(1),t(2));
fsolve(X02,[1,0.5])
Of course in this case I can use the second variant, but I need to do amore general case, so the varargin variant is more preferable.
Thanks for any help.
2 Commenti
Walter Roberson
il 9 Ott 2020
I recommend against using feval() when it can be avoided.
MatrixExp = @(t) expm(JordanNormalForm.*t);
MatrixUnderIntegral = @(t) expm(-JordanNormalForm.*t)*Bp;
IntExp1 = @(t1) integral( MatrixUnderIntegral,0,t1,'ArrayValued',true);
X01 = @(t1) MatrixExp(t1) * (IntExp1(t1)+x0');
IntExp2 = @(t2) integral( MatrixUnderIntegral,0,t2,'ArrayValued',true);
IntPlusX01 = @(t1,t2) -IntExp2(t2) + X01(t1, t2);
X02 = @(t) MatrixExp(t(2)) * IntPlusX01(t(1),t(2));
fsolve(X02, [1,0.5])
Also I recommend that you recheck whether you truly do want the * matrix multiplication operator instead of the .* element-by-element multiplication.
Risposta accettata
Walter Roberson
il 9 Ott 2020
IntPlusX01=@(t1,t2) -feval(IntExp2,t2)+feval(X01,t1);
X02=@(varargin) feval(MatrixExp, varargin{1})*feval(IntPlusX01,varargin{1:2});
fsolve(X02,[1,0.5])
fsolve() invokes the given handle with a row vector of values. A row vector of values occupies one argument no matter how large the vector is.
So X02 is going to be invoked with a single argument -- varargin is going to be a cell with one element that is the vector.
Inside X02 you have feval(MatrixExp, varargin{1}) so the complete vector is going to be passed as the (only) argument to MatrixExp . MatrixExp is @(t) expm(JordanNormalForm.*t) so that would potentially be valid, provided that JodanNormalForm has compatible dimensions for multiplying by the vector (of two elements) in t and the result is a square matrix.
(If t is expected to be a scalar there, then you could save computation by computing the svd ahead of time and using V*diag(exp(t.*diag(D)))/V )
IntPulsX01 would then be invoked with the single argument that is the vector of values. But InPlusX01 expects to be invoked with two arguments so you have a problem.
2 Commenti
Walter Roberson
il 10 Ott 2020
If you examine doc expm then it says
Y = expm(X) computes the matrix exponential of X. Although it is not computed this way, if X has a full set of eigenvectors V with corresponding eigenvalues D, then [V,D] = eig(X) and expm(X) = V*diag(exp(diag(D)))/V
And you are wanting to take expm(JordanNormalForm.*t), then potentially we could find
%{
[V, D] = eig(JordanNormalForm);
eJNFt = V*diag(exp(t.*diag(D)))/V;
%}
But does that actually work? Let us test:
format short g
rng(42); A = randi([-9 9],3,3)
expm(A)
e2A = expm(2*A)
[V, D] = eig(A);
V*diag(exp(diag(D)))/V %mathematical equivalent to expm(A)
e2Aalt = V*diag(exp(2*diag(D)))/V %is this equivalent to expm(2*A) ?
e2A - e2Aalt
So, yes, to within round-off the two are equivalent. If you are working with real-valued matrices, take real() of the result to remove the noise complex parts.
(Note: for reasons I am not clear on at the moment, the 3 x 3 complex output might have been truncated to 1 1/2 columns wide in this experimental facility I am using.)
Why this matters is that you are doing the expm() step many times, so potentially if you pre-decomposed the JodanNormalForm matrix, then possibly the V*diag(exp(t*diag(D)))/V might be faster than expm(t*JordanNormalForm) . Something that might be worth timing at some point.
Più risposte (0)
Vedere anche
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!