Changeset 9e269a0 in git for kernel/linearAlgebra.cc


Ignore:
Timestamp:
Dec 22, 2010, 1:54:29 PM (13 years ago)
Author:
Frank Seelisch <seelisch@…>
Branches:
(u'spielwiese', 'd0474371d8c5d8068ab70bfb42719c97936b18a6')
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
File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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
Note: See TracChangeset for help on using the changeset viewer.