1 // @HEADER
2 // ************************************************************************
3 //
4 //               Rapid Optimization Library (ROL) Package
5 //                 Copyright (2014) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact lead developers:
38 //              Drew Kouri   (dpkouri@sandia.gov) and
39 //              Denis Ridzal (dridzal@sandia.gov)
40 //
41 // ************************************************************************
42 // @HEADER
43 
44 #ifndef ROL_UNARYFUNCTIONS_H
45 #define ROL_UNARYFUNCTIONS_H
46 
47 #include "ROL_Types.hpp"
48 #include "ROL_Elementwise_Function.hpp"
49 
50 #include <cstdlib>
51 #include <ctime>
52 #include <random>
53 #include <chrono>
54 
55 
56 namespace ROL {
57 namespace Elementwise {
58 
59 // Used to set every element in a vector to a specific value
60 template<class Real>
61 class Fill : public UnaryFunction<Real> {
62 public:
Fill(const Real & value)63   Fill( const Real &value ) : value_(value) {}
apply(const Real & x) const64   Real apply( const Real &x ) const {
65     return value_;
66   }
67 private:
68   Real value_;
69 }; // class Fill
70 
71 // Used to shift every element in a vector by a specific value
72 template<class Real>
73 class Shift : public UnaryFunction<Real> {
74 private:
75   Real value_;
76 public:
Shift(const Real & value)77   Shift( const Real &value ) : value_(value) {}
apply(const Real & x) const78   Real apply( const Real &x ) const {
79     return x+value_;
80   }
81 }; // class Shift
82 
83 
84 // Get the elementwise reciprocal of a vector
85 template<class Real>
86 class Reciprocal : public UnaryFunction<Real> {
87 public:
apply(const Real & x) const88   Real apply( const Real &x ) const {
89     return static_cast<Real>(1)/x;
90   }
91 }; // class Reciprocal
92 
93 // Get the elementwise absolute value of a vector
94 template<class Real>
95 class AbsoluteValue : public UnaryFunction<Real> {
96 public:
apply(const Real & x) const97   Real apply( const Real &x ) const {
98     return std::abs(x);
99   }
100 
101 };
102 
103 template<class Real>
104 class Sign : public Elementwise::UnaryFunction<Real> {
105 private:
106   Real zero_;
107   Real one_;
108 public:
Sign()109   Sign() : zero_(0), one_(1) {}
apply(const Real & x) const110   Real apply(const Real &x) const {
111     if(x==zero_) {
112       return zero_;
113     }
114     else {
115       return x>zero_ ? one_ : -one_;
116     }
117    }
118 };
119 
120 
121 // Compute the elementwise power of a vector
122 template<class Real>
123 class Power : public UnaryFunction<Real> {
124 private:
125   Real exponent_;
126 public:
Power(const Real & exponent)127   Power( const Real &exponent ) : exponent_(exponent) {}
128 
apply(const Real & x) const129   Real apply( const Real &x ) const {
130     return std::pow(x,exponent_);
131   }
132 }; // class Power
133 
134 
135 // Compute the elementwise square root of a vector
136 template<class Real>
137 class SquareRoot : public UnaryFunction<Real> {
138 public:
SquareRoot(void)139   SquareRoot( void ) {}
140 
apply(const Real & x) const141   Real apply( const Real &x ) const {
142     return std::sqrt(x);
143   }
144 }; // class Power
145 
146 
147 // Generate a normally distributed random number
148 // with mean mu and standard deviation sigma
149 template<class Real>
150 class NormalRandom : public UnaryFunction<Real> {
151 private:
152   Ptr<std::mt19937_64>  gen_;
153   Ptr<std::normal_distribution<Real>> dist_;
154 
155 public:
NormalRandom(const Real & mu=0.0,const Real & sigma=1.0,const unsigned & iseed=0)156   NormalRandom(const Real &mu = 0.0, const Real &sigma = 1.0,
157                const unsigned &iseed = 0) {
158     unsigned seed = iseed;
159     if (seed == 0) {
160       seed = std::chrono::system_clock::now().time_since_epoch().count();
161     }
162     gen_  = makePtr<std::mt19937_64>(seed);
163     dist_ = makePtr<std::normal_distribution<Real>>(mu,sigma);
164   }
165 
apply(const Real & x) const166   Real apply( const Real &x ) const {
167     return (*dist_)(*gen_);
168   }
169 }; // class NormalRandom
170 
171 
172 // Generate a uniformly distributed random number
173 // between lower and upper
174 template<class Real>
175 class UniformlyRandom : public UnaryFunction<Real> {
176 private:
177   const Real lower_;
178   const Real upper_;
179 
180 public:
UniformlyRandom(const Real & lower=0.0,const Real & upper=1.0)181   UniformlyRandom( const Real &lower = 0.0, const Real &upper = 1.0) :
182     lower_(lower), upper_(upper) {
183   }
184 
apply(const Real & x) const185   Real apply( const Real &x ) const {
186     return (static_cast<Real>(rand()) / static_cast<Real>(RAND_MAX)) * (upper_-lower_) + lower_;
187   }
188 }; // class UniformlyRandom
189 
190 // Multiply element by a uniformly distributed random number
191 // between lower and upper
192 template<class Real>
193 class UniformlyRandomMultiply : public UnaryFunction<Real> {
194 private:
195   const Real lower_;
196   const Real upper_;
197 
198 public:
UniformlyRandomMultiply(const Real & lower=0.0,const Real & upper=1.0)199   UniformlyRandomMultiply( const Real &lower = 0.0, const Real &upper = 1.0) :
200     lower_(lower), upper_(upper) {
201   }
202 
apply(const Real & x) const203   Real apply( const Real &x ) const {
204     return x*((static_cast<Real>(rand()) / static_cast<Real>(RAND_MAX)) * (upper_-lower_) + lower_);
205   }
206 }; // class UniformlyRandom
207 
208 
209 
210 // Returns max(x,s) where s is the given scalar
211 template<class Real>
212 class ThresholdUpper : public UnaryFunction<Real> {
213 
214 private:
215   const Real threshold_;
216 
217 public:
ThresholdUpper(const Real threshold)218   ThresholdUpper( const Real threshold ) :
219     threshold_(threshold) {}
220 
apply(const Real & x) const221   Real apply( const Real &x ) const {
222     return std::max(threshold_,x);
223   }
224 };
225 
226 // Returns min(x,s) where s is the given scalar
227 template<class Real>
228 class ThresholdLower : public UnaryFunction<Real> {
229 
230 private:
231   const Real threshold_;
232 
233 public:
ThresholdLower(const Real threshold)234   ThresholdLower( const Real threshold ) :
235     threshold_(threshold) {}
236 
apply(const Real & x) const237   Real apply( const Real &x ) const {
238     return std::min(threshold_,x);
239   }
240 };
241 
242 
243 template<class Real>
244 class Scale : public UnaryFunction<Real> {
245 private:
246   Real value_;
247 public:
Scale(const Real value)248   Scale( const Real value ) : value_(value) {}
apply(const Real & x) const249   Real apply( const Real &x ) const {
250     return value_*x;
251   }
252 };
253 
254 
255 
256 
257 template<class Real>
258 class Logarithm : public UnaryFunction<Real> {
259 public:
260 
apply(const Real & x) const261   Real apply( const Real &x ) const {
262     // To avoid circular dependency
263     Real NINF = -0.1*std::abs(ROL::ScalarTraits<Real>::rmax());
264     return (x>0) ? std::log(x) : NINF;
265   }
266 
267 };
268 
269 
270 // Heaviside step function
271 template<class Real>
272 class Heaviside : public UnaryFunction<Real> {
273 public:
274 
apply(const Real & x) const275   Real apply( const Real &x ) const {
276     Real value = 0;
277     if( x>0 ) {
278       value = 1.0;
279     } else if( x==0 ) {
280       value = 0.5;
281     } else {
282       value = 0.0;
283     }
284     return value;
285   }
286 
287 };
288 
289 template<class Real>
290 class Round : public UnaryFunction<Real> {
291 public:
Round(void)292   Round(void) {}
apply(const Real & x) const293   Real apply(const Real &x) const {
294     const Real half(0.5), fx = std::floor(x), cx = std::ceil(x);
295     return (x-fx < half ? fx : cx);
296   }
297 };
298 
299 // Evaluate g(f(x))
300 template<class Real>
301 class UnaryComposition : public UnaryFunction<Real> {
302 
303 private:
304 
305   ROL::Ptr<UnaryFunction<Real> > f_;
306   ROL::Ptr<UnaryFunction<Real> > g_;
307 
308 public:
UnaryComposition(ROL::Ptr<UnaryFunction<Real>> & f,ROL::Ptr<UnaryFunction<Real>> & g)309   UnaryComposition( ROL::Ptr<UnaryFunction<Real> > &f,
310                     ROL::Ptr<UnaryFunction<Real> > &g ) : f_(f), g_(g) {}
apply(const Real & x) const311   Real apply( const Real &x ) const {
312     return g_->apply(f_->apply(x));
313   }
314 
315 };
316 
317 
318 
319 } // namespace Elementwise
320 } // namespace ROL
321 
322 #endif // ROL_UNARYFUNCTIONS_H
323