ROL
ROL_StdLinearOperatorFactory.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ************************************************************************
3 //
4 // Rapid Optimization Library (ROL) Package
5 // Copyright (2014) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact lead developers:
38 // Drew Kouri (dpkouri@sandia.gov) and
39 // Denis Ridzal (dridzal@sandia.gov)
40 //
41 // ************************************************************************
42 // @HEADER
43 
44 
45 #ifndef ROL_STDLINEAROPERATORFACTORY_H
46 #define ROL_STDLINEAROPERATORFACTORY_H
47 
49 
50 #include <ctime>
51 #include <cstdlib>
52 #include <string>
53 
61 namespace ROL {
62 
63 template<class Real>
64 class StdLinearOperatorFactory {
65 
66  template <typename T> using ROL::Ptr = ROL::Ptr<T>;
67 
68  typedef LinearOperator<Real> OP;
69  typedef StdLinearOperator<Real> StdOP;
70 
71  typedef std::vector<Real> vector;
72 
73 private:
74 
75 
76  Teuchos::BLAS<int,Real> blas_;
77  ROL::LAPACK<int,Real> lapack_;
78 
79  // Fill x with uniformly-distributed random values from [lower,upper]
80  void randomize( vector &x, Real lower=0.0, Real upper=1.0 ) {
81  int N = x.size();
82  for( int i=0; i<N; ++i ) {
83  x[i] = lower+(upper-lower)*static_cast<Real>(rand())/static_cast<Real>(RAND_MAX);
84  }
85  }
86 
87  void diagonal( vector &D, const vector& d ) {
88  int N = d.size();
89  int N2 = N*N;
90  D.reserve(N2);
91  D.assign(N2,0.0);
92  for( int i=0; i<N; ++i ) {
93  D[(N+1)*i] = d[i];
94  }
95  }
96 
97  // C = A*B with optional transposes
98  void multiply( vector &C, const vector &A, const vector &B, bool transA=false, bool transB=false ) {
99  int N2 = A.size();
100  int N = (std::round(std::sqrt(N2)));
101  bool isSquare = N*N == N2;
102  ROL_TEST_FOR_EXCEPTION( !isSquare, std::invalid_argument,
103  "Error: vector representation A of matrix must have a square "
104  "number of elements.");
105  ROL_TEST_FOR_EXCEPTION( B.size() != N2, std::invalid_argument,
106  "Error: vectors A and B must have the same length.");
107  ROL_TEST_FOR_EXCEPTION( C.size() != N2, std::invalid_argument,
108  "Error: vectors A and C must have the same length.");
109 
110  char tra = transA : 'T' : 'N';
111  char trb = transB : 'T' : 'N';
112 
113  blas_.GEMM(tra,trb,N,N,N,1.0,&A[0],&B[0],N,0.0,N);
114 
115  }
116 
117  // Orthogonalize the columns of A
118  void orthogonalize( vector &A ) {
119  int N2 = A.size();
120  int N = (std::round(std::sqrt(N2)));
121  bool isSquare = N*N == N2;
122  ROL_TEST_FOR_EXCEPTION( !isSquare, std::invalid_argument,
123  "Error: vector representation of matrix must have a square "
124  "number of elements.");
125 
126  vector TAU(N,0.0);
127 
128  int LDA = N;
129  Real LWORK1, LWORK2;
130  int INFO = 0;
131 
132  // Query workspace
133  lapack_.GEQRF(N,N,&A[0],LDA,&TAU[0],&LWORK1,-1,&INFO);
134  ROL_TEST_FOR_EXCEPTION(INFO,std::logic_error,"LAPACK GEQRF LWORK query failed.");
135 
136  lapack_.ORGQR(N,N,N,&A[0],LDA,&TAU[0],&LWORK2,-1,&INFO);
137  ROL_TEST_FOR_EXCEPTION(INFO,std::logic_error,"LAPACK ORGQR LWORK query failed.");
138 
139  const int LWORK = std::max(std::abs(LWORK1),std::abs(LWORK2));
140 
141  vector WORK(LWORK);
142 
143  // Factor the input matrix
144  lapack_.GEQRF(N,N,&A[0],LDA,&TAU[0],LWORK,&INFO);
145  ROL_TEST_FOR_EXCEPTION(INFO,std::logic_error,"LAPACK GEQRF failed with INFO = " << INFO );
146 
147  // Overwrite the input matrix with the orthogonal matrix Q
148  lapack_.ORGQR(N,N,N,&A[0],LDA,&TAU[0],&WORK[0],LWORK,&INFO);
149  ROL_TEST_FOR_EXCEPTION(INFO,std::logic_error,"LAPACK ORGQR failed with INFO = " << INFO );
150 
151  }
152 
153 
154 public:
155 
156  enum class EMatrixType unsigned {
157  MATRIX_SPD = 0, // Symmetric Positive Definite matrix
158  MATRIX_SYMMETRIC, // Symmetric Indefinite matrix
159  MATRIX_UNITARY, // Unitary matrix
160  MATRIX_SINGULAR_S, // Singular symmetric matrix
161  MATRIX_SINGULAR_N, // Singular nonsymmetric matrix
162  MATRIX_DEFAULT, // Random nonsymmetric matrix
163  MATRIX_LAST
164  };
165 
166  ~StdLinearOperatorFactor(void) {}
167 
168  EMatrixType StringToEMatrixType( satd::string s ) {
169  s = removeStringFormat(s);
170  for ( EMatrixType mt = MATRIX_SPD; mt < MATRIX_LAST; ++ ) {
171  if ( !s.compare(removeStringFormat(EStepToString(mt))) ) {
172  return mt;
173  }
174  }
175 
176  std::string EMatrixTypeToString( EMatrixType mt ) {
177  std::string retString;
178  switch( mt ) {
179  case MATRIX_SPD: retString = "Symmetric Positive Definite"; break;
180  case MATRIX_SYMMETRIC: retString = "Symmetric Indefinite"; break;
181  case MATRIX_UNITARY: retString = "Unitary"; break;
182  case MATRIX_SINGULAR_S: retString = "Singular Symmetric"; break;
183  case MATRIX_SINGILAR_N: retString = "Singular Nonsymmetric"; break;
184  case MATRIX_DEFAULT: retString = "Default"; break;
185  case MATRIX_LAST: retString = "Last (dummy)"; break;
186  }
187  return retString;
188  }
189 
190  ROL::Ptr<LinearOperator<Real> > getOperator( int size, const std::string &type="" ) const {
191  EMatrixType emt = StringToEMatrixType(type);
192 
193 
194 
195  int n2 = size*size;
196 
197  ROL::Ptr<vector> Ap = ROL::makePtr<vector>(n2);
198 
199  switch( emt ) {
200  case MATRIX_SPD: {
201 
202  vector d(size);
203  randomize(d,1.0,2.0);
204 
205  // A = D
206  diagonal(*Ap,d);
207 
208  vector Q(n2);
209  randomize(Q,-1.0,1.0);
210  orthogonalize(Q);
211 
212  // A = D*Q
213  multiply(*Ap,*Ap,Q);
214 
215  // A = Q'*D*Q
216  multiply(*Ap,Q,*Ap,true);
217 
218  }
219  break;
220 
221  case MATRIX_SYMMETRIC: {
222  vector d(size);
223  randomize(d);
224 
225  // A = D
226  diagonal(*Ap,d);
227 
228  vector Q(n2);
229  randomize(Q,-1.0,1.0);
230  orthogonalize(Q);
231 
232  // A = D*Q
233  multiply(*Ap,*Ap,Q);
234 
235  // A = Q'*D*Q
236  multiply(*Ap,Q,*Ap,true);
237  }
238  break;
239 
240  case MATRIX_UNITARY: {
241  randomize(*Ap);
242  orthogonalize(*Ap);
243  }
244 
245  case MATRIX_SINGULAR_S: {
246  vector d(size);
247  randomize(d);
248 
249  d[0] = 0;
250 
251  // A = D
252  diagonal(*Ap,d);
253 
254  vector Q(n2);
255  randomize(Q,-1.0,1.0);
256  orthogonalize(Q);
257 
258  // A = D*Q
259  multiply(*Ap,*Ap,Q);
260 
261  // A = Q'*D*Q
262  multiply(*Ap,Q,*Ap,true);
263 
264 
265  case MATRIX_SINGULAR_N: {
266 
267  vector d(size);
268  randomize(d,0.0,1.0);
269 
270  d[0] = 0;
271 
272  // A = D
273  diagonal(*Ap,d);
274 
275  vector V(n2);
276  randomize(V,-1.0,1.0);
277  orthogonalize(V);
278 
279  // A = D*V'
280  multiply(*Ap,*Ap,Q,false,true);
281 
282  vector U(n2);
283  randomize(U,-1.0,1.0);
284  orthogonalize(U);
285 
286  // A = U*D*V'
287  multiply(*Ap,U,*Ap);
288 
289  }
290 
291  case MATRIX_DEFAULT:
292  default: {
293  randomize(*Ap);
294  }
295 
296  }
297  return ROL::makePtr<StdOP>(Ap);
298  }
299 
300 
301 
302 }; // class StdLinearOperatorFactory
303 
304 } // namespace ROL
305 
306 
307 #endif // ROL_STDLINEAROPERATORFACTORY_H
ROL::Ptr< LinearOperator< Real > > getOperator(int row, int col) const
std::string removeStringFormat(std::string s)
Definition: ROL_Types.hpp:247
Vector< Real > V
LinearOperator< Real > OP
std::string EStepToString(EStep tr)
Definition: ROL_Types.hpp:287