58
58
# ##
59
59
# ## Structural check
60
60
# ##
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 )
62
96
fullvars = get_fullvars (state)
63
97
neqs = n_concrete_eqs (state)
64
98
@unpack graph, var_to_diff = state. structure
@@ -72,6 +106,7 @@ function check_consistency(state::TransformationState, orig_inputs)
72
106
is_balanced = n_highest_vars == neqs
73
107
74
108
if neqs > 0 && ! is_balanced
109
+ nothrow && return false
75
110
varwhitelist = var_to_diff .== nothing
76
111
var_eq_matching = maximal_matching (graph, eq -> true , v -> varwhitelist[v]) # not assigned
77
112
# Just use `error_reporting` to do conditional
@@ -85,20 +120,7 @@ function check_consistency(state::TransformationState, orig_inputs)
85
120
error_reporting (state, bad_idxs, n_highest_vars, iseqs, orig_inputs)
86
121
end
87
122
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)
102
124
103
125
if ! isempty (unassigned_var) || ! is_balanced
104
126
io = IOBuffer ()
@@ -107,10 +129,14 @@ function check_consistency(state::TransformationState, orig_inputs)
107
129
errmsg = " The system is structurally singular! " *
108
130
" Here are the problematic variables: \n " *
109
131
unassigned_var_str
132
+ if nothrow
133
+ @warn errmsg
134
+ return false
135
+ end
110
136
throw (InvalidSystemException (errmsg))
111
137
end
112
138
113
- return nothing
139
+ return true
114
140
end
115
141
116
142
# ##
0 commit comments