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