Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cgls-shift algorithm #853

Draft
wants to merge 230 commits into
base: main
Choose a base branch
from
Draft

Add cgls-shift algorithm #853

wants to merge 230 commits into from

Conversation

tmigot
Copy link
Member

@tmigot tmigot commented Feb 6, 2024

  • Add a file cgls_lanczos_shift.jl in the folder src
  • Add include("cgls_lanczos_shift.jl") in src/Krylov.jl
  • Add a file test_cgls_lanczos_shift.jl in the folder test
  • Add include("test_cgls_lanczos_shift.jl") in test/runtests.jl
  • Add a CglsLanczosShiftSolver structure in src/krylov_solvers.jl
  • Add export CglsLanczosShiftSolver in src/krylov_solvers.jl
  • Update KRYLOV_SOLVERS in src/krylov_solvers.jl
  • Update the loop for (KS, fun, nsol, ...) at the end of src/krylov_solvers.jl
  • Add the docstring of CglsLanczosShiftSolver in docs/src/api.md (section Solver Types)
  • Add @docs cgls_lanczos_shift cgls_lanczos_shift! in the most relevant markdown file of docs/src/solvers
  • Add an allocation test for CGLS_LANCZOS_SHIFT in test/test_allocations.jl
  • Add :cgls_lanczos_shift in test/test_mp.jl
  • Add tests for CglsLanczosShiftSolver in test/test_solvers.jl
  • Add a test for the warm-start feature of CGLS_LANCZOS_SHIFT in test/test_warm_start.jl
  • Add a test for the verbose mode of CGLS_LANCZOS_SHIFT in test/test_verbose.jl
  • Add CGLS_LANCZOS_SHIFT in docs/src/preconditioners.md
  • Add CGLS_LANCZOS_SHIFT in docs/src/processes.md
  • Add CGLS_LANCZOS_SHIFT in docs/src/factorization-free.md (not needed for methods with multiple shifts)
  • Add CGLS_LANCZOS_SHIFT in docs/src/storage.md
  • Add a file cgls_lanczos_shift.md in the folder docs/src/examples and update docs/make.jl
  • Add CglsLanczosShiftSolver in a note of docs/src/inplace.md if the solver requires the argument memory or nshifts
  • Add a dispatch for solve! and cgls_lanczos_shift! in src/krylov_solve.jl

Copy link
Contributor

github-actions bot commented Feb 6, 2024

Package name latest stable
CaNNOLeS.jl
DCISolver.jl
FletcherPenaltySolver.jl
JSOSolvers.jl
LLSModels.jl
LinearSolve.jl
Percival.jl
RipQP.jl

expected_cgls_lanczos_shift_bytes = storage_cgls_lanczos_shift_bytes(m, k, nshifts)
(x, stats) = cgls_lanczos_shift(Ao, b, shifts) # warmup
actual_cgls_lanczos_shift_bytes = @allocated cgls_lanczos_shift(Ao, b, shifts)
@test expected_cgls_lanczos_shift_bytes ≤ actual_cgls_lanczos_shift_bytes ≤ 1.03 * expected_cgls_lanczos_shift_bytes
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@amontoison I replaced 1.02 used here by 1.03 and it sort of "fix" the tests with Julia 1.6. What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try a bigger linear system ;)


#### Input arguments

* `A`: a linear operator that models a Hermitian matrix of dimension n;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A is a rectangular matrix not a square Hermitian one.


#### Keyword arguments

* `M`: linear operator that models a Hermitian positive-definite matrix of size `n` used for centered preconditioning;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many keyword arguments are missing in the signature at the top of the docstring (atol, rtol, ldiv, M, ...).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a Hermitian -> an Hermitian

* `check_curvature`: if `true`, check that the curvature of the quadratic along the search direction is positive, and abort if not, unless `linesearch` is also `true`;
* `atol`: absolute stopping tolerance based on the residual norm;
* `rtol`: relative stopping tolerance based on the residual norm;
* `itmax`: the maximum number of iterations. If `itmax=0`, the default number of iterations is set to `2n`;
Copy link
Member

@amontoison amontoison Feb 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If A is rectangular, it's 2 × dimension(A'*A) in practice. We should verify that it's 2n and not 2m.


def_kwargs_cgls_lanczos_shift = (:(; M = I ),
:(; ldiv::Bool = false ),
:(; check_curvature::Bool = false),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed because A'A + \lambda I is always SPD due to the structure. In CG-LANCZOS-SHIFT, it's just A + \lambda I.

@@ -42,6 +42,10 @@
@test norm((A - I) * x[1] - b) ≤ Κ * (atol + norm(b) * rtol)
@test norm((A + I) * x[2] - b) ≤ Κ * (atol + norm(b) * rtol)
@test eltype(x) == Vector{FC}
elseif fn == :cgls_lanczos_shift
@test norm(A' * (b - A * x[1]) + x[1]) ≤ Κ * (atol + norm(b) * rtol)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@test norm(A' * (b - A * x[1]) + x[1]) Κ * (atol + norm(b) * rtol)
@test norm(A' * (b - A * x[1]) + x[1]) Κ * (atol + norm(A' * b) * rtol)

@@ -42,6 +42,10 @@
@test norm((A - I) * x[1] - b) ≤ Κ * (atol + norm(b) * rtol)
@test norm((A + I) * x[2] - b) ≤ Κ * (atol + norm(b) * rtol)
@test eltype(x) == Vector{FC}
elseif fn == :cgls_lanczos_shift
@test norm(A' * (b - A * x[1]) + x[1]) ≤ Κ * (atol + norm(b) * rtol)
@test norm(A' * (b - A * x[2]) - x[2]) ≤ Κ * (atol + norm(b) * rtol)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@test norm(A' * (b - A * x[2]) - x[2]) Κ * (atol + norm(b) * rtol)
@test norm(A' * (b - A * x[2]) - x[2]) Κ * (atol + norm(A' * b) * rtol)

@@ -4,8 +4,8 @@ function test_solvers(FC)
m = div(n, 2)
Au = A[1:m,:] # Dimension m x n
Ao = A[:,1:m] # Dimension n x m
b = Ao * ones(FC, m) # Dimension n
c = Au * ones(FC, n) # Dimension m
b = Ao * ones(FC, m) # Dimension m
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you modify the dimension?

Copy link
Member

@amontoison amontoison left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good work @tmigot!

Can you explain what are the differences in terms of implementation between cgls-lanczos-shift and cg-lanczos-shift when you provide A'A as input?

It seems that you are not doing the products with A and A' so I suppose that it's a trick of the implementation.

We could add a comment about it in the docstring.
I'm curious to also compare the convergence history of cgls-shift and cg-shift on an ill-conditioned LS problem.

@amontoison
Copy link
Member

@tmigot Any update?

@tmigot
Copy link
Member Author

tmigot commented Apr 16, 2024

Hey @amontoison ! I didn't find the time to figure out the changes to add the preconditioner, so no real update.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants