Пример #1
0
void Tikhonov
( Orientation orientation,
  const SparseMatrix<F>& A,
  const Matrix<F>& B,
  const SparseMatrix<F>& G,
        Matrix<F>& X, 
  const LeastSquaresCtrl<Base<F>>& ctrl )
{
    DEBUG_CSE
    
    // Explicitly form W := op(A)
    // ==========================
    SparseMatrix<F> W;
    if( orientation == NORMAL )
        W = A;
    else if( orientation == TRANSPOSE )
        Transpose( A, W );
    else
        Adjoint( A, W );

    const Int m = W.Height();
    const Int n = W.Width();
    const Int numRHS = B.Width();

    // Embed into a higher-dimensional problem via appending regularization
    // ====================================================================
    SparseMatrix<F> WEmb;
    if( m >= n )
        VCat( W, G, WEmb ); 
    else
        HCat( W, G, WEmb );
    Matrix<F> BEmb;
    Zeros( BEmb, WEmb.Height(), numRHS );
    if( m >= n )
    {
        auto BEmbT = BEmb( IR(0,m), IR(0,numRHS) );
        BEmbT = B;
    }
    else
        BEmb = B;

    // Solve the higher-dimensional problem
    // ====================================
    Matrix<F> XEmb;
    LeastSquares( NORMAL, WEmb, BEmb, XEmb, ctrl );

    // Extract the solution
    // ====================
    if( m >= n )
        X = XEmb;
    else
        X = XEmb( IR(0,n), IR(0,numRHS) ); 
}
Пример #2
0
void StackedRuizEquil
( SparseMatrix<Field>& A,
  SparseMatrix<Field>& B,
  Matrix<Base<Field>>& dRowA,
  Matrix<Base<Field>>& dRowB,
  Matrix<Base<Field>>& dCol,
  bool progress )
{
    EL_DEBUG_CSE
    typedef Base<Field> Real;
    const Int mA = A.Height();
    const Int mB = B.Height();
    const Int n = A.Width();
    Ones( dRowA, mA, 1 );
    Ones( dRowB, mB, 1 );
    Ones( dCol, n, 1 );

    // TODO(poulson): Expose these as control parameters
    // For now, simply hard-code the number of iterations
    const Int maxIter = 4;

    Matrix<Real> scales, maxAbsValsB;
    const Int indent = PushIndent();
    for( Int iter=0; iter<maxIter; ++iter )
    {
        // Rescale the columns
        // -------------------
        ColumnMaxNorms( A, scales );
        ColumnMaxNorms( B, maxAbsValsB );
        for( Int j=0; j<n; ++j )
            scales(j) = Max(scales(j),maxAbsValsB(j));
        EntrywiseMap( scales, MakeFunction(DampScaling<Real>) );
        DiagonalScale( LEFT, NORMAL, scales, dCol );
        DiagonalSolve( RIGHT, NORMAL, scales, A );
        DiagonalSolve( RIGHT, NORMAL, scales, B );

        // Rescale the rows
        // ----------------
        RowMaxNorms( A, scales );
        EntrywiseMap( scales, MakeFunction(DampScaling<Real>) );
        DiagonalScale( LEFT, NORMAL, scales, dRowA );
        DiagonalSolve( LEFT, NORMAL, scales, A );

        RowMaxNorms( B, scales );
        EntrywiseMap( scales, MakeFunction(DampScaling<Real>) );
        DiagonalScale( LEFT, NORMAL, scales, dRowB );
        DiagonalSolve( LEFT, NORMAL, scales, B );
    }
    SetIndent( indent );
}
Пример #3
0
void ShiftDiagonal
( SparseMatrix<T>& A, S alphaPre, Int offset, bool existingDiag )
{
    EL_DEBUG_CSE
    const Int m = A.Height();
    const Int n = A.Width();
    const T alpha = T(alphaPre);
    if( existingDiag )
    {
        T* valBuf = A.ValueBuffer();
        for( Int i=Max(0,-offset); i<Min(m,n-offset); ++i )
        {
            const Int e = A.Offset( i, i+offset );
            valBuf[e] += alpha;
        } 
    }
    else
    {
        const Int diagLength = Min(m,n-offset) - Max(0,-offset);
        A.Reserve( diagLength );
        for( Int i=Max(0,-offset); i<Min(m,n-offset); ++i )
            A.QueueUpdate( i, i+offset, alpha );
        A.ProcessQueues();
    }
}
Пример #4
0
void LAV
( const SparseMatrix<Real>& A,
  const Matrix<Real>& b,
        Matrix<Real>& x,
  const lp::affine::Ctrl<Real>& ctrl )
{
    EL_DEBUG_CSE
    const Int m = A.Height();
    const Int n = A.Width();
    const Range<Int> xInd(0,n), uInd(n,n+m), vInd(n+m,n+2*m);
    SparseMatrix<Real> AHat, G;
    Matrix<Real> c, h;

    // c := [0;1;1]
    // ============
    Zeros( c, n+2*m, 1 );
    auto cuv = c( IR(n,n+2*m), ALL );
    Fill( cuv, Real(1) );

    // \hat A := [A, I, -I]
    // ====================
    Zeros( AHat, m, n+2*m );
    const Int numEntriesA = A.NumEntries();
    AHat.Reserve( numEntriesA + 2*m );
    for( Int e=0; e<numEntriesA; ++e )
        AHat.QueueUpdate( A.Row(e), A.Col(e), A.Value(e) );
    for( Int i=0; i<m; ++i )
    {
        AHat.QueueUpdate( i, i+n,   Real( 1) );
        AHat.QueueUpdate( i, i+n+m, Real(-1) );
    }
    AHat.ProcessQueues();

    // G := | 0 -I  0 |
    //      | 0  0 -I |
    // ================
    Zeros( G, 2*m, n+2*m );
    G.Reserve( G.Height() );
    for( Int i=0; i<2*m; ++i )
        G.QueueUpdate( i, i+n, Real(-1) );
    G.ProcessQueues();

    // h := | 0 |
    //      | 0 |
    // ==========
    Zeros( h, 2*m, 1 );

    // Solve the affine linear program
    // ===============================
    Matrix<Real> xHat, y, z, s;
    LP( AHat, G, b, c, h, xHat, y, z, s, ctrl );

    // Extract x
    // =========
    x = xHat( xInd, ALL );
}
Пример #5
0
void Fill( SparseMatrix<T>& A, T alpha )
{
    EL_DEBUG_CSE
    const Int m = A.Height();
    const Int n = A.Width();
    A.Resize( m, n );
    Zero( A );
    if( alpha != T(0) )
    {
        A.Reserve( m*n ); 
        for( Int i=0; i<m; ++i )
            for( Int j=0; j<n; ++j )
                A.QueueUpdate( i, j, alpha );
        A.ProcessQueues();
    }
}
Пример #6
0
void MatrixMarket( const SparseMatrix<T>& A, string basename="matrix" )
{
    EL_DEBUG_CSE
    
    string filename = basename + "." + FileExtension(MATRIX_MARKET);
    ofstream file( filename.c_str(), std::ios::binary );
    if( !file.is_open() )
        RuntimeError("Could not open ",filename);

    // Write the header
    // ================
    {
        ostringstream os;
        os << "%%MatrixMarket matrix coordinate ";
        if( IsComplex<T>::value )
            os << "complex "; 
        else
            os << "real ";
        os << "general\n";
        file << os.str();
    }
    
    // Write the size line
    // ===================
    const Int m = A.Height();
    const Int n = A.Width();
    const Int numNonzeros = A.NumEntries();
    file << BuildString(m," ",n," ",numNonzeros,"\n");
    
    // Write the entries
    // =================
    for( Int e=0; e<numNonzeros; ++e )
    {
        const Int i = A.Row(e);
        const Int j = A.Col(e);
        const T value = A.Value(e);
        if( IsComplex<T>::value )
        {
            file << 
              BuildString(i," ",j," ",RealPart(value)," ",ImagPart(value),"\n");
        }
        else
        {
            file << BuildString(i," ",j," ",RealPart(value),"\n");
        }
    }
}
Пример #7
0
void Lanczos
( const SparseMatrix<F>& A,
        Matrix<Base<F>>& T,
        Int basisSize )
{
    DEBUG_CSE
    const Int n = A.Height();
    if( n != A.Width() )
        LogicError("A was not square");
    
    auto applyA =
      [&]( const Matrix<F>& X, Matrix<F>& Y )
      {
          Zeros( Y, n, X.Width() );
          Multiply( NORMAL, F(1), A, X, F(0), Y );
      };
    Lanczos<F>( n, applyA, T, basisSize );
}
Пример #8
0
bool WriteMatrixMarketFile(const std::string& file_path,
                           const SparseMatrix<T>& A,
                           const unsigned int precision)
{
    // Write a MatrixMarket file with no comments.  Note that the
    // MatrixMarket format uses 1-based indexing for rows and columns.

    std::ofstream outfile(file_path);
    if (!outfile)
        return false;

    unsigned int height = A.Height();
    unsigned int width  = A.Width();
    unsigned int nnz    = A.Size();
    
    // write the 'banner'
    outfile << MM_BANNER << " matrix coordinate real general" << std::endl;

    // write matrix dimensions and number of nonzeros
    outfile << height << " " << width << " " << nnz << std::endl;

    outfile << std::fixed;
    outfile.precision(precision);
    
    const unsigned int* cols_a = A.LockedColBuffer();
    const unsigned int* rows_a = A.LockedRowBuffer();
    const T*            data_a = A.LockedDataBuffer();
    unsigned int width_a = A.Width();

    for (unsigned int c=0; c != width_a; ++c)
    {
        unsigned int start = cols_a[c];
        unsigned int end   = cols_a[c+1];
        for (unsigned int offset=start; offset != end; ++offset)
        {
            unsigned int r = rows_a[offset];
            T val = data_a[offset];
            outfile << r+1 << " " << c+1 << " " << val << std::endl;
        }
    }

    outfile.close();
    return true;
}
Пример #9
0
void RowMaxNorms( const SparseMatrix<F>& A, Matrix<Base<F>>& norms )
{
    DEBUG_CSE
    typedef Base<F> Real;
    const Int m = A.Height();
    const F* valBuf = A.LockedValueBuffer();
    const Int* offsetBuf = A.LockedOffsetBuffer();

    norms.Resize( m, 1 );
    for( Int i=0; i<m; ++i )
    {
        Real rowMax = 0;
        const Int offset = offsetBuf[i];
        const Int numConn = offsetBuf[i+1] - offset;
        for( Int e=offset; e<offset+numConn; ++e )
            rowMax = Max(rowMax,Abs(valBuf[e]));
        norms(i) = rowMax;
    }
}
Пример #10
0
Base<Field> ProductLanczosDecomp
( const SparseMatrix<Field>& A,
        Matrix<Field>& V,
        Matrix<Base<Field>>& T,
        Matrix<Field>& v,
        Int basisSize )
{
    EL_DEBUG_CSE
    const Int m = A.Height();
    const Int n = A.Width();

    Matrix<Field> S;

    // Cache the adjoint
    // -----------------
    SparseMatrix<Field> AAdj;
    Adjoint( A, AAdj );

    if( m >= n )
    {
        auto applyA =
          [&]( const Matrix<Field>& X, Matrix<Field>& Y )
          {
              Zeros( S, m, X.Width() );
              Multiply( NORMAL, Field(1), A,    X, Field(0), S );
              Zeros( Y, n, X.Width() );
              Multiply( NORMAL, Field(1), AAdj, S, Field(0), Y );
          };
        return LanczosDecomp( n, applyA, V, T, v, basisSize );
    }
    else
    {
        auto applyA =
          [&]( const Matrix<Field>& X, Matrix<Field>& Y )
          {
              Zeros( S, n, X.Width() );
              Multiply( NORMAL, Field(1), AAdj, X, Field(0), S );
              Zeros( Y, m, X.Width() );
              Multiply( NORMAL, Field(1), A,    S, Field(0), Y );
          };
        return LanczosDecomp( m, applyA, V, T, v, basisSize );
    }
}
Пример #11
0
Base<Field> LanczosDecomp
( const SparseMatrix<Field>& A,
        Matrix<Field>& V,
        Matrix<Base<Field>>& T,
        Matrix<Field>& v,
        Int basisSize )
{
    EL_DEBUG_CSE
    const Int n = A.Height();
    if( n != A.Width() )
        LogicError("A was not square");

    auto applyA =
      [&]( const Matrix<Field>& X, Matrix<Field>& Y )
      {
          Zeros( Y, n, X.Width() );
          Multiply( NORMAL, Field(1), A, X, Field(0), Y );
      };
    return LanczosDecomp( n, applyA, V, T, v, basisSize );
}
Пример #12
0
void RowTwoNorms( const SparseMatrix<F>& A, Matrix<Base<F>>& norms )
{
    DEBUG_CSE
    typedef Base<F> Real;
    const Int m = A.Height();
    const F* valBuf = A.LockedValueBuffer();
    const Int* offsetBuf = A.LockedOffsetBuffer();

    norms.Resize( m, 1 );
    for( Int i=0; i<m; ++i )
    {
        Real scale = 0;
        Real scaledSquare = 1;
        const Int offset = offsetBuf[i];
        const Int numConn = offsetBuf[i+1] - offset;
        for( Int e=offset; e<offset+numConn; ++e )
            UpdateScaledSquare( valBuf[e], scale, scaledSquare );
        norms(i) = scale*Sqrt(scaledSquare);
    }
}
Пример #13
0
void GetMappedDiagonal
( const SparseMatrix<T>& A,
        Matrix<S>& d,
        function<S(const T&)> func,
        Int offset )
{
    EL_DEBUG_CSE
    const Int m = A.Height();
    const Int n = A.Width();
    const T* valBuf = A.LockedValueBuffer();
    const Int* colBuf = A.LockedTargetBuffer();

    const Int iStart = Max(-offset,0);
    const Int jStart = Max( offset,0);

    const Int diagLength = El::DiagonalLength(m,n,offset);
    d.Resize( diagLength, 1 );
    Zero( d );
    S* dBuf = d.Buffer();

    for( Int k=0; k<diagLength; ++k )
    {
        const Int i = iStart + k;
        const Int j = jStart + k;
        const Int thisOff = A.RowOffset(i);
        const Int nextOff = A.RowOffset(i+1);
        auto it = std::lower_bound( colBuf+thisOff, colBuf+nextOff, j );
        if( *it == j )
        {
            const Int e = it-colBuf;
            dBuf[Min(i,j)] = func(valBuf[e]);
        }
        else
            dBuf[Min(i,j)] = func(0);
    }
}
Пример #14
0
void SymmetricRuizEquil
( SparseMatrix<F>& A, 
  Matrix<Base<F>>& d,
  Int maxIter, bool progress )
{
    DEBUG_CSE
    typedef Base<F> Real;
    const Int n = A.Height();
    Ones( d, n, 1 );

    Matrix<Real> scales;
    const Int indent = PushIndent();
    for( Int iter=0; iter<maxIter; ++iter )
    {
        // Rescale the columns (and rows)
        // ------------------------------
        ColumnMaxNorms( A, scales );
        EntrywiseMap( scales, function<Real(Real)>(DampScaling<Real>) );
        EntrywiseMap( scales, function<Real(Real)>(SquareRootScaling<Real>) );
        DiagonalScale( LEFT, NORMAL, scales, d );
        SymmetricDiagonalSolve( scales, A );
    }
    SetIndent( indent );
}
Пример #15
0
Файл: ex2.cpp Проект: LLNL/mfem
int main(int argc, char *argv[])
{
   // 1. Parse command-line options.
   const char *mesh_file = "../data/beam-tri.mesh";
   int order = 1;
   bool static_cond = false;
   bool visualization = 1;

   OptionsParser args(argc, argv);
   args.AddOption(&mesh_file, "-m", "--mesh",
                  "Mesh file to use.");
   args.AddOption(&order, "-o", "--order",
                  "Finite element order (polynomial degree).");
   args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
                  "--no-static-condensation", "Enable static condensation.");
   args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
                  "--no-visualization",
                  "Enable or disable GLVis visualization.");
   args.Parse();
   if (!args.Good())
   {
      args.PrintUsage(cout);
      return 1;
   }
   args.PrintOptions(cout);

   // 2. Read the mesh from the given mesh file. We can handle triangular,
   //    quadrilateral, tetrahedral or hexahedral elements with the same code.
   Mesh *mesh = new Mesh(mesh_file, 1, 1);
   int dim = mesh->Dimension();

   if (mesh->attributes.Max() < 2 || mesh->bdr_attributes.Max() < 2)
   {
      cerr << "\nInput mesh should have at least two materials and "
           << "two boundary attributes! (See schematic in ex2.cpp)\n"
           << endl;
      return 3;
   }

   // 3. Select the order of the finite element discretization space. For NURBS
   //    meshes, we increase the order by degree elevation.
   if (mesh->NURBSext)
   {
      mesh->DegreeElevate(order, order);
   }

   // 4. Refine the mesh to increase the resolution. In this example we do
   //    'ref_levels' of uniform refinement. We choose 'ref_levels' to be the
   //    largest number that gives a final mesh with no more than 5,000
   //    elements.
   {
      int ref_levels =
         (int)floor(log(5000./mesh->GetNE())/log(2.)/dim);
      for (int l = 0; l < ref_levels; l++)
      {
         mesh->UniformRefinement();
      }
   }

   // 5. Define a finite element space on the mesh. Here we use vector finite
   //    elements, i.e. dim copies of a scalar finite element space. The vector
   //    dimension is specified by the last argument of the FiniteElementSpace
   //    constructor. For NURBS meshes, we use the (degree elevated) NURBS space
   //    associated with the mesh nodes.
   FiniteElementCollection *fec;
   FiniteElementSpace *fespace;
   if (mesh->NURBSext)
   {
      fec = NULL;
      fespace = mesh->GetNodes()->FESpace();
   }
   else
   {
      fec = new H1_FECollection(order, dim);
      fespace = new FiniteElementSpace(mesh, fec, dim);
   }
   cout << "Number of finite element unknowns: " << fespace->GetTrueVSize()
        << endl << "Assembling: " << flush;

   // 6. Determine the list of true (i.e. conforming) essential boundary dofs.
   //    In this example, the boundary conditions are defined by marking only
   //    boundary attribute 1 from the mesh as essential and converting it to a
   //    list of true dofs.
   Array<int> ess_tdof_list, ess_bdr(mesh->bdr_attributes.Max());
   ess_bdr = 0;
   ess_bdr[0] = 1;
   fespace->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);

   // 7. Set up the linear form b(.) which corresponds to the right-hand side of
   //    the FEM linear system. In this case, b_i equals the boundary integral
   //    of f*phi_i where f represents a "pull down" force on the Neumann part
   //    of the boundary and phi_i are the basis functions in the finite element
   //    fespace. The force is defined by the VectorArrayCoefficient object f,
   //    which is a vector of Coefficient objects. The fact that f is non-zero
   //    on boundary attribute 2 is indicated by the use of piece-wise constants
   //    coefficient for its last component.
   VectorArrayCoefficient f(dim);
   for (int i = 0; i < dim-1; i++)
   {
      f.Set(i, new ConstantCoefficient(0.0));
   }
   {
      Vector pull_force(mesh->bdr_attributes.Max());
      pull_force = 0.0;
      pull_force(1) = -1.0e-2;
      f.Set(dim-1, new PWConstCoefficient(pull_force));
   }

   LinearForm *b = new LinearForm(fespace);
   b->AddBoundaryIntegrator(new VectorBoundaryLFIntegrator(f));
   cout << "r.h.s. ... " << flush;
   b->Assemble();

   // 8. Define the solution vector x as a finite element grid function
   //    corresponding to fespace. Initialize x with initial guess of zero,
   //    which satisfies the boundary conditions.
   GridFunction x(fespace);
   x = 0.0;

   // 9. Set up the bilinear form a(.,.) on the finite element space
   //    corresponding to the linear elasticity integrator with piece-wise
   //    constants coefficient lambda and mu.
   Vector lambda(mesh->attributes.Max());
   lambda = 1.0;
   lambda(0) = lambda(1)*50;
   PWConstCoefficient lambda_func(lambda);
   Vector mu(mesh->attributes.Max());
   mu = 1.0;
   mu(0) = mu(1)*50;
   PWConstCoefficient mu_func(mu);

   BilinearForm *a = new BilinearForm(fespace);
   a->AddDomainIntegrator(new ElasticityIntegrator(lambda_func,mu_func));

   // 10. Assemble the bilinear form and the corresponding linear system,
   //     applying any necessary transformations such as: eliminating boundary
   //     conditions, applying conforming constraints for non-conforming AMR,
   //     static condensation, etc.
   cout << "matrix ... " << flush;
   if (static_cond) { a->EnableStaticCondensation(); }
   a->Assemble();

   SparseMatrix A;
   Vector B, X;
   a->FormLinearSystem(ess_tdof_list, x, *b, A, X, B);
   cout << "done." << endl;

   cout << "Size of linear system: " << A.Height() << endl;

#ifndef MFEM_USE_SUITESPARSE
   // 11. Define a simple symmetric Gauss-Seidel preconditioner and use it to
   //     solve the system Ax=b with PCG.
   GSSmoother M(A);
   PCG(A, M, B, X, 1, 500, 1e-8, 0.0);
#else
   // 11. If MFEM was compiled with SuiteSparse, use UMFPACK to solve the system.
   UMFPackSolver umf_solver;
   umf_solver.Control[UMFPACK_ORDERING] = UMFPACK_ORDERING_METIS;
   umf_solver.SetOperator(A);
   umf_solver.Mult(B, X);
#endif

   // 12. Recover the solution as a finite element grid function.
   a->RecoverFEMSolution(X, *b, x);

   // 13. For non-NURBS meshes, make the mesh curved based on the finite element
   //     space. This means that we define the mesh elements through a fespace
   //     based transformation of the reference element. This allows us to save
   //     the displaced mesh as a curved mesh when using high-order finite
   //     element displacement field. We assume that the initial mesh (read from
   //     the file) is not higher order curved mesh compared to the chosen FE
   //     space.
   if (!mesh->NURBSext)
   {
      mesh->SetNodalFESpace(fespace);
   }

   // 14. Save the displaced mesh and the inverted solution (which gives the
   //     backward displacements to the original grid). This output can be
   //     viewed later using GLVis: "glvis -m displaced.mesh -g sol.gf".
   {
      GridFunction *nodes = mesh->GetNodes();
      *nodes += x;
      x *= -1;
      ofstream mesh_ofs("displaced.mesh");
      mesh_ofs.precision(8);
      mesh->Print(mesh_ofs);
      ofstream sol_ofs("sol.gf");
      sol_ofs.precision(8);
      x.Save(sol_ofs);
   }

   // 15. Send the above data by socket to a GLVis server. Use the "n" and "b"
   //     keys in GLVis to visualize the displacements.
   if (visualization)
   {
      char vishost[] = "localhost";
      int  visport   = 19916;
      socketstream sol_sock(vishost, visport);
      sol_sock.precision(8);
      sol_sock << "solution\n" << *mesh << x << flush;
   }

   // 16. Free the used memory.
   delete a;
   delete b;
   if (fec)
   {
      delete fespace;
      delete fec;
   }
   delete mesh;

   return 0;
}
Пример #16
0
void IPM
( const SparseMatrix<Real>& A,
  const Matrix<Real>& b, 
        Real lambda,
        Matrix<Real>& x,
  const qp::affine::Ctrl<Real>& ctrl )
{
    DEBUG_CSE
    const Int m = A.Height();
    const Int n = A.Width();
    const Range<Int> uInd(0,n), vInd(n,2*n), rInd(2*n,2*n+m);
    SparseMatrix<Real> Q, AHat, G;
    Matrix<Real> c, h;

    // Q := | 0 0 0 |
    //      | 0 0 0 |
    //      | 0 0 I |
    // ==============
    Zeros( Q, 2*n+m, 2*n+m );
    Q.Reserve( m );
    for( Int e=0; e<m; ++e )
        Q.QueueUpdate( 2*n+e, 2*n+e, Real(1) );
    Q.ProcessQueues();

    // c := lambda*[1;1;0]
    // ===================
    Zeros( c, 2*n+m, 1 );
    auto cuv = c( IR(0,2*n), ALL );
    Fill( cuv, lambda );

    // \hat A := [A, -A, I]
    // ====================
    const Int numEntriesA = A.NumEntries();
    Zeros( AHat, m, 2*n+m );
    AHat.Reserve( 2*numEntriesA+m );
    for( Int e=0; e<numEntriesA; ++e )
    {
        AHat.QueueUpdate( A.Row(e), A.Col(e),    A.Value(e) );
        AHat.QueueUpdate( A.Row(e), A.Col(e)+n, -A.Value(e) );
    }
    for( Int e=0; e<m; ++e )
        AHat.QueueUpdate( e, e+2*n, Real(1) );
    AHat.ProcessQueues();

    // G := | -I  0 0 |
    //      |  0 -I 0 |
    // ================
    Zeros( G, 2*n, 2*n+m );
    G.Reserve( 2*m );
    for( Int e=0; e<2*m; ++e )
        G.QueueUpdate( e, e, Real(-1) );
    G.ProcessQueues();

    // h := 0
    // ======
    Zeros( h, 2*n, 1 );

    // Solve the affine QP
    // ===================
    Matrix<Real> xHat, y, z, s;
    QP( Q, AHat, G, b, c, h, xHat, y, z, s, ctrl );

    // x := u - v
    // ==========
    x = xHat( uInd, ALL );
    x -= xHat( vInd, ALL );
}
Пример #17
0
//-----------------------------------------------------------------------------
void Nmf(const unsigned int kval, 
         const Algorithm algorithm,
         const std::string& csv_file_w,
         const std::string& csv_file_h)
{
    if (!matrix_loaded)
        throw std::logic_error("smallk error (NMF): no matrix has been loaded.");

    if (max_iter < min_iter)
        throw std::logic_error("smallk error (NMF): min_iterations exceeds max_iterations.");

    if (0 == kval)
        throw std::logic_error("smallk error (NMF): k must be greater than 0.");

    // Check the sizes of matrix W(m, k) and matrix H(k, n) and make sure 
    // they don't overflow Elemental's default signed int index type.

    if (!SizeCheck<int>(m, kval))
        throw std::logic_error("smallk error (Nmf): mxk matrix W is too large.");
    
    if (!SizeCheck<int>(kval, n))
        throw std::logic_error("smallk error (Nmf): kxn matrix H is too large.");

    k = kval;

    // convert to the 'NmfAlgorithm' type in nmf.hpp
    switch (algorithm)
    {
    case Algorithm::MU:
        nmf_opts.algorithm = NmfAlgorithm::MU;
        break;
    case Algorithm::HALS:
        nmf_opts.algorithm = NmfAlgorithm::HALS;
        break;
    case Algorithm::RANK2:
        nmf_opts.algorithm = NmfAlgorithm::RANK2;
        break;
    case Algorithm::BPP:
        nmf_opts.algorithm = NmfAlgorithm::BPP;
        break;
    default:
        throw std::logic_error("smallk error (NMF): unknown NMF algorithm.");
    }

    // set k == 2 for Rank2 algorithm
    if (NmfAlgorithm::RANK2 == nmf_opts.algorithm)
        k = 2;

    ldim_w = m;
    ldim_h = k;

    if (buf_w.size() < m*k)
        buf_w.resize(m*k);
    if (buf_h.size() < k*n)
        buf_h.resize(k*n);
    
    // initialize matrices W and H
    bool ok;
    unsigned int height_w = m, width_w = k, height_h = k, width_h = n;

    cout << "Initializing matrix W..." << endl;
    if (csv_file_w.empty())
        ok = RandomMatrix(&buf_w[0], ldim_w, m, k, rng);
    else
        ok = LoadDelimitedFile(buf_w, height_w, width_w, csv_file_w);
    if (!ok)
    {
        std::ostringstream msg;
        msg << "smallk error (Nmf): load failed for file ";
        msg << "\"" << csv_file_w << "\"";
        throw std::runtime_error(msg.str());
    }

    if ( (height_w != m) || (width_w != k))
    {
        cerr << "\tdimensions of matrix W are " << height_w
             << " x " << width_w << endl;
        cerr << "\texpected " << m << " x " << k << endl;
        throw std::logic_error("smallk error (Nmf): non-conformant matrix W.");
    }

    cout << "Initializing matrix H..." << endl;
    if (csv_file_h.empty())
        ok = RandomMatrix(&buf_h[0], ldim_h, k, n, rng);
    else
        ok = LoadDelimitedFile(buf_h, height_h, width_h, csv_file_h);

    if (!ok)
    {
        std::ostringstream msg;
        msg << "smallk error (Nmf): load failed for file ";
        msg << "\"" << csv_file_h << "\"";
        throw std::runtime_error(msg.str());
    }
    
    if ( (height_h != k) || (width_h != n))
    {
        cerr << "\tdimensions of matrix H are " << height_h
             << " x " << width_h << endl;
        cerr << "\texpected " << k << " x " << n << endl;
        throw std::logic_error("smallk error (Nmf): non-conformant matrix H.");
    }    

    // The ratio of projected gradient norms doesn't seem to work very well
    // with MU.  We frequently observe a 'leveling off' behavior and the 
    // convergence is even slower than usual.  So for MU use the relative
    // change in the Frobenius norm of W as the stopping criterion, which
    // always seems to behave well, even though it is on shaky theoretical
    // ground.

    if (NmfAlgorithm::MU == nmf_opts.algorithm)
        nmf_opts.prog_est_algorithm = NmfProgressAlgorithm::DELTA_FNORM;
    else
        nmf_opts.prog_est_algorithm = NmfProgressAlgorithm::PG_RATIO;

    nmf_opts.tol         = nmf_tolerance;
    nmf_opts.height      = m;
    nmf_opts.width       = n;
    nmf_opts.k           = k;
    nmf_opts.min_iter    = min_iter;
    nmf_opts.max_iter    = max_iter;
    nmf_opts.tolcount    = 1;
    nmf_opts.max_threads = max_threads;
    nmf_opts.verbose     = true;
    nmf_opts.normalize   = true;

    // display all params to user
    PrintNmfOpts(nmf_opts);

    NmfStats stats;
    Result result;
    if (is_sparse)
    {
        result = NmfSparse(nmf_opts, 
                           A.Height(), A.Width(), A.Size(),
                           A.LockedColBuffer(),
                           A.LockedRowBuffer(),
                           A.LockedDataBuffer(),
                           &buf_w[0], ldim_w,
                           &buf_h[0], ldim_h,
                           stats);
    }
    else
    {
        result = Nmf(nmf_opts,
                     &buf_a[0], ldim_a,
                     &buf_w[0], ldim_w,
                     &buf_h[0], ldim_h,
                     stats);
    }

    cout << "Elapsed wall clock time: ";
    cout << ElapsedTime(stats.elapsed_us) << endl;
    cout << endl;

    if (Result::OK != result)
        throw std::runtime_error("smallk error (Nmf): NMF solver failure.");

    // write the computed W and H factors to disk

    std::string outfile_w, outfile_h;
    if (outdir.empty())
    {
        outfile_w = DEFAULT_FILENAME_W;
        outfile_h = DEFAULT_FILENAME_H;
    }
    else
    {
        outfile_w = outdir + DEFAULT_FILENAME_W;
        outfile_h = outdir + DEFAULT_FILENAME_H;
    }

    cout << "Writing output files..." << endl;
    
    if (!WriteDelimitedFile(&buf_w[0], ldim_w, m, k, outfile_w, outprecision))
        throw std::runtime_error("smallk error (Nmf): could not write W result.");
    
    if (!WriteDelimitedFile(&buf_h[0], ldim_h, k, n, outfile_h, outprecision))
        throw std::runtime_error("smallk error (Nmf): could not write H result.");
}
Пример #18
0
void SparseMatrix<T>::SubMatrixColsCompact(SparseMatrix<T>& result,
                                           const std::vector<unsigned int>& col_indices,
                                           std::vector<unsigned int>& old_to_new_rows,
                                           std::vector<unsigned int>& new_to_old_rows) const
{
    const unsigned int UNUSED_ROW = 0xFFFFFFFF;

    // extract entire columns from the source matrix to form the dest matrix

    unsigned int new_width = col_indices.size();
    if (0u == new_width)
        throw std::logic_error("SparseMatrix::SubMatrixColsCompact: empty column set");
    
    // need one entry per original row in the row_map
    if (old_to_new_rows.size() < height_)
        old_to_new_rows.resize(height_);

    std::fill(old_to_new_rows.begin(), old_to_new_rows.begin() + height_, UNUSED_ROW);
    // no need to fill 'new_to_old_rows'

    // check the column indices for validty and count nonzeros

    unsigned int new_size = 0;
    for (auto it=col_indices.begin(); it != col_indices.end(); ++it)
    {
        // index of next source column
        unsigned int c = *it;
        if (c >= width_)
            throw std::logic_error("SparseMatrix::SubMatrixColsCompact: column index out of range");
        
        // number of nonzeros in source column c
        new_size += (col_offsets_[c+1] - col_offsets_[c]);
    }

    if (0u == new_size)
        throw std::logic_error("SparseMatrix::SubMatrixColsCompact: submatrix is the zero matrix");

    // allocate memory in the result; won't allocate if sufficient memory available
    result.Reserve(height_, new_width, new_size);

    unsigned int* cols_b = result.ColBuffer();
    unsigned int* rows_b = result.RowBuffer();
    T* data_b            = result.DataBuffer();

    unsigned int c_dest = 0;
    unsigned int elt_count = 0;
    for (auto it=col_indices.begin(); it != col_indices.end(); ++it)
    {
        // index of the next source column
        unsigned int c = *it;

        // set element offset for the next dest column
        cols_b[c_dest] = elt_count;

        unsigned int start = col_offsets_[c];
        unsigned int end   = col_offsets_[c+1];
        for (unsigned int offset = start; offset != end; ++offset)
        {
            unsigned int row = row_indices_[offset];
            old_to_new_rows[row] = row;
            rows_b[elt_count] = row;
            data_b[elt_count] = data_[offset];
            ++elt_count;
        }

        // have now completed another column
        ++c_dest;
    }

    cols_b[new_width] = elt_count;
    assert(new_width == c_dest);

    // set the size of the new matrix explicitly, since Load() has been bypassed
    result.SetSize(elt_count);

    // determine the new height of the submatrix
    unsigned int new_height = 0;
    for (unsigned int r=0; r != height_; ++r)
    {
        if (UNUSED_ROW != old_to_new_rows[r])
            ++new_height;
    }
    
    new_to_old_rows.resize(new_height);

    // renumber the rows in the submatrix

    unsigned int new_r = 0;
    for (unsigned int r=0; r<height_; ++r)
    {
        if (UNUSED_ROW != old_to_new_rows[r])
        {
            old_to_new_rows[r] = new_r;
            new_to_old_rows[new_r] = r;
            ++new_r;
        }
    }

    // set the height of the new matrix explicitly
    assert(new_r == new_height);
    result.SetHeight(new_height);

    // re-index the rows in the submatrix 
    for (unsigned int s=0; s != elt_count; ++s)
    {
        unsigned int old_row_index = rows_b[s];
        rows_b[s] = old_to_new_rows[old_row_index];
    }

    assert(result.Height() == new_height);
    assert(new_to_old_rows.size() == new_height);
    assert(old_to_new_rows.size() == height_);
}
Пример #19
0
//-----------------------------------------------------------------------------
int main(int argc, char* argv[])
{
    Timer timer;
    double elapsed_s;

    // print usage info if no command line args were specified
    std::string prog_name(argv[0]);
    if (1 == argc)
    {
        PrintUsage(prog_name);
        return 0;
    }

    CommandLineOptions opts;
    ParseCommandLine(argc, argv, opts);
    if (!IsValid(opts))
        return -1;

    //
    // Check to see if the specified directories exist.
    //

    if (!DirectoryExists(opts.indir))
    {
        cerr << "\npreprocessor: the specified input directory "
             << opts.indir << " does not exist." << endl;
        return -1;
    }

    if (!opts.outdir.empty())
    {
        if (!DirectoryExists(opts.outdir))
        {
            cerr << "\npreprocessor: the specified output directory "
                 << opts.outdir << " does not exist." << endl;
            return -1;
        }
    }

    // setup paths and filenames
    std::string inputdir  = EnsureTrailingPathSep(opts.indir);
    std::string infile = inputdir + std::string("matrix.mtx");
    std::string indict = inputdir + std::string("dictionary.txt");
    std::string indocs = inputdir + std::string("documents.txt");

    std::string outputdir, outfile, outdict, outdocs;
    if (!opts.outdir.empty())
    {
        outputdir = EnsureTrailingPathSep(opts.outdir);
        outfile = outputdir + std::string("reduced_matrix.mtx");
        outdict = outputdir + std::string("reduced_dictionary.txt");
        outdocs = outputdir + std::string("reduced_documents.txt");
    }
    else
    {
        outfile = std::string("reduced_matrix.mtx");
        outdict = std::string("reduced_dictionary.txt");
        outdocs = std::string("reduced_documents.txt");
    }

    //
    // load the input dictionary and documents
    //
    std::vector<std::string> dictionary, documents;

    if (!LoadStringsFromFile(indict, dictionary))
    {
        cerr << "\npreprocessor: could not open dictionary file " 
             << indict << endl;
        return -1;
    }
    
    unsigned int num_terms = dictionary.size();

    if (!LoadStringsFromFile(indocs, documents))
    {
        cerr << "\npreprocessor: could not open documents file "
             << indocs << endl;
        return -1;
    }

    unsigned int num_docs = documents.size();

    // print options to screen prior to run
    opts.indir = inputdir;
    if (outputdir.empty())
        opts.outdir = std::string("current directory");
    else
        opts.outdir = outputdir;
    PrintOpts(opts);

    bool boolean_mode = (0 != opts.boolean_mode);
    
    SparseMatrix<double> A;
    unsigned int height, width, nonzeros;

    //
    // load the input matrix
    //

    cout << "Loading input matrix " << infile << endl;
    timer.Start();
    if (!LoadMatrixMarketFile(infile, A, height, width, nonzeros))
    {
        cerr << "\npreprocessor: could not load file " << infile << endl;
        return -1;
    }
    timer.Stop();
    elapsed_s = static_cast<double>(timer.ReportMilliseconds() * 0.001);
    cout << "\tInput file load time: " << elapsed_s << "s." << endl;

    //
    // check num_terms and num_docs
    //

    if (num_terms < A.Height())
    {
        cerr << "\npreprocessor error: expected " << A.Height() 
             << " terms in the dictionary; found " << num_terms << "." << endl;
        return -1;
    }

    if (num_docs < A.Width())
    {
        cerr << "\npreprocessor error: expected " << A.Width()
             << " strings in the documents file; found " << num_docs
             << "." << endl;
        return -1;
    }

    //
    // do the preprocessing
    //

    timer.Start();

    TermFrequencyMatrix  M(A, boolean_mode);

    // allocate the index sets for the terms and docs
    std::vector<unsigned int> term_indices(height);
    std::vector<unsigned int> doc_indices(width);
    std::vector<double> scores;
  
    bool ok = preprocess_tf(M, term_indices, doc_indices, scores,
                            opts.max_iter, opts.docs_per_term, opts.terms_per_doc);
    timer.Stop();
    elapsed_s = static_cast<double>(timer.ReportMilliseconds() * 0.001);
    cout << "Processing time: " << elapsed_s << "s." << endl;
    cout << endl;

    if (!ok)
    {
        cerr << "\npreprocessor: matrix has dimension zero." << endl;
        cerr << "no output files will be written" << endl;
        return false;
    }

    //
    // write the result matrix to disk
    //

    cout << "Writing output matrix " << outfile << endl;
    timer.Start();
    if (!M.WriteMtxFile(outfile, &scores[0], opts.precision))
    {
        cerr << "\npreprocessor: could not write file " 
             << outfile << endl;
        return -1;
    }
    timer.Stop();
    elapsed_s = static_cast<double>(timer.ReportMilliseconds() * 0.001);
    cout << "Output file write time: " << elapsed_s << "s." << endl;

    //
    // write the reduced dictionary and documents to disk
    //
    cout << "Writing dictionary file " << outdict << endl;
    timer.Start();
    if (!WriteStringsToFile(outdict, dictionary, term_indices, M.Height()))
    {
        cerr << "\npreprocessor: could not write file "
             << outdict << endl;
    }
    timer.Stop();
    elapsed_s = static_cast<double>(timer.ReportMilliseconds() * 0.001);
    
    cout << "Writing documents file " << outdocs << endl;
    timer.Start();
    if (!WriteStringsToFile(outdocs, documents, doc_indices, M.Width()))
    {
        cerr << "\npreprocessor: could not write file "
             << outdocs << endl;
    }
    timer.Stop();
    elapsed_s += static_cast<double>(timer.ReportMilliseconds() * 0.001);
    cout << "Dictionary + documents write time: " << elapsed_s << "s." << endl;    

    return 0;
}
Пример #20
0
int main(int argc, char *argv[])
{
   // 1. Parse command-line options.
   const char *mesh_file = "../../data/fichera.mesh";
   int order = sol_p;
   bool static_cond = false;
   bool visualization = 1;
   bool perf = true;

   OptionsParser args(argc, argv);
   args.AddOption(&mesh_file, "-m", "--mesh",
                  "Mesh file to use.");
   args.AddOption(&order, "-o", "--order",
                  "Finite element order (polynomial degree) or -1 for"
                  " isoparametric space.");
   args.AddOption(&perf, "-perf", "--hpc-version", "-std", "--standard-version",
                  "Enable high-performance, tensor-based, assembly.");
   args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
                  "--no-static-condensation", "Enable static condensation.");
   args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
                  "--no-visualization",
                  "Enable or disable GLVis visualization.");
   args.Parse();
   if (!args.Good())
   {
      args.PrintUsage(cout);
      return 1;
   }
   args.PrintOptions(cout);

   // 2. Read the mesh from the given mesh file. We can handle triangular,
   //    quadrilateral, tetrahedral, hexahedral, surface and volume meshes with
   //    the same code.
   Mesh *mesh = new Mesh(mesh_file, 1, 1);
   int dim = mesh->Dimension();

   // 3. Check if the optimized version matches the given mesh
   if (perf)
   {
      cout << "High-performance version using integration rule with "
           << int_rule_t::qpts << " points ..." << endl;
      if (!mesh_t::MatchesGeometry(*mesh))
      {
         cout << "The given mesh does not match the optimized 'geom' parameter.\n"
              << "Recompile with suitable 'geom' value." << endl;
         delete mesh;
         return 3;
      }
      else if (!mesh_t::MatchesNodes(*mesh))
      {
         cout << "Switching the mesh curvature to match the "
              << "optimized value (order " << mesh_p << ") ..." << endl;
         mesh->SetCurvature(mesh_p, false, -1, Ordering::byNODES);
      }
   }

   // 4. Refine the mesh to increase the resolution. In this example we do
   //    'ref_levels' of uniform refinement. We choose 'ref_levels' to be the
   //    largest number that gives a final mesh with no more than 50,000
   //    elements.
   {
      int ref_levels =
         (int)floor(log(50000./mesh->GetNE())/log(2.)/dim);
      for (int l = 0; l < ref_levels; l++)
      {
         mesh->UniformRefinement();
      }
   }

   // 5. Define a finite element space on the mesh. Here we use continuous
   //    Lagrange finite elements of the specified order. If order < 1, we
   //    instead use an isoparametric/isogeometric space.
   FiniteElementCollection *fec;
   if (order > 0)
   {
      fec = new H1_FECollection(order, dim);
   }
   else if (mesh->GetNodes())
   {
      fec = mesh->GetNodes()->OwnFEC();
      cout << "Using isoparametric FEs: " << fec->Name() << endl;
   }
   else
   {
      fec = new H1_FECollection(order = 1, dim);
   }
   FiniteElementSpace *fespace = new FiniteElementSpace(mesh, fec);
   cout << "Number of finite element unknowns: "
        << fespace->GetTrueVSize() << endl;

   // 6. Check if the optimized version matches the given space
   if (perf && !sol_fes_t::Matches(*fespace))
   {
      cout << "The given order does not match the optimized parameter.\n"
           << "Recompile with suitable 'sol_p' value." << endl;
      delete fespace;
      delete fec;
      delete mesh;
      return 4;
   }

   // 7. Determine the list of true (i.e. conforming) essential boundary dofs.
   //    In this example, the boundary conditions are defined by marking all
   //    the boundary attributes from the mesh as essential (Dirichlet) and
   //    converting them to a list of true dofs.
   Array<int> ess_tdof_list;
   if (mesh->bdr_attributes.Size())
   {
      Array<int> ess_bdr(mesh->bdr_attributes.Max());
      ess_bdr = 1;
      fespace->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
   }

   // 8. Set up the linear form b(.) which corresponds to the right-hand side of
   //    the FEM linear system, which in this case is (1,phi_i) where phi_i are
   //    the basis functions in the finite element fespace.
   LinearForm *b = new LinearForm(fespace);
   ConstantCoefficient one(1.0);
   b->AddDomainIntegrator(new DomainLFIntegrator(one));
   b->Assemble();

   // 9. Define the solution vector x as a finite element grid function
   //    corresponding to fespace. Initialize x with initial guess of zero,
   //    which satisfies the boundary conditions.
   GridFunction x(fespace);
   x = 0.0;

   // 10. Set up the bilinear form a(.,.) on the finite element space that will
   //     hold the matrix corresponding to the Laplacian operator -Delta.
   BilinearForm *a = new BilinearForm(fespace);

   // 11. Assemble the bilinear form and the corresponding linear system,
   //     applying any necessary transformations such as: eliminating boundary
   //     conditions, applying conforming constraints for non-conforming AMR,
   //     static condensation, etc.
   if (static_cond) { a->EnableStaticCondensation(); }

   cout << "Assembling the matrix ..." << flush;
   tic_toc.Clear();
   tic_toc.Start();
   // Pre-allocate sparsity assuming dense element matrices
   a->UsePrecomputedSparsity();
   if (!perf)
   {
      // Standard assembly using a diffusion domain integrator
      a->AddDomainIntegrator(new DiffusionIntegrator(one));
      a->Assemble();
   }
   else
   {
      // High-performance assembly using the templated operator type
      oper_t a_oper(integ_t(coeff_t(1.0)), *fespace);
      a_oper.AssembleBilinearForm(*a);
   }
   tic_toc.Stop();
   cout << " done, " << tic_toc.RealTime() << "s." << endl;

   SparseMatrix A;
   Vector B, X;
   a->FormLinearSystem(ess_tdof_list, x, *b, A, X, B);

   cout << "Size of linear system: " << A.Height() << endl;

#ifndef MFEM_USE_SUITESPARSE
   // 12. Define a simple symmetric Gauss-Seidel preconditioner and use it to
   //     solve the system A X = B with PCG.
   GSSmoother M(A);
   PCG(A, M, B, X, 1, 500, 1e-12, 0.0);
#else
   // 12. If MFEM was compiled with SuiteSparse, use UMFPACK to solve the system.
   UMFPackSolver umf_solver;
   umf_solver.Control[UMFPACK_ORDERING] = UMFPACK_ORDERING_METIS;
   umf_solver.SetOperator(A);
   umf_solver.Mult(B, X);
#endif

   // 13. Recover the solution as a finite element grid function.
   a->RecoverFEMSolution(X, *b, x);

   // 14. Save the refined mesh and the solution. This output can be viewed later
   //     using GLVis: "glvis -m refined.mesh -g sol.gf".
   ofstream mesh_ofs("refined.mesh");
   mesh_ofs.precision(8);
   mesh->Print(mesh_ofs);
   ofstream sol_ofs("sol.gf");
   sol_ofs.precision(8);
   x.Save(sol_ofs);

   // 15. Send the solution by socket to a GLVis server.
   if (visualization)
   {
      char vishost[] = "localhost";
      int  visport   = 19916;
      socketstream sol_sock(vishost, visport);
      sol_sock.precision(8);
      sol_sock << "solution\n" << *mesh << x << flush;
   }

   // 16. Free the used memory.
   delete a;
   delete b;
   delete fespace;
   if (order > 0) { delete fec; }
   delete mesh;

   return 0;
}
Пример #21
0
void RLS
( const SparseMatrix<Real>& A, 
  const Matrix<Real>& b, 
        Real rho,
        Matrix<Real>& x, 
  const socp::affine::Ctrl<Real>& ctrl )
{
    DEBUG_CSE
    const Int m = A.Height();
    const Int n = A.Width();

    Matrix<Int> orders, firstInds;
    Zeros( orders, m+n+3, 1 );
    Zeros( firstInds, m+n+3, 1 );
    for( Int i=0; i<m+1; ++i )
    {
        orders.Set( i, 0, m+1 );
        firstInds.Set( i, 0, 0 );
    }
    for( Int i=0; i<n+2; ++i )
    {
        orders.Set( i+m+1, 0, n+2 ); 
        firstInds.Set( i+m+1, 0, m+1 );
    }

    // G := | -1  0  0 |
    //      |  0  0  A |
    //      |  0 -1  0 |
    //      |  0  0 -I |
    //      |  0  0  0 |
    SparseMatrix<Real> G;
    {
        const Int numEntriesA = A.NumEntries();
        Zeros( G, m+n+3, n+2 );
        G.Reserve( numEntriesA+n+2 );
        G.QueueUpdate( 0, 0, -1 );
        for( Int e=0; e<numEntriesA; ++e )
            G.QueueUpdate( A.Row(e)+1, A.Col(e)+2, A.Value(e) );
        G.QueueUpdate( m+1, 1, -1 );
        for( Int j=0; j<n; ++j )
            G.QueueUpdate( j+m+2, j+2, -1 );
        G.ProcessQueues();
    }

    // h := | 0 |
    //      | b |
    //      | 0 |
    //      | 0 |
    //      | 1 |
    Matrix<Real> h;
    Zeros( h, m+n+3, 1 ); 
    auto hb = h( IR(1,m+1), ALL );
    hb = b;
    h.Set( END, 0, 1 );

    // c := [1; rho; 0]
    Matrix<Real> c;
    Zeros( c, n+2, 1 );
    c.Set( 0, 0, 1 );
    c.Set( 1, 0, rho );

    SparseMatrix<Real> AHat;
    Zeros( AHat, 0, n+2 );
    Matrix<Real> bHat;
    Zeros( bHat, 0, 1 );

    Matrix<Real> xHat, y, z, s;
    SOCP( AHat, G, bHat, c, h, orders, firstInds, xHat, y, z, s, ctrl );
    x = xHat( IR(2,END), ALL );
}
Пример #22
0
void IPM
( const SparseMatrix<Real>& A,
  const Matrix<Real>& d,
        Real lambda,
        Matrix<Real>& x,
  const qp::affine::Ctrl<Real>& ctrl )
{
    EL_DEBUG_CSE
    const Int m = A.Height();
    const Int n = A.Width();
    const Range<Int> wInd(0,n), betaInd(n,n+1), zInd(n+1,n+m+1);

    SparseMatrix<Real> Q, AHat, G;
    Matrix<Real> c, b, h;

    // Q := | I 0 0 |
    //      | 0 0 0 |
    //      | 0 0 0 |
    // ==============
    Zeros( Q, n+m+1, n+m+1 );
    Q.Reserve( n );
    for( Int e=0; e<n; ++e )
        Q.QueueUpdate( e, e, Real(1) );
    Q.ProcessQueues();

    // c := [0;0;lambda]
    // =================
    Zeros( c, n+m+1, 1 );
    auto cz = c( zInd, ALL );
    Fill( cz, lambda );

    // AHat = []
    // =========
    Zeros( AHat, 0, n+m+1 );

    // b = []
    // ======
    Zeros( b, 0, 1 );

    // G := |-diag(d) A, -d, -I|
    //      |      0,     0, -I|
    // =========================
    Zeros( G, 2*m, n+m+1 );
    const Int numEntriesA = A.NumEntries();
    G.Reserve( numEntriesA+3*m );
    for( Int e=0; e<numEntriesA; ++e )
        G.QueueUpdate( A.Row(e), A.Col(e), -d(A.Row(e))*A.Value(e) );
    for( Int e=0; e<m; ++e )
        G.QueueUpdate( e, n, -d(e) );
    for( Int e=0; e<m; ++e )
    {
        G.QueueUpdate( e,   e+n+1, Real(-1) );
        G.QueueUpdate( e+m, e+n+1, Real(-1) );
    }
    G.ProcessQueues();

    // h := [-ones(m,1); zeros(m,1)]
    // =============================
    Zeros( h, 2*m, 1 );
    auto h0 = h( IR(0,m), ALL );
    Fill( h0, Real(-1) );

    // Solve the affine QP
    // ===================
    Matrix<Real> y, z, s;
    QP( Q, AHat, G, b, c, h, x, y, z, s, ctrl );
}