Changeset 19bf86 in git for kernel/linearAlgebra.cc


Ignore:
Timestamp:
Jun 21, 2010, 1:20:59 PM (14 years ago)
Author:
Frank Seelisch <seelisch@…>
Branches:
(u'spielwiese', 'fe61d9c35bf7c61f2b6cbf1b56e25e2f08d536cc')
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
File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/linearAlgebra.cc

    re558c41 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}
Note: See TracChangeset for help on using the changeset viewer.