Changeset 19bf86 in git


Ignore:
Timestamp:
Jun 21, 2010, 1:20:59 PM (13 years ago)
Author:
Frank Seelisch <seelisch@…>
Branches:
(u'jengelh-datetime', 'ceac47cbc86fe4a15902392bdbb9bd2ae0ea02c6')(u'spielwiese', 'f875bbaccd0831e36aaed09ff6adeb3eb45aeb94')
Children:
e3cc9c88085d8e217de6a163ac2bc7d891c19815
Parents:
e558c41b132228287898863201fbd5c35b4231fd
Message:
implemented and doc'ed lusolve; available thru interpreter

git-svn-id: file:///usr/local/Singular/svn/trunk@12885 2c84dea3-7e68-4137-9b89-c4e89433aadc
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • Singular/iparith.cc

    re558c4 r19bf86  
    317317  { "ludecomp",    0, LU_CMD ,            CMD_1},
    318318  { "luinverse",   0, LUI_CMD ,           CMD_M},
     319  { "lusolve",     0, LUS_CMD ,           CMD_M},
    319320  { "map",         0, MAP_CMD ,           RING_DECL},
    320321  { "matrix",      0, MATRIX_CMD ,        MATRIX_CMD},
     
    71097110  return FALSE;
    71107111}
     7112static BOOLEAN jjLU_SOLVE(leftv res, leftv v)
     7113{
     7114  /* for solving a linear equation system A * x = b, via the
     7115     given LU-decomposition of the matrix A;
     7116     There is one valid parametrisation:
     7117     1) exactly four arguments P, L, U, b;
     7118        P, L, and U realise the L-U-decomposition of A, that is,
     7119        P * A = L * U, and P, L, and U satisfy the
     7120        properties decribed in method 'jjLU_DECOMP';
     7121        see there;
     7122        b is the right-hand side vector of the equation system;
     7123     The method will return a list of either 1 entry or three entries:
     7124     1) [0] if there is no solution to the system;
     7125     2) [1, x, dim] if there is at least one solution;
     7126        x is any solution, dim is the dimension of the affine solution
     7127        space.
     7128     The method produces an error if matrix and vector sizes do not fit. */
     7129  if ((v == NULL) || (v->Typ() != MATRIX_CMD) ||
     7130      (v->next == NULL) || (v->next->Typ() != MATRIX_CMD) ||
     7131      (v->next->next == NULL) || (v->next->next->Typ() != MATRIX_CMD) ||
     7132      (v->next->next->next == NULL) ||
     7133      (v->next->next->next->Typ() != MATRIX_CMD) ||
     7134      (v->next->next->next->next != NULL))
     7135  {
     7136    Werror("expected exactly three matrices and one vector as input");
     7137    return TRUE;
     7138  }
     7139  matrix pMat = (matrix)v->Data();
     7140  matrix lMat = (matrix)v->next->Data();
     7141  matrix uMat = (matrix)v->next->next->Data();
     7142  matrix bVec = (matrix)v->next->next->next->Data();
     7143  matrix xVec; int solvable; int dim;
     7144  if (pMat->rows() != pMat->cols())
     7145  {
     7146    Werror("first matrix (%d x %d) is not quadratic",
     7147           pMat->rows(), pMat->cols());
     7148    return TRUE;
     7149  }
     7150  if (lMat->rows() != lMat->cols())
     7151  {
     7152    Werror("second matrix (%d x %d) is not quadratic",
     7153           lMat->rows(), lMat->cols());
     7154    return TRUE;
     7155  }
     7156  if (lMat->rows() != uMat->rows())
     7157  {
     7158    Werror("second matrix (%d x %d) and third matrix (%d x %d) do not fit",
     7159           lMat->rows(), lMat->cols(), uMat->rows(), uMat->cols());
     7160    return TRUE;
     7161  }
     7162  if (uMat->rows() != bVec->rows())
     7163  {
     7164    Werror("third matrix (%d x %d) and vector (%d x 1) do not fit",
     7165           uMat->rows(), uMat->cols(), bVec->rows());
     7166    return TRUE;
     7167  }
     7168  solvable = luSolveViaLUDecomp(pMat, lMat, uMat, bVec, xVec, &dim);
     7169
     7170  /* build the return structure; a list with either one or three entries */
     7171  lists ll = (lists)omAllocBin(slists_bin);
     7172  if (solvable)
     7173  {
     7174    ll->Init(3);
     7175    ll->m[0].rtyp=INT_CMD;    ll->m[0].data=(void *)solvable;
     7176    ll->m[1].rtyp=MATRIX_CMD; ll->m[1].data=(void *)xVec;
     7177    ll->m[2].rtyp=INT_CMD;    ll->m[2].data=(void *)dim;
     7178  }
     7179  else
     7180  {
     7181    ll->Init(1);
     7182    ll->m[0].rtyp=INT_CMD;    ll->m[0].data=(void *)solvable;
     7183  }
     7184
     7185  res->data=(char*)ll;
     7186  return FALSE;
     7187}
    71117188static BOOLEAN jjINTVEC_PL(leftv res, leftv v)
    71127189{
     
    75927669,{jjLIST_PL,   LIST_CMD,        LIST_CMD,           -1      , ALLOW_PLURAL |ALLOW_RING}
    75937670,{jjLU_INVERSE,LUI_CMD,         LIST_CMD,           -2      , NO_PLURAL |NO_RING}
     7671,{jjLU_SOLVE,  LUS_CMD,         LIST_CMD,           -2      , NO_PLURAL |NO_RING}
    75947672,{jjWRONG,     MINOR_CMD,       NONE,               1       , ALLOW_PLURAL |ALLOW_RING}
    75957673,{jjMINOR_M,   MINOR_CMD,       IDEAL_CMD,          -2      , ALLOW_PLURAL |ALLOW_RING}
  • Singular/tok.h

    re558c4 r19bf86  
    9797  LU_CMD,
    9898  LUI_CMD,
     99  LUS_CMD,
    99100  MEMORY_CMD,
    100101  MONITOR_CMD,
  • kernel/linearAlgebra.cc

    re558c4 r19bf86  
    103103  for (int r = 1; r <= rr; r++) MATELEM(lMat, r, r) = pOne();
    104104
    105   int bestR; int bestC; int intSwap; poly pSwap;
     105  int bestR; int bestC; int intSwap; poly pSwap; int cOffset = 0;
    106106  for (int r = 1; r < rr; r++)
    107107  {
    108     if ((r <= cc) && (pivot(uMat, r, rr, r, r, &bestR, &bestC)))
     108    if (r > cc) break;
     109    while ((r + cOffset <= cc) &&
     110           (!pivot(uMat, r, rr, r + cOffset, r + cOffset, &bestR, &bestC)))
     111      cOffset++;
     112    if (r + cOffset <= cc)
    109113    {
    110114      /* swap rows with indices r and bestR in permut */
     
    114118
    115119      /* swap rows with indices r and bestR in uMat;
    116          it is sufficient to do this for columns >= r */
    117       for (int c = r; c <= cc; c++)
     120         it is sufficient to do this for columns >= r + cOffset*/
     121      for (int c = r + cOffset; c <= cc; c++)
    118122      {
    119123        pSwap = MATELEM(uMat, r, c);
     
    134138         row with index r;
    135139         we need to adjust lMat and uMat;
    136          we are certain that the matrix entry at [r, r] is non-zero: */
    137       number pivotElement = pGetCoeff(MATELEM(uMat, r, r));
     140         we are certain that the matrix entry at [r, r + cOffset]
     141         is non-zero: */
     142      number pivotElement = pGetCoeff(MATELEM(uMat, r, r + cOffset));
    138143      poly p; number n;
    139144      for (int rGauss = r + 1; rGauss <= rr; rGauss++)
    140145      {
    141         p = MATELEM(uMat, rGauss, r);
     146        p = MATELEM(uMat, rGauss, r + cOffset);
    142147        if (p != NULL)
    143148        {
     
    149154
    150155          /* adjusting uMat: */
    151           MATELEM(uMat, rGauss, r) = NULL; pDelete(&p);
     156          MATELEM(uMat, rGauss, r + cOffset) = NULL; pDelete(&p);
    152157          n = nNeg(n);
    153           for (int cGauss = r + 1; cGauss <= cc; cGauss++)
     158          for (int cGauss = r + cOffset + 1; cGauss <= cc; cGauss++)
    154159            MATELEM(uMat, rGauss, cGauss)
    155160              = pAdd(MATELEM(uMat, rGauss, cGauss),
     
    316321  return result;
    317322}
     323
     324bool luSolveViaLUDecomp(const matrix pMat, const matrix lMat,
     325                        const matrix uMat, const matrix bVec,
     326                        matrix &xVec, int* dim)
     327{
     328  int m = uMat->rows(); int n = uMat->cols();
     329  matrix cVec = mpNew(m, 1);  /* for storing pMat * bVec */
     330  matrix yVec = mpNew(m, 1);  /* for storing the unique solution of
     331                                 lMat * yVec = cVec */
     332
     333  /* compute cVec = pMat * bVec but without actual multiplications */
     334  for (int r = 1; r <= m; r++)
     335  {
     336    for (int c = 1; c <= m; c++)
     337    {
     338      if (MATELEM(pMat, r, c) != NULL)
     339        { MATELEM(cVec, r, 1) = pCopy(MATELEM(bVec, c, 1)); break; }
     340    }
     341  }
     342
     343  /* solve lMat * yVec = cVec; this will always work as lMat is invertible;
     344     moreover, no divisions are needed, since lMat[i, i] = 1, for all i */
     345  for (int r = 1; r <= m; r++)
     346  {
     347    poly p = pNeg(pCopy(MATELEM(cVec, r, 1)));
     348    for (int c = 1; c < r; c++)
     349      p = pAdd(p, ppMult_qq(MATELEM(lMat, r, c), MATELEM(yVec, c, 1) ));
     350    MATELEM(yVec, r, 1) = pNeg(p);
     351  }
     352 
     353  /* determine whether uMat * xVec = yVec is solvable */
     354  bool isSolvable = true;
     355  bool isZeroRow; int nonZeroRowIndex;
     356  for (int r = m; r >= 1; r--)
     357  {
     358    isZeroRow = true;
     359    for (int c = 1; c <= n; c++)
     360      if (MATELEM(uMat, r, c) != NULL) { isZeroRow = false; break; }
     361    if (isZeroRow)
     362    {
     363      if (MATELEM(yVec, r, 1) != NULL) { isSolvable = false; break; }
     364    }
     365    else { nonZeroRowIndex = r; break; }
     366  }
     367 
     368  if (isSolvable)
     369  {
     370    xVec = mpNew(n, 1); *dim = 0;
     371    /* solve uMat * xVec = yVec and determine the dimension of the affine
     372       solution space */
     373    int nonZeroC; int lastNonZeroC = n + 1;
     374    for (int r = nonZeroRowIndex; r >= 1; r--)
     375    {
     376      for (nonZeroC = 1; nonZeroC <= n; nonZeroC++)
     377        if (MATELEM(uMat, r, nonZeroC) != NULL) break;
     378      *dim = *dim + lastNonZeroC - nonZeroC - 1;
     379      poly p = pNeg(pCopy(MATELEM(yVec, r, 1)));
     380      for (int c = nonZeroC + 1; c <= n; c++)
     381        if (MATELEM(xVec, c, 1) != NULL)
     382          p = pAdd(p, ppMult_qq(MATELEM(uMat, r, c), MATELEM(xVec, c, 1)));
     383      poly q = pNSet(nInvers(pGetCoeff(MATELEM(uMat, r, nonZeroC))));
     384      MATELEM(xVec, nonZeroC, 1) = pMult(pNeg(p), q);
     385      lastNonZeroC = nonZeroC;
     386    }
     387  }
     388
     389  idDelete((ideal*)&cVec);
     390  idDelete((ideal*)&yVec);
     391
     392  return isSolvable;
     393}
  • kernel/linearAlgebra.h

    re558c4 r19bf86  
    198198       matrix &iMat       /**< [out] inverse of A if invertible   */
    199199                          );
     200                         
     201/**
     202 * Solves the linear system A*x = b, where A is an (n x n)-matrix
     203 * which is given by its LU-decomposition.
     204 *
     205 * The method expects the LU-decomposition of A, that is,
     206 * pMat * A = lMat * uMat, where the argument matrices have the
     207 * appropriate proteries; see method
     208 * 'luDecomp(const matrix aMat, matrix &pMat, matrix &lMat,
     209 * matrix &uMat)'.<br>
     210 * Instead of trying to invert A and return x = A^(-1)*b, this
     211 * method
     212 * 1) computes b' = pMat * b,
     213 * 2) solves the easy system L * y = b', and then
     214 * 3) solves the easy system U * x = y.
     215 * Note that steps 1) and 2) will always work, as L is in any case
     216 * invertible. Moreover, y is uniquely determined. Step 3) will only
     217 * work if and only if y is in the column span of U. In that case,
     218 * there may be infinitely many solutions.
     219 * Thus, there are three cases:<br>
     220 * 1) There is no solution. Then the method returns false, and &xVec
     221      as well as &dim remain unchanged.<br>
     222 * 2) There is a unique solution. Then the method returns true and
     223 *    the dimension of the affine solution space is zero.<br>
     224 * 3) There are infinitely many solutions. Then the method returns
     225 *    true and some solution. Furthermore, the dimension of the
     226      affine solution space is set accordingly.
     227 *
     228 * @return true if there is at least one solution, false otherwise
     229 **/
     230bool luSolveViaLUDecomp(
     231       const matrix pMat, /**< [in]  permutation matrix of an LU-
     232                                     decomposition                */
     233       const matrix lMat, /**< [in]  lower left matrix of an LU-
     234                                     decomposition                */
     235       const matrix uMat, /**< [in]  upper right matrix of an LU-
     236                                     decomposition                */
     237       const matrix bVec, /**< [in]  right-hand side of the linear
     238                                     system to be solved          */
     239       matrix &xVec,      /**< [out] solution of A*x = b          */
     240       int* dim           /**< [out] dimension of affine solution
     241                                     space                        */
     242                          );
    200243
    201244#endif
Note: See TracChangeset for help on using the changeset viewer.