Skip to content

Commit 7bb635d

Browse files
feat: add NonlinearSolveHomotopyContinuation.jl (#523)
* feat: add `NonlinearSolveHomotopyContinuation.jl` * feat: add `solve` implementations * test: add tests for all roots solve * fix: fix jacobian implementation, add taylor implementation * fix: fix system evaluate and jacobian * fix: fix inplace system taylor * fix: fix homotopy and implement taylor * fix: fix jacobian building for systems * fix: fix single root solve implementation * build: add TaylorSeries as a dependency * fix: fix jacobian and taylor implementations * test: add tests for single roots, fix allroots tests * build: add compat entries * docs: add docstrings to NonlinearSolveHomotopyContinuation.jl * ci: add NonlinearSolveHomotopyContinuation.jl to CI * docs: add NonlinearSolveHomotopyContinuation to docs * build: fix LinearAlgebra compat * test: do not rely on singular roots for tests * test: sort roots in `allroots` test * refactor: format * test: do not rely on singular roots * Update homotopycontinuation.md * docs: add `NonlinearSolveHomotopyContinuation` to doc build * refactor: use TaylorDiff.jl instead of TaylorSeries.jl --------- Co-authored-by: Christopher Rackauckas <[email protected]>
1 parent 258e49d commit 7bb635d

14 files changed

+1060
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
name: CI (NonlinearSolveHomotopyContinuation)
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- master
7+
paths:
8+
- "lib/NonlinearSolveHomotopyContinuation/**"
9+
- ".github/workflows/CI_NonlinearSolveHomotopyContinuation.yml"
10+
- "lib/NonlinearSolveBase/**"
11+
push:
12+
branches:
13+
- master
14+
15+
concurrency:
16+
# Skip intermediate builds: always.
17+
# Cancel intermediate builds: only if it is a pull request build.
18+
group: ${{ github.workflow }}-${{ github.ref }}
19+
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
20+
21+
jobs:
22+
test:
23+
runs-on: ${{ matrix.os }}
24+
strategy:
25+
fail-fast: false
26+
matrix:
27+
version:
28+
- "1.10"
29+
- "1"
30+
os:
31+
- ubuntu-latest
32+
- macos-latest
33+
- windows-latest
34+
steps:
35+
- uses: actions/checkout@v4
36+
- uses: julia-actions/setup-julia@v2
37+
with:
38+
version: ${{ matrix.version }}
39+
- uses: actions/cache@v4
40+
env:
41+
cache-name: cache-artifacts
42+
with:
43+
path: ~/.julia/artifacts
44+
key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
45+
restore-keys: |
46+
${{ runner.os }}-test-${{ env.cache-name }}-
47+
${{ runner.os }}-test-
48+
${{ runner.os }}-
49+
- name: "Install Dependencies and Run Tests"
50+
run: |
51+
import Pkg
52+
Pkg.Registry.update()
53+
# Install packages present in subdirectories
54+
dev_pks = Pkg.PackageSpec[]
55+
for path in ("lib/NonlinearSolveBase",)
56+
push!(dev_pks, Pkg.PackageSpec(; path))
57+
end
58+
Pkg.develop(dev_pks)
59+
Pkg.instantiate()
60+
Pkg.test(; coverage="user")
61+
shell: julia --color=yes --code-coverage=user --depwarn=yes --project=lib/NonlinearSolveHomotopyContinuation {0}
62+
- uses: julia-actions/julia-processcoverage@v1
63+
with:
64+
directories: lib/NonlinearSolveBase/src,lib/NonlinearSolveBase/ext,lib/NonlinearSolveHomotopyContinuation/src
65+
- uses: codecov/codecov-action@v5
66+
with:
67+
file: lcov.info
68+
token: ${{ secrets.CODECOV_TOKEN }}
69+
verbose: true
70+
fail_ci_if_error: false
71+
72+
downgrade:
73+
runs-on: ubuntu-latest
74+
strategy:
75+
fail-fast: false
76+
matrix:
77+
version:
78+
- "1.10"
79+
steps:
80+
- uses: actions/checkout@v4
81+
- uses: julia-actions/setup-julia@v2
82+
with:
83+
version: ${{ matrix.version }}
84+
- uses: julia-actions/julia-downgrade-compat@v1
85+
with:
86+
skip: NonlinearSolveBase, SciMLJacobianOperators
87+
- name: "Install Dependencies and Run Tests"
88+
run: |
89+
import Pkg
90+
Pkg.Registry.update()
91+
# Install packages present in subdirectories
92+
dev_pks = Pkg.PackageSpec[]
93+
for path in ("lib/NonlinearSolveBase",)
94+
push!(dev_pks, Pkg.PackageSpec(; path))
95+
end
96+
Pkg.develop(dev_pks)
97+
Pkg.instantiate()
98+
Pkg.test(; coverage="user")
99+
shell: julia --color=yes --code-coverage=user --depwarn=yes --project=lib/NonlinearSolveHomotopyContinuation {0}
100+
- uses: julia-actions/julia-processcoverage@v1
101+
with:
102+
directories: lib/NonlinearSolveBase/src,lib/NonlinearSolveBase/ext,lib/NonlinearSolveHomotopyContinuation/src
103+
- uses: codecov/codecov-action@v5
104+
with:
105+
file: lcov.info
106+
token: ${{ secrets.CODECOV_TOKEN }}
107+
verbose: true
108+
fail_ci_if_error: false

.github/workflows/Documentation.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
Pkg.Registry.update()
2323
# Install packages present in subdirectories
2424
dev_pks = Pkg.PackageSpec[]
25-
for path in ("lib/SciMLJacobianOperators", ".", "lib/SimpleNonlinearSolve", "lib/NonlinearSolveBase", "lib/BracketingNonlinearSolve", "lib/NonlinearSolveFirstOrder", "lib/NonlinearSolveQuasiNewton", "lib/NonlinearSolveSpectralMethods")
25+
for path in ("lib/SciMLJacobianOperators", ".", "lib/SimpleNonlinearSolve", "lib/NonlinearSolveBase", "lib/BracketingNonlinearSolve", "lib/NonlinearSolveFirstOrder", "lib/NonlinearSolveQuasiNewton", "lib/NonlinearSolveSpectralMethods", "lib/NonlinearSolveHomotopyContinuation")
2626
push!(dev_pks, Pkg.PackageSpec(; path))
2727
end
2828
Pkg.develop(dev_pks)

docs/Project.toml

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae"
1515
NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec"
1616
NonlinearSolveBase = "be0214bd-f91f-a760-ac4e-3421ce2b2da0"
1717
NonlinearSolveFirstOrder = "5959db7a-ea39-4486-b5fe-2dd0bf03d60d"
18+
NonlinearSolveHomotopyContinuation = "2ac3b008-d579-4536-8c91-a1a5998c2f8b"
1819
NonlinearSolveQuasiNewton = "9a2c21bd-3a47-402d-9113-8faf9a0ee114"
1920
NonlinearSolveSpectralMethods = "26075421-4e9a-44e1-8bd1-420ed7ad02b2"
2021
OrdinaryDiffEqTsit5 = "b1df2697-797e-41e3-8120-5422d3b24e4a"

docs/make.jl

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ using Sundials
55
using NonlinearSolveBase, SciMLBase, DiffEqBase
66
using SimpleNonlinearSolve, BracketingNonlinearSolve
77
using NonlinearSolveFirstOrder, NonlinearSolveQuasiNewton, NonlinearSolveSpectralMethods
8+
using NonlinearSolveHomotopyContinuation
89
using SciMLJacobianOperators
910
using NonlinearSolve, SteadyStateDiffEq
1011

@@ -35,6 +36,7 @@ makedocs(;
3536
NonlinearSolveBase, SciMLBase, DiffEqBase,
3637
SimpleNonlinearSolve, BracketingNonlinearSolve,
3738
NonlinearSolveFirstOrder, NonlinearSolveQuasiNewton, NonlinearSolveSpectralMethods,
39+
NonlinearSolveHomotopyContinuation,
3840
Sundials,
3941
SciMLJacobianOperators,
4042
NonlinearSolve, SteadyStateDiffEq

docs/pages.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ pages = [
4949
"api/petsc.md",
5050
"api/siamfanlequations.md",
5151
"api/speedmapping.md",
52-
"api/sundials.md"
52+
"api/sundials.md",
53+
"api/homotopycontinuation.md"
5354
],
5455
"Sub-Packages" => Any[
5556
"api/SciMLJacobianOperators.md",

docs/src/api/homotopycontinuation.md

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# HomotopyContinuation.jl
2+
3+
NonlinearSolve wraps the homotopy continuation algorithm implemented in
4+
HomotopyContinuation.jl. This solver is not included by default and needs
5+
to be installed separately:
6+
7+
```julia
8+
using Pkg
9+
Pkg.add("NonlinearSolveHomotopyContinuation")
10+
using NonlinearSolveHomotopyContinuation, NonlinearSolve
11+
```
12+
13+
# Solver API
14+
15+
```@docs
16+
NonlinearSolveHomotopyContinuation.HomotopyContinuationJL
17+
SciMLBase.HomotopyContinuationFunction
18+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 Aayush Sabharwal <[email protected]> and contributors
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name = "NonlinearSolveHomotopyContinuation"
2+
uuid = "2ac3b008-d579-4536-8c91-a1a5998c2f8b"
3+
authors = ["Aayush Sabharwal <[email protected]> and contributors"]
4+
version = "0.1.0"
5+
6+
[deps]
7+
ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b"
8+
CommonSolve = "38540f10-b2f7-11e9-35d8-d573e4eb0ff2"
9+
ConcreteStructs = "2569d6c7-a4a2-43d3-a901-331e8e4be471"
10+
DifferentiationInterface = "a0c0ee7d-e4b9-4e03-894e-1c5f64a51d63"
11+
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
12+
HomotopyContinuation = "f213a82b-91d6-5c5d-acf7-10f1c761b327"
13+
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
14+
NonlinearSolveBase = "be0214bd-f91f-a760-ac4e-3421ce2b2da0"
15+
SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462"
16+
SymbolicIndexingInterface = "2efcf032-c050-4f8e-a9bb-153293bab1f5"
17+
TaylorDiff = "b36ab563-344f-407b-a36a-4f200bebf99c"
18+
19+
[compat]
20+
ADTypes = "1.11.0"
21+
Aqua = "0.8"
22+
CommonSolve = "0.2.4"
23+
ConcreteStructs = "0.2.3"
24+
DifferentiationInterface = "0.6.27"
25+
DocStringExtensions = "0.9.3"
26+
HomotopyContinuation = "2.12.0"
27+
LinearAlgebra = "1.10"
28+
NonlinearSolve = "4"
29+
NonlinearSolveBase = "1.3.3"
30+
SciMLBase = "2.71"
31+
SymbolicIndexingInterface = "0.3.36"
32+
TaylorDiff = "0.3.1"
33+
Test = "1.10"
34+
julia = "1.10"
35+
36+
[extras]
37+
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
38+
NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec"
39+
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
40+
41+
[targets]
42+
test = ["Aqua", "Test", "NonlinearSolve"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
module NonlinearSolveHomotopyContinuation
2+
3+
using SciMLBase: AbstractNonlinearProblem
4+
using SciMLBase
5+
using NonlinearSolveBase
6+
using SymbolicIndexingInterface
7+
using LinearAlgebra
8+
using ADTypes
9+
using TaylorDiff
10+
using DocStringExtensions
11+
import CommonSolve
12+
import HomotopyContinuation as HC
13+
import DifferentiationInterface as DI
14+
15+
using ConcreteStructs: @concrete
16+
17+
export HomotopyContinuationJL, HomotopyNonlinearFunction
18+
19+
"""
20+
HomotopyContinuationJL{AllRoots}(; autodiff = true, kwargs...)
21+
HomotopyContinuationJL(; kwargs...) = HomotopyContinuationJL{false}(; kwargs...)
22+
23+
This algorithm is an interface to `HomotopyContinuation.jl`. It is only valid for
24+
fully determined polynomial systems. The `AllRoots` type parameter can be `true` or
25+
`false` and controls whether the solver will find all roots of the polynomial
26+
or a single root close to the initial guess provided to the `NonlinearProblem`.
27+
The polynomial function must allow complex numbers to be provided as the state.
28+
29+
If `AllRoots` is `true`, the initial guess in the `NonlinearProblem` is ignored.
30+
The function must be traceable using HomotopyContinuation.jl's symbolic variables.
31+
Note that higher degree polynomials and systems with multiple unknowns can increase
32+
solve time significantly.
33+
34+
If `AllRoots` is `false`, a single path is traced during the homotopy. The traced path
35+
depends on the initial guess provided to the `NonlinearProblem` being solved. This method
36+
does not require that the polynomial function is traceable via HomotopyContinuation.jl's
37+
symbolic variables.
38+
39+
HomotopyContinuation.jl requires the jacobian of the system. In case a jacobian function
40+
is provided, it will be used. Otherwise, the `autodiff` keyword argument controls the
41+
autodiff method used to compute the jacobian. A value of `true` refers to
42+
`AutoForwardDiff` and `false` refers to `AutoFiniteDiff`. Alternate algorithms can be
43+
specified using ADTypes.jl.
44+
45+
HomotopyContinuation.jl requires the taylor series of the polynomial system for the single
46+
root method. This is automatically computed using TaylorSeries.jl.
47+
"""
48+
@concrete struct HomotopyContinuationJL{AllRoots} <:
49+
NonlinearSolveBase.AbstractNonlinearSolveAlgorithm
50+
autodiff
51+
kwargs
52+
end
53+
54+
function HomotopyContinuationJL{AllRoots}(; autodiff = true, kwargs...) where {AllRoots}
55+
if autodiff isa Bool
56+
autodiff = autodiff ? AutoForwardDiff() : AutoFiniteDiff()
57+
end
58+
HomotopyContinuationJL{AllRoots}(autodiff, kwargs)
59+
end
60+
61+
HomotopyContinuationJL(; kwargs...) = HomotopyContinuationJL{false}(; kwargs...)
62+
63+
include("interface_types.jl")
64+
include("solve.jl")
65+
66+
end

0 commit comments

Comments
 (0)