ROL
ROL_StdLinearOperatorFactory.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Rapid Optimization Library (ROL) Package
4 //
5 // Copyright 2014 NTESS and the ROL contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef ROL_STDLINEAROPERATORFACTORY_H
11 #define ROL_STDLINEAROPERATORFACTORY_H
12 
14 
15 #include <ctime>
16 #include <cstdlib>
17 #include <string>
18 
26 namespace ROL {
27 
28 template<class Real>
29 class StdLinearOperatorFactory {
30 
31  template <typename T> using ROL::Ptr = ROL::Ptr<T>;
32 
33  typedef LinearOperator<Real> OP;
34  typedef StdLinearOperator<Real> StdOP;
35 
36  typedef std::vector<Real> vector;
37 
38 private:
39 
40 
41  Teuchos::BLAS<int,Real> blas_;
42  ROL::LAPACK<int,Real> lapack_;
43 
44  // Fill x with uniformly-distributed random values from [lower,upper]
45  void randomize( vector &x, Real lower=0.0, Real upper=1.0 ) {
46  int N = x.size();
47  for( int i=0; i<N; ++i ) {
48  x[i] = lower+(upper-lower)*static_cast<Real>(rand())/static_cast<Real>(RAND_MAX);
49  }
50  }
51 
52  void diagonal( vector &D, const vector& d ) {
53  int N = d.size();
54  int N2 = N*N;
55  D.reserve(N2);
56  D.assign(N2,0.0);
57  for( int i=0; i<N; ++i ) {
58  D[(N+1)*i] = d[i];
59  }
60  }
61 
62  // C = A*B with optional transposes
63  void multiply( vector &C, const vector &A, const vector &B, bool transA=false, bool transB=false ) {
64  int N2 = A.size();
65  int N = (std::round(std::sqrt(N2)));
66  bool isSquare = N*N == N2;
67  ROL_TEST_FOR_EXCEPTION( !isSquare, std::invalid_argument,
68  "Error: vector representation A of matrix must have a square "
69  "number of elements.");
70  ROL_TEST_FOR_EXCEPTION( B.size() != N2, std::invalid_argument,
71  "Error: vectors A and B must have the same length.");
72  ROL_TEST_FOR_EXCEPTION( C.size() != N2, std::invalid_argument,
73  "Error: vectors A and C must have the same length.");
74 
75  char tra = transA : 'T' : 'N';
76  char trb = transB : 'T' : 'N';
77 
78  blas_.GEMM(tra,trb,N,N,N,1.0,&A[0],&B[0],N,0.0,N);
79 
80  }
81 
82  // Orthogonalize the columns of A
83  void orthogonalize( vector &A ) {
84  int N2 = A.size();
85  int N = (std::round(std::sqrt(N2)));
86  bool isSquare = N*N == N2;
87  ROL_TEST_FOR_EXCEPTION( !isSquare, std::invalid_argument,
88  "Error: vector representation of matrix must have a square "
89  "number of elements.");
90 
91  vector TAU(N,0.0);
92 
93  int LDA = N;
94  Real LWORK1, LWORK2;
95  int INFO = 0;
96 
97  // Query workspace
98  lapack_.GEQRF(N,N,&A[0],LDA,&TAU[0],&LWORK1,-1,&INFO);
99  ROL_TEST_FOR_EXCEPTION(INFO,std::logic_error,"LAPACK GEQRF LWORK query failed.");
100 
101  lapack_.ORGQR(N,N,N,&A[0],LDA,&TAU[0],&LWORK2,-1,&INFO);
102  ROL_TEST_FOR_EXCEPTION(INFO,std::logic_error,"LAPACK ORGQR LWORK query failed.");
103 
104  const int LWORK = std::max(std::abs(LWORK1),std::abs(LWORK2));
105 
106  vector WORK(LWORK);
107 
108  // Factor the input matrix
109  lapack_.GEQRF(N,N,&A[0],LDA,&TAU[0],LWORK,&INFO);
110  ROL_TEST_FOR_EXCEPTION(INFO,std::logic_error,"LAPACK GEQRF failed with INFO = " << INFO );
111 
112  // Overwrite the input matrix with the orthogonal matrix Q
113  lapack_.ORGQR(N,N,N,&A[0],LDA,&TAU[0],&WORK[0],LWORK,&INFO);
114  ROL_TEST_FOR_EXCEPTION(INFO,std::logic_error,"LAPACK ORGQR failed with INFO = " << INFO );
115 
116  }
117 
118 
119 public:
120 
121  enum class EMatrixType unsigned {
122  MATRIX_SPD = 0, // Symmetric Positive Definite matrix
123  MATRIX_SYMMETRIC, // Symmetric Indefinite matrix
124  MATRIX_UNITARY, // Unitary matrix
125  MATRIX_SINGULAR_S, // Singular symmetric matrix
126  MATRIX_SINGULAR_N, // Singular nonsymmetric matrix
127  MATRIX_DEFAULT, // Random nonsymmetric matrix
128  MATRIX_LAST
129  };
130 
131  ~StdLinearOperatorFactor(void) {}
132 
133  EMatrixType StringToEMatrixType( satd::string s ) {
134  s = removeStringFormat(s);
135  for ( EMatrixType mt = MATRIX_SPD; mt < MATRIX_LAST; ++ ) {
136  if ( !s.compare(removeStringFormat(EStepToString(mt))) ) {
137  return mt;
138  }
139  }
140 
141  std::string EMatrixTypeToString( EMatrixType mt ) {
142  std::string retString;
143  switch( mt ) {
144  case MATRIX_SPD: retString = "Symmetric Positive Definite"; break;
145  case MATRIX_SYMMETRIC: retString = "Symmetric Indefinite"; break;
146  case MATRIX_UNITARY: retString = "Unitary"; break;
147  case MATRIX_SINGULAR_S: retString = "Singular Symmetric"; break;
148  case MATRIX_SINGILAR_N: retString = "Singular Nonsymmetric"; break;
149  case MATRIX_DEFAULT: retString = "Default"; break;
150  case MATRIX_LAST: retString = "Last (dummy)"; break;
151  }
152  return retString;
153  }
154 
155  ROL::Ptr<LinearOperator<Real> > getOperator( int size, const std::string &type="" ) const {
156  EMatrixType emt = StringToEMatrixType(type);
157 
158 
159 
160  int n2 = size*size;
161 
162  ROL::Ptr<vector> Ap = ROL::makePtr<vector>(n2);
163 
164  switch( emt ) {
165  case MATRIX_SPD: {
166 
167  vector d(size);
168  randomize(d,1.0,2.0);
169 
170  // A = D
171  diagonal(*Ap,d);
172 
173  vector Q(n2);
174  randomize(Q,-1.0,1.0);
175  orthogonalize(Q);
176 
177  // A = D*Q
178  multiply(*Ap,*Ap,Q);
179 
180  // A = Q'*D*Q
181  multiply(*Ap,Q,*Ap,true);
182 
183  }
184  break;
185 
186  case MATRIX_SYMMETRIC: {
187  vector d(size);
188  randomize(d);
189 
190  // A = D
191  diagonal(*Ap,d);
192 
193  vector Q(n2);
194  randomize(Q,-1.0,1.0);
195  orthogonalize(Q);
196 
197  // A = D*Q
198  multiply(*Ap,*Ap,Q);
199 
200  // A = Q'*D*Q
201  multiply(*Ap,Q,*Ap,true);
202  }
203  break;
204 
205  case MATRIX_UNITARY: {
206  randomize(*Ap);
207  orthogonalize(*Ap);
208  }
209 
210  case MATRIX_SINGULAR_S: {
211  vector d(size);
212  randomize(d);
213 
214  d[0] = 0;
215 
216  // A = D
217  diagonal(*Ap,d);
218 
219  vector Q(n2);
220  randomize(Q,-1.0,1.0);
221  orthogonalize(Q);
222 
223  // A = D*Q
224  multiply(*Ap,*Ap,Q);
225 
226  // A = Q'*D*Q
227  multiply(*Ap,Q,*Ap,true);
228 
229 
230  case MATRIX_SINGULAR_N: {
231 
232  vector d(size);
233  randomize(d,0.0,1.0);
234 
235  d[0] = 0;
236 
237  // A = D
238  diagonal(*Ap,d);
239 
240  vector V(n2);
241  randomize(V,-1.0,1.0);
242  orthogonalize(V);
243 
244  // A = D*V'
245  multiply(*Ap,*Ap,Q,false,true);
246 
247  vector U(n2);
248  randomize(U,-1.0,1.0);
249  orthogonalize(U);
250 
251  // A = U*D*V'
252  multiply(*Ap,U,*Ap);
253 
254  }
255 
256  case MATRIX_DEFAULT:
257  default: {
258  randomize(*Ap);
259  }
260 
261  }
262  return ROL::makePtr<StdOP>(Ap);
263  }
264 
265 
266 
267 }; // class StdLinearOperatorFactory
268 
269 } // namespace ROL
270 
271 
272 #endif // ROL_STDLINEAROPERATORFACTORY_H
ROL::Ptr< LinearOperator< Real > > getOperator(int row, int col) const
std::string removeStringFormat(std::string s)
Definition: ROL_Types.hpp:215
Vector< Real > V
LinearOperator< Real > OP
std::string EStepToString(EStep tr)
Definition: ROL_Types.hpp:256