void RowEchelon<T>::backSub(VectorT& x) const
{
  Assert(EB.n == 1);
  Assert(EB.m == R.m);
  x.resize(R.n);
  VectorT b;
  EB.getColRef(0,b);

  Assert((int)firstEntry.size() == R.m+1);
  x.setZero();
  int m=R.m,n=R.n;
  for(int i=m-1;i>=0;i--) {
    VectorT ri; R.getRowRef(i,ri);
    //solve to set R*x = b[i]
    //calculate alpha = dot between rest of x[>ji] and R[i]
    int ji=firstEntry[i];
    if(ji == n) continue;
    int ji2=firstEntry[i+1];  //(i+1==m?n:firstEntry[i+1]);
    T alpha;
    if(ji2 == n) alpha = Zero;
    else {
      VectorT rji2; rji2.setRef(ri,ji2,1,R.n-ji2);
      VectorT xji2; xji2.setRef(x,ji2,1,R.n-ji2);
      alpha = xji2.dot(rji2);
    }
    x[ji] = (b[i]-alpha)/ri[ji];
  }
}
void SparseMatrixTemplate_RM<T>::mulTranspose(const VectorT& a,VectorT& x) const
{
  if(x.n == 0) x.resize(n);
  if(x.n != n) {
    FatalError("Destination vector has incorrect dimensions");
  }
  if(a.n != m) {
    FatalError("Source vector has incorrect dimensions");
  }
  x.setZero();
  for(int i=0;i<m;i++) {
    for(ConstRowIterator it=rows[i].begin();it!=rows[i].end();it++)
      x(it->first) += it->second*a(i);
  }
}
Exemple #3
0
void QRDecomposition<T>::leastSquares(const VectorT& b, VectorT& x, VectorT& residual) const
{
  if(x.n == 0) x.resize(QR.n);
  Assert(QR.m >= QR.n);
  Assert(QR.m == b.n);
  Assert(QR.n == x.n);
  Assert(QR.m == residual.n);

  MatrixT R;
  R.setRef(QR,0,0,1,1,QR.n,QR.n);
  VectorT c;
  c.setRef(residual,0,1,QR.n);

  /* compute rhs = Q^T b */ 
  QtMul(b,residual);
  
  /* Solve R x = rhs */
  UBackSubstitute(R,c,x);
  
  /* Compute residual = b - A x = Q (Q^T b - R x) */
  c.setZero();
  QMul(residual,residual);
}
void RowEchelon<T>::getNullspace(MatrixT& N) const
{
  if(R.isEmpty()) {
    N.clear();
    return;
  }
  Assert((int)firstEntry.size() == R.m+1);

  int nullspace_dims=getNull();
  N.resize(R.n,nullspace_dims);

  //first get nullspace vectors from 0 to firstEntry[0]
  int i,j,numVecs=0;
  int m=R.m,n=R.n;
  for(j=0;j<firstEntry[0];j++) {
    N.setCol(numVecs,0); N(j,numVecs)=1;
    numVecs++;
  }
  for(i=0;i<m;i++) {
    //cancel out the i'th entry
    for(j=firstEntry[i]+1;j<firstEntry[i+1];j++) {
      if(numVecs >= N.n) {
	LOG4CXX_INFO(KrisLibrary::logger(),"Num nullspace vectors "<<numVecs);
	LOG4CXX_INFO(KrisLibrary::logger(),"Found more nullspace vectors than found dims, row "<<i);
	LOG4CXX_INFO(KrisLibrary::logger(),MatrixPrinter(R));
      }
      Assert(numVecs < N.n);
      VectorT xn; N.getColRef(numVecs,xn);
      xn.setZero();
      xn[firstEntry[i]] = R(i,j);
      xn[j] = -R(i,firstEntry[i]);

      //cancel out all the entries prior to i 
      int isave=i;
      i--;
      for(;i>=0;i--) {
        VectorT ri; R.getRowRef(i,ri);
	//calculate alpha
	int ji=firstEntry[i];
	Assert(ji != n);
	int ji2=firstEntry[i+1]; //(i+1==m?n:firstEntry[i+1]);
	T alpha;
	if(ji2 == n) alpha = Zero;
        else {
          VectorT rji2; rji2.setRef(ri,ji2,1,R.n-ji2);
          VectorT xji2; xji2.setRef(xn,ji2,1,R.n-ji2);
          alpha = xji2.dot(rji2);
        }
	xn[ji] = -alpha/ri[ji];
      }
      i=isave;
      numVecs++;
    }
  }
  if(numVecs != nullspace_dims) {
    LOG4CXX_ERROR(KrisLibrary::logger(),"Error in counting rank in row-eschelon decomposition");
    LOG4CXX_INFO(KrisLibrary::logger(),"Num nullspace vectors "<<numVecs);
    LOG4CXX_INFO(KrisLibrary::logger(),MatrixPrinter(R));
  }
  Assert(numVecs == nullspace_dims);

  /*
  VectorT temp;
  for(int i=0;i<numVecs;i++) {
    VectorT xi; N.getColRef(i,xi);
    xi.print();
    R.mul(xi,temp);
    if(temp.maxAbsElement() > 1e-4) {
      LOG4CXX_INFO(KrisLibrary::logger(),"Nullspace vector "<<i<<" not in null space!");
      xi.print();
      LOG4CXX_INFO(KrisLibrary::logger(),"Result = "); temp.print();
      KrisLibrary::loggerWait();
    }
  }
  */

  VectorT* N0 = new VectorT[nullspace_dims];
  for(int i=0;i<nullspace_dims;i++) N.getColRef(i,N0[i]);
  int num=OrthonormalBasis(N0,N0,nullspace_dims);
  Assert(num == nullspace_dims);
  delete [] N0;
}