Hello,
Can you help me with an answer?
Given e.g. the following statement:
proc iml;
A=I(2);
B=expmatrix(A);
print A B;
quit;
Then the printed matrix A is I-halved instead of I. Why?
Many thanks,
Dan
This does not happen in PROC IML, but it does happen in SAS/IML Studio.
I'm guessing that you are running this in SAS/IML Studio or got a copy of the module that is distributed with SAS/IML Studio.
You are right: The ExpMatrix function is incorrectly changing your input matrix A.
There is a simple fix: Use the following (correct) module to store a new module in SAS/IML Studio. As long as the new module is stored in a location earlier in the search path, you will pick up the new copy. This should happen automatically, unless you have changed the default search path.
In summary, run the following in SAS/IML Studio one time. From then on, you will pick up the correct behavior.
start ExpMatrix( A );
/* Compute a matrix exponential. Algorithm from
Golub/Van Loan, 2nd ed, p. 558. Based on
Moler & Van Loan (1978) "Nineteen Dubious Ways
to Compute the Exponential of a Matrix,"
SIAM Review 20, 801-836.
Given delta>0 and an nxn matrix A, the algorithm
computes F = exp(A+E) where
InfinityNorm(E)<= delta*InfinityNorm(A).
We use a delta of approx 1e-15. */
AX = A;
n = nrow(AX);
InfinityNorm = max( abs(AX)[+,] );
j = max( 0, 1+floor( Log2(InfinityNorm) ) );
AX = AX / 2##j;
/* Compute Pade' approximation to exp(A) */
X = AX;
c = 0.5;
M = I(n) + c*AX;
D = I(n) - c*AX;
q = 6; /* try to approximate with 6 terms (implies delta approx 1e-15)*/
do k = 2 to q;
c = c*(q-k+1)/( (2*q-k+1)*k );
X = AX*X;
M = M + c*X;
D = D + (-1)##k * c*X;
end;
F = solve(D,M);
do k = 1 to j;
F = F*F;
end;
return ( F );
finish ExpMatrix;
store module=ExpMatrix;
This works for me. Try using commas to make the output more clear.
print A, B;
thaks for the answer. it doesn't work; same effect... it seems that I should put the "print" option for A before exponetiating the matrix... quite strange...
expmatrix is not an in-built function, it is an IML module that is read from the library. So it is possible we have different versions of the library, and that your versions modifies the matrix A. You can examine the source code of the module by entering
COPY SASHELP.IML.EXPMATRIX.SOURCE into the SAS command box.
This does not happen in PROC IML, but it does happen in SAS/IML Studio.
I'm guessing that you are running this in SAS/IML Studio or got a copy of the module that is distributed with SAS/IML Studio.
You are right: The ExpMatrix function is incorrectly changing your input matrix A.
There is a simple fix: Use the following (correct) module to store a new module in SAS/IML Studio. As long as the new module is stored in a location earlier in the search path, you will pick up the new copy. This should happen automatically, unless you have changed the default search path.
In summary, run the following in SAS/IML Studio one time. From then on, you will pick up the correct behavior.
start ExpMatrix( A );
/* Compute a matrix exponential. Algorithm from
Golub/Van Loan, 2nd ed, p. 558. Based on
Moler & Van Loan (1978) "Nineteen Dubious Ways
to Compute the Exponential of a Matrix,"
SIAM Review 20, 801-836.
Given delta>0 and an nxn matrix A, the algorithm
computes F = exp(A+E) where
InfinityNorm(E)<= delta*InfinityNorm(A).
We use a delta of approx 1e-15. */
AX = A;
n = nrow(AX);
InfinityNorm = max( abs(AX)[+,] );
j = max( 0, 1+floor( Log2(InfinityNorm) ) );
AX = AX / 2##j;
/* Compute Pade' approximation to exp(A) */
X = AX;
c = 0.5;
M = I(n) + c*AX;
D = I(n) - c*AX;
q = 6; /* try to approximate with 6 terms (implies delta approx 1e-15)*/
do k = 2 to q;
c = c*(q-k+1)/( (2*q-k+1)*k );
X = AX*X;
M = M + c*X;
D = D + (-1)##k * c*X;
end;
F = solve(D,M);
do k = 1 to j;
F = F*F;
end;
return ( F );
finish ExpMatrix;
store module=ExpMatrix;
Yep:)
Thanks for your help Rick; a brilliant answer; it works !!
In order to avoid the expmatrix function, I could tried to approximate the exponential matrix by writing in IML the Taylor expansion (summation up to e.g.100), but I would prefer your option. Thanks Rick!
I should have mentioned an even simpler solution, pass in a COPY of your matrix instead of the matrix itself!
start MyExpMatrix(A);
A2 = A; /* copy it; A2 gets changed, but A does not */
return( ExpMatrix(A2) );
finish;
Many thanks Rick.
Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9.
Early bird rate extended! Save $200 when you sign up by March 31.