ROL
ROL_AbsoluteValue.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Rapid Optimization Library (ROL) Package
4 //
5 // Copyright 2014 NTESS and the ROL contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef ROL_ABSOLUTEVALUE_HPP
11 #define ROL_ABSOLUTEVALUE_HPP
12 
13 #include "ROL_Types.hpp"
14 #include "ROL_PositiveFunction.hpp"
15 #include "ROL_ParameterList.hpp"
16 
17 namespace ROL {
18 
25 };
26 
27 template<class Real>
28 class AbsoluteValue : public PositiveFunction<Real> {
29 private:
30  Real param_;
32 
33 public:
35  : param_(1./param), eav_(eav) {
36  if ( eav != ABSOLUTEVALUE_TRUE && std::abs(param) < ROL_EPSILON<Real>() ) { param_ = 1.e2; }
37  }
38 
39  AbsoluteValue(ROL::ParameterList &parlist) {
40  Real param = parlist.get("Smoothing Parameter",1.);
41  param_ = 1./((param > 0.) ? param : 1.);
42  std::string type = parlist.get("Absolute Value Approximation","true");
44  if ( type == "Square Root" ) { eav_ = ABSOLUTEVALUE_SQUAREROOT; }
45  else if ( type == "Square Root Denominator" ) { eav_ = ABSOLUTEVALUE_SQRTDENOM; }
46  else if ( type == "C2") { eav_ = ABSOLUTEVALUE_C2; }
47  else if ( type == "true") { eav_ = ABSOLUTEVALUE_TRUE; }
48  }
49 
50  Real evaluate(Real input, int deriv) {
51  Real val = 0.0;
52  switch(eav_) {
53  case ABSOLUTEVALUE_TRUE: val = true_absolute_value(input,deriv); break;
54  case ABSOLUTEVALUE_SQUAREROOT: val = sqrt_absolute_value(input,deriv); break;
55  case ABSOLUTEVALUE_SQRTDENOM: val = sqrtd_absolute_value(input,deriv); break;
56  case ABSOLUTEVALUE_C2: val = c2_absolute_value(input,deriv); break;
57  default:
58  ROL_TEST_FOR_EXCEPTION( true, std::invalid_argument,
59  ">>> ERROR (ROL::AbsoluteValue): Absolute value approximation not defined!");
60  }
61  return val;
62  }
63 
64 private:
65  Real true_absolute_value( Real input, int deriv ) {
66  Real output = 0.0, e = 0.0;
67  if ( std::abs(param_) > ROL_EPSILON<Real>() ) { e = 0.5/param_; }
68 
69  int region = 0;
70  if ( input < -e ) { region = -1; }
71  else if ( input > e ) { region = 1; }
72 
73  if ( deriv == 0 ) { output = std::abs(input); }
74  else if ( deriv == 1 ) { output = (input < 0.0 ? -1.0 : 1.0); }
75  else if ( deriv == 2 ) {
76  if ( region == -1 ) { output = 0.0; }
77  else if ( region == 0 ) { output = e*std::exp( -1.0/(1.0 - std::pow(std::abs(input/e),2.0)) ); }
78  else if ( region == 1 ) { output = 0.0; }
79  }
80  return output;
81  }
82 
83  Real sqrt_absolute_value( Real input, int deriv ) {
84  Real output = 0.0;
85  if ( deriv == 0 ) { output = std::sqrt(input*input + 1.0/param_); }
86  else if ( deriv == 1 ) { output = input/std::sqrt(input*input+1.0/param_); }
87  else if ( deriv == 2 ) { output = (1.0/param_)/std::pow(input*input+1.0/param_,1.5); }
88  return output;
89  }
90 
91  Real sqrtd_absolute_value( Real input, int deriv ) {
92  Real output = 0.0;
93  if ( deriv == 0 ) { output = input*input/std::sqrt(input*input + 1.0/param_); }
94  else if ( deriv == 1 ) { output = (2.0/param_*input+std::pow(input,3.0)) /
95  std::pow(input*input+1.0/param_,1.5); }
96  else if ( deriv == 2 ) { output = ((2.0/param_-input*input)/param_) /
97  std::pow(input*input+1.0/param_,2.5); }
98  return output;
99  }
100 
101  Real c2_absolute_value( Real input, int deriv ) {
102  Real output = 0.0, e = 1.0;
103  if ( std::abs(param_) > ROL_EPSILON<Real>() ) { e = 0.5/param_; }
104 
105  int region = 0;
106  if ( input < -e ) { region = -1; }
107  else if ( input > e ) { region = 1; }
108 
109  if ( deriv == 0 ) {
110  if ( std::abs(region) == 1 ) { output = std::abs(input); }
111  else if ( region == 0 ) { output = 1.875*std::pow(input*e,2.0) -
112  1.25 *std::pow(input*e,4.0) +
113  0.375*std::pow(input*e,6.0); }
114  }
115  else if ( deriv == 1 ) {
116  if ( std::abs(region) == 1 ) { output = (input < 0.0 ? -1.0 : 1.0); }
117  else if ( region == 0 ) { output = e*2.0*1.875*input*e -
118  e*4.0*1.25 *std::pow(input*e,3.0) +
119  e*6.0*0.375*std::pow(input*e,5.0); }
120  }
121  else if ( deriv == 2 ) {
122  if ( std::abs(region) == 1 ) { output = 0.0; }
123  else if ( region == 0 ) { output = e* 2.0*1.875 -
124  e*e*12.0*1.25 *std::pow(input*e,2.0) +
125  e*e*30.0*0.375*std::pow(input*e,4.0); }
126  }
127  return output;
128  }
129 };
130 
131 }
132 
133 #endif
Real sqrtd_absolute_value(Real input, int deriv)
Contains definitions of custom data types in ROL.
Real c2_absolute_value(Real input, int deriv)
AbsoluteValue(Real param=1., EAbsoluteValue eav=ABSOLUTEVALUE_TRUE)
Real sqrt_absolute_value(Real input, int deriv)
AbsoluteValue(ROL::ParameterList &parlist)
Real evaluate(Real input, int deriv)
Real true_absolute_value(Real input, int deriv)