joaoleal / cppadcodegen Goto Github PK
View Code? Open in Web Editor NEWSource Code Generation for Automatic Differentiation using Operator Overloading
License: Other
Source Code Generation for Automatic Differentiation using Operator Overloading
License: Other
cmake/FindCppAD.cmake searches for cppad_ipopt library (libcppad_ipopt.so/.a), but I don't see any other references to ipopt in the code. Does CppADCodeGen use ipopt? If not, can we instead search for the default library cppad_lib (libcppad_lib.so/.a)?
For example, Pinocchio dynamics library uses this Findcppad.cmake:
# Copyright 2020 CNRS INRIA
# Author: Guilhem Saurel, Rohan Budhiraja
# Try to find cppad in standard prefixes and in ${cppad_PREFIX} Once done this
# will define cppad_FOUND - System has cppad cppad_INCLUDE_DIR - The cppad
# include directories cppad_LIBRARY - The libraries needed to use cppad
# cppad_DEFINITIONS - Compiler switches required for using cppad cppad_VERSION -
# Version of cppad found
find_path(
cppad_INCLUDE_DIR
NAMES cppad/configure.hpp
PATHS ${cppad_PREFIX}
PATH_SUFFIXES include)
find_library(
cppad_LIBRARY
NAMES cppad_lib
PATHS ${cppad_PREFIX}
PATH_SUFFIXES lib)
if(cppad_INCLUDE_DIR AND EXISTS "${cppad_INCLUDE_DIR}/cppad/configure.hpp")
file(STRINGS "${cppad_INCLUDE_DIR}/cppad/configure.hpp" cppad_version_str
REGEX "^# *define[\t ]+CPPAD_PACKAGE_STRING[\t ]+\"cppad-.*\"")
string(
REGEX
REPLACE "^# *define[\t ]+CPPAD_PACKAGE_STRING[\t ]+\"cppad-([^\"]*)\".*"
"\\1" cppad_VERSION "${cppad_version_str}")
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
cppad
REQUIRED_VARS cppad_LIBRARY cppad_INCLUDE_DIR
VERSION_VAR cppad_VERSION)
mark_as_advanced(cppad_INCLUDE_DIR cppad_LIBRARY)
Is there any precise schedule for the next release?
I plan to package CppADCodeGen for homebrew (in https://github.com/Gepetto/homebrew-gepetto) and Linux systems (via http://robotpkg.openrobots.org/), and it would be nice to have a new release before that.
Hello,
I wanted to share a problem I ran into using this very well written and very useful library. I work using high dimensional models and my computational graphs tend to be large.
If the computational graph reaches a certain threshold, and the number of arrays and symbols exceed 2GB, we run into a relocation truncated to fit error. You can read more about this kind of error here
https://stackoverflow.com/questions/6093547/what-do-r-x86-64-32s-and-r-x86-64-64-relocation-mean/33289761#33289761
This problem can in principle be addressed by linking with -mcmodel=large or mcmodel=medium flags. However in this case the library generated by CppADCodeGen requires linking to libc.a, which is built in 32 bit mode. Therefore the problem persists.
I believe that if the generated code was C++ with linkage to libgcc.a instead, the problem would be addressed. This in principle should require very little change since from my observations of the generated code all the mathematical operations are supported in C++ and the only difference should be changing the header to include <cmath> and of course renaming the files to use a cpp extension.
I would be happy to make the code changes, but I wanted to understand if that is in principle possible and whether the subsequent loading of the library after compilation would fail if the code was compiled with C++ mangling in the method signatures.
I'm trying to use CppADCodegen, CppAD, and eigen3 in a project, all as header-only libraries. Is there a way to do this in a project using CMake? I try to include all three directories in my project, as such:
target_include_directories(AutodiffEngine PRIVATE ${PROJECT_SOURCE_DIR}/../ExternalLibs/eigen3/Eigen)
target_include_directories(AutodiffEngine PRIVATE ${PROJECT_SOURCE_DIR}/../ExternalLibs/eigen3/unsupported)
target_include_directories(AutodiffEngine PRIVATE ${PROJECT_SOURCE_DIR}/../ExternalLibs/CppAD)
target_include_directories(AutodiffEngine PRIVATE ${PROJECT_SOURCE_DIR}/../ExternalLibs/CppADCodeGen/include)
This works fine for Eigen3 and CppAD, but not for codegen. Is there a way to use CppADCodegen in a similar way?
Using version 2.4.1 I get the following message
... snip ...
multiple definition of `CppAD::cg::readStringFromFile(
std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> > const&)';
... snip ...
The following patch seems to fix the problem:
sed -i include/cppad/cg/util.hpp \
-e 's|^std::string readStringFromFile(|inline &|'
First: Great Work! This provides sparse derivatives without memory allocations as far as I
understand. Before, I was using Eigen::AutoDiffScalar<Eigen::SparseVector>.
Here a slightly adapted code from the trivial example. The code uses Eigen::Vector inplace of std::vector, but somehow this does not compile with gcc-5 oder clang-3.7.
``
#include
#include
#include <cppad/cg.hpp>
#include <cppad/example/cppad_eigen.hpp>
int main() {
// use a special object for source code generation
typedef CppAD::cg::CG CGD; // this is the code generation type
typedef CppAD::AD ADCG;
// independent variable vector
Eigen::Matrix<ADCG,Eigen::Dynamic,1> x(1);
CppAD::Independent(x);
// dependent variable vector
Eigen::Matrix<ADCG,Eigen::Dynamic,1> y(1);
y = 1. * x;
// This works:
//y = CGD(1.) * x;
CppAD::ADFun<CGD> fun(x, y);
}
``
Most important is also, that this code works when using
typedef CppAD::AD ADCG;
I tried to dig into this and from my guesswork somewhere in the clang error messages it says:
/home_local/wern_al/optimalwalk_env_gcc5/install/include/eigen3/Eigen/src/Core/../plugins/CommonCwiseBinaryOps.h:50:29: note:
candidate template ignored: substitution failure [with T = double]: no type named 'type'
in 'Eigen::internal::promote_scalar_arg<CppAD::AD<CppAD::cg::CG >, double,
false>'
EIGEN_MAKE_SCALAR_BINARY_OP(operator*,product)
Here Eigen tries to promote the type (double->ADCG), but this fails. I do not understand this
because the NumTraits are available for the CppAD<T> template.
Hello,
calling "createDynamicLibrary(...)" causes fatal stack overflow
when the code (e.g. for a "zero-order forward") is to be generated for
more complex models.
These contain a one-deimensional "dependent" vector and a high dimensional "independent" one.
The dependencies in the respective function are implemented, i.a., via nested loops (of nesting order > 2) .
Dependent on the complexity of the function body everything works fine below a particular low threshold dimension of the "independent" vector.
Above such a threshold dimension, however, the stack overflow occurs.
This problem is obviously originated in the recursion methods in code_handler_impl.hpp and /lang/c/language_c.hpp. Among the very bad behaving methods seems to be "markCodeBlockUsed(...)" in code_handler_impl.hpp .
Hello,
there occurs a "cppad" error during the code creation of a "sparse" Jacobian.
Please see a code example below (tested in Ubuntu (Wsl, g++) and Windows (VS 2015)):
#include <string.h>
#include <cppad/cg.hpp>
#include <cppad/cg/support/cppadcg_eigen.hpp>
using namespace CppAD;
using namespace CppAD::cg;
typedef CppAD::cg::CG<double> CGD;
typedef CppAD::AD<CGD> ADCG;
typedef Eigen::Matrix<ADCG, Eigen::Dynamic, 1> ADCGvec;
void ThisAdFunc(ADCGvec& adscalar, const ADCGvec& advec, int dim1, int dim2, int dim3) {
adscalar(0) = 0;
double testCoeff = 0;
for (int ii = 0; ii < dim2; ++ii) {
for (int jj = 0; jj < dim1; ++jj) {
adscalar[0] = adscalar[0] + advec((ii*dim1 + jj) * dim3 + 0)*advec((ii*dim1 + jj) * dim3 + 0)
+ testCoeff*advec((ii*dim1 + jj) * dim3 + 1)*advec((ii*dim1 + jj) * dim3 + 1)
+ advec((ii*dim1 + jj) * dim3 + 2)*advec((ii*dim1 + jj) * dim3 + 2);
}
}
}
int main(void) {
int dim1 = 40;
int dim2 = 10;
int dim3 = 3;
ADCGvec thisAdvec(dim1*dim2*dim3);
ADCGvec thisAdscalar(1);
CppAD::Independent(thisAdvec);
ThisAdFunc(thisAdscalar, thisAdvec, dim1, dim2, dim3);
CppAD::ADFun<CGD> adfun(thisAdvec, thisAdscalar);
CppAD::cg::ModelCSourceGen<double> cgen(adfun, "adModel");
// test sparsity:
cgen.setCreateSparseJacobian(true);
std::vector<size_t> mappingCols, mappingRows;
for (int jj = 0; jj < thisAdvec.size(); ++jj) {
mappingCols.push_back( jj);
mappingRows.push_back(0);
}
cgen.setCustomSparseJacobianElements(mappingRows, mappingCols);
CppAD::cg::ModelLibraryCSourceGen<double> libcgen(cgen);
CppAD::cg::DynamicModelLibraryProcessor<double> dynLibProc(libcgen, "<path of dynamic lib.>");
CppAD::cg::GccCompiler<double> compiler("<compiler path>");
string storageDir = "<code storage directory>";
compiler.setSaveToDiskFirst(true);
compiler.setTemporaryFolder(storageDir );
compiler.setSourcesFolder(storageDir );
dynLibProc.createDynamicLibrary(compiler);
return 0;
}
Note, that the error appears if one sets "testCoeff = 0" in the code above.
Moreover, it's obviously unrelated to the values of the dimensions dim1, dim2, dim3.
I have a few quick questions about the sparsity detection that I couldn't figure out from the docs:
It seems from the code that the system evaluates the function once on dummy variables, see which elements of the result are non-empty, and from that, determines the sparsity. Is this correct? If so, how are conditionals in an expression handled? Are they safe here?
How does, say, SparseJacobian() work? Is using :
```
cgen.setCreateSparseJacobian(true);
cgen.setCustomSparseJacobianElements(rows, cols);
The same as using:
`fun.SparseJacobian(x0)`
with
`cgen.setCreateForwardZero(true);`
3. I haven't tried this yet, nor do I know if it's supported, but how would this play with Eigen's SparseMatrix (on input elements)?
/usr/include/cppad/cg/model/dynamic_lib/dynamic_library_processor.hpp: In member function ‘const string* CppAD::cg::DynamicModelLibraryProcessor<Base>::getCustomLibraryExtension() const’:
/usr/include/cppad/cg/model/dynamic_lib/dynamic_library_processor.hpp:84:16: error: cannot convert ‘const std::unique_ptr<const std::__cxx11::basic_string<char> >’ to ‘const string*’ {aka ‘const std::__cxx11::basic_string<char>*’} in return
84 | return _customLibExtension;
| ^~~~~~~~~~~~~~~~~~~
| |
| const std::unique_ptr<const std::__cxx11::basic_string<char> >
OS: ArchLinux
GCC: 9.3.0
CppAD: 20200000.2
Is there any support in CppADCodeGen for third and higher order derivatives?
Hi João,
I'm trying to understand the performance benefits of using CppADCodeGen for doing sparse eigen multiplications.
There is an issue that I'm facing, which I hope you might be able to help with.
In order to do a multiplication of two matrices in Eigen, A*B
, and A.transpose() * B
are almost equivalent in terms of performance. There is no additional computation burder imposed in Eigen because of the .transpose()
operation.
However, when I try to code-generate these two computations, I see a difference in the computation time taken by codegen(A*B)
and codegen(A.transpose() * B)
.
I've added a small unit-test that checks this computation. https://gist.github.com/proyan/76edb14c2835c53e66e086239a7e828f
In this file, there is a code-generated function calc
that computes A*transpose() * B
, where A is a triangular matrix, and B is a diagonal matrix.
When running this calc
function in normal, and code-generated (and compiled) modes, I get the following timings:
$ ./test-cg
calc code-gen = 16.1503 us
calc = 25.685 us
So there is some performance benefit in code-generation.
However, if I remove the .transpose()
operation from the above calc
operation i.e., replace Line 119 of the script with
tmp.OSIMinv_tmp.noalias() = -tmp.U1inv * M.diagonal().asDiagonal();
I get the following timings after compiling the new calc, which computes A*B
:
$ ./test-cg
calc code-gen = 10.1578 us
calc = 25.0839 us
As you can see, there is a difference of 5us (quite high when compared to the total time taken), while the operation in Eigen is following the same computation performance.
I've checked other parts of this function, and solveInPlace
work as it should, and the other matrix multiplication works as it should. Eigen simply changes the order of operations when doing the .transpose()
multiplication, so I'm guessing that there is a flag that is not being taken care of here. But this is only my guess, I wonder if you understand what the issue is here?
Thanks, and best,
Rohan
Hi João,
I would like to generate code for loops where the intermediate results from prior iterations are reused. For example, I define a dynamics function that computes the change in state given the current state, and then define the integrator that for N time steps has to call this function, and integrate the state derivatives that are added up to the current state.
Following your response in issue #10, I adapted one of your pattern examples that generates for-loops. But, as you also mentioned, the pattern detection assumes each entry in the output vector is independent from previous calculations. This seems to be the case even when I manually define the dependent variables that related (see below). Unfortunately, this wouldn't work for my integration example where I have to accumulate results from earlier iterations. The generated code reflects this, when I include a previously computed y
element, this index cannot be part of the generated loop anymore, the calculation gets unrolled for the N iterations:
Extract from the C++ example code:
// independent variable vector
std::vector<ADCG> x(5, ADCG(1));
Independent(x);
// dependent variable vector
std::vector<ADCG> y(8);
// temporary variables
ADCG a, b;
// the model
a = exp(3 * x[1]);
b = 5 * x[0] * x[4];
y[0] = a / 2 + b;
// one equation not defined!
y[1] = x[2] - b;
b = 5 * x[1] * x[3];
y[2] = a / 2 + b + y[0]; // !!! we reuse the result from the previous iteration
y[3] = x[4] * x[1] + b;
y[4] = x[3] - b;
b = 5 * x[2] * x[2];
y[5] = a / 2 + b + y[2]; // !!! we reuse the result from the previous iteration
y[6] = x[4] * x[2] + b;
y[7] = x[4] - b;
ADFun<CGD> fun(x, y);
// ...
// set up the related dependencies as before:
std::vector<std::set<size_t>> relatedDep{{0, 2, 5}, {3, 6}, {1, 4, 7}};
// ...
Generated C code (forward zero pass):
// independent variables
const double* x = in[0];
//dependent variables
double* y = out[0];
// auxiliary variables
double v[2];
unsigned long j;
v[0] = exp(3. * x[1]);
y[0] = v[0] / 2. + 5. * x[0] * x[4];
for(j = 0; j < 3; j++) {
v[1] = 5. * x[j] * x[j * -1 + 4];
if(1 <= j) {
y[j * 3] = x[4] * x[j] + v[1];
}
y[j * 3 + 1] = x[j + 2] - v[1];
}
y[2] = v[0] / 2. + 5. * x[1] * x[3] + y[0];
y[5] = v[0] / 2. + 5. * x[2] * x[2] + y[2]; // !!! {0, 2, 5} are not part of the loop anymore
I also tried to wrap my dynamics function into an inner atomic function and then call it from the outer function (option 2 from your suggestions in #33):
Simulation<...> simulation;
std::vector<ADCG> ax(simulation.input_dim(), ADCG(0));
CppAD::Independent(ax);
std::vector<ADCG> ay(simulation.output_dim());
// First create an ADFun for your inner model:
ADFun<CGD> innerModelFun;
ay = simulation(ax);
innerModelFun.Dependent(ax, ay);
// Then use it during the outer model taping
CGAtomicFunBridge<double> atomicFun("innerModel", innerModelFun, true);
std::vector<ADCG> x_outer(simulation.input_dim(), ADCG(0));
CppAD::Independent(x_outer);
std::vector<ADCG> y_outer(simulation.output_dim());
std::vector<ADCG> state = x_outer, derivative(simulation.output_dim());
for (int t = 0; t < 10; ++t) { // Euler integration
atomicFun(state, derivative);
for (std::size_t i = 0; i < simulation.output_dim(); ++i) {
state[i] += 1e-3 * derivative[i];
}
}
y_outer = state;
ADFun<CGD> outerModelFun;
outerModelFun.Dependent(x_outer, y_outer);
// compile both models in the same lib
ModelCSourceGen<double> cSourceInner(innerModelFun, "innerModel");
ModelCSourceGen<double> cSourceOuter(outerModelFun, "outerModel");
// try to set dependent variables that are related (unsuccessful)
std::vector<std::set<size_t>> relatedDepCandidates;
for (std::size_t i = 0; i < simulation.output_dim(); ++i) {
relatedDepCandidates.push_back({i});
}
cSourceOuter.setRelatedDependents(relatedDepCandidates);
// ...
In the generated code for the outer model, however, the loop is unrolled.
Is there any way to generate code for-loops that reuse intermediate results?
When I try to build the tests (make build_tests
) I get a flood of warnings like shown below:
In file included from /usr/include/c++/9.2.0/x86_64-pc-linux-gnu/bits/os_defines.h:39,
from /usr/include/c++/9.2.0/x86_64-pc-linux-gnu/bits/c++config.h:524,
from /usr/include/c++/9.2.0/bits/stl_algobase.h:59,
from /usr/include/c++/9.2.0/vector:60,
from /home/acxz/vcs/git/github/joaoleal/CppADCodeGen/test/CppADCGTest.hpp:19,
from /home/acxz/vcs/git/github/joaoleal/CppADCodeGen/test/cppad/cg/patterns/CppADCGPatternTest.hpp:18,
from /home/acxz/vcs/git/github/joaoleal/CppADCodeGen/test/cppad/cg/patterns/simple_atomic_2.cpp:15:
/usr/include/features.h:382:4: warning: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Wcpp]
382 | # warning _FORTIFY_SOURCE requires compiling with optimization (-O)
| ^~~~~~~
Add. Info.
GCC: 9.2.0
OS: ArchLinux
Master branch
In my applications, I use CppADCodeGen in the JIT-mode, therefore I compile dynamic libraries at runtime.
After every program execution, a *.so file is left somewhere in my directories. So far, I have used a script to simply clean up after CppADCG - but anyway I've been wondering for a while now: is there an officially supported way to delete the *.so files after they are not needed any more, e.g. at destruction time?
Thanks a lot in advance, and keep up the great work!
Hi Joel,
Thanks for this nice piece of software.
I wonder if you have any plans to release a new version that is compatible with cppad 2020? I see that the last release was made for v2018, and it was more that a year ago.
It would be helpful for us to maintain build compatibility for our software as well.
Best,
Rohan
Hi João,
first of all, thank you for making such a great project open source! I am actively using CppADCodeGen in my research projects and it performs great!
I am mostly working with Rigid Body Dynamics, which are (fairly) large differential equations. This results in generated code for the derivatives that is easily 45k of lines. As suggested, I am using CLANG for compiling them and it makes it bearable. However, I have seen some code in CppADCodeGen that looks like you can break down the derivative code in smaller chunks, i.e. several functions?
So I was wondering whether you are dealing with equally large or larger derivatives? If so, do you have any experience in further reducing compilation time?
If you have any leads, I would highly appreciate it! In return, I could contribute a little example to CppADCodeGen.
Thanks again,
Michael
Using gcc 9.2.1 the program below generates a compile error. It can be fixed by switching the order of the include commands:
# include <cppad/cppad.hpp>
# include <cppad/cg/cppadcg.hpp>
int main(void)
{
typedef CppAD::cg::CG<double> cg_double;
typedef CppAD::AD<cg_double> cppadcg_double;
cppadcg_double r;
r = 0.0;
if( CppAD::IdenticalZero(r) )
return 0;
return 1;
}
I am trying to compile code which employs CppAD-CG on Ubuntu 16.04 with clang++ (3.6).
I run into the following compiler error, coming directly from one of the pattern headers...:
In file included from /usr/local/include/cppad/cg.hpp:18:
In file included from /usr/local/include/cppad/cg/cppadcg.hpp:183:
/usr/local/include/cppad/cg/patterns/iter_equation_group.hpp:253:68: fatal error: default initialization of an object of const type 'const std::map<size_t, std::set<size_t> >' (aka 'const map<unsigned long, set<unsigned long> >') without a user-provided default constructor
const std::map<size_t, std::set<size_t> > IterEquationGroup<Base>::EMPTYMAPSETS;
If I understand it right, the problem might be the following: the default constructor for std::set() has only been made availble from C++14 onwards, for C++11 only compilers it does not exist, see also here and here.
Now that LLVM 10.0 has been released, it would be nice if CppAD CG supports it. As of now LlvmModelLibrary
and LlvmModelLibraryProcessor
are not created for LLVM 10.
Hello @joaoleal ,
I created my own atomic function by deriving from CppAD::cg::CGAbstractAtomicFun.
When invoking the Jacobian method on the dynamicLib model (I'm following the linux example), I get a missingAtomicFunction error.
cppad-20160000.1 error from a known source: Some atomic functions used by the compiled model have not been specified yet Error detected by false result for _missingAtomicFunctions == 0
I saw that the GenericModel class has an addAtomicFunction method. This method however takes an object of the type atomic_base<Base>
. My custom atomic class only has atomic_base<CppAD::cg::CG<Base> >
as a parent.
Could you please hint me into the right direction on how to use user defined atomic functions in code generation models?
Thank you very much
Johannes
Getting error: cannot convert ‘const std::unique_ptr<const std::__cxx11::basic_string<char> >’ to ‘const string*’ {aka ‘const std::__cxx11::basic_string<char>*’} in return
while compiling.
Explicit casting seems to fix this.
Compiler: GCC 9.2.1 and Clang 9.0.1
CppAD: 20200000.2
CppADCodegen: 2.4.2
I managed to define and generate code for functions of the form ADFun adFun(x, y);
, but this is not desirable if x
must always be assembled from an array of independent variable vectors. Luckily, in the file generic_model.hpp I found the following declaration:
/**
* Determines the dependent variable values using a variable number of
* independent variable arrays.
* This method can be useful if the generic model was prepared
* considering that the independent variables are provided by several
* arrays.
*
* @param x Contains the several independent variable vectors
* @param dep The values of the dependent variables
*/
virtual void ForwardZero(const std::vector<const Base*> &x,
ArrayView<Base> dep) = 0;
I would really like to use this functionality! However, I cannot manage to create an ADFun
object that satisfies the above interface (it seems that an adequate constructor is missing). Also, I could not find any examples about this matter. How can I enable my models to be used as in the above snippet?
Current master branch of CppAD allows the use of dynamic parameters.
In other words, it is possible to change at running time some parameters values that are not consider as Independent variables.
See https://github.com/coin-or/CppAD/blob/46be2e2dbcaba47d8a38e8d9110efc48c7245754/cppad/core/new_dynamic.hpp#L103 for further details.
I want to know how to implement this feature in CppADCOdeGen.
@joaoleal can you explain me where I need to edit this new feature?
Attempting to install CppAD and CppADCodeGen using CMake 3.18.4 on macOS 10.15.6 and running into some issues.
First, I clone the master branch of CppAD, and run:
cd CppAD
mkdir build
cd build
cmake ..
make
sudo make install
Everything runs fine, no issues.
Next, I clone the master branch of CppADCodeGen, and run:
cp CppADCodeGen
mkdir build
cd build
cmake ..
and get the error:
CMake Error at cmake/FindCppAD.cmake:99 (MESSAGE):
Found CppAD version '' but at least version '20200000.1' is required
Call Stack (most recent call first):
CMakeLists.txt:42 (FIND_PACKAGE)
Following the instructions here I run grep '^SET(cppad_version' CMakeLists.txt
and get:
SET(cppad_version "20200905")
Evidently the version is high enough but it isn't getting pulled in by FindCppAD.cmake
.
Let me know if I made some mistake in the above. I would expect this approach to "just work"... Thanks.
Hi,
First of all, thanks for developing this great tool! I'm new to CppADCodeGen, I'd like to ask is there any way to get the value of a scalar type CppAD::AD<CppAD::cg::CG<double>>
(or convert this type to the double type). I know in CppAD this is possible by using CppAD::Value()
of Var2Par()
function, but I don't know how to do that in CppADCodeGen. Would you please give me any advice? Thanks a lot!
lines 176 and 184 should be multMatrixMatrixSparsity(...) instead of multMatrixTransMatrixSparsity(...) according to requirements here: https://www.coin-or.org/CppAD/Doc/atomic_rev_sparse_hes.htm
line 125 should be CppAD::cg::multMatrixTransMatrixSparsity(jacSparsity, rT, sT, m, n, q);
In case there is some interest regarding the usability of CppADCodeGen within Windows (e.g. VS 2015) I'd like to share a few basic compatibilty issues.
In fact, these are rather minor but have quite an impact since they appear in several places throughout all the source code.
Therefore, in the following I list representative examples and suggestions for their principle replacements which should work for both, Windows and Linux (g++):
suggested change of, e.g., std::max(size_t(123), 124)
to std::max<size_t>(size_t(123), 124)
and std::min(size_t(123), 124)
to std::min<size_t>(size_t(123), 124)
, i.e. std::max/std::min should carry a template argument specifying the data type which is relevant for the two passed numbers.
suggested change of, e.g., std::numeric_limits<int>::max()
to (std::numeric_limits<int>::max)()
and std::numeric_limits<int>::min()
to (std::numeric_limits<int>::min)()
there exist some problems with the operator <<
, it's overloading and the type size_t
/__int64
in Windows. This, at least, applies only to recent changes (commit from Jun 13, 2019) and, so far, can be easily fixed in /lang/lang_stream_stack.hpp by adding:
friend inline LangStreamStack<Base>& operator<<(LangStreamStack<Base>& lss, size_t i) {
return (lss << std::to_string(i));
}
I have modified the simple example in the documentation by changing the line
y[0] = a / 2;
to
if (a > 1.0) {
y[0] = a / 2;
} else {
y[0] = a * 2;
}
but this results in the following error:
terminate called after throwing an instance of 'CppAD::cg::CGException'
what(): GreaterThanOrZero cannot be called for non-parameters
This means that to generate the code for if/else statements I should use CppAD parameters. However, to the best of my knowledge, this feature is currently missing in CppADCodeGen, where parameters can only be emulated by editing the sparsity patterns of the models. Is there a way to generate the derivatives for code containing if/else statements? If yes, how should I modify the above example to make it work?
Hi,
I am not an AD expert, I have nested conditions and I am wondering if booleans are supported ?
Is this possible "If{ //some code } then{//some code} else{//some code}" (with conditions inside braces) ?
Thank you.
Hi,
I am trying to use eigen determinant together with CppADCG. However, it reports "GreaterThanZero cannot be called for non-parameters" error when the codes are generated for eigen determinant. The codes are compiled ok though. This error occurs at run-time when auto diff codes are generated. My code snippets are listed below:
`void RigidBodyDynamicsPinocchio::CreateManipulabilityAutoDiff(const ADDataStruct& arguments)
{
body_id_ = robot_ad_model_.getFrameId(arguments.body_name_);
auto func = [&, this](const ad_vector_t& x, ad_vector_t& y) {
ad_matrix_t J(6, robot_ad_model_.nq);
pinocchio::computeFrameJacobian(
robot_ad_model_, robot_ad_data_, x, body_id_, pinocchio::LOCAL_WORLD_ALIGNED, J);
y.resize(1);
y[0] = (J * J.eval().transpose()).determinant();
};
manipulability_deriv_ptr_.reset(
new CppAdInterface(func, robot_ad_model_.nq, arguments.model_name_, arguments.model_folder_));
CreateAutoDiffFunc(arguments, manipulability_deriv_ptr_);
}`
If the determinant() is commented out, the codes are generated successfully. Any suggestions for how to fix this? Thanks!
Best regards,
Chris.
I am having trouble getting started using the current version of CppADCodeGen. To be specific, I would like a prescription for how to run a simple example ?
I began with the following:
git clone https://github.com/joaoleal/CppADCodeGen.git cppad_cg.git
cd cppad_cg.git
mkdir build
cd build
cmake ..
And I got the following error message:
CMake Error at test/CMakeLists.txt:54 (MESSAGE):
GoogleTest source folder not found
I tried installing gtest (googletest) on my Fedora-31 system and still got the same error.
So if I understand correctly, it should be possible to add the parameters to the independent variables and then leave them out of the Jacobian calculation by calling setCustomSparseJacobianElements
.
So here's what I'm doing to just compute the left columns in the Jacobian that are of interest:
// Jacobian sparsity
std::vector<size_t> rows;
std::vector<size_t> cols;
for (size_t row = 0; row < jacobian_t::RowsAtCompileTime; row++)
{
for (size_t col = 0; col < jacobian_t::ColsAtCompileTime; col++)
{
rows.push_back(row);
cols.push_back(col);
}
}
cgen.setCustomSparseJacobianElements(rows, cols);
Now this would work if the Jacobian didn't already have zero-elements in it, right? Mine however does have those and I assume this is why it fails with:
cppad-20190200.5 error from unknown source
Error detected by false result for
pattern.is_element(row[k], col[k])
Is there a way to get the rows, cols of the current sparsity, so that I can remove the ones that are not needed? Or is there a completely different way that I'm missing?
Thanks a lot, CppADCG is a great tool.
Hi, Would you be able to help me run this ipopt example using CppADCodeGen? What changes should I make to replicate this example but with the AD performed by CppADCodeGen? I have successfully compiled and run this example with my local ipopt and CppAD builds and it works well.
Many thanks,
Hi all,
I'm trying to run the Lagrangian example in the examples folder. I'm using cppad-20180000.0, and everything else follows the requirements from the README.md. Eigen 3.4 and CppAD are installed system-wide. I copy the Lagrangian code into my main.cpp file, and invoke:
$ g++ -std=gnu++11 main.cpp
/tmp/ccdPwdGa.o: In function `CppAD::cg::LinuxDynamicLib<double>::LinuxDynamicLib(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)':
main.cpp:(.text._ZN5CppAD2cg15LinuxDynamicLibIdEC2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEi[_ZN5CppAD2cg15LinuxDynamicLibIdEC5ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEi]+0x1d9): undefined reference to `dlopen'
main.cpp:(.text._ZN5CppAD2cg15LinuxDynamicLibIdEC2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEi[_ZN5CppAD2cg15LinuxDynamicLibIdEC5ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEi]+0x206): undefined reference to `dlerror'
/tmp/ccdPwdGa.o: In function `CppAD::cg::LinuxDynamicLib<double>::~LinuxDynamicLib()':
main.cpp:(.text._ZN5CppAD2cg15LinuxDynamicLibIdED2Ev[_ZN5CppAD2cg15LinuxDynamicLibIdED5Ev]+0xdc): undefined reference to `dlclose'
/tmp/ccdPwdGa.o: In function `CppAD::cg::LinuxDynamicLib<double>::loadFunction(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool)':
main.cpp:(.text._ZN5CppAD2cg15LinuxDynamicLibIdE12loadFunctionERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb[_ZN5CppAD2cg15LinuxDynamicLibIdE12loadFunctionERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb]+0x46): undefined reference to `dlsym'
main.cpp:(.text._ZN5CppAD2cg15LinuxDynamicLibIdE12loadFunctionERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb[_ZN5CppAD2cg15LinuxDynamicLibIdE12loadFunctionERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb]+0x55): undefined reference to `dlerror'
collect2: error: ld returned 1 exit status
/tmp/ccdPwdGa.o: In function `CppAD::cg::LinuxDynamicLib<double>::LinuxDynamicLib(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)':
main.cpp:(.text._ZN5CppAD2cg15LinuxDynamicLibIdEC2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEi[_ZN5CppAD2cg15LinuxDynamicLibIdEC5ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEi]+0x1d9): undefined reference to `dlopen'
main.cpp:(.text._ZN5CppAD2cg15LinuxDynamicLibIdEC2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEi[_ZN5CppAD2cg15LinuxDynamicLibIdEC5ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEi]+0x206): undefined reference to `dlerror'
/tmp/ccdPwdGa.o: In function `CppAD::cg::LinuxDynamicLib<double>::~LinuxDynamicLib()':
main.cpp:(.text._ZN5CppAD2cg15LinuxDynamicLibIdED2Ev[_ZN5CppAD2cg15LinuxDynamicLibIdED5Ev]+0xdc): undefined reference to `dlclose'
/tmp/ccdPwdGa.o: In function `CppAD::cg::LinuxDynamicLib<double>::loadFunction(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool)':
main.cpp:(.text._ZN5CppAD2cg15LinuxDynamicLibIdE12loadFunctionERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb[_ZN5CppAD2cg15LinuxDynamicLibIdE12loadFunctionERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb]+0x46): undefined reference to `dlsym'
main.cpp:(.text._ZN5CppAD2cg15LinuxDynamicLibIdE12loadFunctionERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb[_ZN5CppAD2cg15LinuxDynamicLibIdE12loadFunctionERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEb]+0x55): undefined reference to `dlerror'
collect2: error: ld returned 1 exit status
Adding the -ldl flag doesn't solve this. Is there a bug, or am I missing a step?
There are use cases e.g. in optimal control where the trajectories and associated gradients and jacobians are required to be calculated in parallel. An simple example would be generating optimal trajectories in phase space using some statistical objective for uncertain initial conditions.
Other AD frameworks such as Google Jax do a poor job of calculating Jacobians explicitly, but a very good job vectorizing the calculations in parallel using a GPU.
Is there a way to generate tensors (e.g. pytorch tensors) as the output of CppAD instead of matrix jacobians? This would allow for the efficient calculation of explicit Jacobians on a GPU without much effort. I don't think this would be a huge change. I am not asking you to do this but if you could point out which files need to be modified I can tackle it.
I am struggling to generate AD code involving Eigen vectors (both with fixed and dynamic sizes) and matrices (both sparse and dense). Until now, I have been using autodiff with great satisfaction. Unfortunately, now I require very efficient code, and since autodiff does not separately generate the derivatives, it is not sufficient anymore. Hence my decision to switch to CppADCodeGen! However, its documentation is very succinct and not user-friendly -- at least, for an AD layman like myself. This is especially true when talking about the differentiation of Eigen-based functions.
Would it be possible for some advanced users/developers of CppADCodeGen to add more examples using Eigen types? The more articulated, the better! As a starting point, you may consider the examples from the autodiff library I mentioned, which are clear and exhaustive in my opinion. As a user, that is exactly what I would like to have when I start using a new library: it quickly sets me on track to employ it and, eventually, contribute to it.
Thank you very much!
P.S.: if such examples exist and I missed them, could you kindly address me to them?
I am trying to use a cg::CGAtomicGenericModel to compute the Hessian of a CppAD::ADFun. For example in this schematic code:
...
CGAtomicGenericModel<double> atomic_model;
ADFun<double> fun;
...
std::vector<AD<double>> X, Y, Z;
Y = atomic_model(X, Y);
Z = Y * Y; // some nonlinear function
fun(X, Z);
...
fun.sparse_hes(x, w, hess_subset, hess_pattern, "cppad.general", hes_work);
This would result in the following error:
cppad-20190806 error from a known source:
Second-order reverse mode failed: py[2*i] (i=0...m) must be zero.
Error detected by false result for
ret != 1
at line 552 in the file
/Users/rguseino/sdk/cppadcodegen/include/cppad/cg/model/functor_generic_model.hpp
Assertion failed: (false), function Default, file /Users/rguseino/sdk/cppad/include/cppad/utility/error_handler.hpp, line 206.
In case Z is linear in Y, the error is not reproduced.
Does this mean that for now CGAtomicGenericModel is not supposed to be used in such scenario? Is there a workaround for this problem?
P.S. This happens in my large project but, if necessary, I can write simple code to reproduce this behavior.
I did a fresh install of CppAD (v 2020) and of CppADCodeGen. Everything seems to be fine for now, except for one minor issue with PkgConfig (probably related to #41 and #43?): after configuring pkgconfig/cppadcg.pc.in, the version of CppAD is left blank, i.e., the corresponding line reads as
Requires: cppad >=
I am not sure if I did some mistake - perhaps I forgot to set some variable/option while running CMake...
To install CppAD is simply cloned it and followed the "classical" build flow:
cmake ..
make
make install
and the same for CppADCodeGen (skipping the plain make
step). Do you have any suggestion of what I could have done wrong? Thanks in advance!
Hello,
First I want to thank you for your awesome work, which is very useful to me. I'm trying to perform some code generation but I have the following exception :
terminate called after throwing an instance of 'CppAD::cg::CGException'
what (): GreaterThanZero cannot be called for non-parameters, Aborted (core dumped)
This exception occurs only when I run the code, the latter is indeed compiled with no errors.
Here is my code :
#include "pinocchio/parsers/urdf.hpp"
#include "pinocchio/algorithm/joint-configuration.hpp"
#include "pinocchio/algorithm/kinematics.hpp"
#include <iostream>
#include <urdf_parser/urdf_parser.h>
#include "pinocchio/codegen/cppadcg.hpp"
#include <boost/test/unit_test.hpp>
#include <boost/utility/binary.hpp>
#include <Eigen/Geometry>
// PINOCCHIO_MODEL_DIR is defined by the CMake but you can define your own directory here.
#ifndef PINOCCHIO_MODEL_DIR
#define PINOCCHIO_MODEL_DIR "path_to_the_model_dir"
#endif
using namespace CppAD;
using namespace CppAD::cg;
using namespace pinocchio;
typedef double Scalar;
typedef CppAD::cg::CG<Scalar> CGScalar;
typedef CppAD::AD<CGScalar> ADScalar;
typedef Eigen::Matrix<ADScalar,Eigen::Dynamic,Eigen::Dynamic> ADRotMat;
typedef Eigen::Matrix<ADScalar,Eigen::Dynamic,1> ADVector;
int main(int argc, char ** argv)
{
/**Generate a random robot ADScalar configuration ad_q from Scalarconfiguration q**/
typedef ADModel::ConfigVectorType ADConfigVectorType;
ADConfigVectorType ad_q(model.nq);
Model::ConfigVectorType q = pinocchio::randomConfiguration(model);
ad_q = q.cast<ADScalar>();
/**Generate independent variables X and start recording operations sequence**/
ADConfigVectorType & X = ad_q;
CppAD::Independent(X);
ADVector Quat_ad(4); //This is the ADScalar quaternion vector
/**Perform forward kinematics and get rotation matrix R of the End Effector**/
pinocchio::forwardKinematics(ad_model, ad_data, X); //Compute forward kinematics
ADRotMat R; R = ad_data.oMi[model.nq].rotation(); //Get rotation matrix of End Effector
/**Convert the rotation matrix into a Quaternion**/
rotMatToQuaternion(R, Quat_ad);
/**Stop recording and generate AD function**/
CppAD::ADFun<CGScalar> fun(X,Quat_ad);
/**Generate source code **/
CppAD::cg::ModelCSourceGen<Scalar> cgen(fun, "fkine_angular");
cgen.setCreateJacobian(true);
cgen.setCreateForwardZero(true);
cgen.setCreateForwardOne(true);
cgen.setCreateReverseOne(true);
cgen.setCreateReverseTwo(true);
CppAD::cg::ModelLibraryCSourceGen<Scalar> libcgen(cgen);
/**Compile source code **/
CppAD::cg::DynamicModelLibraryProcessor<Scalar> p(libcgen);
CppAD::cg::GccCompiler<Scalar> compiler;
std::unique_ptr<CppAD::cg::DynamicLib<Scalar>> dynamicLib = p.createDynamicLibrary(compiler);
}
I think the problem comes from the function rotMatToQuaternion()
which converts a rotation matrix into a quaternion, but inside this function there are some GreaterThanZero()
tests. Here is the function :
void rotMatToQuaternion(ADRotMat const & R, ADVector & Quat_ad){
ADScalar tr = R(0,0) + R(1,1) + R(2,2);
if (tr > 0){
ADScalar S = 0.5 / sqrt(tr+1);
Quat_ad(0) = (R(2,1) - R(1,2))*S;
Quat_ad(1) = (R(0,2) - R(2,0))*S;
Quat_ad(2) = (R(1,0) - R(0,1))*S;
Quat_ad(3) = 0.25 / S;
} else {
if (R(0,0) > R(1,1) && R(0,0) > R(2,2)){
ADScalar S = 2 * sqrt(1 + R(0,0) - R(1,1) - R(2,2));
Quat_ad(0) = 0.25 * S;
Quat_ad(1) = (R(0,1) + R(1,0)) / S;
Quat_ad(2) = (R(0,2) + R(2,0)) / S;
Quat_ad(3) = (R(2,1) - R(1,2)) / S;
} else if (R(1,1) > R(2,2)) {
ADScalar S = 2 * sqrt(1 + R(1,1) - R(0,0) - R(2,2));
Quat_ad(0) = (R(0,1) + R(1,0)) / S;
Quat_ad(1) = 0.25 * S;
Quat_ad(2) = (R(1,2) + R(2,1)) / S;
Quat_ad(3) = (R(0,2) - R(2,0)) / S;
} else {
ADScalar S = 2 * sqrt(1 + R(2,2) - R(0,0) - R(1,1));
Quat_ad(0) = (R(0,2) + R(2,0)) / S;
Quat_ad(1) = (R(1,2) + R(2,1)) / S;
Quat_ad(2) = 0.25 * S;
Quat_ad(3) = (R(1,0) - R(0,1)) / S;
}
}
}
As you can see, the GreaterThan
tests are performed on the values of the rotation matrix, which are not a part of the independent variables vector X. I think that is probably why the exception says GreaterThanZero cannot be called for non parameters
.
Indeed, this rotation matrix R is calculated from the independent variables vector X using pinocchio::forwardKinematics(ad_model, ad_data, X);
. And then, once the forward Kinematics performed, I get the rotation matrix using ADRotMat R; R = ad_data.oMi[model.nq].rotation();
. Actually, I really need to convert the rotation matrix R into a quaternion because I want to compute the gradient of my Quaternion relatively to the vector X, that is why I have CppAD::ADFun<CGScalar> fun(X,Quat_ad)
. I hope I was clear enough, otherwise feel free to ask me further questions. Thank you again :)
CppADCodegen generates wrong code if there are conditional statements in the tape and if I add an optimization pass in CppAD, for example, the output of the following code:
#include <iosfwd>
#include <vector>
using namespace std;
#include <cppad/cg/cppadcg.hpp>
using namespace CppAD;
using namespace CppAD::cg;
int main(void) {
typedef CG<double> CGD;
typedef AD<CGD> ADCG;
CppAD::vector<ADCG> U(2);
U[0] = 0.;
U[1] = 0.;
Independent(U);
CppAD::vector<ADCG> Z(1);
ADCG a = U[0] * U[1];
Z[0] = CondExpEq(U[0], ADCG(1.0), a, ADCG(0.0));
ADFun<CGD> fun(U, Z);
fun.optimize();
CodeHandler<double> handler;
CppAD::vector<CGD> indVars(2);
handler.makeVariables(indVars);
CppAD::vector<CGD> fwd = fun.Forward(0, indVars);
LanguageC<double> langC("double");
LangCDefaultVariableNameGenerator<double> nameGen;
std::ostringstream code;
handler.generateCode(code, langC, fwd, nameGen);
std::cout << code.str();
}
is:
// dependent variables without operations
y[0] = 0;
If I remove the fun.optimize() line, the output becomes:
if( x[0] == 1 ) {
y[0] = x[0] * x[1];
} else {
y[0] = 0;
}
I notice that CppADCodeGen does some optimizations on its own. Does it mean that I do not need to call fun.optimize() at all?
I installed CppAD and CppADCodeGen, and tested all CppADCodeGen examples on two different PCs both running Ubuntu 16.4, and I always get the following error.
g++ -std=c++11 lagrangian.cpp -o lagrangian
In file included from /usr/local/include/cppad/cg/cppadcg.hpp:77:0,
from /usr/local/include/cppad/cg.hpp:18,
from lagrangian.cpp:18:
/usr/local/include/cppad/cg/declare_cg.hpp:28:7: error: redeclared with 1 template parameter
class ADFun;
^
In file included from /usr/include/cppad/base_require.hpp:163:0,
from /usr/local/include/cppad/cg/cppadcg.hpp:71,
from /usr/local/include/cppad/cg.hpp:18,
from lagrangian.cpp:18:
/usr/include/cppad/local/declare_ad.hpp:53:50: note: previous declaration ‘template<class Base, class RecBase> class CppAD::ADFun’ used 2 template parameters template <class Base, class RecBase=Base> class ADFun;
Does someone know what I did wrong, or is this an issue due to changes in CppAD?
Thanks,
Alex
Dear @joaoleal,
I have been trying to use llvm-based JIT (without creating dynamic libraries) in an external project.
I noticed that I cannot find any place where a previously installed instance of CppADCG exports the compile definitions that were allocated in the original CMakeLists.txt in the CppADCG root folder (e.g. found version of llvm, etc.)
For instance, when including LLVM and CppADCG, an external project needs to access the LLVM version compile definitions in this header.
How does CppADCG currently export its compile definitions, and what is the appropriate way for other projects to retrieve them?
Since CppADCG is header-only, one possible workflow would be to declare cppadcg as an interface library, e.g. include something like
add_library(cppadcg INTERFACE)
target_compile_definitions(cppadcg INTERFACE ${<some_compile_definitions>})
in which case an external project will receive all CppADCG internal compile-definitions automatically when linking against the interface library
target_link_libraries(<some_external_project> INTERFACE cppadcg)
_
Hi,
I have a number of for loops in my algorithm. They have a fixed iteration number, hence work perfectly fine with CppAD codegen, but they produce a lot of (unnecessary?) temporary variables in the generated code and massively bloat the size of the code.
Is there a way to declare such for loops explicitly to CppADGC such that it results also in loop expressions in the generated code? I found some references to loops in CppADCodeGen/include/cppad/cg/model/patterns , but I'm not sure if it's for this purpose.
A tiny example how to use such functionality would be great :) Thank you!
Introduciton
This is really a request for help in CppAD development that is closely related to CppADCodegen.
I have questions about how to use LLVM and I hoping this group can help me.
Optimization
I am working on using the llvm optimizer as a replacement for the CppAD optimizer; see the example:
https://github.com/coin-or/CppAD/blob/llvm/example/llvm/optimize.cpp
I am close to being able to test how this compares to the CppAD optimizer for a simple example.
Complied Object Files
As a side benefit, inspired by CppADCodeGen, CppAD should be able to directly general object libraries corresponding to the llvm IR representation of an ADFun; see the example
https://github.com/coin-or/CppAD/blob/llvm/example/llvm/grad_det_minor.cpp
I am not sure how this will compare to the CppADCodeGen method for generating code.
Development
Work on this effect is happening on the llvm branch of CppAD in the following files and directories
https://github.com/coin-or/CppAD/blob/llvm/include/cppad/core/llvm_ir.hpp
https://github.com/coin-or/CppAD/blob/llvm/include/cppad/core/llvm_link.hpp
https://github.com/coin-or/CppAD/tree/llvm/cppad_lib/llvm
https://github.com/coin-or/CppAD/tree/llvm/example/llvm
https://github.com/coin-or/CppAD/blob/llvm/test_more/general/llvm_tst.cpp
LLVM Version
This work is currently only tested with the following version of llvm:
https://github.com/llvm/llvm-project/tree/release/11.x
Questions
I will post individual questons below.
Hi João Rui Leal,
I've been trying to use your CppADCodeGen library to generate fast c code for our problems, and have recently integrated it in our optimization solver Crocoddyl(https://github.com/loco-3d/crocoddyl).
I have a problem which deals with the temporary folder cppadcg_tmp
that gets created by the compiler (https://github.com/joaoleal/CppADCodeGen/blob/master/include/cppad/cg/model/compiler/abstract_c_compiler.hpp#L45). This hardcoded value is quite restrictive if the user does not have permission to create a folder in that directory.
Could we move this directory to /tmp
for example? Or would you have some suggestion to deal with this?
Best,
Rohan
Hello,
First I want to thank you for code and your help.
I actually have a problem. I would like to load a LinuxDynamicLib
(lets call it myLib
) and the corresponding model (lets call it myModel
) at the beggining of my main()
. And then, I want to send both as argument for different functions, to be able to use myModel
inside those functions. In fact, for the moment, I have to load myLib
and myModel
, inside those functions, which takes pretty much time as myLib
and myModel
are loaded at every call of those functions. The code would run much faster if I instantiate only once myModel
and myLib
at the beggining of main(),
and then send them as argument for the functions that need myModel
.
To do so, I coded the following function to load myModel
and myLib
and save them:
LinuxDynamicLib<Scalar> loadLibrary(std::vector<std::unique_ptr<GenericModel<double>>> & models){
LinuxDynamicLib<Scalar> myLib("./fkine_angular_IMU1.so"); //Instantiation of the dynamic library
std::unique_ptr<GenericModel<double>> myModel = myLib.model("fkine_angular_IMU1"); //Instantiation of the model, from the dynamic library
models.push_back(std::move(myModel));
return myLib;
}
This function takes as input a std::vector
of GenericModel<double>
s, loads myLib
, loads myModel
, adds myModel
to my vector models
(which can contain several models from different libs), then returns myLib
. Actually, I have to return myLib
, otherwise myModel
will be deleted. But when I do return myLib
I get the following compilation error :
error : use of deleted function 'cppAD::cg::LinuxDynamicLib<Base>::LinuxDynamicLib(const cppAD::cg::LinuxDynamicLib<Base>&) [with Base = double]'
This error is actually pointing on the line return myLib
.
I also have a note : declared here
, which is pointing on LinuxDynamicLib(const LinuxDynamicLib&) = delete;
code line, in linux_dynamiclib.hpp file.
Thank you very much for your help, I don't know if i'm misunderstanding someting, as i'm a begginer on C++. I wish you a nice day
Is it possible for cppadcodegen to accept parameters that we are not taken their derivatives as input? For example, in the Hessian of Lagrangian (http://www.coin-or.org/CppAD/Doc/hes_lagrangian.cpp.htm) example, how do we generate code for the "Usefg" function, which takes the Lagrangian multipliers as input?
By the way, thanks for this wonderful piece of software.
Hi,
Is it expected that icpc (from intel oneAPI) can't build codeGen? Happy to post compile error, just wanted to check that it should build using icpc first before requesting help?
Thanks,
Andy
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.