Macaulay2 » Documentation
Packages » ForeignFunctions » general linear model example
next | previous | forward | backward | up | index | toc

general linear model example -- constrained least squares using foreign function calls to the LAPACK library

In this example, we make foreign function calls to LAPACK to solve constrained least squares problems. LAPACK is already used by Macaulay2 for a number of its linear algebra computations, but some functions aren't available.

One of these is dggglm, which solves constrained least squares problems that have applications to general Gauss-Markov linear models in statistics. In particular, suppose $A$ is an $n\times m$ real matrix, $B$ is an $n\times p$ real matrix, and $\mathbf d$ is a vector in $\RR^n$. We would like to find the vectors $\mathbf x\in\RR^m$ and $\mathbf y\in\RR^p$ that minimize $\|\mathbf y\|$ subject to the constraint $\mathbf d = A\mathbf x + B\mathbf y$.

The dggglm function does exactly this. Its signature is void dggglm_(int *n, int *m, int *p, double *A, int *ldA, double *B, int *ldB, double *d, double *x, double *y, double *work, int *lwork, int *info). Note the trailing underscore that was added by the Fortran compiler. Each of the 13 arguments are pointers, so we use voidstar to represent them in our call to foreignFunction. Since Macaulay2 is already linked against LAPACK, we don't need to worry about calling openSharedLibrary.

i1 : dggglm = foreignFunction("dggglm_", void, toList(13:voidstar))

o1 = dggglm_

o1 : ForeignFunction

The parameters n, m and p are exactly the numbers $n$, $m$, and $p$ above. The parameters A, B, and d are arrays that will store the entries of $A$, $B$, and $\mathbf d$. LAPACK expects these to be in column-major order, in contrast to the row-major order used by Macaulay2. So we add helper methods to take care of this conversion. The local variable T is a ForeignArrayType created by ZZ * ForeignType.

i2 : toLAPACK = method();
i3 : toLAPACK Matrix := A -> (
        T := (numRows A * numColumns A) * double;
        T flatten entries transpose A);
i4 : toLAPACK Vector := toLAPACK @@ matrix;

The parameters ldA and ldB are the "leading dimensions" of the arrays A and B. We will use $n$ for both. The arrays x and y will store the solutions. The array work has dimension lwork (for which we will use $n + m + p$) that the procedure will use as a workspace. Finally, info stores the return value (0 on success).

The following method prepares matrices $A$ and $B$ and a vector $\mathbf d$ to be sent to the foreign function we created above, and then converts the solutions into a sequence two of Macaulay2 vectors. Note that we use getMemory to allocate memory for x, y, and info (which we name i here to avoid conflicting with info) and address to get pointers to the other integer arguments. We also use ForeignType * voidstar to dereference i and determine whether the call was successful.

i5 : generalLinearModel= method();
i6 : generalLinearModel(Matrix, Matrix, Vector) := (A, B, d) -> (
         if numRows A != numRows B
         then error "expected first two arguments to have the same number of rows";
         n := numRows A;
         m := numColumns A;
         p := numColumns B;
         x := getMemory(m * size double);
         y := getMemory(p * size double);
         lwork := n + m + p;
         work := getMemory(lwork * size double);
         i := getMemory int;
         dggglm(address int n, address int m, address int p, toLAPACK A,
             address int n, toLAPACK B, address int n, toLAPACK d, x, y, work,
             address int lwork, i);
         if value(int * i) != 0 then error("call to dggglm failed");
         (vector value (m * double) x, vector value (p * double) y));

Finally, let's call this method and solve a constrained least squares problem. This example is from Kourouklis, S., & Paige, "A Constrained Least Squares Approach to the General Gauss-Markov Linear Model".

i7 : A = matrix {{1, 2, 3}, {4, 1, 2}, {5, 6, 7}, {3, 4, 6}};

              4       3
o7 : Matrix ZZ  <-- ZZ
i8 : B = matrix {{1, 0, 0, 0}, {2, 3, 0, 0}, {4, 5, 1e-5, 0}, {7, 8, 9, 10}};

                4         4
o8 : Matrix RR    <-- RR
              53        53
i9 : d = vector {1, 2, 3, 4};

       4
o9 : ZZ
i10 : generalLinearModel(A, B, d)

o10 = (|   .3141  |, | .0296627 |)
       | -.334417 |  | .0451036 |
       |  .441691 |  | .0585128 |
                     | .0650142 |

o10 : Sequence

The source of this document is in ForeignFunctions.m2:2316:0.