Changeset 9e269a0 in git


Ignore:
Timestamp:
Dec 22, 2010, 1:54:29 PM (12 years ago)
Author:
Frank Seelisch <seelisch@…>
Branches:
(u'spielwiese', 'd1ba061a762c62d3a25159d8da8b6e17332291fa')
Children:
e2fd5d453ccf5a7982b273cf039c5c7f41f41080
Parents:
2fd30cb3d4e41a93238b92df65a30fb88c8276de
Message:
LDU decomposition and command in extra.cc

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

Legend:

Unmodified
Added
Removed
  • Singular/extra.cc

    r2fd30cb r9e269a0  
    667667        }
    668668      }
     669  /*==================== lduDecomp ======================*/
     670      if(strcmp(sys_cmd, "lduDecomp")==0)
     671      {
     672        if ((h != NULL) && (h->Typ() == MATRIX_CMD) && (h->next == NULL))
     673        {
     674          matrix aMat = (matrix)h->Data();
     675          matrix pMat; matrix lMat; matrix dMat; matrix uMat;
     676          poly l; poly u; poly prodLU;
     677          lduDecomp(aMat, pMat, lMat, dMat, uMat, l, u, prodLU);
     678          lists L = (lists)omAllocBin(slists_bin);
     679          L->Init(7);
     680          L->m[0].rtyp = MATRIX_CMD; L->m[0].data=(void*)pMat;
     681          L->m[1].rtyp = MATRIX_CMD; L->m[1].data=(void*)lMat;
     682          L->m[2].rtyp = MATRIX_CMD; L->m[2].data=(void*)dMat;
     683          L->m[3].rtyp = MATRIX_CMD; L->m[3].data=(void*)uMat;
     684          L->m[4].rtyp = POLY_CMD; L->m[4].data=(void*)l;
     685          L->m[5].rtyp = POLY_CMD; L->m[5].data=(void*)u;
     686          L->m[6].rtyp = POLY_CMD; L->m[6].data=(void*)prodLU;
     687          res->rtyp = LIST_CMD;
     688          res->data = (char *)L;
     689          return FALSE;
     690        }
     691        else
     692        {
     693          Werror( "expected argument list (int, int, poly, poly, poly, int)");
     694          return TRUE;
     695        }
     696      }
     697  /*==================== lduSolve ======================*/
     698      if(strcmp(sys_cmd, "lduSolve")==0)
     699      {
     700        /* for solving a linear equation system A * x = b, via the
     701           given LDU-decomposition of the matrix A;
     702           There is one valid parametrisation:
     703           1) exactly eight arguments P, L, D, U, l, u, lTimesU, b;
     704              P, L, D, and U realise the LDU-decomposition of A, that is,
     705              P * A = L * D^(-1) * U, and P, L, D, and U satisfy the
     706              properties decribed in method 'luSolveViaLDUDecomp' in
     707              linearAlgebra.h; see there;
     708              l, u, and lTimesU are as described in the same location;
     709              b is the right-hand side vector of the linear equation system;
     710           The method will return a list of either 1 entry or three entries:
     711           1) [0] if there is no solution to the system;
     712           2) [1, x, H] if there is at least one solution;
     713              x is any solution of the given linear system,
     714              H is the matrix with column vectors spanning the homogeneous
     715              solution space.
     716           The method produces an error if matrix and vector sizes do not
     717           fit. */
     718        if ((h == NULL) || (h->Typ() != MATRIX_CMD) ||
     719            (h->next == NULL) || (h->next->Typ() != MATRIX_CMD) ||
     720            (h->next->next == NULL) || (h->next->next->Typ() != MATRIX_CMD) ||
     721            (h->next->next->next == NULL) ||
     722              (h->next->next->next->Typ() != MATRIX_CMD) ||
     723            (h->next->next->next->next == NULL) ||
     724              (h->next->next->next->next->Typ() != POLY_CMD) ||
     725            (h->next->next->next->next->next == NULL) ||
     726              (h->next->next->next->next->next->Typ() != POLY_CMD) ||
     727            (h->next->next->next->next->next->next == NULL) ||
     728              (h->next->next->next->next->next->next->Typ() != POLY_CMD) ||
     729            (h->next->next->next->next->next->next->next == NULL) ||
     730              (h->next->next->next->next->next->next->next->Typ()
     731                != MATRIX_CMD) ||
     732            (h->next->next->next->next->next->next->next->next != NULL))
     733        {
     734          Werror("expected input (matrix, matrix, matrix, matrix, %s",
     735                                 "poly, poly, poly, matrix)");
     736          return TRUE;
     737        }
     738        matrix pMat  = (matrix)h->Data();
     739        matrix lMat  = (matrix)h->next->Data();
     740        matrix dMat  = (matrix)h->next->next->Data();
     741        matrix uMat  = (matrix)h->next->next->next->Data();
     742        poly l       = (poly)  h->next->next->next->next->Data();
     743        poly u       = (poly)  h->next->next->next->next->next->Data();
     744        poly lTimesU = (poly)  h->next->next->next->next->next->next
     745                                                              ->Data();
     746        matrix bVec  = (matrix)h->next->next->next->next->next->next
     747                                                        ->next->Data();
     748        matrix xVec; int solvable; matrix homogSolSpace;
     749        if (pMat->rows() != pMat->cols())
     750        {
     751          Werror("first matrix (%d x %d) is not quadratic",
     752                 pMat->rows(), pMat->cols());
     753          return TRUE;
     754        }
     755        if (lMat->rows() != lMat->cols())
     756        {
     757          Werror("second matrix (%d x %d) is not quadratic",
     758                 lMat->rows(), lMat->cols());
     759          return TRUE;
     760        }
     761        if (dMat->rows() != dMat->cols())
     762        {
     763          Werror("third matrix (%d x %d) is not quadratic",
     764                 dMat->rows(), dMat->cols());
     765          return TRUE;
     766        }
     767        if (dMat->cols() != uMat->rows())
     768        {
     769          Werror("third matrix (%d x %d) and fourth matrix (%d x %d) %s",
     770                 "do not t",
     771                 dMat->rows(), dMat->cols(), uMat->rows(), uMat->cols());
     772          return TRUE;
     773        }
     774        if (uMat->rows() != bVec->rows())
     775        {
     776          Werror("fourth matrix (%d x %d) and vector (%d x 1) do not fit",
     777                 uMat->rows(), uMat->cols(), bVec->rows());
     778          return TRUE;
     779        }
     780        solvable = luSolveViaLDUDecomp(pMat, lMat, dMat, uMat, l, u, lTimesU,
     781                                       bVec, xVec, homogSolSpace);
     782
     783        /* build the return structure; a list with either one or
     784           three entries */
     785        lists ll = (lists)omAllocBin(slists_bin);
     786        if (solvable)
     787        {
     788          ll->Init(3);
     789          ll->m[0].rtyp=INT_CMD;    ll->m[0].data=(void *)solvable;
     790          ll->m[1].rtyp=MATRIX_CMD; ll->m[1].data=(void *)xVec;
     791          ll->m[2].rtyp=MATRIX_CMD; ll->m[2].data=(void *)homogSolSpace;
     792        }
     793        else
     794        {
     795          ll->Init(1);
     796          ll->m[0].rtyp=INT_CMD;    ll->m[0].data=(void *)solvable;
     797        }
     798        res->rtyp = LIST_CMD;
     799        res->data=(char*)ll;
     800        return FALSE;
     801      }
    669802  /*==================== forking experiments ======================*/
    670803      if(strcmp(sys_cmd, "waitforssilinks")==0)
  • Singular/iparith.cc

    r2fd30cb r9e269a0  
    74627462      (v->next->next->next->next != NULL))
    74637463  {
    7464     Werror("expected exactly three matrices and one vector as input");
     7464    WerrorS("expected exactly three matrices and one vector as input");
    74657465    return TRUE;
    74667466  }
  • kernel/linearAlgebra.cc

    r2fd30cb r9e269a0  
    9898  int cc = aMat->cols();
    9999  pMat = mpNew(rr, rr);
    100   lMat = mpNew(rr, rr);
    101100  uMat = mpNew(rr, cc);
    102101  /* copy aMat into uMat: */
     
    440439        MATELEM(N, nonZeroC, dim) = pCopy(MATELEM(uMat, r, w));
    441440      }
     441      number z;
    442442      for (int d = 1; d <= dim; d++)
    443443      {
     
    450450          if (MATELEM(N, c, d) != NULL)
    451451            p = pAdd(p, ppMult_qq(MATELEM(uMat, r, c), MATELEM(N, c, d)));
    452         q = pNSet(nInvers(pGetCoeff(MATELEM(uMat, r, nonZeroC))));
    453         MATELEM(N, nonZeroC, d) = pMult(pNeg(p), q);;
     452        MATELEM(N, nonZeroC, d) = pNeg(p);
     453        if (MATELEM(N, nonZeroC, d) != NULL)
     454        {
     455          z = nDiv(pGetCoeff(MATELEM(N, nonZeroC, d)),
     456                   pGetCoeff(MATELEM(uMat, r, nonZeroC)));
     457          nNormalize(z); pDelete(&MATELEM(N, nonZeroC, d));
     458          MATELEM(N, nonZeroC, d) = pNSet(z);
     459        }
    454460      }
    455461      p = pNeg(pCopy(MATELEM(yVec, r, 1)));
     
    457463        if (MATELEM(xVec, c, 1) != NULL)
    458464          p = pAdd(p, ppMult_qq(MATELEM(uMat, r, c), MATELEM(xVec, c, 1)));
    459       q = pNSet(nInvers(pGetCoeff(MATELEM(uMat, r, nonZeroC))));
    460       MATELEM(xVec, nonZeroC, 1) = pMult(pNeg(p), q);
    461       pNormalize(MATELEM(xVec, nonZeroC, 1));
     465      MATELEM(xVec, nonZeroC, 1) = pNeg(p);
     466      if (MATELEM(xVec, nonZeroC, 1) != NULL)
     467      {
     468        z = nDiv(pGetCoeff(MATELEM(xVec, nonZeroC, 1)),
     469                 pGetCoeff(MATELEM(uMat, r, nonZeroC)));
     470        nNormalize(z); pDelete(&MATELEM(xVec, nonZeroC, 1));
     471        MATELEM(xVec, nonZeroC, 1) = pNSet(z);       
     472      }
    462473      lastNonZeroC = nonZeroC;
    463474    }
     
    491502void printNumber(const number z)
    492503{
    493         if (nIsZero(z)) printf("number = 0\n");
    494         else
    495         {
     504  if (nIsZero(z)) printf("number = 0\n");
     505  else
     506  {
    496507    poly p = pOne();
    497508    pSetCoeff(p, nCopy(z));
     
    13891400}
    13901401
     1402void lduDecomp(const matrix aMat, matrix &pMat, matrix &lMat, matrix &dMat,
     1403               matrix &uMat, poly &l, poly &u, poly &lTimesU)
     1404{
     1405  int rr = aMat->rows();
     1406  int cc = aMat->cols();
     1407  /* we use an int array to store all row permutations;
     1408     note that we only make use of the entries [1..rr] */
     1409  int* permut = new int[rr + 1];
     1410  for (int i = 1; i <= rr; i++) permut[i] = i;
     1411  /* fill lMat and dMat with the (rr x rr) unit matrix */
     1412  unitMatrix(rr, lMat);
     1413  unitMatrix(rr, dMat);
     1414  uMat = mpNew(rr, cc);
     1415  /* copy aMat into uMat: */
     1416  for (int r = 1; r <= rr; r++)
     1417    for (int c = 1; c <= cc; c++)
     1418      MATELEM(uMat, r, c) = pCopy(MATELEM(aMat, r, c));
     1419  u = pOne(); l = pOne();
     1420 
     1421  int col = 1; int row = 1;
     1422  while ((col <= cc) & (row < rr))
     1423  {
     1424    int pivotR; int pivotC; bool pivotValid = false;
     1425    while (col <= cc)
     1426    {
     1427      pivotValid = pivot(uMat, row, rr, col, col, &pivotR, &pivotC);
     1428      if (pivotValid)  break;
     1429      col++;
     1430    }
     1431    if (pivotValid)
     1432    {
     1433      if (pivotR != row)
     1434      {
     1435        swapRows(row, pivotR, uMat);
     1436        poly p = MATELEM(dMat, row, row);
     1437        MATELEM(dMat, row, row) = MATELEM(dMat, pivotR, pivotR);
     1438        MATELEM(dMat, pivotR, pivotR) = p;
     1439        swapColumns(row, pivotR, lMat);
     1440        swapRows(row, pivotR, lMat);
     1441        int temp = permut[row];
     1442        permut[row] = permut[pivotR]; permut[pivotR] = temp;
     1443      }
     1444      /* in gg, we compute the gcd of all non-zero elements in
     1445         uMat[row..rr, col];
     1446         the next number is the pivot and thus guaranteed to be different
     1447         from zero: */
     1448      number gg = nCopy(pGetCoeff(MATELEM(uMat, row, col))); number t;
     1449      for (int r = row + 1; r <= rr; r++)
     1450      {
     1451        if (MATELEM(uMat, r, col) != NULL)
     1452        {
     1453          t = gg;
     1454          gg = nGcd(t, pGetCoeff(MATELEM(uMat, r, col)), currRing);
     1455          nDelete(&t);
     1456        }
     1457      }
     1458      t = nDiv(pGetCoeff(MATELEM(uMat, row, col)), gg);
     1459      nNormalize(t);   /* this division works without remainder */
     1460      if (!nIsOne(t))
     1461      {
     1462        for (int r = row; r <= rr; r++)
     1463          pMult_nn(MATELEM(dMat, r, r), t);
     1464        pMult_nn(MATELEM(lMat, row, row), t);
     1465      }
     1466      l = pMult(l, pCopy(MATELEM(lMat, row, row)));
     1467      u = pMult(u, pCopy(MATELEM(uMat, row, col)));
     1468     
     1469      for (int r = row + 1; r <= rr; r++)
     1470      {
     1471        if (MATELEM(uMat, r, col) != NULL)
     1472        {
     1473          number g = nGcd(pGetCoeff(MATELEM(uMat, row, col)),
     1474                          pGetCoeff(MATELEM(uMat, r, col)), currRing);
     1475          number f1 = nDiv(pGetCoeff(MATELEM(uMat, r, col)), g);
     1476          nNormalize(f1);   /* this division works without remainder */
     1477          number f2 = nDiv(pGetCoeff(MATELEM(uMat, row, col)), g);
     1478          nNormalize(f2);   /* this division works without remainder */
     1479          pDelete(&MATELEM(uMat, r, col)); MATELEM(uMat, r, col) = NULL;
     1480          for (int c = col + 1; c <= cc; c++)
     1481          {
     1482            poly p = MATELEM(uMat, r, c);
     1483            pMult_nn(p, f2);
     1484            poly q = pCopy(MATELEM(uMat, row, c));
     1485            pMult_nn(q, f1); q = pNeg(q);
     1486            MATELEM(uMat, r, c) = pAdd(p, q);
     1487          }
     1488          number tt = nDiv(g, gg);
     1489          nNormalize(tt);   /* this division works without remainder */
     1490          pMult_nn(MATELEM(lMat, r, r), tt); nDelete(&tt);
     1491          MATELEM(lMat, r, row) = pCopy(MATELEM(lMat, r, r));
     1492          pMult_nn(MATELEM(lMat, r, row), f1);
     1493          nDelete(&f1); nDelete(&f2); nDelete(&g);
     1494        }
     1495        else pMult_nn(MATELEM(lMat, r, r), t);
     1496      }
     1497      nDelete(&t); nDelete(&gg);
     1498      col++; row++;
     1499    }
     1500  }
     1501  /* one factor in the product u might be missing: */
     1502  if (row == rr)
     1503  {
     1504    while ((col <= cc) && (MATELEM(uMat, row, col) == NULL)) col++;
     1505    if (col <= cc) u = pMult(u, pCopy(MATELEM(uMat, row, col)));
     1506  }
     1507 
     1508  /* building the permutation matrix from 'permut' and computing l */
     1509  pMat = mpNew(rr, rr);
     1510  for (int r = 1; r <= rr; r++)
     1511    MATELEM(pMat, r, permut[r]) = pOne();
     1512  delete[] permut;
     1513 
     1514  lTimesU = ppMult_qq(l, u);
     1515}
     1516
     1517bool luSolveViaLDUDecomp(const matrix pMat, const matrix lMat,
     1518                         const matrix dMat, const matrix uMat,
     1519                         const poly l, const poly u, const poly lTimesU,
     1520                         const matrix bVec, matrix &xVec, matrix &H)
     1521{
     1522  int m = uMat->rows(); int n = uMat->cols();
     1523  matrix cVec = mpNew(m, 1);  /* for storing l * pMat * bVec */
     1524  matrix yVec = mpNew(m, 1);  /* for storing the unique solution of
     1525                                 lMat * yVec = cVec */
     1526
     1527  /* compute cVec = l * pMat * bVec but without actual matrix mult. */
     1528  for (int r = 1; r <= m; r++)
     1529  {
     1530    for (int c = 1; c <= m; c++)
     1531    {
     1532      if (MATELEM(pMat, r, c) != NULL)
     1533        { MATELEM(cVec, r, 1) = ppMult_qq(l, MATELEM(bVec, c, 1)); break; }
     1534    }
     1535  }
     1536
     1537  /* solve lMat * yVec = cVec; this will always work as lMat is invertible;
     1538     moreover, all divisions are guaranteed to be without remainder */
     1539  number z;
     1540  for (int r = 1; r <= m; r++)
     1541  {
     1542    poly p = pNeg(pCopy(MATELEM(cVec, r, 1)));
     1543    for (int c = 1; c < r; c++)
     1544      p = pAdd(p, ppMult_qq(MATELEM(lMat, r, c), MATELEM(yVec, c, 1) ));
     1545    MATELEM(yVec, r, 1) = pNeg(p);
     1546    if (MATELEM(yVec, r, 1) != NULL)
     1547    {
     1548      z = nDiv(pGetCoeff(MATELEM(yVec, r, 1)), pGetCoeff(MATELEM(lMat, r, r)));
     1549      nNormalize(z);   /* division is without remainder */
     1550      pDelete(&MATELEM(yVec, r, 1));
     1551      MATELEM(yVec, r, 1) = pNSet(z);
     1552    }
     1553  }
     1554 
     1555  /* compute u * dMat * yVec and put result into yVec */
     1556  poly p;
     1557  for (int r = 1; r <= m; r++)
     1558  {
     1559    p = ppMult_qq(u, MATELEM(dMat, r, r));
     1560    MATELEM(yVec, r, 1) = pMult(p, MATELEM(yVec, r, 1));
     1561  }
     1562 
     1563  /* determine whether uMat * xVec = yVec is solvable */
     1564  bool isSolvable = true;
     1565  bool isZeroRow; int nonZeroRowIndex;
     1566  for (int r = m; r >= 1; r--)
     1567  {
     1568    isZeroRow = true;
     1569    for (int c = 1; c <= n; c++)
     1570      if (MATELEM(uMat, r, c) != NULL) { isZeroRow = false; break; }
     1571    if (isZeroRow)
     1572    {
     1573      if (MATELEM(yVec, r, 1) != NULL) { isSolvable = false; break; }
     1574    }
     1575    else { nonZeroRowIndex = r; break; }
     1576  }
     1577
     1578  if (isSolvable)
     1579  {
     1580    xVec = mpNew(n, 1);
     1581    matrix N = mpNew(n, n); int dim = 0;
     1582    poly p; poly q;
     1583    /* solve uMat * xVec = yVec and determine a basis of the solution
     1584       space of the homogeneous system uMat * xVec = 0;
     1585       We do not know in advance what the dimension (dim) of the latter
     1586       solution space will be. Thus, we start with the possibly too wide
     1587       matrix N and later copy the relevant columns of N into H. */
     1588    int nonZeroC; int lastNonZeroC = n + 1;
     1589    for (int r = nonZeroRowIndex; r >= 1; r--)
     1590    {
     1591      for (nonZeroC = 1; nonZeroC <= n; nonZeroC++)
     1592        if (MATELEM(uMat, r, nonZeroC) != NULL) break;
     1593      for (int w = lastNonZeroC - 1; w >= nonZeroC + 1; w--)
     1594      {
     1595        /* this loop will only be done when the given linear system has
     1596           more than one, i.e., infinitely many solutions */
     1597        dim++;
     1598        /* now we fill two entries of the dim-th column of N */
     1599        MATELEM(N, w, dim) = pNeg(pCopy(MATELEM(uMat, r, nonZeroC)));
     1600        MATELEM(N, nonZeroC, dim) = pCopy(MATELEM(uMat, r, w));
     1601      }
     1602      for (int d = 1; d <= dim; d++)
     1603      {
     1604        /* here we fill the entry of N at [r, d], for each valid vector
     1605           that we already have in N;
     1606           again, this will only be done when the given linear system has
     1607           more than one, i.e., infinitely many solutions */
     1608        p = NULL;
     1609        for (int c = nonZeroC + 1; c <= n; c++)
     1610          if (MATELEM(N, c, d) != NULL)
     1611            p = pAdd(p, ppMult_qq(MATELEM(uMat, r, c), MATELEM(N, c, d)));
     1612        MATELEM(N, nonZeroC, d) = pNeg(p);
     1613        if (MATELEM(N, nonZeroC, d) != NULL)
     1614        {
     1615          z = nDiv(pGetCoeff(MATELEM(N, nonZeroC, d)),
     1616                   pGetCoeff(MATELEM(uMat, r, nonZeroC)));
     1617          nNormalize(z);   /* division may be with remainder but only takes
     1618                              place for dim > 0 */
     1619          pDelete(&MATELEM(N, nonZeroC, d));
     1620          MATELEM(N, nonZeroC, d) = pNSet(z);
     1621        }
     1622      }
     1623      p = pNeg(pCopy(MATELEM(yVec, r, 1)));
     1624      for (int c = nonZeroC + 1; c <= n; c++)
     1625        if (MATELEM(xVec, c, 1) != NULL)
     1626          p = pAdd(p, ppMult_qq(MATELEM(uMat, r, c), MATELEM(xVec, c, 1)));
     1627      MATELEM(xVec, nonZeroC, 1) = pNeg(p);
     1628      if (MATELEM(xVec, nonZeroC, 1) != NULL)
     1629      {
     1630        z = nDiv(pGetCoeff(MATELEM(xVec, nonZeroC, 1)),
     1631                 pGetCoeff(MATELEM(uMat, r, nonZeroC)));
     1632        nNormalize(z);   /* division is without remainder */
     1633        pDelete(&MATELEM(xVec, nonZeroC, 1));
     1634        MATELEM(xVec, nonZeroC, 1) = pNSet(z);
     1635      }
     1636      lastNonZeroC = nonZeroC;
     1637    }
     1638   
     1639    /* divide xVec by l*u = lTimesU and put result in xVec */
     1640    number zz = pGetCoeff(lTimesU);
     1641    for (int c = 1; c <= n; c++)
     1642    {
     1643      if (MATELEM(xVec, c, 1) != NULL)
     1644      {
     1645        z = nDiv(pGetCoeff(MATELEM(xVec, c, 1)), zz);
     1646        nNormalize(z);
     1647        pDelete(&MATELEM(xVec, c, 1));
     1648        MATELEM(xVec, c, 1) = pNSet(z);
     1649      }
     1650    }
     1651   
     1652    if (dim == 0)
     1653    {
     1654      /* that means the given linear system has exactly one solution;
     1655         we return as H the 1x1 matrix with entry zero */
     1656      H = mpNew(1, 1);
     1657    }
     1658    else
     1659    {
     1660      /* copy the first 'dim' columns of N into H */
     1661      H = mpNew(n, dim);
     1662      for (int r = 1; r <= n; r++)
     1663        for (int c = 1; c <= dim; c++)
     1664          MATELEM(H, r, c) = pCopy(MATELEM(N, r, c));
     1665    }
     1666    /* clean up N */
     1667    idDelete((ideal*)&N);
     1668  }
     1669
     1670  idDelete((ideal*)&cVec);
     1671  idDelete((ideal*)&yVec);
     1672
     1673  return isSolvable;
     1674}
     1675
  • kernel/linearAlgebra.h

    r2fd30cb r9e269a0  
    3939 *   entries equal to 1,<br>
    4040 * - U is an (m x n) matrix in upper row echelon form.<br>
    41  * From these conditions, it easily follows that also A = P * L * U,
     41 * From these conditions, it follows immediately that also A = P * L * U,
    4242 * since P is self-inverse.<br>
     43 *
    4344 * The method will modify all argument matrices except aMat, so that
    4445 * they will finally contain the matrices P, L, and U as specified
     
    264265
    265266/**
     267 * Solves the linear system A * x = b, where A is an (m x n)-matrix
     268 * which is given by its LDU-decomposition.
     269 *
     270 * The method expects the LDU-decomposition of A, that is,
     271 * pMat * A = lMat * dMat^(-1) * uMat, where the argument matrices have
     272 * the appropriate proteries; see method
     273 * 'lduDecomp(const matrix aMat, matrix &pMat, matrix &lMat,
     274 * matrix &dMat, matrix &uMat, poly &l, poly &u, poly &lTimesU)'.<br>
     275 * Instead of trying to invert A and return x = A^(-1)*b, this
     276 * method
     277 * 1) computes b' = l * pMat * b,
     278 * 2) solves the simple system L * y = b',
     279 * 3) computes y' = u * dMat * y,
     280 * 4) solves the simple system U * y'' = y',
     281 * 5) computes x = 1/(lTimesU) * y''.
     282 * Note that steps 1), 2) and 3) will always work, as L is in any case
     283 * invertible. Moreover, y and thus y' are uniquely determined.
     284 * Step 4) will only work if and only if y' is in the column span of U.
     285 * In that case, there may be infinitely many solutions.
     286 * In contrast to luSolveViaLUDecomp, this algorithm guarantees that
     287 * all divisions which have to be performed in steps 2) and 4) will
     288 * work without remainder. This is due to properties of the given LDU-
     289 * decomposition. Only the final step 5) performs a division of a vector
     290 * by a member of the ground field. (Suppose the ground field is Q or
     291 * some rational function field. Then, if A contains only integers or
     292 * polynomials, respectively, then steps 1) - 4) will keep all data
     293 * integer or polynomial, respectively. This may speed up computations
     294 * considerably.)
     295 * For the outcome, there are three cases:<br>
     296 * 1) There is no solution. Then the method returns false, and &xVec
     297 *    as well as &H remain unchanged.<br>
     298 * 2) There is a unique solution. Then the method returns true and
     299 *    H is the 1x1 matrix with zero entry.<br>
     300 * 3) There are infinitely many solutions. Then the method returns
     301 *    true and some solution of the given original linear system.
     302 *    Furthermore, the columns of H span the solution space of the
     303 *    homogeneous linear system. The dimension of the solution
     304 *    space is then the number of columns of H.
     305 *
     306 * @return true if there is at least one solution, false otherwise
     307 **/
     308bool luSolveViaLDUDecomp(
     309       const matrix pMat,  /**< [in]  permutation matrix of an LDU-
     310                                      decomposition                     */
     311       const matrix lMat,  /**< [in]  lower left matrix of an LDU-
     312                                      decomposition                     */
     313       const matrix dMat,  /**< [in]  diagonal matrix of an LDU-
     314                                      decomposition                     */
     315       const matrix uMat,  /**< [in]  upper right matrix of an LDU-
     316                                      decomposition                     */
     317       const poly l,       /**< [in]  pivot product l of an LDU decomp. */
     318       const poly u,       /**< [in]  pivot product u of an LDU decomp. */
     319       const poly lTimesU, /**< [in]  product of l and u                */
     320       const matrix bVec,  /**< [in]  right-hand side of the linear
     321                                      system to be solved               */
     322       matrix &xVec,       /**< [out] solution of A*x = b               */
     323       matrix &H           /**< [out] matrix with columns spanning
     324                                      homogeneous solution space        */
     325                          );
     326
     327/**
    266328 * Creates a new matrix which is the (nxn) unit matrix, and returns true
    267329 * in case of success.
     
    489551                              );
    490552
     553/**
     554 * LU-decomposition of a given (m x n)-matrix with performing only those
     555 * divisions that yield zero remainders.
     556 *
     557 * Given an (m x n) matrix A, the method computes its LDU-decomposition,
     558 * that is, it computes matrices P, L, D, and U such that<br>
     559 * - P * A = L * D^(-1) * U,<br>
     560 * - P is an (m x m) permutation matrix, i.e., its row/columns form the
     561 *   standard basis of K^m,<br>
     562 * - L is an (m x m) matrix in lower triangular form of full rank,<br>
     563 * - D is an (m x m) diagonal matrix with full rank, and<br>
     564 * - U is an (m x n) matrix in upper row echelon form.<br>
     565 * From these conditions, it follows immediately that also
     566 * A = P * L * D^(-1) * U, since P is self-inverse.<br>
     567 *
     568 * In contrast to luDecomp, this method only performs those divisions which
     569 * yield zero remainders. Hence, when e.g. computing over a rational function
     570 * field and starting with polynomial entries only (or over Q and starting
     571 * with integer entries only), then any newly computed matrix entry will again
     572 * be polynomial (or integer).
     573 *
     574 * The method will modify all argument matrices except aMat, so that
     575 * they will finally contain the matrices P, L, D, and U as specified
     576 * above. Moreover, in order to further speed up subsequent calls of
     577 * luSolveViaLDUDecomp, the two denominators and their product will also be
     578 * returned.
     579 **/
     580void lduDecomp(
     581       const matrix aMat, /**< [in]  the initial matrix A,          */
     582       matrix &pMat,      /**< [out] the row permutation matrix P   */
     583       matrix &lMat,      /**< [out] the lower triangular matrix L  */
     584       matrix &dMat,      /**< [out] the diagonal matrix D          */
     585       matrix &uMat,      /**< [out] the upper row echelon matrix U */
     586       poly &l,           /**< [out] the product of pivots of L     */
     587       poly &u,           /**< [out] the product of pivots of U     */
     588       poly &lTimesU      /**< [out] the product of l and u         */
     589             );
     590
    491591#endif
    492592/* LINEAR_ALGEBRA_H */
Note: See TracChangeset for help on using the changeset viewer.