This project was created to solve the following optimization problem:
For a given matrix
The Lie group
The methods used in this project are explained and analyzed in our preprint paper How to project onto SL(n) with the DOI https://doi.org/10.48550/arXiv.2501.19310.
Please cite our work if you use the code:
@misc{jaap2025projectsln,
title={How to project onto SL($n$)},
author={Patrick Jaap and Oliver Sander},
year={2025},
eprint={2501.19310},
archivePrefix={arXiv},
primaryClass={math.OC},
url={https://arxiv.org/abs/2501.19310},
}
To include this project into our own Julia project, you simply run
pkg> add https://github.com/pjaap/ProjectionOntoSLn.jl
The main function exported by this package is project_onto_sln
.
This function can be called with a square matrix.
using ProjectionOntoSLn
using LinearAlgebra
A = rand(3,3)
P = project_onto_sln(A)
@show det(P) # will be close to 1
Currently, there are four methods implemented to compute the projection:
- Direct root finding:
root_finding
(this is the default if no method is specified, as seen above) - Iterative composite step:
composite_step
- Newton with scalar constraint:
constrained_newton
- An unconstrained Newton method:
unconstrained_newton
The methods are explained in depth in the our paper.
To use, e.g., the constrained Newton method, you can run
P = project_onto_sln(constrained_newton, A; maxIter=100, tolerance=1e-12, debug=false)
Internally, the matrix methods compute a singular value decomposition
Therefore, you can call project_onto_sln
also with a vector a
a = rand(3)
result = project_onto_sln(a)
p = result.projection
@show prod(p) # will be close to 1
Note, in the vector case, a solution object of type ProjectionResult
is returned.
This also contains the number of iterations.
See ProjectionOntoSLnBenchmark.jl for the benchmarks performed for the paper.
Feel free to open PRs in order to contribute to the project :)