| 
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