Derivatives with respect to derivatives of symbolic functions
Derivatives can now be taken with respect to the _derivative expression_ of a symbolic function invocation. For instance, this can be used when computing the Euler-Lagrange equations of a system:
python
from wrenfold import sym
t = sym.symbols('t')
x = sym.Function("x")(t) x is the generalized coordinate of our system
x_dot = x.diff(t)
print(x_dot) prints: Derivative(x(t), t)
L = ... omitted, we compute the Lagrangian `L` wrt `x` and `x_dot`
Then compute the canonical momenta by taking the derivative wrt `x_dot`.
q_x = L.diff(x_dot)
The `stop_derivative` expression type
The [new `sym.stop_derivative`](https://github.com/wrenfold/wrenfold/pull/290) expression is conceptually similar to [`tf.stop_gradient`](https://www.tensorflow.org/api_docs/python/tf/stop_gradient) and can be used to truncate derivatives:
python
from wrenfold import sym
x, y = sym.symbols('x, y')
f = sym.stop_derivative(x * y) * sym.sin(x)
f.diff(x) prints: cos(x)*StopDerivative(x*y), x*y does not influence the gradient
f.diff(y) prints: 0
This is useful if you want to evaluate a residual function without incorporating additional terms in the derivative - for example to evaluate the weighting function of a robust norm.
New Examples
Three new examples have been added:
- An example implementation of the [Kannala-Brandt](https://oulu3dvision.github.io/calibgeneric/Kannala_Brandt_calibration.pdf) camera model that [compiles via `jax.jit`](https://github.com/wrenfold/wrenfold/blob/main/examples/jax_camera_model/jax_camera_model.py).
- Generating C99 by [implementing a custom code generator](https://github.com/wrenfold/wrenfold/blob/main/examples/c_generation/c_code_generator.py).
- Deriving and generating the dynamics of a [cart-pole system with a double pendulum](https://github.com/wrenfold/wrenfold/blob/main/examples/cart_pole/cart_pole_dynamics.py).
Performance improvements
Changes 279 and 284 improved the performance of symbolic expression manipulations.
Code coverage ๐
As of 296, the project is now using `gcov` and `lcov` to generate weekly coverage reports. These will be used to ameliorate places with insufficient coverage.
๐ Features
- Add stack allocator implementation for use with addition/multiplication
- PR: 279
- Support taking derivative wrt the derivative of a symbolic function
- PR: 283
- Add `convert_ternaries` option to allow conditionals to remain in ternary form
- PR: 285
- Add `stop_derivative` expression type
- PR: 290
- Add C99 generation example + an example of Kannala-Brandt camera model
- PR: 291
- Add Python code generation for PyTorch, JAX, and NumPy
- PR: 288
- Add example of generating KB camera model and invoking it w/ JAX
- PR: 294
- Add code coverage github action
- PR: 296
- Add cart-pole/double-pendulum to the examples
- PR: 300
๐ Fixes
- Remove unnecessary parentheses around numeric negative literals in code generation
- PR: 287
- Fix bug where nested matrix in custom type resulted in segfault
- PR: 292
๐ Documentation
- Add basic contributing.md
- PR: 295
๐งน Cleanup
- Update scikit-build-core version
- PR: 280
- Update pre-commit and clang-format versions
- PR: 281
Note: Due to a silly mistake this version incremented the minor digit but did not reset the patch digit, hence there is no `v0.2.0`. Rather than edit the git history in a confusing way I have opted to skip that version. In future I will add some tooling to avoid this sort of gaffe.