1 //                                               -*- C++ -*-
2 /**
3  *  @brief NearestPointProblem allows to describe an optimization problem
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 #include <cstdlib>
22 
23 #include "openturns/NearestPointProblem.hxx"
24 #include "openturns/ResourceMap.hxx"
25 #include "openturns/PersistentObjectFactory.hxx"
26 #include "openturns/LinearFunction.hxx"
27 #include "openturns/QuadraticFunction.hxx"
28 
29 BEGIN_NAMESPACE_OPENTURNS
30 
31 CLASSNAMEINIT(NearestPointProblem)
32 
33 static const Factory<NearestPointProblem> Factory_NearestPointProblem;
34 
35 /* Default constructor */
NearestPointProblem()36 NearestPointProblem::NearestPointProblem()
37   : OptimizationProblemImplementation()
38   , levelValue_(0.0)
39 {
40   // Nothing to do
41 }
42 
43 /* Constructor for nearest point problem */
NearestPointProblem(const Function & levelFunction,Scalar levelValue)44 NearestPointProblem::NearestPointProblem(const Function & levelFunction,
45     Scalar levelValue)
46   : OptimizationProblemImplementation()
47   , levelValue_(levelValue)
48 {
49   setLevelFunction(levelFunction);
50 }
51 
52 /* Virtual constructor */
clone() const53 NearestPointProblem * NearestPointProblem::clone() const
54 {
55   return new NearestPointProblem(*this);
56 }
57 
58 
59 /* Level function accessor */
getLevelFunction() const60 Function NearestPointProblem::getLevelFunction() const
61 {
62   return levelFunction_;
63 }
64 
setLevelFunction(const Function & levelFunction)65 void NearestPointProblem::setLevelFunction(const Function & levelFunction)
66 {
67   if (levelFunction.getOutputDimension() != 1) throw InvalidArgumentException(HERE) << "Error: level function has an output dimension=" << levelFunction.getOutputDimension() << " but only dimension 1 is supported.";
68 
69   levelFunction_ = levelFunction;
70   dimension_ = levelFunction_.getInputDimension();
71   // Update objective function
72   const Point center(dimension_);
73   const Point constant(1);
74   const Matrix linear(dimension_, 1);
75   const IdentityMatrix identity(dimension_);
76   const SymmetricTensor quadratic(dimension_, 1, *(identity.getImplementation().get()));
77   objective_ = QuadraticFunction(center, constant, linear, quadratic);
78   setNearestPointConstraints();
79   setVariablesType(Indices(dimension_, CONTINUOUS));
80 }
81 
hasLevelFunction() const82 Bool NearestPointProblem::hasLevelFunction() const
83 {
84   return true;
85 }
86 
87 /* Level value accessor */
getLevelValue() const88 Scalar NearestPointProblem::getLevelValue() const
89 {
90   return levelValue_;
91 }
92 
setLevelValue(Scalar levelValue)93 void NearestPointProblem::setLevelValue(Scalar levelValue)
94 {
95   levelValue_ = levelValue;
96   if (levelFunction_.getEvaluation().getImplementation()->isActualImplementation()) setNearestPointConstraints();
97 }
98 
setNearestPointConstraints()99 void NearestPointProblem::setNearestPointConstraints()
100 {
101   const Point center(dimension_);
102   const Matrix linear(dimension_, 1);
103   LinearFunction constantFunction(center, Point(1, levelValue_), linear.transpose());
104   Function equalityConstraint(levelFunction_);
105   equalityConstraint_ = equalityConstraint.operator - (constantFunction);
106   inequalityConstraint_ = Function();
107 }
108 
clearLevelFunction()109 void NearestPointProblem::clearLevelFunction()
110 {
111   if (levelFunction_.getEvaluation().getImplementation()->isActualImplementation())
112   {
113     LOGWARN(OSS() << "Clearing level function");
114     levelFunction_ = Function();
115   }
116   levelValue_ = 0.0;
117 }
118 
119 
120 /* String converter */
__repr__() const121 String NearestPointProblem::__repr__() const
122 {
123   OSS oss;
124   oss << "class=" << NearestPointProblem::GetClassName();
125   oss << " level function=" << levelFunction_.__repr__()
126       << " level value=" << levelValue_
127       << " dimension=" << dimension_;
128   return oss;
129 }
130 
131 /* Method save() stores the object through the StorageManager */
save(Advocate & adv) const132 void NearestPointProblem::save(Advocate & adv) const
133 {
134   OptimizationProblemImplementation::save(adv);
135   adv.saveAttribute( "levelFunction_", levelFunction_ );
136   adv.saveAttribute( "levelValue_", levelValue_ );
137 }
138 
139 /* Method load() reloads the object from the StorageManager */
load(Advocate & adv)140 void NearestPointProblem::load(Advocate & adv)
141 {
142   OptimizationProblemImplementation::load(adv);
143   adv.loadAttribute( "levelFunction_", levelFunction_ );
144   adv.loadAttribute( "levelValue_", levelValue_ );
145 }
146 
147 END_NAMESPACE_OPENTURNS
148