1 /*  _______________________________________________________________________
2 
3     PECOS: Parallel Environment for Creation Of Stochastics
4     Copyright (c) 2011, Sandia National Laboratories.
5     This software is distributed under the GNU Lesser General Public License.
6     For more information, see the README file in the top Pecos directory.
7     _______________________________________________________________________ */
8 
9 //- Class:        SharedRegressPolyApproxData
10 //- Description:  Class for Multivariate Orthogonal Polynomial Approximations
11 //-
12 //- Owner:        John Jakeman
13 
14 #ifndef SHARED_REGRESS_ORTHOG_POLY_APPROX_DATA_HPP
15 #define SHARED_REGRESS_ORTHOG_POLY_APPROX_DATA_HPP
16 
17 #include "SharedOrthogPolyApproxData.hpp"
18 #include "LightweightSparseGridDriver.hpp"
19 #include "LinearSolverPecosSrc.hpp"
20 
21 namespace Pecos {
22 
23 
24 /// Container class for various regression configuration options
25 
26 /** The RegressionConfigOptions class provides a simple container class
27     for regression configuration options related to ... */
28 
29 class RegressionConfigOptions
30 {
31   //
32   //- Heading: Friends
33   //
34 
35   //friend class PolynomialApproximation;
36 
37 public:
38 
39   /// default constructor
40   RegressionConfigOptions();
41   /// constructor
42   RegressionConfigOptions(bool cv, bool cv_noise_only, int seed,
43 			  const RealVector& noise_tols, Real l2_penalty,
44 			  bool normalize_cv, unsigned short init_lev,
45 			  unsigned short growth_fact,
46 			  unsigned short num_advance);
47   /// copy constructor
48   RegressionConfigOptions(const RegressionConfigOptions& rc_options);
49   /// destructor
50   ~RegressionConfigOptions();
51 
52 //private:
53 
54   /// flag for use of automatic cross-validation for parameter
55   /// selection in regression approaches
56   bool crossValidation;
57   /// flag to restrict cross-validation to only estimate the noise
58   /// tolerance in order to manage computational cost
59   bool crossValidNoiseOnly;
60 
61   /// random seed for data fold definition within cross validation
62   int randomSeed;
63 
64   /// noise tolerance(s) for compressed sensing algorithms; vector form
65   /// used in cross-validation
66   RealVector noiseTols;
67   /// the L2 penalty parameter for LASSO (elastic net variant)
68   Real l2Penalty;
69 
70   /// flag indicating whether to scale the CV error estimates by the size
71   /// of the candidate basis expansion within adapted basis selection
72   bool normalizeCV;
73 
74   /// initial sparse grid level that provides the starting point for basis
75   /// adaptation in ADAPTED_BASIS_GENERALIZED mode
76   unsigned short initSGLevel;
77   /// a scalar growth factor for defining the tpMultiIndex contribution
78   /// from a particular trial index set for basis adaptation in
79   /// ADAPTED_BASIS_GENERALIZED mode
80   unsigned short multiIndexGrowthFactor;
81 
82   /// number of front expansions per iteration for basis adaptation in
83   /// ADAPTED_BASIS_EXPANDING_FRONT mode
84   unsigned short numAdvancements;
85 
86   /// flag indicating restriction and front expansion using a multi-index
87   /// frontier
88   /** This option reduces memory requirements somewhat, but allowing
89       multi-index gaps in the general case results in reduced mutual
90       coherence and better numerical performance. */
91   bool advanceByFrontier;
92 };
93 
94 
RegressionConfigOptions()95 inline RegressionConfigOptions::RegressionConfigOptions():
96   crossValidation(false), crossValidNoiseOnly(false), randomSeed(0),
97   l2Penalty(0.), normalizeCV(false), initSGLevel(0), multiIndexGrowthFactor(2),
98   numAdvancements(3), advanceByFrontier(false)
99 { }
100 
101 
102 inline RegressionConfigOptions::
RegressionConfigOptions(bool cv,bool cv_noise_only,int seed,const RealVector & noise_tols,Real l2_penalty,bool normalize_cv,unsigned short init_lev,unsigned short growth_fact,unsigned short num_advance)103 RegressionConfigOptions(bool cv, bool cv_noise_only, int seed,
104 			const RealVector& noise_tols,
105 			Real l2_penalty, bool normalize_cv,
106 			unsigned short init_lev, unsigned short growth_fact,
107 			unsigned short num_advance):
108   crossValidation(cv), crossValidNoiseOnly(cv_noise_only), randomSeed(seed),
109   noiseTols(noise_tols), l2Penalty(l2_penalty), normalizeCV(normalize_cv),
110   initSGLevel(init_lev), multiIndexGrowthFactor(growth_fact),
111   numAdvancements(num_advance), advanceByFrontier(false)
112 { }
113 
114 
115 inline RegressionConfigOptions::
RegressionConfigOptions(const RegressionConfigOptions & rc_options)116 RegressionConfigOptions(const RegressionConfigOptions& rc_options):
117   crossValidation(rc_options.crossValidation),
118   crossValidNoiseOnly(rc_options.crossValidNoiseOnly),
119   randomSeed(rc_options.randomSeed), noiseTols(rc_options.noiseTols),
120   l2Penalty(rc_options.l2Penalty), normalizeCV(rc_options.normalizeCV),
121   initSGLevel(rc_options.initSGLevel),
122   multiIndexGrowthFactor(rc_options.multiIndexGrowthFactor),
123   numAdvancements(rc_options.numAdvancements),
124   advanceByFrontier(rc_options.advanceByFrontier)
125 { }
126 
127 
~RegressionConfigOptions()128 inline RegressionConfigOptions::~RegressionConfigOptions()
129 { }
130 
131 
132 /// Derived approximation class for multivariate orthogonal polynomial
133 /// approximation with coefficient estimation via regression.
134 
135 /** The SharedRegressOrthogPolyApproxData class provides a global
136     approximation based on multivariate orthogonal polynomials, where
137     the coefficients are computed using regression approaches such as
138     least squares (L2) or compressed sensing (L1).  It is used
139     primarily for polynomial chaos expansion aproaches to UQ. */
140 
141 class SharedRegressOrthogPolyApproxData: public SharedOrthogPolyApproxData
142 {
143   //
144   //- Heading: Friends
145   //
146 
147   friend class RegressOrthogPolyApproximation;
148 
149 public:
150 
151   //
152   //- Heading: Constructor and destructor
153   //
154 
155   /// lightweight constructor
156   SharedRegressOrthogPolyApproxData(short basis_type,
157 				    const UShortArray& approx_order,
158 				    size_t num_vars);
159   /// full constructor
160   SharedRegressOrthogPolyApproxData(short basis_type,
161 				    const UShortArray& approx_order,
162 				    size_t num_vars,
163 				    const ExpansionConfigOptions& ec_options,
164 				    const BasisConfigOptions& bc_options,
165 				    const RegressionConfigOptions& rc_options);
166   /// destructor
167   ~SharedRegressOrthogPolyApproxData();
168 
169   //
170   //- Heading: Member functions
171   //
172 
173   /// helper function for incrementing that is modular on trial set and
174   /// multi-index
175   void increment_trial_set(const UShortArray& trial_set,
176 			   UShort2DArray& aggregated_mi);
177 
178   /// define the TP index sets that can be removed from a generalized
179   /// sparse grid based on the recovered sparse_indices; used for the
180   /// restriction operation within basis adaptation
181   bool set_restriction(UShort2DArray& aggregated_mi, SizetSet& sparse_indices,
182 		       SizetSet& save_tp);
183 
184   /// clear adapted basis bookkeeping
185   void clear_adapted();
186 
187   /// set regressConfigOptions
188   void configuration_options(const RegressionConfigOptions& rc_options);
189 
190 protected:
191 
192   //
193   //- Heading: Virtual function redefinitions
194   //
195 
196   void allocate_data();
197   void increment_data();
198   void decrement_data();
199 
200   void pre_push_data();
201   //void post_push_data();
202 
203   //void pre_finalize_data();
204   //void post_finalize_data();
205 
206   //
207   //- Heading: Member functions
208   //
209 
210   /// append multi-indices from append_mi that do not already appear in
211   /// combined_mi (consistent ordering assumed); define append_mi_map
212   /// and append_mi_map_ref
213   void append_leading_multi_index(const UShort2DArray& append_mi,
214 				  UShort2DArray& combined_mi,
215 				  SizetSet& append_mi_map,
216 				  size_t& append_mi_map_ref);
217   /// append multi-indices from append_mi that do not already appear in
218   /// combined_mi, updating sparse_indices, exp_coeffs, and exp_coeff_grads
219   void append_sparse_multi_index(SizetSet& sparse_indices,
220 				 const UShort2DArray& append_mi,
221 				 UShort2DArray& combined_mi,
222 				 RealVector& exp_coeffs,
223 				 RealMatrix& exp_coeff_grads);
224 
225 private:
226 
227   //
228   //- Heading: Member functions
229   //
230 
231   /// update shared approxOrder based on settings computed for one of the QoI
232   void update_approx_order(unsigned short new_order);
233   /// convert active approxOrder to active multiIndex according to basis type
234   void approx_order_to_multi_index();
235 
236   /// pack polynomial contributions to Psi matrix for regression
237   void pack_polynomial_data(const RealVector& c_vars, const UShortArray& mi,
238 			    bool add_val,  double* pack_val,  size_t& pv_cntr,
239 			    bool add_grad, double* pack_grad, size_t& pg_cntr);
240   /// pack response contributions to RHS for regression
241   void pack_response_data(const SurrogateDataResp& sdr,
242 			  bool add_val,  double* pack_val,  size_t& pv_cntr,
243 			  bool add_grad, double* pack_grad, size_t& pg_cntr);
244 
245   //
246   //- Heading: Data
247   //
248 
249   /// container for regression configuration options
250   RegressionConfigOptions regressConfigOptions;
251 
252   /// Wrapper class that is used to solve regression problems
253   CompressedSensingTool CSTool;
254 
255   /// lower matrix factor in factorization
256   RealMatrix lowerFactor;
257   /// upper matrix factor in factorization
258   RealMatrix upperFactor;
259   /// pivoting history of block-LU factorization
260   RealMatrix pivotHistory;
261   /// pivoting vector
262   IntVector pivotVect;
263 
264   /// sparse grid driver for adapting a CS candidate basis using greedy
265   /// adaptation via the generalized sparse grid algorithm; it's state
266   /// is reset for each response QoI
267   LightweightSparseGridDriver lsgDriver;
268 };
269 
270 
271 inline SharedRegressOrthogPolyApproxData::
SharedRegressOrthogPolyApproxData(short basis_type,const UShortArray & approx_order,size_t num_vars)272 SharedRegressOrthogPolyApproxData(short basis_type,
273 				  const UShortArray& approx_order,
274 				  size_t num_vars):
275   SharedOrthogPolyApproxData(basis_type, approx_order, num_vars)
276 { }
277 
278 
279 inline SharedRegressOrthogPolyApproxData::
SharedRegressOrthogPolyApproxData(short basis_type,const UShortArray & approx_order,size_t num_vars,const ExpansionConfigOptions & ec_options,const BasisConfigOptions & bc_options,const RegressionConfigOptions & rc_options)280 SharedRegressOrthogPolyApproxData(short basis_type,
281 				  const UShortArray& approx_order,
282 				  size_t num_vars,
283 				  const ExpansionConfigOptions& ec_options,
284 				  const BasisConfigOptions& bc_options,
285 				  const RegressionConfigOptions& rc_options):
286   SharedOrthogPolyApproxData(basis_type, approx_order, num_vars,
287 			     ec_options, bc_options),
288   regressConfigOptions(rc_options)
289 { }
290 
291 
~SharedRegressOrthogPolyApproxData()292 inline SharedRegressOrthogPolyApproxData::~SharedRegressOrthogPolyApproxData()
293 { }
294 
295 
296 inline void SharedRegressOrthogPolyApproxData::
configuration_options(const RegressionConfigOptions & rc_options)297 configuration_options(const RegressionConfigOptions& rc_options)
298 { regressConfigOptions = rc_options; }
299 
300 
clear_adapted()301 inline void SharedRegressOrthogPolyApproxData::clear_adapted()
302 {
303   switch (expConfigOptions.expBasisType) {
304   case ADAPTED_BASIS_GENERALIZED:
305     // reset tensor-product bookkeeping and save restorable data
306     //poppedLevMultiIndex[activeKey].clear();
307     poppedMultiIndex[activeKey].clear();
308     poppedMultiIndexMap[activeKey].clear();
309     poppedMultiIndexMapRef[activeKey].clear();
310 
311     tpMultiIndex[activeKey].clear();       // will be rebuilt in allocate_data()
312     tpMultiIndexMap[activeKey].clear();    // will be rebuilt in allocate_data()
313     tpMultiIndexMapRef[activeKey].clear(); // will be rebuilt in allocate_data()
314     break;
315   }
316 }
317 
318 } // namespace Pecos
319 
320 #endif
321