@@ -509,6 +509,21 @@ function varmap_get(varmap, var, default = nothing)
509
509
return default
510
510
end
511
511
512
+ """
513
+ $(TYPEDSIGNATURES)
514
+
515
+ Check if `varmap::Dict{Any, Any}` contains cyclic values for any symbolic variables in
516
+ `syms`. Falls back on the basis of `symbolic_container(indp)`. Returns `false` by default.
517
+ """
518
+ function detect_cycles (indp, varmap, syms)
519
+ if hasmethod (symbolic_container, Tuple{typeof (indp)}) &&
520
+ (sc = symbolic_container (indp)) != indp
521
+ return detect_cycles (sc, varmap, syms)
522
+ else
523
+ return false
524
+ end
525
+ end
526
+
512
527
anydict (d:: Dict{Any, Any} ) = d
513
528
anydict (d) = Dict {Any, Any} (d)
514
529
anydict () = Dict {Any, Any} ()
571
586
572
587
function fill_vars (
573
588
prob, varmap; defs = nothing , use_defaults = false , allsyms, index_function)
574
- idx_to_vsym = anydict (variable_index (prob, sym) => sym for sym in allsyms)
589
+ idx_to_vsym = anydict (index_function (prob, sym) => sym for sym in allsyms)
575
590
sym_to_idx = anydict ()
576
591
idx_to_sym = anydict ()
577
592
idx_to_val = anydict ()
@@ -617,10 +632,26 @@ function fill_vars(
617
632
return newvals
618
633
end
619
634
635
+ struct CyclicDependencyError <: Exception
636
+ varmap:: Dict{Any, Any}
637
+ vars:: Any
638
+ end
639
+
640
+ function Base. showerror (io:: IO , err:: CyclicDependencyError )
641
+ println (io, " Detected cyclic dependency in initial values:" )
642
+ for (k, v) in err. varmap
643
+ println (io, k, " => " , " v" )
644
+ end
645
+ println (io, " While trying to solve for variables: " , err. vars)
646
+ end
647
+
620
648
function _updated_u0_p_symmap (prob, u0, :: Val{true} , p, :: Val{false} , t0)
621
649
isdep = any (symbolic_type (v) != = NotSymbolic () for (_, v) in u0)
622
650
isdep || return remake_buffer (prob, state_values (prob), keys (u0), values (u0)), p
623
651
652
+ if detect_cycles (prob, u0, variable_symbols (prob))
653
+ throw (CyclicDependencyError (u0, variable_symbols (prob)))
654
+ end
624
655
for (k, v) in u0
625
656
u0[k] = symbolic_type (v) === NotSymbolic () ? v : symbolic_evaluate (v, u0)
626
657
end
@@ -642,6 +673,9 @@ function _updated_u0_p_symmap(prob, u0, ::Val{false}, p, ::Val{true}, t0)
642
673
isdep = any (symbolic_type (v) != = NotSymbolic () for (_, v) in p)
643
674
isdep || return u0, remake_buffer (prob, parameter_values (prob), keys (p), values (p))
644
675
676
+ if detect_cycles (prob, p, parameter_symbols (prob))
677
+ throw (CyclicDependencyError (p, parameter_symbols (prob)))
678
+ end
645
679
for (k, v) in p
646
680
p[k] = symbolic_type (v) === NotSymbolic () ? v : symbolic_evaluate (v, p)
647
681
end
@@ -669,6 +703,10 @@ function _updated_u0_p_symmap(prob, u0, ::Val{true}, p, ::Val{true}, t0)
669
703
end
670
704
671
705
varmap = merge (u0, p)
706
+ allsyms = [variable_symbols (prob); parameter_symbols (prob)]
707
+ if detect_cycles (prob, varmap, allsyms)
708
+ throw (CyclicDependencyError (varmap, allsyms))
709
+ end
672
710
if is_time_dependent (prob)
673
711
varmap[only (independent_variable_symbols (prob))] = t0
674
712
end
0 commit comments