5858# ##
5959# ## Structural check
6060# ##
61- function check_consistency (state:: TransformationState , orig_inputs)
61+
62+ """
63+ $(TYPEDSIGNATURES)
64+
65+ Check if the `state` represents a singular system, and return the unmatched variables.
66+ """
67+ function singular_check (state:: TransformationState )
68+ @unpack graph, var_to_diff = state. structure
69+ fullvars = get_fullvars (state)
70+ # This is defined to check if Pantelides algorithm terminates. For more
71+ # details, check the equation (15) of the original paper.
72+ extended_graph = (@set graph. fadjlist = Vector{Int}[graph. fadjlist;
73+ map (collect, edges (var_to_diff))])
74+ extended_var_eq_matching = maximal_matching (extended_graph)
75+
76+ nvars = ndsts (graph)
77+ unassigned_var = []
78+ for (vj, eq) in enumerate (extended_var_eq_matching)
79+ vj > nvars && break
80+ if eq === unassigned && ! isempty (𝑑neighbors (graph, vj))
81+ push! (unassigned_var, fullvars[vj])
82+ end
83+ end
84+ return unassigned_var
85+ end
86+
87+ """
88+ $(TYPEDSIGNATURES)
89+
90+ Check the consistency of `state`, given the inputs `orig_inputs`. If `nothrow == false`,
91+ throws an error if the system is under-/over-determined or singular. In this case, if the
92+ function returns it will return `true`. If `nothrow == true`, it will return `false`
93+ instead of throwing an error. The singular case will print a warning.
94+ """
95+ function check_consistency (state:: TransformationState , orig_inputs; nothrow = false )
6296 fullvars = get_fullvars (state)
6397 neqs = n_concrete_eqs (state)
6498 @unpack graph, var_to_diff = state. structure
@@ -72,6 +106,7 @@ function check_consistency(state::TransformationState, orig_inputs)
72106 is_balanced = n_highest_vars == neqs
73107
74108 if neqs > 0 && ! is_balanced
109+ nothrow && return false
75110 varwhitelist = var_to_diff .== nothing
76111 var_eq_matching = maximal_matching (graph, eq -> true , v -> varwhitelist[v]) # not assigned
77112 # Just use `error_reporting` to do conditional
@@ -85,20 +120,7 @@ function check_consistency(state::TransformationState, orig_inputs)
85120 error_reporting (state, bad_idxs, n_highest_vars, iseqs, orig_inputs)
86121 end
87122
88- # This is defined to check if Pantelides algorithm terminates. For more
89- # details, check the equation (15) of the original paper.
90- extended_graph = (@set graph. fadjlist = Vector{Int}[graph. fadjlist;
91- map (collect, edges (var_to_diff))])
92- extended_var_eq_matching = maximal_matching (extended_graph)
93-
94- nvars = ndsts (graph)
95- unassigned_var = []
96- for (vj, eq) in enumerate (extended_var_eq_matching)
97- vj > nvars && break
98- if eq === unassigned && ! isempty (𝑑neighbors (graph, vj))
99- push! (unassigned_var, fullvars[vj])
100- end
101- end
123+ unassigned_var = singular_check (state)
102124
103125 if ! isempty (unassigned_var) || ! is_balanced
104126 io = IOBuffer ()
@@ -107,10 +129,14 @@ function check_consistency(state::TransformationState, orig_inputs)
107129 errmsg = " The system is structurally singular! " *
108130 " Here are the problematic variables: \n " *
109131 unassigned_var_str
132+ if nothrow
133+ @warn errmsg
134+ return false
135+ end
110136 throw (InvalidSystemException (errmsg))
111137 end
112138
113- return nothing
139+ return true
114140end
115141
116142# ##
0 commit comments