|
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