-
Notifications
You must be signed in to change notification settings - Fork 122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Error during compilation of a code trying to calculate the jacobian of a function with many function calls #533
Comments
Hi Aniket, There are multiple problems involved here, few of them are current limitations of Clad. I'd like to briefly go over the important ones. Right now, I will go over the main issue -- incorrect compilation command used. I will go over other important issues tomorrow. For now, please note that Clad does not support this example as it is. We will need to make changes to the example to make it work. Compilation command issue The compilation command used is not quite correct. Using clang I would suggest you to explicitly pass options to the clang compiler from the clang driver using
|
Hi @parth-07, actually this issue has been raised with the intention of making clad support object oriented programming and other constructs. |
Hi @A-K-Mishra Yes, currently, Clad does not support your example code. It would currently crash with the example you have provided. Reverse mode currently does not support pointers.It is something pending for a long time. It is not necessarily difficult, but we haven't had a chance to implement this in But this should not be a blocker for you if you can convert pointers to references in the code that is to be differentiated. Global variables are assumed to be constant.This is by design. Functions that are to be differentiated by Clad are expected to be pure. That informally means, the same input should give the same output. Global variables potentially violate this. One effect of considering global variables to be constant is that there is no corresponding derivative variable of global variables. This behaviour can result in incorrect behaviour depending on how global variables are used within the primal function. This is also not necessarily a blocker if you can pass Differentiable class type needs to have a default constructor that represents zero derivative object for the class.It was the first prototype, we did not get time to improve it. Design can definitely be improved here by making things more explicit. We would always need some way to define zero-derivative objects of a class.
There are other issues as well, for example, differentiating
If the goal is to make Clad support object-oriented differentiable programming, then I would recommend first supporting all the necessary constructs in the forward and reverse mode AD. We should focus on other modes (hessian, and jacobian) later on. Jacobian mode, in particular, has a few existing bugs which should be fixed first. Please let me know if you want to have a discussion about object-oriented differentiable programming. |
Hi @A-K-Mishra I have changed the code presented in the issue such that it works with Clad. #include "clad/Differentiator/Differentiator.h"
#include <iostream>
#include <vector>
using namespace std;
struct C_Super {
C_Super() {}
vector<double> _jumps;
vector<double> _jumpsValue;
C_Super(vector<double> &jumps, vector<double> &jumpsValue)
: _jumps(jumps), _jumpsValue(jumpsValue) {}
};
namespace clad {
namespace custom_derivatives {
void multiply_val_pullback(::std::vector<double> &v, int idx, double val,
::clad::array_ref<::std::vector<double>> d_v,
::clad::array_ref<int> d_idx,
::clad::array_ref<double> d_val) {
double t = *d_val;
*d_val = 0;
(*d_v)[idx] += val * t;
*d_val += v[idx] * t;
}
} // namespace custom_derivatives
} // namespace clad
void multiply_val(::std::vector<double> &v, int idx, double &val) {
val *= v[idx];
}
// Region I can't control
// starts here
vector<double> jumps({-1, 0.2, 4.5, 9.0, 7.7}),
jumpsValue({0.1, 0.01, 0.3, 0.1, 0.1});
C_Super *C_obj = new C_Super(jumps, jumpsValue);
C_Super *d_C_obj = new C_Super();
// ends here
double calculate_m(C_Super &obj, double t) {
double jumpEffect = 1.0;
for (int i = 0; i < obj._jumps.size(); i++) {
if (obj._jumps[i] >= 0 && obj._jumps[i] <= t) {
multiply_val(obj._jumpsValue, i, jumpEffect);
}
}
return jumpEffect;
}
double calculate(double t, C_Super &c) {
// return 0.0;
return calculate_m(c, t);
}
void npvCalc(double t, double t_end, C_Super &c, double &npv) {
npv = 0.4 * calculate(t, c) + 0.6 * calculate(t_end, c);
}
double npvCalcWrapper(double t, double t_end, C_Super &c, double &npv) {
npvCalc(t, t_end, c, npv);
return npv;
}
int main() {
double t1 = 0.1, t2 = 10.0;
double npv[1] = {};
double derivatives[2] = {};
auto d_npv = clad::gradient(npvCalcWrapper);
d_npv.dump();
// d_npv.execute(t1, t2, npv, derivatives);
} Notable changes are:
multiply_val(obj._jumpsValue, i, jumpEffect); namespace clad {
namespace custom_derivatives {
void multiply_val_pullback(::std::vector<double> &v, int idx, double val,
::clad::array_ref<::std::vector<double>> d_v,
::clad::array_ref<int> d_idx,
::clad::array_ref<double> d_val) {
double t = *d_val;
*d_val = 0;
(*d_v)[idx] += val * t;
*d_val += v[idx] * t;
}
} // namespace custom_derivatives
} // namespace clad
void multiply_val(::std::vector<double> &v, int idx, double &val) {
val *= v[idx];
} We need to add support for the below two features to support automatic differentiation of
Apart from this, I suspect the below loop is being differentiated incorrectly: for (int i = 0; i < obj._jumps.size(); i++) {
if (obj._jumps[i] >= 0 && obj._jumps[i] <= t) {
jumpEffect *= obj._jumpsValue[i];
}
} As per the differentiated code, Please let me know if you have any questions. |
Consider the code:
This code on compilation with the command:
clang-15 -cc1 -x c++ -std=c++11 -load '/content/inst/lib/clad.so' -plugin clad sample.cpp
gives the following Stack dump:
The text was updated successfully, but these errors were encountered: