Skip to content

Commit 1802947

Browse files
refactor: rewrite HomotopyContinuationProblem to target NonlinearSolveHomotopyContinuation.jl
1 parent ef5e7a0 commit 1802947

File tree

2 files changed

+142
-151
lines changed

2 files changed

+142
-151
lines changed

src/systems/nonlinear/homotopy_continuation.jl

Lines changed: 89 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,3 @@
1-
"""
2-
$(TYPEDEF)
3-
4-
A type of Nonlinear problem which specializes on polynomial systems and uses
5-
HomotopyContinuation.jl to solve the system. Requires importing HomotopyContinuation.jl to
6-
create and solve.
7-
"""
8-
struct HomotopyContinuationProblem{uType, H, D, O, SS, U} <:
9-
SciMLBase.AbstractNonlinearProblem{uType, true}
10-
"""
11-
The initial values of states in the system. If there are multiple real roots of
12-
the system, the one closest to this point is returned.
13-
"""
14-
u0::uType
15-
"""
16-
A subtype of `HomotopyContinuation.AbstractSystem` to solve. Also contains the
17-
parameter object.
18-
"""
19-
homotopy_continuation_system::H
20-
"""
21-
A function with signature `(u, p) -> resid`. In case of rational functions, this
22-
is used to rule out roots of the system which would cause the denominator to be
23-
zero.
24-
"""
25-
denominator::D
26-
"""
27-
The `NonlinearSystem` used to create this problem. Used for symbolic indexing.
28-
"""
29-
sys::NonlinearSystem
30-
"""
31-
A function which generates and returns observed expressions for the given system.
32-
"""
33-
obsfn::O
34-
"""
35-
The HomotopyContinuation.jl solver and start system, obtained through
36-
`HomotopyContinuation.solver_startsystems`.
37-
"""
38-
solver_and_starts::SS
39-
"""
40-
A function which takes a solution of the transformed system, and returns a vector
41-
of solutions for the original system. This is utilized when converting systems
42-
to polynomials.
43-
"""
44-
unpack_solution::U
45-
end
46-
47-
function HomotopyContinuationProblem(::AbstractSystem, _u0, _p; kwargs...)
48-
error("HomotopyContinuation.jl is required to create and solve `HomotopyContinuationProblem`s. Please run `Pkg.add(\"HomotopyContinuation\")` to continue.")
49-
end
50-
51-
"""
52-
$(TYPEDSIGNATURES)
53-
54-
Utility function for `safe_HomotopyContinuationProblem`, implemented in the extension.
55-
"""
56-
function _safe_HomotopyContinuationProblem end
57-
58-
"""
59-
$(TYPEDSIGNATURES)
60-
61-
Return a `HomotopyContinuationProblem` if the extension is loaded and the system is
62-
polynomial. If the extension is not loaded, return `nothing`. If the system is not
63-
polynomial, return the appropriate `NotPolynomialError`.
64-
"""
65-
function safe_HomotopyContinuationProblem(sys::NonlinearSystem, args...; kwargs...)
66-
if Base.get_extension(ModelingToolkit, :MTKHomotopyContinuationExt) === nothing
67-
return nothing
68-
end
69-
return _safe_HomotopyContinuationProblem(sys, args...; kwargs...)
70-
end
71-
72-
SymbolicIndexingInterface.symbolic_container(p::HomotopyContinuationProblem) = p.sys
73-
SymbolicIndexingInterface.state_values(p::HomotopyContinuationProblem) = p.u0
74-
function SymbolicIndexingInterface.set_state!(p::HomotopyContinuationProblem, args...)
75-
set_state!(p.u0, args...)
76-
end
77-
function SymbolicIndexingInterface.parameter_values(p::HomotopyContinuationProblem)
78-
parameter_values(p.homotopy_continuation_system)
79-
end
80-
function SymbolicIndexingInterface.set_parameter!(p::HomotopyContinuationProblem, args...)
81-
set_parameter!(parameter_values(p), args...)
82-
end
83-
function SymbolicIndexingInterface.observed(p::HomotopyContinuationProblem, sym)
84-
if p.obsfn !== nothing
85-
return p.obsfn(sym)
86-
else
87-
return SymbolicIndexingInterface.observed(p.sys, sym)
88-
end
89-
end
90-
911
function contains_variable(x, wrt)
922
any(y -> occursin(y, x), wrt)
933
end
@@ -562,3 +472,92 @@ function handle_rational_polynomials(x, wrt; fraction_cancel_fn = simplify_fract
562472
end
563473
return num, den
564474
end
475+
476+
function SciMLBase.HomotopyNonlinearFunction(sys::NonlinearSystem, args...; kwargs...)
477+
ODEFunction{true}(sys, args...; kwargs...)
478+
end
479+
480+
function SciMLBase.HomotopyNonlinearFunction{true}(sys::NonlinearSystem, args...;
481+
kwargs...)
482+
ODEFunction{true, SciMLBase.AutoSpecialize}(sys, args...; kwargs...)
483+
end
484+
485+
function SciMLBase.HomotopyNonlinearFunction{false}(sys::NonlinearSystem, args...;
486+
kwargs...)
487+
ODEFunction{false, SciMLBase.FullSpecialize}(sys, args...; kwargs...)
488+
end
489+
490+
function SciMLBase.HomotopyNonlinearFunction{iip, specialize}(
491+
sys::NonlinearSystem, args...; eval_expression = false, eval_module = @__MODULE__,
492+
p = nothing, fraction_cancel_fn = SymbolicUtils.simplify_fractions,
493+
kwargs...) where {iip, specialize}
494+
if !iscomplete(sys)
495+
error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `HomotopyContinuationFunction`")
496+
end
497+
transformation = PolynomialTransformation(sys)
498+
if transformation isa NotPolynomialError
499+
throw(transformation)
500+
end
501+
result = transform_system(sys, transformation; fraction_cancel_fn)
502+
if result isa NotPolynomialError
503+
throw(result)
504+
end
505+
506+
sys2 = result.sys
507+
denoms = result.denominators
508+
polydata = transformation.polydata
509+
new_dvs = transformation.new_dvs
510+
all_solutions = transformation.all_solutions
511+
512+
# we want to create f, jac etc. according to `sys2` since that will do the solving
513+
# but the `sys` inside for symbolic indexing should be the non-polynomial system
514+
fn = NonlinearFunction{iip}(sys2; eval_expression, eval_module, kwargs...)
515+
obsfn = ObservedFunctionCache(
516+
sys; eval_expression, eval_module, checkbounds = get(kwargs, :checkbounds, false))
517+
fn = remake(fn; sys = sys, observed = obsfn)
518+
519+
denominator = build_explicit_observed_function(sys2, denoms)
520+
unpolynomialize = build_explicit_observed_function(sys2, all_solutions)
521+
522+
inv_mapping = Dict(v => k for (k, v) in transformation.substitution_rules)
523+
polynomialize_terms = [get(inv_mapping, var, var) for var in unknowns(sys2)]
524+
polynomialize = build_explicit_observed_function(sys, polynomialize_terms)
525+
526+
return HomotopyNonlinearFunction{iip, specialize}(
527+
fn; polynomialize, unpolynomialize, denominator)
528+
end
529+
530+
struct HomotopyContinuationProblem{iip, specialization} end
531+
532+
function HomotopyContinuationProblem(sys::NonlinearSystem, args...; kwargs...)
533+
HomotopyContinuationProblem{true}(sys, args...; kwargs...)
534+
end
535+
536+
function HomotopyContinuationProblem(sys::NonlinearSystem, t,
537+
u0map::StaticArray,
538+
args...;
539+
kwargs...)
540+
HomotopyContinuationProblem{false, SciMLBase.FullSpecialize}(
541+
sys, t, u0map, args...; kwargs...)
542+
end
543+
544+
function HomotopyContinuationProblem{true}(sys::NonlinearSystem, args...; kwargs...)
545+
HomotopyContinuationProblem{true, SciMLBase.AutoSpecialize}(sys, args...; kwargs...)
546+
end
547+
548+
function HomotopyContinuationProblem{false}(sys::NonlinearSystem, args...; kwargs...)
549+
HomotopyContinuationProblem{false, SciMLBase.FullSpecialize}(sys, args...; kwargs...)
550+
end
551+
552+
function HomotopyContinuationProblem{iip, spec}(
553+
sys::NonlinearSystem, u0map, pmap = SciMLBase.NullParameters();
554+
kwargs...) where {iip, spec}
555+
if !iscomplete(sys)
556+
error("A completed `NonlinearSystem` is required. Call `complete` or `structural_simplify` on the system before creating a `HomotopyContinuationProblem`")
557+
end
558+
f, u0, p = process_SciMLProblem(
559+
HomotopyNonlinearFunction{iip, spec}, sys, u0map, pmap; kwargs...)
560+
561+
kwargs = filter_kwargs(kwargs)
562+
return NonlinearProblem{iip}(f, u0, p; kwargs...)
563+
end

0 commit comments

Comments
 (0)