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