coin-or / CppAD

A C++ Algorithmic Differentiation Package: Home Page
https://cppad.readthedocs.io
Other
446 stars 94 forks source link

Using C++ conditional operators #149

Closed nixwang closed 2 years ago

nixwang commented 2 years ago

I define a function like this. I have ensured the pos_x is right from 0.0 to 10.0. But the output is always 0.0, seen that the comparison do not work.

AD<double> _threshold = 4.8;
AD<double> _p_set = 0.48;
AD<double> _zero_set = 0.0;
AD<double> get_p(AD<double> pos_x){
  return (pos_x > _threshold) ? _pitch_set : _zero_set;
}

So I tested the output of 'AD pos_x'. test1 can output the right data from 0.0 to 10.0, but test2 output the wrong data with always 0.0.

test1

AD<double> get_p(AD<double> pos_x){
    return pos_x;
  }

test2

AD<double> get_p(AD<double> pos_x){
  double _pos_x = Value( Var2Par(pos_x));
  return _pos_x;
}

So can you provide any suggestion please, thanks a lot.

bradbell commented 2 years ago

Your example above is somewhat incomplete. I assume you are creating an ADFun object corresponding to get_p(x) and then evaluating it. If so, using the test2 definition, you will always get the value of x during the creation of the ADFun object because you have converted x from a variable to a constant parameter; see https://coin-or.github.io/CppAD/doc/var2par.htm

nixwang commented 2 years ago

Yes, your assume is right. In fact, the parameter 'pos_x' of function 'get_p' is a variable when optimizing, but I can not get the right result with following code. So is there any problem in the following code? Is the problem in the comparison ' (pos_x > _threshold)'?

AD<double> _threshold = 4.8;
AD<double> _p_set = 0.48;
AD<double> _zero_set = 0.0;
AD<double> get_p(AD<double> pos_x){
  return (pos_x > _threshold) ? _pitch_set : _zero_set;
}
nixwang commented 2 years ago

Here is more code.

class FG_eval {
public:
// Fitted polynomial coefficients
Eigen::VectorXd ref_wp;
FG_eval(Eigen::VectorXd ref_wp) { this->ref_wp = ref_wp; }

AD<double> _threshold = 4.8;
AD<double> _pitch_set = 0.48;
AD<double> _zero_set = 0.0;

AD<double> get_pitch(AD<double> pos_x){
  return (pos_x > _threshold) ? _pitch_set : _zero_set;
}

typedef CPPAD_TESTVECTOR(AD<double>) ADvector;
void operator()(ADvector &fg, const ADvector &vars) {
.........
........
........
}
bradbell commented 2 years ago

This is because comparison operations have a bool result and hence are not part of the operation sequence that gets recorded; see https://coin-or.github.io/CppAD/doc/glossary.htm#Operation.Sequence In a case like this you need to make a new recording of the function when the comparison results change; see https://coin-or.github.io/CppAD/doc/compare_change.htm

I think what you want is a conditional expression; see https://coin-or.github.io/CppAD/doc/condexp.htm

nixwang commented 2 years ago

Wow, wonderful, the conditional expression is work. Thanks a lot.