[ANN] AffineMaps.jl

Just wanted to announce AffineMaps.

AffineMaps is a very lightweight package to express affine transforms (A * x + b, and variants). It provides function objects for add, mul, muladd and addmul. These support InverseFunctions.inverse as well as ChangesOfVariables.logabsdetjacobian and the Functors API.

Example:

using AffineMaps
using LinearAlgebra, InverseFunctions, ChangesOfVariables
A = rand(5, 5)
b = rand(5)
x = rand(5)

f = MulAdd(A, b)
y = f(x)
y ≈ A * x + b

inverse(f)(y) ≈ x

y, ladj = with_logabsdet_jacobian(f, x)
y ≈ A * x + b && ladj ≈ logabsdet(A)[1]

We have similar functionality in many packages of course, AffineMaps is mainly about offering this as very lightweight dependency.

8 Likes

Does/can it provide traits like islinear(f) and isaffine(f) for arbitrary functions?
These are occasionally useful, eg in FlexiMaps to determine when mapview(f, range) can return a range vs array.

1 Like

Oh, I wasn’t aware of FlexiMaps (nice package!) but I’m happy to support it via an AffineMaps Pkg extension. Are islinear and isaffine originally defined in FlexiMaps, or are they owned by another package?

I can also add islinear and isaffine propagation to FunctionChains (need to properly announce that package sometime :slight_smile: ).

1 Like

@aplavin AffineMaps and FunctionChains support FlexiMaps.islinear and FlexiMaps.isaffine now. :slight_smile:

Great!
I was also looking for a more natural way to put those islinear/isaffine traits, FlexiMaps seems very adhoc for this…

Can you comment on how the packages compares with the AffineMap from CoordinateTransformations.jl?

2 Likes

@evetion: Can you comment on how the packages compares with the AffineMap from CoordinateTransformations.jl?

I would say it’s more fully featured, regarding to the affine maps itself - AffineMaps offers both rotate-then-translate (MulAdd) and translate-then-rotate (AddMul), it also supports InverseFunctions, ChangesOfVariables, FlexiMaps and Functors (so it cal also be used as ML layers). On the other hand the scope of CoordinateTransformations as a whole is wider, and there’s probably also some things in CoordinateTransformations.AffineMap that AffineMaps.jl lacks.

Ideally, one could see if AffineMaps.jl does lack anything that CoordinateTransformations.jl needs (which is likely), add it, and then have CoordinateTransformations.jl depend on AffineMaps.jl and get it’s maps from there. The problem is that CoordinateTransformations.AffineMap is a subtype of CoordinateTransformations.Transformation, so that won’t work. We’d need a AbstractCoordinateTransformations.jl package or so …

Currently CoordinateTransformations is also a much heavier dependency than AffineMaps, due to StaticArrays, but I think CoordinateTransformations could move the StaticArrays code into a Pkg extension. CoordinateTransformations itself shouldn’t be that heavy.

There’s also some discussion here: Comparison to CoordinateTransformations.jl? · Issue #1 · oschulz/AffineMaps.jl · GitHub

3 Likes