|
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 |
| - |
91 | 1 | function contains_variable(x, wrt)
|
92 | 2 | any(y -> occursin(y, x), wrt)
|
93 | 3 | end
|
@@ -562,3 +472,92 @@ function handle_rational_polynomials(x, wrt; fraction_cancel_fn = simplify_fract
|
562 | 472 | end
|
563 | 473 | return num, den
|
564 | 474 | 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