Recent Releases of wrenfold
wrenfold - v0.3.1
v0.3.1 resolves two bugs:
We fix an edge-case where a function that returns the same matrix expression more than once would trigger an internal assertion:
``python
def func(a: FloatScalar, b: FloatScalar):
v = sym.vector(a, b)
#out1andout2` are identical
return [codegeneration.OutputArg(v, "out1"), codegeneration.OutputArg(v, "out2")]
_ = codegeneration.generatefunction(func) # Triggers pywrenfold.AssertionError
```
Additionally, rust-clippy introduced a new lint that would fire on wrenfold-generated code: clippy::neg_multiply 0.3.1 updates RustCodeGenerator to automatically suppress this lint on generated functions:
```rust
[allow(clippy::neg_multiply, ...)]
pub fn cartdoublepoledynamics
๐ Fixes
- Fix assertion caused by having duplicated output expressions with matrix type
- PR: #327
Scientific Software - Peer-reviewed
- C++
Published by github-actions[bot] 5 months ago
wrenfold - v0.3.0
v0.3.0 introduces one new feature: CppGenerator supports a new mode in which eigen types can be directly utilized in function signatures. To try this feature, pass the desired mode to CppGenerator:
python
generator = code_generation.CppGenerator(code_generation.CppMatrixTypeBehavior.Eigen)
code = code_generation.generate_function(rosenbrock, generator=generator)
This will produce:
cpp
template <typename Scalar>
Scalar rosenbrock(const Scalar a, const Scalar b,
const Eigen::Matrix<Scalar, 2, 1> &xy,
Eigen::Matrix<Scalar, 2, 1> &h,
Eigen::Matrix<Scalar, 2, 2> *const h_D_xy) { ... }
Instead of the default (CppMatrixTypeBehavior.GenericSpan):
cpp
template <typename Scalar, typename T2, typename T3, typename T4>
Scalar rosenbrock(const Scalar a, const Scalar b, const T2 &xy, T3 &&h,
T4 &&h_D_xy) { ... }
Breaking Changes
CppGenerator.apply_preambleis no longer a static method. It is now a member function as it depends on the value ofCppMatrixTypeBehaviorpassed toCppGenerator. See example here.FunctionArgumentVariableexpressions can no longer be converted to/from SymPy expressions.
๐ Features
- CppGenerator supports directly emitting Eigen types in function signatures
- PR: #319
- Function argument expressions have string names matching the generated function signature
- PR: #321
Scientific Software - Peer-reviewed
- C++
Published by github-actions[bot] 10 months ago
wrenfold - v0.2.3
v0.2.3 resolves an issue (via #314) causing wrenfold wheels to include erroneous function stubs. These stubs included incorrect type annotations that caused some functions (such as sym.cos or sym.abs) to be annotated with a return type of T.Any instead of sym.Expr.
๐ Features
- Make NumPy the default python target
- PR: #308
๐ Fixes
- Re-generate stubs on stubgen 1.15
- PR: #314
๐ Documentation
- Improve documentation for some new functionality
- PR: #310
- JOSS submission
- PR: #256
- Add new documentation page regarding returning matrices
- PR: #313
๐งน Cleanup
- Split
variableexpression into different expressions- PR: #317
Scientific Software - Peer-reviewed
- C++
Published by github-actions[bot] 10 months ago
wrenfold - v0.2.2
Support for osx-arm64 on conda
v0.2.2 resolves an issue (via PR #305) that prevented arm64 builds for OSX on conda-forge. There are no breaking changes in this release.
๐ Features
- Add apply_preamble to the python code generator
- PR: #302
- Stubs are generated into the repo and committed to
components/wrapper/stubs- PR: #305
๐ Fixes
- Do not set git hash at build time if we failed to obtain it
- PR: #304
๐งน Cleanup
- Remove old python_generation example
- PR: #306
Scientific Software - Peer-reviewed
- C++
Published by github-actions[bot] about 1 year ago
wrenfold - v0.2.1
Version v0.2.1 includes some exciting new features:
Python code generation
wrenfold can now generate python code targeting three different APIs: JAX, NumPy, and PyTorch. These are implemented in the new PythonCodeGenerator class. With this feature, symbolic functions can be generated and invoked within the same python script or notebook, thereby facilitating quicker prototyping.
In addition to generate_function, there is now generate_python which will return both the code and a callable object you can invoke with numerical types:
```python
from wrenfold import codegeneration, sym, geometry, typeannotations
def quatfrommatrix(R: typeannotations.Matrix3): """A hypothetical symbolic function.""" return geometry.Quaternion.fromrotationmatrix(R).tovector_wxyz()
func, code = codegeneration.generatepython( func=quatfrommatrix, target=code_generation.PythonGeneratorTarget.JAX, # Target the JAX api. ) print(code) # Visualize the generated code for the purpose of debugging.
We can then batch and JIT the generated function using jax:
funcbatched = jax.vmap(func, inaxes=(0, ), out_axes=0)
func_jit accepts (B, 3, 3) shaped JAX arrays (of rotation matrices) and returns (B, 4, 1) arrays of quaternions!
It can also be used as part of a larger auto-diffed JAX loss function.
funcjit = jax.jit(funcbatched)
Ridentity = np.eye(3).reshape(1, 3, 3) print(funcjit(R_identity)) # prints [[[1.0, 0.0, 0.0, 0.0]]] ```
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 xdot = x.diff(t) print(xdot) # 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.
qx = L.diff(xdot) ```
The stop_derivative expression type
The new sym.stop_derivative expression is conceptually similar to 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 camera model that compiles via jax.jit.
- Generating C99 by implementing a custom code generator.
- Deriving and generating the dynamics of a cart-pole system with a double pendulum.
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_ternariesoption to allow conditionals to remain in ternary form- PR: #285
- Add
stop_derivativeexpression 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.
Scientific Software - Peer-reviewed
- C++
Published by github-actions[bot] about 1 year ago
wrenfold - v0.1.1
Summary
This release enables support for CPython 3.13 and adds one new feature: Derivatives can now be taken with respect to symbolic function invocations.
For example, you can define a symbolic function and then use it as the argument to a diff operation:
```python
from wrenfold import sym
f = sym.Function('f') x, y = sym.symbols('x, y') g = 2 * x * sym.cos(f(y)) result = g.diff(f(y)) print(result) # prints: -2xsin(f(y)) ```
In addition, there are two performance improvements: - Printing/stringify times for large expressions are dramatically improved (around 20x faster). - Code-generation times are meaningfully improved on some expressions by PR #266. The binarization algorithm had a tendency to grow rapidly in complexity on some expression trees - this issue is now resolved. โ ๏ธ Note: This change does affect the number of output expressions. You may see a marginal increase in total operations in exchange.
For example, some representative operation counts from wrenfold-extra-examples:
- snavelyreprojectionerror: 460 --> 465
- sophus pose3_interpolate: 4343 --> 4357
๐ Features
- Enable taking derivatives wrt symbolic function invocations
- PR: #268
- Improve performance when printing large expressions
- PR: #275
- Update pybind11 to 2.13.6 to enable python 3.13 wheels
- PR: #278
๐ Fixes
- Upgrade
setup-minicondastep, switch to miniforge3- PR: #271
๐ Documentation
- Add conda-forge instructions to the documentation
- PR: #269
๐งน Cleanup
- Simplify binarization algorithm and cleanup code
- PR: #266
- Cleanup CMake + fix brittleness with docs build
- PR: #270
- Update rustc version to 1.81
- PR: #273
Scientific Software - Peer-reviewed
- C++
Published by github-actions[bot] about 1 year ago
wrenfold - v0.1.0
Summary
This release implements some new features and is an API breaking release (see note below about integer arguments).
This release also resolves the issue where wrenfold-traits was pinned to nalegbra version 0.32.
Symbolic function invocation expressions
It is now possible to create an abstract symbolic function, which can be invoked with scalar-valued expression arguments. For example: ```python from wrenfold import sym
f = sym.Function('f') x, y = sym.symbols('x, y') g = f(x, sym.sin(y))
We can take derivatives of symbolic function invocations:
g.diff(x) # produces: Derivative(f(x, y), x)
``
Taking the derivative of a symbolic function can be used to create abstract derivative expressions. This can be used to represent a function and its temporal derivativesf(t), f'(t), f''(t)` symbolically as part of a larger expression.
Integer arguments are supported
You may now annotate function arguments (and members on custom types) as integral valued. Integral args will always be generated as std::int64_t (or i64 in Rust) for now.
```python
from wrenfold import sym, typeannotations, codegeneration
def func(x: typeannotations.FloatScalar, mode: typeannotations.IntScalar): # Switch on the integer value to change behavior, for example... return sym.where(sym.eq(mode, 1), sym.cos(x), sym.sin(x))
print(codegeneration.generatefunction(func, generator=codegeneration.CppGenerator()))
Will produce:
cpp
template
Operations that combine integer and floating point values are automatically promoted toScalarviastaticcast<>. If float-scalar-valued values are assigned to integral output values, they are demoted viastaticcast<std::in64t>`.
โ ๏ธ This is an API breaking change because all functions previously annotated with sym.Expr must now be annotated with type_annotations.FloatScalar (or type_annotations.IntScalar, in the case of an integer arg).
If previously you wrote: ```python from wrenfold import sym
def foo(x: sym.Expr): # ... some expressions ... ````
You should now write:
```python from wrenfold import type_annotations
def foo(x: type_annotations.FloatScalar): # ... some expressions ... ```
conda-build recipe
We have added a conda-build recipe to the repository, and will shortly submit wrenfold v0.1.0 to conda-forge.
๐ Features
- Add conda recipe and build scripts
- PR: #251
- Add deferred substitution and symbolic function invocation expressions
- PR: #254
- Add
compare()function to the python wrapper to enable canonical ordering from python- PR: #259
- Add standalone versions of the sym.subs and sym.distribute functions
- PR: #262
- Get rid of expressiongroup type, use anyexpression to store function outputs
- PR: #263
- Support integer arguments to generated functions
- PR: #260
๐ Fixes
- Fix issue where
distributedid not recurse, causing some products of fractional powers to not expand- PR: #258
- Fix
__array__method on MatrixExpr (missing kwargs)- PR: #265
๐ Documentation
- Add architecture image to the documentation
- PR: #257
๐งน Cleanup
- Rename
code_numeric_type-->numeric_primitive_typefor clarity- PR: #261
Scientific Software - Peer-reviewed
- C++
Published by github-actions[bot] over 1 year ago
wrenfold - v0.0.7
Version 0.0.7 resolves an issue in previous releases where Windows wheels were built in Debug mode by mistake. Prior Linux and OSX wheels are unaffected by this issue.
๐ Fixes
- Fix for Windows wheels having wrong build type
- PR: #252
Scientific Software - Peer-reviewed
- C++
Published by github-actions[bot] over 1 year ago
wrenfold - v0.0.6
- Fixed an issue present in
v0.0.5where the generated stubs for the pybind library were omitted from the python wheel. - Releases now include a source archive that includes the full repo, including submodules.
๐ Features
- Update install instructions to reflect PyPi repository
- PR: #240
๐ Fixes
- Fix issue where stubs are missing from wheel files
- PR: #246
Scientific Software - Peer-reviewed
- C++
Published by github-actions[bot] over 1 year ago
wrenfold - v0.0.5
Release v0.0.5 is the first set of public wheels for wrenfold. ๐ฅณ
wrenfold can now be installed via:
bash
pip install wrenfold
There are no code changes from v0.0.4 - the version number had to be incremented for PyPi.
Scientific Software - Peer-reviewed
- C++
Published by github-actions[bot] over 1 year ago
wrenfold - v0.0.4
This release primarily fixes bugs and improves documentation. The most significant bug was an issue where non-optional output arguments were not assigned correctly in generated Rust code (fixed by PR #228).
๐ Features
- build-wheels creates archive of all wheels
- PR: #217
- Add rust example to custom types docs, show how to customize constructor
- PR: #227
- Add an improved quick start guide
- PR: #231
- Add rosenbrock function to the examples
- PR: #233
๐ Fixes
- Fix CI runner build parallelism specification
- PR: #223
- Fixes for gcc-14 compilation issues
- PR: #222
- Fix assignment to non-optional custom type output arguments in rust
- PR: #228
- Disable broken full-piv LU code path
- PR: #236
- Fix integer overflow in bspline example
- PR: #237
Scientific Software - Peer-reviewed
- C++
Published by github-actions[bot] over 1 year ago
wrenfold - v0.0.3
๐ Features
- Add inverse left Jacobian of SO(3) to geometry module
- PR: #195
- Simplify runtime library to two headers (merge span_eigen.h into span.h)
- PR: #196
- Unify the
subsfunction interface (eliminatesubs_variables)- PR: #199
- Add parameter to
CppCodeGenerator.apply_preambleto specify imports- PR: #202
- Substitute visitor uses caching
- PR: #203
- Add
unique_symbolsmethod to the python wrapper- PR: #204
- Add a diff test that checks rustgenerationtest output code is up to date
- PR: #205
- Do not insert superfluous intermediate variables (more compact output)
- PR: #206
- Remove unused traits from the rust traits crate
- PR: #208
- Improve documentation
- PR: #215
๐ Fixes
- Fix bug preventing nesting of vectors/matrices in custom types
- PR: #194
- Fix bug in torotationvector, add more test coverage
- PR: #201
Scientific Software - Peer-reviewed
- C++
Published by github-actions[bot] over 1 year ago
wrenfold - v0.0.2
The second release of wrenfold focuses on improving the generated code, namely by reducing operation counts (sometimes meaningfully). This version will find additional opportunities to reduce operations by factorizing repeated sum-of-product expressions.
New features:
- Added a faster version of Quaternion.to_rotation_vector that can be used by passing use_atan2=False.
- Added sym.unevaluated(...) expression, which allows the user to prevent certain automatic simplifications. sympy.UnevaluatedExpr will now correctly convert to this when calling from_sympy.
- Added code_generation.cse_function_description function. This method allows the user to run their symbolic function through the CSE/simplifications steps, but then convert the result back to a series of symbolic expressions for easier inspection and debugging.
- Sympy operations Min, Max and Heaviside can now be converted to and from wrenfold.
Breaking changes:
- The type RealScalar from type_annotations is renamed to FloatScalar.
๐ Features
- Operation counts report maximum over all branches
- PR: #176
- Add missing SymPy conversions for
Min,Max, andHeaviside- PR: #177
- Add alternate
to_rotation_vectorimplementation that uses acos- PR: #179
- Add
eliminate_subexpressionsmethod for breaking down complex expressions- PR: #180
- Add method for factorizing sums of products
- PR: #181
- Add ability to convert CSE outputs back to symbolic tree (from python)
- PR: #182
- Add
Unevaluatedexpression type to avoid automatic simplifications- PR: #183
- Speed up sum-of-product factorizer
- PR: #184
- Improve subexpression elimination (remove more operations)
- PR: #187
- Add missing annotations to
type_annotations.pyfor Matrix2, Matrix3, etc- PR: #191
๐ฆ Uncategorized
- Add logo to docs directory, add it to the readme and the sphinx output
- PR: #175
- Pin rust toolchain version to 1.77
- PR: #178
- Set rust version to 1.77 in
ci.yml- PR: #185
- Value does not use hash-set to store consumers
- PR: #186
- Remove non-deterministic hash from
custom_type- PR: #189
- Add missing
__hash__and__eq__implementation to Quaternion type- PR: #188
- Speed up ordering operator for scalar expressions
- PR: #190
- Rename RealScalar to FloatScalar to clarify type
- PR: #192
Scientific Software - Peer-reviewed
- C++
Published by github-actions[bot] over 1 year ago
wrenfold - v0.0.1
This is the very first set of wrenfold wheels! ๐
Documentation is live at wrenfold.org. The username and password is in README.md.
Select the wheel file appropriate for your OS and python version. For example:
- Windows w/ Python 3.11 on AMD64: wrenfold-0.0.1-cp311-cp311-win_amd64.whl
- OSX w/ Python 3.9 on ARM64: wrenfold-0.0.1-cp39-cp39-macosx_11_0_arm64.whl
Scientific Software - Peer-reviewed
- C++
Published by github-actions[bot] over 1 year ago