BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
dannegrila
Calcite | Level 5

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

 

1 ACCEPTED SOLUTION

Accepted Solutions
Rick_SAS
SAS Super FREQ

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;

View solution in original post

8 REPLIES 8
IanWakeling
Barite | Level 11

This works for me.  Try using commas to make the output more clear.

 

print A, B;

dannegrila
Calcite | Level 5

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...

IanWakeling
Barite | Level 11

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.

Rick_SAS
SAS Super FREQ

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;
dannegrila
Calcite | Level 5

Yep:)

Thanks for your help Rick; a brilliant answer; it works !!

 

dannegrila
Calcite | Level 5

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!

Rick_SAS
SAS Super FREQ

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;

dannegrila
Calcite | Level 5

Many thanks Rick.

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

Multiple Linear Regression in SAS

Learn how to run multiple linear regression models with and without interactions, presented by SAS user Alex Chaplin.

Find more tutorials on the SAS Users YouTube channel.

From The DO Loop
Want more? Visit our blog for more articles like these.
Discussion stats
  • 8 replies
  • 1467 views
  • 1 like
  • 3 in conversation