@@ -245,3 +245,120 @@ function sorted_incidence_matrix(ts::TransformationState, val = true; only_algeq
245245 end
246246 SparseArrays. sparse (I, J, val, nsrcs (graph), ndsts (graph))
247247end
248+
249+ function add_row_coeffs! (
250+ row_col_i:: Vector{Int} , row_val_i:: Vector{T} , old_to_new_var:: Vector{Int} ,
251+ aliases:: Dict{Int, Int} , old_var:: Int , coeff:: T
252+ ) where {T <: Integer }
253+ alias = get (aliases, old_var, 0 )
254+ iszero (alias) && return
255+ push! (row_col_i, old_to_new_var[alias])
256+ push! (row_val_i, coeff)
257+ return nothing
258+ end
259+
260+ function add_row_coeffs! (
261+ row_col_i:: Vector{Int} , row_val_i:: Vector{T} , old_to_new_var:: Vector{Int} ,
262+ aliases:: Dict{Int, SparseArrays.SparseVector{T, Int}} , old_var:: Int , coeff:: T
263+ ) where {T <: Integer }
264+ alias = get (aliases, old_var, nothing )
265+ if alias isa SparseArrays. SparseVector{T, Int}
266+ I, V = SparseArrays. findnz (alias)
267+ for (i, v) in zip (I, V)
268+ iszero (old_to_new_var[i])
269+ end
270+ append! (row_col_i, Iterators. map (Base. Fix1 (getindex, old_to_new_var), I))
271+ append! (row_val_i, Iterators. map (Base. Fix1 (* , coeff), V))
272+ end
273+ return nothing
274+ end
275+
276+ """
277+ $TYPEDSIGNATURES
278+
279+ Construct the new coefficient matrix with:
280+
281+ - Some equations removed, as indicated by `old_to_new_eq` which is obtained from
282+ `get_old_to_new_idxs`.
283+ - Some variables removed and aliased to other variables, as indicated by `old_to_new_var`
284+ and `aliases`. `aliases` can be a `Dict{Int, Int}` indicating variables exactly aliased
285+ to others, or `Dict{Int, SparseVector{eltype(mm)}}` indicating variables aliased to linear
286+ combinations of others. Note that this is not recursive - if one variable
287+ depends on another aliased variable, it will lead to incorrect results.
288+ """
289+ function get_new_mm (
290+ aliases:: Dict{Int} , old_to_new_eq:: Vector{Int} , old_to_new_var:: Vector{Int} ,
291+ mm:: CLIL.SparseMatrixCLIL
292+ )
293+
294+ new_nparentrows = mm. nparentrows
295+ new_row_cols = eltype (mm. row_cols)[]
296+ new_row_vals = eltype (mm. row_vals)[]
297+ new_nzrows = Int[]
298+ indices = Int[]
299+
300+ for (i, eq) in enumerate (mm. nzrows)
301+ old_to_new_eq[eq] > 0 || continue
302+ new_row_col_i = eltype (eltype (new_row_cols))[]
303+ new_row_val_i = eltype (eltype (new_row_vals))[]
304+ sizehint! (new_row_col_i, length (mm. row_cols[i]))
305+ sizehint! (new_row_val_i, length (mm. row_vals[i]))
306+ still_valid_eq = true
307+ for (var, coeff) in zip (mm. row_cols[i], mm. row_vals[i])
308+ if old_to_new_var[var] > 0
309+ push! (new_row_col_i, old_to_new_var[var])
310+ push! (new_row_val_i, coeff)
311+ continue
312+ end
313+ # This variable is removed, but not aliased to an integer coefficient linear
314+ # combination. As a result, this equation cannot be retained in `mm`.
315+ if ! haskey (aliases, var)
316+ still_valid_eq = false
317+ break
318+ end
319+
320+ add_row_coeffs! (new_row_col_i, new_row_val_i, old_to_new_var, aliases, var, coeff)
321+ end
322+
323+ bad_idx = findfirst (iszero, new_row_col_i)
324+ if bad_idx isa Int
325+ throw (BadMMAliasError (bad_idx))
326+ end
327+ still_valid_eq || continue
328+ empty! (indices)
329+ append! (indices, LinearIndices (new_row_col_i))
330+ sortperm! (indices, new_row_col_i)
331+ final_row_cols = empty (new_row_col_i)
332+ final_row_vals = empty (new_row_val_i)
333+ push! (final_row_cols, new_row_col_i[indices[1 ]])
334+ push! (final_row_vals, new_row_val_i[indices[1 ]])
335+ for i in Iterators. drop (eachindex (indices), 1 )
336+ if new_row_col_i[indices[i]] == new_row_col_i[indices[i - 1 ]]
337+ final_row_vals[end ] += new_row_val_i[indices[i]]
338+ else
339+ push! (final_row_cols, new_row_col_i[indices[i]])
340+ push! (final_row_vals, new_row_val_i[indices[i]])
341+ end
342+ end
343+
344+ push! (new_row_cols, final_row_cols)
345+ push! (new_row_vals, final_row_vals)
346+ push! (new_nzrows, old_to_new_eq[eq])
347+ end
348+
349+ return typeof (mm)(new_nparentrows, count (! iszero, old_to_new_var), new_nzrows, new_row_cols, new_row_vals)
350+ end
351+
352+ struct BadMMAliasError <: Exception
353+ eq:: Int
354+ end
355+
356+ function Base. showerror (io:: IO , err:: BadMMAliasError )
357+ return print (
358+ io, """
359+ When processing equation $(err. eq) , the list of aliases resulted in a linear
360+ combination of a removed variable. No variable should be aliased to a removed
361+ variable.
362+ """
363+ )
364+ end
0 commit comments