1 //                                               -*- C++ -*-
2 /**
3  *  @brief The class building gaussian process regression
4  *
5  *  Copyright 2005-2021 Airbus-EDF-IMACS-ONERA-Phimeca
6  *
7  *  This library is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU Lesser General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public License
18  *  along with this library.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #include "openturns/KrigingAlgorithm.hxx"
23 #include "openturns/PersistentObjectFactory.hxx"
24 #include "openturns/LinearFunction.hxx"
25 #include "openturns/SpecFunc.hxx"
26 #include "openturns/KrigingEvaluation.hxx"
27 #include "openturns/KrigingGradient.hxx"
28 #include "openturns/CenteredFiniteDifferenceHessian.hxx"
29 #include "openturns/GeneralLinearModelResult.hxx"
30 #include "openturns/ComposedFunction.hxx"
31 
32 BEGIN_NAMESPACE_OPENTURNS
33 
34 CLASSNAMEINIT(KrigingAlgorithm)
35 
36 static const Factory<KrigingAlgorithm> Factory_KrigingAlgorithm;
37 
38 
39 /* Default constructor */
KrigingAlgorithm()40 KrigingAlgorithm::KrigingAlgorithm()
41   : MetaModelAlgorithm()
42   , inputSample_(0, 0)
43   , outputSample_(0, 0)
44   , covarianceModel_()
45   , glmAlgo_()
46   , gamma_(0)
47   , rho_(0)
48   , result_()
49   , covarianceCholeskyFactor_()
50   , covarianceCholeskyFactorHMatrix_()
51 {
52   // Force the GLM algo to use the exact same linear algebra as the Kriging algorithm
53   if (ResourceMap::GetAsString("KrigingAlgorithm-LinearAlgebra") == "HMAT") glmAlgo_.setMethod(1);
54   else glmAlgo_.setMethod(0);
55 }
56 
57 
58 /* Constructor */
KrigingAlgorithm(const Sample & inputSample,const Sample & outputSample,const CovarianceModel & covarianceModel,const Basis & basis)59 KrigingAlgorithm::KrigingAlgorithm(const Sample & inputSample,
60                                    const Sample & outputSample,
61                                    const CovarianceModel & covarianceModel,
62                                    const Basis & basis)
63   : MetaModelAlgorithm()
64   , inputSample_(inputSample)
65   , outputSample_(outputSample)
66   , covarianceModel_()
67   , glmAlgo_(inputSample, outputSample, covarianceModel, basis, true)
68   , gamma_(0)
69   , rho_(0)
70   , result_()
71   , covarianceCholeskyFactor_()
72   , covarianceCholeskyFactorHMatrix_()
73 {
74   // Force the GLM algo to use the exact same linear algebra as the Kriging algorithm
75   if (ResourceMap::GetAsString("KrigingAlgorithm-LinearAlgebra") == "HMAT") glmAlgo_.setMethod(1);
76   else glmAlgo_.setMethod(0);
77 }
78 
79 
80 /* Constructor */
KrigingAlgorithm(const Sample & inputSample,const Sample & outputSample,const CovarianceModel & covarianceModel,const BasisCollection & basisCollection)81 KrigingAlgorithm::KrigingAlgorithm(const Sample & inputSample,
82                                    const Sample & outputSample,
83                                    const CovarianceModel & covarianceModel,
84                                    const BasisCollection & basisCollection)
85   : MetaModelAlgorithm()
86   , inputSample_(inputSample)
87   , outputSample_(outputSample)
88   , covarianceModel_(covarianceModel)
89   , glmAlgo_(inputSample, outputSample, covarianceModel, basisCollection, true)
90   , gamma_(0)
91   , rho_(0)
92   , result_()
93   , covarianceCholeskyFactor_()
94   , covarianceCholeskyFactorHMatrix_()
95 {
96   // Force the GLM algo to use the exact same linear algebra as the Kriging algorithm
97   if (ResourceMap::GetAsString("KrigingAlgorithm-LinearAlgebra") == "HMAT") glmAlgo_.setMethod(1);
98   else glmAlgo_.setMethod(0);
99 }
100 
101 /* Virtual constructor */
clone() const102 KrigingAlgorithm * KrigingAlgorithm::clone() const
103 {
104   return new KrigingAlgorithm(*this);
105 }
106 
computeGamma()107 void KrigingAlgorithm::computeGamma()
108 {
109   // Get cholesky factor & rho from glm
110   LOGINFO("Solve L^t.gamma = rho");
111   if (ResourceMap::GetAsString("KrigingAlgorithm-LinearAlgebra") == "HMAT")
112   {
113     gamma_ = covarianceCholeskyFactorHMatrix_.solveLower(rho_, true);
114   }
115   else
116   {
117     // Arguments are keepIntact=true, matrix_lower=true & solving_transposed=true
118     gamma_ = covarianceCholeskyFactor_.getImplementation()->solveLinearSystemTri(rho_, true, true, true);
119   }
120 }
121 
122 /* Perform regression */
run()123 void KrigingAlgorithm::run()
124 {
125   LOGINFO("Launch GeneralLinearModelAlgorithm for the optimization");
126   glmAlgo_.run();
127   LOGINFO("End of GeneralLinearModelAlgorithm run");
128 
129   // Covariance coefficients are computed once, ever if optimiser is fixed
130   rho_ = glmAlgo_.getRho();
131 
132   /* Method that returns the covariance factor - hmat */
133   const GeneralLinearModelResult glmResult(glmAlgo_.getResult());
134   if (ResourceMap::GetAsString("KrigingAlgorithm-LinearAlgebra") == "HMAT")
135     covarianceCholeskyFactorHMatrix_ = glmResult.getHMatCholeskyFactor();
136   else
137     covarianceCholeskyFactor_ = glmResult.getCholeskyFactor();
138   LOGINFO("Compute the interpolation part");
139   computeGamma();
140   LOGINFO("Store the estimates");
141   LOGINFO("Build the output meta-model");
142   Function metaModel;
143   // We use directly the collection of points
144   const BasisCollection basis(glmResult.getBasisCollection());
145   const CovarianceModel conditionalCovarianceModel(glmResult.getCovarianceModel());
146   const Collection<Point> trendCoefficients(glmResult.getTrendCoefficients());
147   const UnsignedInteger outputDimension = outputSample_.getDimension();
148   Sample covarianceCoefficients(inputSample_.getSize(), outputDimension);
149   covarianceCoefficients.getImplementation()->setData(gamma_);
150   // Meta model definition
151   metaModel.setEvaluation(new KrigingEvaluation(basis, inputSample_, conditionalCovarianceModel, trendCoefficients, covarianceCoefficients));
152   metaModel.setGradient(new KrigingGradient(basis, inputSample_, conditionalCovarianceModel, trendCoefficients, covarianceCoefficients));
153   metaModel.setHessian(new CenteredFiniteDifferenceHessian(ResourceMap::GetAsScalar( "CenteredFiniteDifferenceGradient-DefaultEpsilon" ), metaModel.getEvaluation()));
154 
155   // compute residual, relative error
156   const Point outputVariance(outputSample_.computeVariance());
157   const Sample mY(metaModel(inputSample_));
158   //const Sample mY(outputSample_.getSize(), outputSample_.getDimension());
159   const Point squaredResiduals((outputSample_ - mY).computeRawMoment(2));
160 
161   const UnsignedInteger size = inputSample_.getSize();
162   Point residuals(outputDimension);
163   Point relativeErrors(outputDimension);
164   for (UnsignedInteger outputIndex = 0; outputIndex < outputDimension; ++ outputIndex)
165   {
166     residuals[outputIndex] = sqrt(squaredResiduals[outputIndex] / size);
167     relativeErrors[outputIndex] = squaredResiduals[outputIndex] / outputVariance[outputIndex];
168   }
169   result_ = KrigingResult(inputSample_, outputSample_, metaModel, residuals, relativeErrors, basis, trendCoefficients, conditionalCovarianceModel, covarianceCoefficients, covarianceCholeskyFactor_, covarianceCholeskyFactorHMatrix_);
170 }
171 
172 
173 /* String converter */
__repr__() const174 String KrigingAlgorithm::__repr__() const
175 {
176   return OSS() << "class=" << getClassName();
177 }
178 
179 
getInputSample() const180 Sample KrigingAlgorithm::getInputSample() const
181 {
182   return inputSample_;
183 }
184 
185 
getOutputSample() const186 Sample KrigingAlgorithm::getOutputSample() const
187 {
188   return outputSample_;
189 }
190 
191 
getResult()192 KrigingResult KrigingAlgorithm::getResult()
193 {
194   return result_;
195 }
196 
197 /* Optimization solver accessor */
getOptimizationAlgorithm() const198 OptimizationAlgorithm KrigingAlgorithm::getOptimizationAlgorithm() const
199 {
200   return glmAlgo_.getOptimizationAlgorithm();
201 }
202 
setOptimizationAlgorithm(const OptimizationAlgorithm & solver)203 void KrigingAlgorithm::setOptimizationAlgorithm(const OptimizationAlgorithm & solver)
204 {
205   glmAlgo_.setOptimizationAlgorithm(solver);
206 }
207 
208 
209 /* Accessor to optimization bounds */
setOptimizationBounds(const Interval & optimizationBounds)210 void KrigingAlgorithm::setOptimizationBounds(const Interval & optimizationBounds)
211 {
212   glmAlgo_.setOptimizationBounds(optimizationBounds);
213 }
214 
getOptimizationBounds() const215 Interval KrigingAlgorithm::getOptimizationBounds() const
216 {
217   return glmAlgo_.getOptimizationBounds();
218 }
219 
220 /* Log-Likelihood function accessor */
getReducedLogLikelihoodFunction()221 Function KrigingAlgorithm::getReducedLogLikelihoodFunction()
222 {
223   return glmAlgo_.getObjectiveFunction();
224 }
225 
226 /* Optimize parameters flag accessor */
getOptimizeParameters() const227 Bool KrigingAlgorithm::getOptimizeParameters() const
228 {
229   return glmAlgo_.getOptimizeParameters();
230 }
231 
setOptimizeParameters(const Bool optimizeParameters)232 void KrigingAlgorithm::setOptimizeParameters(const Bool optimizeParameters)
233 {
234   glmAlgo_.setOptimizeParameters(optimizeParameters);
235 }
236 
237 /* Observation noise accessor */
setNoise(const Point & noise)238 void KrigingAlgorithm::setNoise(const Point & noise)
239 {
240   glmAlgo_.setNoise(noise);
241 }
242 
getNoise() const243 Point KrigingAlgorithm::getNoise() const
244 {
245   return glmAlgo_.getNoise();
246 }
247 
getMethod() const248 String KrigingAlgorithm::getMethod() const
249 {
250   const UnsignedInteger method = glmAlgo_.getMethod();
251   if (method) return "HMAT";
252   return "LAPACK";
253 }
254 
setMethod(const String & method)255 void KrigingAlgorithm::setMethod(const String & method)
256 {
257   if (method == "HMAT")
258     glmAlgo_.setMethod(1);
259   glmAlgo_.setMethod(0);
260 }
261 
262 /* Method save() stores the object through the StorageManager */
save(Advocate & adv) const263 void KrigingAlgorithm::save(Advocate & adv) const
264 {
265   MetaModelAlgorithm::save(adv);
266   adv.saveAttribute( "inputSample_", inputSample_ );
267   adv.saveAttribute( "outputSample_", outputSample_ );
268   adv.saveAttribute( "covarianceModel_", covarianceModel_ );
269   adv.saveAttribute( "result_", result_ );
270   adv.saveAttribute( "covarianceCholeskyFactor_", covarianceCholeskyFactor_ );
271 }
272 
273 
274 /* Method load() reloads the object from the StorageManager */
load(Advocate & adv)275 void KrigingAlgorithm::load(Advocate & adv)
276 {
277   MetaModelAlgorithm::load(adv);
278   adv.loadAttribute( "inputSample_", inputSample_ );
279   adv.loadAttribute( "outputSample_", outputSample_ );
280   adv.loadAttribute( "covarianceModel_", covarianceModel_ );
281   adv.loadAttribute( "result_", result_ );
282   adv.loadAttribute( "covarianceCholeskyFactor_", covarianceCholeskyFactor_ );
283 }
284 
285 END_NAMESPACE_OPENTURNS
286