예제 #1
0
    // ------------------------------------------------------------------------
    //
    //         Init function - call prior to start of iterations
    //
    // ------------------------------------------------------------------------
    void Init(const Matrix<T>& A,
              DenseMatrix<T>& W,
              DenseMatrix<T>& H)
    {
        WtW.Resize(W.Width(), W.Width());
        WtA.Resize(W.Width(), A.Width());
        HHt.Resize(H.Height(), H.Height());
        AHt.Resize(A.Height(), H.Height());
        ScaleFactors.Resize(H.Height(), 1);

        // compute the kxk matrix WtW = W' * W
        Gemm(TRANSPOSE, NORMAL, T(1), W, W, T(0), WtW);

        // compute the kxn matrix WtA =  W' * A
        Gemm(TRANSPOSE, NORMAL, T(1), W, A, T(0), WtA);
    }
예제 #2
0
파일: coefficient.hpp 프로젝트: LLNL/mfem
 /// Construct a constant matrix coefficient times a scalar Coefficient
 MatrixFunctionCoefficient(const DenseMatrix &m, Coefficient &q)
    : MatrixCoefficient(m.Height(), m.Width()), Q(&q)
 {
    Function = NULL;
    TDFunction = NULL;
    mat = m;
 }
예제 #3
0
void OverwriteCols(DenseMatrix<T>& A, 
                   const DenseMatrix<T>& B, 
                   const std::vector<unsigned int>& col_indices,
                   const unsigned int num_cols)
{
    const unsigned int height = A.Height();

    // Overwrite columns of A with B.
    if (B.Height() != A.Height())
        throw std::logic_error("OverwriteCols: height mismatch");
    if (num_cols > static_cast<unsigned int>(A.Width()))
        throw std::logic_error("OverwriteCols: col indices out of bounds");

    T* buf_a = A.Buffer();
    const unsigned int ldim_a = A.LDim();

    const T* buf_b = B.LockedBuffer();
    const unsigned int ldim_b = B.LDim();

    for (unsigned int c=0; c<num_cols; ++c)
    {
        unsigned int col_a = col_indices[c];
        unsigned int offset_a = col_a*ldim_a;
        unsigned int offset_b = c*ldim_b;
            
        memcpy(&buf_a[offset_a], &buf_b[offset_b], height * sizeof(T));
    }
}
예제 #4
0
bool SolveNormalEq(const DenseMatrix<T>& LHS, // kxk
                   const DenseMatrix<T>& RHS, // kxn
                   DenseMatrix<T>& X)         // kxn
{
    // Solve LHS * X = RHS for X, where LHS is assumed SPD.

    if (LHS.Width() != LHS.Height())
        throw std::logic_error("SolveNormalEq: expected square matrix on LHS");
    if ( (X.Height() != LHS.Height()) || (X.Width() != RHS.Width()))
        throw std::logic_error("SolveNormalEq: non-conformant matrix X");
    
    // copy the input, since the solver overwrites it
    DenseMatrix<T> M(LHS);
    X = RHS;

    return SolveNormalEq(M, X);
}
예제 #5
0
파일: eltrans.cpp 프로젝트: LLNL/mfem
void IsoparametricTransformation::Transform (const DenseMatrix &matrix,
                                             DenseMatrix &result)
{
   MFEM_ASSERT(matrix.Height() == GetDimension(), "invalid input");
   result.SetSize(PointMat.Height(), matrix.Width());

   IntegrationPoint ip;
   Vector col;

   for (int j = 0; j < matrix.Width(); j++)
   {
      ip.Set(matrix.GetColumn(j), matrix.Height());

      result.GetColumnReference(j, col);
      Transform(ip, col);
   }
}
예제 #6
0
void VisualizationSceneVector3d::PrepareFlat()
{
   int i, j;

   glNewList (displlist, GL_COMPILE);

   int nbe = mesh -> GetNBE();
   DenseMatrix pointmat;
   Array<int> vertices;
   double p[4][3], c[4];

   for (i = 0; i < nbe; i++)
   {
      if (!bdr_attr_to_show[mesh->GetBdrAttribute(i)-1]) continue;

      mesh->GetBdrPointMatrix(i, pointmat);
      mesh->GetBdrElementVertices(i, vertices);

      for (j = 0; j < pointmat.Width(); j++)
      {
         pointmat(0, j) += (*solx)(vertices[j])*(ianim)/ianimmax;
         pointmat(1, j) += (*soly)(vertices[j])*(ianim)/ianimmax;
         pointmat(2, j) += (*solz)(vertices[j])*(ianim)/ianimmax;
      }

      for (j = 0; j < pointmat.Width(); j++)
      {
         p[j][0] = pointmat(0, j);
         p[j][1] = pointmat(1, j);
         p[j][2] = pointmat(2, j);
         c[j] = (*sol)(vertices[j]);
      }
      if (j == 3)
         DrawTriangle(p, c, minv, maxv);
      else
         DrawQuad(p, c, minv, maxv);
   }
   glEndList();
}
예제 #7
0
void MakeDiagonallyDominant(DenseMatrix<T>& M)
{
    // Make the diagonal element larger than the row sum, to ensure that
    // the matrix is nonsingular.  All entries in the matrix are nonnegative, 
    // so no absolute values are needed.

    for (int r=0; r<M.Height(); ++r)
    {
        T row_sum = 0.0;
        for (int c=0; c<M.Width(); ++c)
            row_sum += M.Get(r, c);
        M.Set(r, r, row_sum + T(1));
    }
}
예제 #8
0
void OptimalActiveSetH(DenseMatrix<T>& H,         // 2 x n
                       const DenseMatrix<T>& WtW, // 2 x 2
                       const DenseMatrix<T>& WtA) // 2 x n
{
    // Remove negative entries in each of the n columns of matrix H, but
    // do so in a manner that minimizes the overall objective function. 
    // Each column can be considered in isolation.
    //
    // The problem for each column i of H, h = H(:,i),  is as follows:
    //
    //     min_{h>=0} |Wh - a|^2
    //
    // This is minimized when h* = w'a / (w'w).  Expressed in terms of the
    // individual elements, this becomes:
    //
    //    h*[0] = w[0]'a / (w[0]'w[0])
    //    h*[1] = w[1]'a / (w[1]'w[1])

    // If both elements of h* are nonnegative, this is the optimal solution.  
    // If any elements are negative, the Rank2 algorithm is used to adjust
    // their values.
    
    int width = H.Width();
    
    const T wtw_00 = WtW.Get(0,0);
    const T wtw_11 = WtW.Get(1,1);
    const T inv_wtw_00 = T(1.0) / wtw_00;
    const T inv_wtw_11 = T(1.0) / wtw_11;
    const T sqrt_wtw_00 = sqrt(wtw_00);
    const T sqrt_wtw_11 = sqrt(wtw_11);

    for (int i=0; i<width; ++i)
    {
        T v1 = WtA.Get(0,i) * inv_wtw_00;
        T v2 = WtA.Get(1,i) * inv_wtw_11;
        T vv1 = v1 * sqrt_wtw_00;
        T vv2 = v2 * sqrt_wtw_11;

        if (vv1 >= vv2)
            v2 = T(0);
        else
            v1 = T(0);

        if ( (H.Get(0,i) <= T(0)) || (H.Get(1,i) <= T(0)))
        {
            H.Set(0, i, v1);
            H.Set(1, i, v2);
        }
    }
}
예제 #9
0
void IsoparametricTransformation::Transform (const DenseMatrix &matrix,
                                             DenseMatrix &result)
{
   result.SetSize(PointMat.Height(), matrix.Width());

   IntegrationPoint ip;
   Vector col;

   for (int j = 0; j < matrix.Width(); j++)
   {
      ip.x = matrix(0, j);
      if (matrix.Height() > 1)
      {
         ip.y = matrix(1, j);
         if (matrix.Height() > 2)
         {
            ip.z = matrix(2, j);
         }
      }

      result.GetColumnReference(j, col);
      Transform(ip, col);
   }
}
예제 #10
0
bool HasNaNs(const DenseMatrix<T>& M)
{
    // returns true if any matrix element is NaN

    int height = M.Height();
    int width  = M.Width();
    for (int c=0; c<width; ++c)
    {
        for (int r=0; r<height; ++r)
        {
            T elt = M.Get(r, c);
            if (std::isnan(elt))
                return true;
        }
    }

    return false;
}
예제 #11
0
파일: fespace.cpp 프로젝트: YPCC/mfem
// helper to set submatrix of A repeated vdim times
static void SetVDofSubMatrixTranspose(SparseMatrix& A,
                                      Array<int>& rows, Array<int>& cols,
                                      const DenseMatrix& subm, int vdim)
{
   if (vdim == 1)
   {
      A.SetSubMatrixTranspose(rows, cols, subm, 1);
   }
   else
   {
      int nr = subm.Width(), nc = subm.Height();
      for (int d = 0; d < vdim; d++)
      {
         Array<int> rows_sub(rows.GetData() + d*nr, nr); // (not owner)
         Array<int> cols_sub(cols.GetData() + d*nc, nc); // (not owner)
         A.SetSubMatrixTranspose(rows_sub, cols_sub, subm, 1);
      }
   }
}
예제 #12
0
void Overwrite(DenseMatrix<T>& A, 
               const DenseMatrix<T>& B, 
               const std::vector<unsigned int>& row_indices,
               const std::vector<unsigned int>& col_indices,
               const unsigned int num_rows,
               const unsigned int num_cols)
{
    // Overwrite entries in A with entries in B.  The row and column
    // index arrays contain the destination indices to be overwritten.
    // Matrix B has size num_rows x num_cols.

    if (num_rows > static_cast<unsigned int>(A.Height()))
        throw std::logic_error("Overwrite: row indices out of bounds");
    if (num_cols > static_cast<unsigned int>(A.Width()))
        throw std::logic_error("Overwrite: col indices out of bounds");

    const T* buf_b = B.LockedBuffer();
    const unsigned int ldim_b = B.LDim();
    
    T* buf_a = A.Buffer();
    const unsigned int ldim_a = A.LDim();

    for (unsigned int c=0; c<num_cols; ++c)
    {
        unsigned int col_a = col_indices[c];
        unsigned int offset_a = ldim_a * col_a;
        unsigned int offset_b = ldim_b * c;

        for (unsigned int r=0; r<num_rows; ++r)
        {
            unsigned int row_a = row_indices[r];
            //T val = B.Get(r, c);
            //A.Set(row_a, col_a, val);
            buf_a[offset_a + row_a] = buf_b[offset_b + r];
        }
    }
}
예제 #13
0
void ZeroizeSmallValues(DenseMatrix<T>& A, const T tol)
{
    // set Aij to zero if |Aij| < tol

    T* buf = A.Buffer();
    const unsigned int ldim = A.LDim();

    const unsigned int height = A.Height();
    const unsigned int width  = A.Width();

    OPENMP_PRAGMA(omp parallel for)
    for (unsigned int c=0; c<width; ++c)
    {
        unsigned int col_offset = c*ldim;
        for (unsigned int r=0; r<height; ++r)
        {
            T val = buf[col_offset + r];
            if (std::abs(val) < tol)
            {
                buf[col_offset + r] = T(0);
            }
        }
    }
}
예제 #14
0
bool SystemSolveH(DenseMatrix<T>& X, // H    2 x n
                  DenseMatrix<T>& A, // WtW  2 x 2
                  DenseMatrix<T>& B) // WtA  2 x n
{
    // This function solves the system A*X = B for X.  The columns of X and B
    // are treated as separate subproblems.  Each subproblem can be expressed
    // as follows, for column i of X and B (the ' means transpose):
    //
    //              A * [x0  x1]' = [b0  b1]'
    //
    // The solution proceeds by transforming matrix A to upper triangular form
    // via a fast Givens rotation.  The resulting triangular system for the 
    // two unknowns in each column of X is then solved by backsubstitution.
    //
    // The fast Givens method relies on the fact that matrix A can be 
    // expressed as the product of a diagonal matrix D and another matrix Y,
    // and that this form is preserved under the rotation.  If J is the 
    // Givens rotation matrix, then:
    //
    //           AX    = B
    //          JAX    = JB        J is the Givens rotation matrix
    //         (JA)X   = JB        letting A = D1Y1
    //        (JD1Y1)X = JB
    //        (D2Y2)X  = JB
    //
    // The matrix D1 is the identity matrix, and the matrix Y1 is the
    // original matrix A.  The matrix J has the form [c -s; c s] in Matlab
    // notation.  NOTE: with this convention, the tangent has a minus sign:
    //
    //            t = -A(1, 0) / A(0, 0)
    //
    // Matrix A has the form [a b; c d], and after the rotation it is
    // transformed to [a2 b2; 0 d2].
    //
    // There are two forms for the D2 and Y2 matrices, depending on whether
    // cosines or sines are 'factored out'.  If |A00| >= |A01|, then the
    // upper left element is factored out and the 'cosine' formulation is
    // used.  If |A00| < |A01|, then the upper right element is factored
    // out and the 'sine' formulation is used.
    //
    // A general reference for this code is the paper 'Fast Plane Rotations
    // with Dynamic Scaling', by A. Anda and H. Park, SIAM Journal on Matrix
    // Analysis and Applications, Vol 15, no. 1, pp. 162-174, Jan. 1994.

    int n = B.Width();
    T abs_A00 = std::abs(A.Get(0, 0));
    T abs_A01 = std::abs(A.Get(0, 1));
    const T epsilon = std::numeric_limits<T>::epsilon();

    if ( (abs_A00 < epsilon) && (abs_A01 < epsilon))
    {
        std::cerr << "SystemSolveH: singular matrix" << std::endl;
        return false;
    }

    T a2, b2, d2, e2, f2, inv_a2, inv_d2, x_1;
    if (abs_A00 >= abs_A01)
    {   
        // use 'cosine' formulation; t is the tangent
        T t = -A.Get(1,0) / A.Get(0,0);
        a2 = A.Get(0,0) - t*A.Get(1,0);
        b2 = A.Get(0,1) - t*A.Get(1,1);
        d2 = A.Get(1,1) + t*A.Get(0,1);

        // precompute 1/a2 and 1/d2 to avoid repeated division
        inv_a2 = T(1.0) / a2;
        inv_d2 = T(1.0) / d2;

        // a2 is guaranteed to be positive
        if (std::abs(d2/a2) < epsilon)
            return false;

        // solve the upper triangular systems by backsubstitution
        for (int i=0; i<n; ++i)
        {
            e2 = B.Get(0,i) - t*B.Get(1,i);
            f2 = B.Get(1,i) + t*B.Get(0,i);
            x_1 = f2 * inv_d2;
            X.Set(1, i, x_1);
            X.Set(0, i, (e2 - b2*x_1)*inv_a2);
        }
    }
    else
    {
        // use 'sine' formulation; ct is the cotangent
        T ct = -A.Get(0,0) / A.Get(1,0);
        a2 = -A.Get(1,0) + ct*A.Get(0,0);
        b2 = -A.Get(1,1) + ct*A.Get(0,1);
        d2 =  A.Get(0,1) + ct*A.Get(1,1);

        // precompute 1/a2 and 1/d2 to avoid repeated division
        inv_a2 = T(1.0) / a2;
        inv_d2 = T(1.0) / d2;

        // a2 is guaranteed to be positive
        if (std::abs(d2/a2) < epsilon)
            return false;

        // solve the upper triangular systems by backsubstitution
        for (int i=0; i<n; ++i)
        {
            e2 = -B.Get(1,i) + ct*B.Get(0,i);
            f2 =  B.Get(0,i) + ct*B.Get(1,i);
            x_1 = f2 * inv_d2;
            X.Set(1, i, x_1);
            X.Set(0, i, (e2 - b2*x_1) * inv_a2);
        }
    }

    return true;
}
예제 #15
0
파일: nnls.hpp 프로젝트: beckgom/smallk
void BppUpdateSets(BitMatrix& nonopt_set,
                   BitMatrix& infeas_set,
                   const BitMatrix& not_opt_mask,
                   const DenseMatrix<T>& X,
                   const DenseMatrix<T>& Y,
                   const BitMatrix& passive_set)
{
    // This function performs the equivalent of these operations:
    //
    //     nonopt_set = not_opt_mask & (Y < T(0)) & ~passive_set;
    //     infeas_set = not_opt_mask & (X < T(0)) & passive_set;

    const unsigned int height = not_opt_mask.Height();
    const unsigned int width  = not_opt_mask.Width();

    if ( (static_cast<unsigned int>(X.Height()) != height) || 
         (static_cast<unsigned int>(Y.Height()) != height) || 
         (passive_set.Height() != height))
        throw std::logic_error("BppUpdateSets: height mismatch");

    if ( (static_cast<unsigned int>(X.Width()) != width) || 
         (static_cast<unsigned int>(Y.Width()) != width) || 
         (passive_set.Width() != width))
        throw std::logic_error("BppUpdateSets: width mismatch");

    nonopt_set.Resize(height, width);
    infeas_set.Resize(height, width);

    const unsigned int BITS = BitMatrix::BITS_PER_WORD;
    const unsigned int MASK   = nonopt_set.Mask();
    assert(infeas_set.Mask() == MASK);

    unsigned int* buf_r = nonopt_set.Buffer();
    const unsigned int ldim_r = nonopt_set.LDim();

    unsigned int* buf_i = infeas_set.Buffer();
    const unsigned int ldim_i = infeas_set.LDim();

    const unsigned int* buf_m = not_opt_mask.LockedBuffer();
    const unsigned int ldim_m = not_opt_mask.LDim();

    const T* buf_x = X.LockedBuffer();
    const unsigned int ldim_x = X.LDim();

    const T* buf_y = Y.LockedBuffer();
    const unsigned int ldim_y = Y.LDim();

    const unsigned int* buf_p = passive_set.LockedBuffer();
    const unsigned int ldim_p = passive_set.LDim();

    const unsigned int full_wds = height / BITS;
    const unsigned int extra    = height - BITS*full_wds;

    assert(ldim_r >= ldim_m);
    assert(ldim_r >= ldim_p);

    OPENMP_PRAGMA(omp parallel for)
    for (unsigned int c=0; c<width; ++c)
    {
        unsigned int offset_r = c*ldim_r;
        unsigned int offset_i = c*ldim_i;
        unsigned int offset_m = c*ldim_m;
        unsigned int offset_x = c*ldim_x;
        unsigned int offset_y = c*ldim_y;
        unsigned int offset_p = c*ldim_p;

        unsigned int r_wd = 0, r=0;
        for (; r_wd<full_wds; ++r_wd)
        {
            unsigned int x_wd = 0, y_wd = 0;
            for (unsigned int q=0; q<BITS; ++q, ++r)
            {
                if (buf_x[offset_x + r] < T(0))
                    x_wd |= (1 << q);
                if (buf_y[offset_y + r] < T(0))
                    y_wd |= (1 << q);
            }
            
            buf_r[offset_r + r_wd] = buf_m[offset_m + r_wd] & y_wd & ~buf_p[offset_p + r_wd];
            buf_i[offset_i + r_wd] = buf_m[offset_m + r_wd] & x_wd & buf_p[offset_p + r_wd];
        }

        if (extra > 0)
        {
            unsigned int x_wd = 0, y_wd = 0;
            for (unsigned int q=0; q<extra; ++q, ++r)
            {
                if (buf_x[offset_x + r] < T(0))
                    x_wd |= (1 << q);
                if (buf_y[offset_y + r] < T(0))
                    y_wd |= (1 << q);
            }

           buf_r[offset_r + r_wd] = MASK & buf_m[offset_m + r_wd] & y_wd & ~buf_p[offset_p + r_wd];
           buf_i[offset_i + r_wd] = MASK & buf_m[offset_m + r_wd] & x_wd & buf_p[offset_p + r_wd];
        }
    }
}
예제 #16
0
파일: nnls.hpp 프로젝트: beckgom/smallk
bool NnlsHals(const MatrixType<T>& A,
              DenseMatrix<T>& W, 
              DenseMatrix<T>& H,
              const T tol,
              const bool verbose,
              const unsigned int max_iter)
{
    unsigned int n = A.Width();
    unsigned int k = W.Width();

    if (static_cast<unsigned int>(W.Height()) != static_cast<unsigned int>(A.Height()))
        throw std::logic_error("NnlsHals: W and A must have identical height");
    if (static_cast<unsigned int>(H.Width()) != static_cast<unsigned int>(A.Width()))
        throw std::logic_error("NnlsHals: H and A must have identical width");
    if (H.Height() != W.Width())
        throw std::logic_error("NnlsHals: non-conformant W and H");

    DenseMatrix<T> WtW(k, k), WtA(k, n), WtWH_r(1, n), gradH(k, n);

    if (verbose)
        std::cout << "\nRunning NNLS solver..." << std::endl;
    
    // compute W'W and W'A for the normal equations
    Gemm(TRANSPOSE, NORMAL, T(1.0), W, W, T(0.0), WtW);
    Gemm(TRANSPOSE, NORMAL, T(1.0), W, A, T(0.0), WtA);

    bool success = false;

    T pg0 = T(0), pg;
    for (unsigned int i=0; i<max_iter; ++i)
    {
        // compute the new matrix H
        UpdateH_Hals(H, WtWH_r, WtW, WtA);
        
        // compute gradH = WtW*H - WtA
        Gemm(NORMAL, NORMAL, T(1.0), WtW, H, T(0.0), gradH);
        Axpy( T(-1.0), WtA, gradH);

        // compute progress metric
        if (0 == i)
        {
            pg0 = ProjectedGradientNorm(gradH, H);
            if (verbose)
                ReportProgress(i+1, T(1.0));
            continue;
        }
        else
        {
            pg = ProjectedGradientNorm(gradH, H);
        }

        if (verbose)
            ReportProgress(i+1, pg/pg0);
        
        // check progress vs. desired tolerance
        if (pg < tol * pg0)
        {
            success = true;
            NormalizeAndScale<T>(W, H);
            break;
        }
    }

    if (!success)
        std::cerr << "NNLS solver reached iteration limit." << std::endl;
    
    return success;
}
예제 #17
0
파일: nnls.hpp 프로젝트: beckgom/smallk
bool NnlsBlockpivot(const DenseMatrix<T>& LHS,
                    const DenseMatrix<T>& RHS,
                    DenseMatrix<T>& X, // input as xinit
                    DenseMatrix<T>& Y) // gradX
{
    // Solve (LHS)*X = RHS for X by block principal pivoting. Matrix LHS
    // is assumed to be symmetric positive definite.

    const int PBAR = 3;
    const unsigned int WIDTH  = RHS.Width();
    const unsigned int HEIGHT = RHS.Height();
    const unsigned int MAX_ITER = HEIGHT*5;

    BitMatrix passive_set = (X > T(0));

    std::vector<unsigned int> tmp_indices(WIDTH);
    for (unsigned int i=0; i<WIDTH; ++i)
        tmp_indices[i] = i;

    MakeZeros(X);
    if (!BppSolveNormalEqNoGroup(tmp_indices, passive_set, LHS, RHS, X))
        return false;

    // Y = LHS * X - RHS
    Gemm(NORMAL, NORMAL, T(1), LHS, X, T(0), Y);
    Axpy( T(-1), RHS, Y);

    std::vector<int> P(WIDTH, PBAR), Ninf(WIDTH, HEIGHT+1);

    BitMatrix nonopt_set = (Y < T(0)) & ~passive_set;
    BitMatrix infeas_set = (X < T(0)) & passive_set;
    std::vector<int> col_sums(WIDTH);
    std::vector<int> not_good(WIDTH);

    nonopt_set.SumColumns(not_good);
    infeas_set.SumColumns(col_sums);
    not_good += col_sums;
    BitMatrix not_opt_cols = (not_good > 0);
    BitMatrix not_opt_mask;

    std::vector<unsigned int> non_opt_col_indices(WIDTH);
    not_opt_cols.Find(non_opt_col_indices);

    DenseMatrix<double> RHSsub(HEIGHT, WIDTH);
    DenseMatrix<double> Xsub(HEIGHT, WIDTH);
    DenseMatrix<double> Ysub(HEIGHT, WIDTH);

    unsigned int iter = 0;
    while (!non_opt_col_indices.empty())
    {
        // exit if not getting anywhere
        if (iter >= MAX_ITER)
            return false;

        UpdatePassiveSet(passive_set, PBAR, HEIGHT,
                         not_opt_cols, nonopt_set, infeas_set,
                         not_good, P, Ninf);

        // equivalent of repmat(NotOptCols, HEIGHT, 1)
        not_opt_mask = MatrixFromColumnMask(not_opt_cols, HEIGHT);

        // Setup for the normal equation solver by extracting submatrices
        // from RHS and X.  The normal equation solver will extract further
        // subproblems from RHSsub and Xsub and write all updated values
        // back into RHSsub and Xsub.
        RHS.SubmatrixFromCols(RHSsub, non_opt_col_indices);
        X.SubmatrixFromCols(Xsub, non_opt_col_indices);

        if (!BppSolveNormalEqNoGroup(non_opt_col_indices, passive_set, LHS, RHSsub, Xsub))
            return false;

        ZeroizeSmallValues(Xsub, 1.0e-12);

        // compute Ysub = LHS * Xsub - RHSsub
        Ysub.Resize(RHSsub.Height(), RHSsub.Width());
        Gemm(NORMAL, NORMAL, T(1), LHS, Xsub, T(0), Ysub);
        Axpy( T(-1), RHSsub, Ysub);

        // update Y and X using the new values in Ysub and Xsub
        OverwriteCols(Y, Ysub, non_opt_col_indices, non_opt_col_indices.size());
        OverwriteCols(X, Xsub, non_opt_col_indices, non_opt_col_indices.size());

        ZeroizeSmallValues(X, 1.0e-12);
        ZeroizeSmallValues(Y, 1.0e-12);

        // Check optimality - BppUpdateSets does the equivalent of the next two lines.
        // nonopt_set = not_opt_mask & (Y < T(0)) & ~passive_set;
        // infeas_set = not_opt_mask & (X < T(0)) & passive_set;
        BppUpdateSets(nonopt_set, infeas_set, not_opt_mask, X, Y, passive_set);

        nonopt_set.SumColumns(not_good);
        infeas_set.SumColumns(col_sums);
        not_good += col_sums;
        not_opt_cols = (not_good > 0);
        not_opt_cols.Find(non_opt_col_indices);

        ++iter;
    }

    return true;
}
예제 #18
0
void VisualizationSceneVector3d::Prepare()
{
   int i,j;

   switch (shading)
   {
   case 0:
      PrepareFlat();
      return;
   case 2:
      PrepareFlat2();
      return;
   default:
      break;
   }

   glNewList(displlist, GL_COMPILE);

   int ne = mesh -> GetNBE();
   int nv = mesh -> GetNV();
   DenseMatrix pointmat;
   Array<int> vertices;
   double nor[3];

   Vector nx(nv);
   Vector ny(nv);
   Vector nz(nv);

   for (int d = 0; d < mesh -> bdr_attributes.Size(); d++)
   {
      if (!bdr_attr_to_show[mesh -> bdr_attributes[d]-1]) continue;

      nx=0.;
      ny=0.;
      nz=0.;

      for (i = 0; i < ne; i++)
         if (mesh -> GetBdrAttribute(i) == mesh -> bdr_attributes[d])
         {
            mesh->GetBdrPointMatrix (i, pointmat);
            mesh->GetBdrElementVertices (i, vertices);

            for (j = 0; j < pointmat.Size(); j++)
            {
               pointmat(0, j) += (*solx)(vertices[j])*(ianim)/ianimmax;
               pointmat(1, j) += (*soly)(vertices[j])*(ianim)/ianimmax;
               pointmat(2, j) += (*solz)(vertices[j])*(ianim)/ianimmax;
            }

            if (pointmat.Width() == 3)
               j = Compute3DUnitNormal(&pointmat(0,0), &pointmat(0,1),
                                       &pointmat(0,2), nor);
            else
               j = Compute3DUnitNormal(&pointmat(0,0), &pointmat(0,1),
                                       &pointmat(0,2), &pointmat(0,3), nor);
            if (j == 0)
               for (j = 0; j < pointmat.Size(); j++)
               {
                  nx(vertices[j]) += nor[0];
                  ny(vertices[j]) += nor[1];
                  nz(vertices[j]) += nor[2];
               }
         }

      for (i = 0; i < ne; i++)
         if (mesh -> GetBdrAttribute(i) == mesh -> bdr_attributes[d])
         {
            switch (mesh->GetBdrElementType(i))
            {
            case Element::TRIANGLE:
               glBegin (GL_TRIANGLES);
               break;

            case Element::QUADRILATERAL:
               glBegin (GL_QUADS);
               break;
            }
            mesh->GetBdrPointMatrix (i, pointmat);
            mesh->GetBdrElementVertices (i, vertices);
            for (j = 0; j < pointmat.Size(); j++)
            {
               pointmat(0, j) += (*solx)(vertices[j])*(ianim)/ianimmax;
               pointmat(1, j) += (*soly)(vertices[j])*(ianim)/ianimmax;
               pointmat(2, j) += (*solz)(vertices[j])*(ianim)/ianimmax;
            }
            for (j = 0; j < pointmat.Size(); j++)
            {
               MySetColor((*sol)(vertices[j]), minv, maxv);
               glNormal3d(nx(vertices[j]), ny(vertices[j]), nz(vertices[j]));
               glVertex3dv(&pointmat(0, j));
            }
            glEnd();
         }
   }
   glEndList();
}
예제 #19
0
bool SolveNormalEqLeft(const DenseMatrix<T>& LHS, // kxk
                       const DenseMatrix<T>& RHS, // mxk
                       DenseMatrix<T>& X)         // mxk
{
    // Solve X * LHS = RHS for X, where LHS is symmetric positive-definite.

    if (LHS.Width() != LHS.Height())
        throw std::logic_error("SolveNormalEqLeft: expected square matrix on LHS");
    if ( (X.Width() != LHS.Height()) || (X.Height() != RHS.Height()))
        throw std::logic_error("SolveNormalEqLeft: non-conformant matrix X");
    
    // // copy the input, since the solver overwrites it
    DenseMatrix<T> U(LHS);

    // Compute the Cholesky factor LHS = U'U
    bool success = true;
    try
    {
        Cholesky(UPPER, U);
    }
    catch (EL::NonHPSDMatrixException& e)
    {
        std::cerr << "Cholesky factorization failure - ";
        std::cerr << "matrix was not symmetric positive-definite." << std::endl;
        success = false;
    }
    catch (std::logic_error& e)
    {
        std::cerr << "Cholesky factorization failure - ";
        std::cerr << "matrix was not symmetric positive-definite." << std::endl;
        success = false;
    }

    if (!success)
        return false;

    // Solve X (U'U) = RHS as follows:
    //
    // Group the two left matrices:
    // 
    //     (XU') U = RHS
    //
    // Let Y = XU', so the equation becomes:
    //
    //     YU = RHS
    //
    // Do a triangular solve: Y = (RHS) * inverse(U)

    X = RHS;
    Trsm(RIGHT, UPPER, NORMAL, NON_UNIT, T(1), U, X);

    // The solution Y is stored in X.  
    // 
    // Now solve XU' = Y, so X = Y * inverse(U')
    Trsm(RIGHT, UPPER, TRANSPOSE, NON_UNIT, T(1), U, X);

    // check
    // DenseMatrix<T> temp(m, k);
    // Gemm(NORMAL, NORMAL, T(1), X, LHS, T(0), temp);
    // Axpy(-1.0, RHS, temp);
    // double norm = Norm(temp, FROBENIUS_NORM);
    // std::cout << "\tSolveNormalEqLeft: norm = " << norm << std::endl;

    return true;
}
예제 #20
0
파일: coefficient.hpp 프로젝트: LLNL/mfem
 MatrixConstantCoefficient(const DenseMatrix &m)
    : MatrixCoefficient(m.Height(), m.Width()), mat(m) { }