@@ -17,17 +17,21 @@ function MathOptAnalyzer.analyze(
1717 threshold_dense_entries:: Int = 1000 ,
1818 threshold_small:: Float64 = 1e-5 ,
1919 threshold_large:: Float64 = 1e+5 ,
20+ threshold_dynamic_range_single:: Float64 = 1e+6 ,
21+ threshold_dynamic_range_matrix:: Float64 = 1e+8 ,
2022)
2123 data = Data ()
2224 data. threshold_dense_fill_in = threshold_dense_fill_in
2325 data. threshold_dense_entries = threshold_dense_entries
2426 data. threshold_small = threshold_small
2527 data. threshold_large = threshold_large
28+ data. threshold_dynamic_range_single = threshold_dynamic_range_single
29+ data. threshold_dynamic_range_matrix = threshold_dynamic_range_matrix
2630
2731 # initialize simples data
2832 data. sense = MOI. get (model, MOI. ObjectiveSense ())
2933 data. number_of_variables = MOI. get (model, MOI. NumberOfVariables ())
30- sizehint! (data. variables_in_constraints , data. number_of_variables)
34+ sizehint! (data. _variables_in_constraints , data. number_of_variables)
3135
3236 # objective pass
3337 objective_type = MOI. get (model, MOI. ObjectiveFunctionType ())
@@ -56,13 +60,15 @@ function MathOptAnalyzer.analyze(
5660 # variable index constraints are not counted in the constraints pass
5761 list_of_variables = MOI. get (model, MOI. ListOfVariableIndices ())
5862 for var in list_of_variables
59- if ! (var in data. variables_in_constraints )
63+ if ! (var in data. _variables_in_constraints )
6064 push! (
6165 data. variables_not_in_constraints,
6266 VariableNotInConstraints (var),
6367 )
6468 end
6569 end
70+ # TODO
71+ # compute ranges and dynamic ranges for variables and matrix
6672 sort! (data. dense_rows, by = x -> x. nnz, rev = true )
6773 sort! (data. matrix_small, by = x -> abs (x. coefficient))
6874 sort! (data. matrix_large, by = x -> abs (x. coefficient), rev = true )
96102
97103function _get_objective_data (data, func:: MOI.ScalarAffineFunction )
98104 nnz = 0
105+ _reset_function_range (data)
99106 for term in func. terms
100107 variable = term. variable
101108 coefficient = term. coefficient
102109 if iszero (coefficient)
103110 continue
104111 end
105- nnz += _update_range (data. objective_range , coefficient)
112+ nnz += _update_function_range (data, coefficient, variable )
106113 if abs (coefficient) < data. threshold_small
107114 push! (
108115 data. objective_small,
@@ -115,9 +122,87 @@ function _get_objective_data(data, func::MOI.ScalarAffineFunction)
115122 )
116123 end
117124 end
125+ range = _function_range (data)
126+ if range > data. threshold_dynamic_range_single
127+ push! (
128+ data. large_dynamic_range_objective,
129+ LargeDynamicRangeObjective (
130+ data. _small_coefficient[1 ][2 ],
131+ data. _large_coefficient[1 ][2 ],
132+ range,
133+ ),
134+ )
135+ end
136+ _reset_function_range (data)
137+ return
138+ end
139+
140+ function _reset_function_range (data:: Data )
141+ empty! (data. _large_coefficient)
142+ empty! (data. _small_coefficient)
143+ sizehint! (data. _large_coefficient, 1 )
144+ sizehint! (data. _small_coefficient, 1 )
118145 return
119146end
120147
148+ function _function_range (data:: Data )
149+ if isempty (data. _large_coefficient) || isempty (data. _small_coefficient)
150+ return 0.0
151+ end
152+ large = data. _large_coefficient[1 ][1 ]
153+ small = data. _small_coefficient[1 ][1 ]
154+ return large / small
155+ end
156+
157+ function _update_function_range (data:: Data , value, variable)
158+ if iszero (value)
159+ return 0
160+ end
161+ value = abs (value)
162+ if isempty (data. _large_coefficient)
163+ push! (data. _large_coefficient, (value, variable))
164+ elseif value > data. _large_coefficient[1 ][1 ]
165+ data. _large_coefficient[1 ] = (value, variable)
166+ end
167+ if isempty (data. _small_coefficient)
168+ push! (data. _small_coefficient, (value, variable))
169+ elseif value < data. _small_coefficient[1 ][1 ]
170+ data. _small_coefficient[1 ] = (value, variable)
171+ end
172+ return 1
173+ end
174+
175+ function _update_constraint_range (data:: Data , value, variable, ref)
176+ if iszero (value)
177+ return 0
178+ end
179+ _update_function_range (data, value, variable)
180+ value = abs (value)
181+ #
182+ if isempty (data. _large_matrix_coefficient)
183+ push! (data. _large_matrix_coefficient, (value, ref, variable))
184+ elseif value > data. _large_matrix_coefficient[1 ][1 ]
185+ data. _large_matrix_coefficient[1 ] = (value, ref, variable)
186+ end
187+ if isempty (data. _small_matrix_coefficient)
188+ push! (data. _small_matrix_coefficient, (value, ref, variable))
189+ elseif value < data. _small_matrix_coefficient[1 ][1 ]
190+ data. _small_matrix_coefficient[1 ] = (value, ref, variable)
191+ end
192+ #
193+ if ! haskey (data. _large_variable_coefficient, variable)
194+ data. _large_variable_coefficient[variable] = (value, ref)
195+ elseif value > data. _large_matrix_coefficient[variable][1 ]
196+ data. _large_variable_coefficient[variable] = (value, ref)
197+ end
198+ if ! haskey (data. _small_variable_coefficient, variable)
199+ data. _small_variable_coefficient[variable] = (value, ref)
200+ elseif value < data. _small_variable_coefficient[variable][1 ]
201+ data. _small_variable_coefficient[variable] = (value, ref)
202+ end
203+ return 1
204+ end
205+
121206function _get_objective_data (
122207 data,
123208 func:: MOI.ScalarQuadraticFunction{T} ,
@@ -231,13 +316,15 @@ function _get_constraint_matrix_data(
231316 end
232317 end
233318 nnz = 0
319+ _reset_function_range (data)
234320 for term in func. terms
235321 variable = term. variable
236322 coefficient = term. coefficient
237323 if iszero (coefficient)
238324 continue
239325 end
240- nnz += _update_range (data. matrix_range, coefficient)
326+ # nnz += _update_range(data.matrix_range, coefficient)
327+ nnz += _update_constraint_range (data, coefficient, variable, ref)
241328 if abs (coefficient) < data. threshold_small
242329 push! (
243330 data. matrix_small,
@@ -249,7 +336,7 @@ function _get_constraint_matrix_data(
249336 LargeMatrixCoefficient (ref, variable, coefficient),
250337 )
251338 end
252- push! (data. variables_in_constraints , variable)
339+ push! (data. _variables_in_constraints , variable)
253340 end
254341 if nnz == 0
255342 if ! ignore_extras
@@ -261,6 +348,19 @@ function _get_constraint_matrix_data(
261348 nnz > data. threshold_dense_entries
262349 push! (data. dense_rows, DenseConstraint (ref, nnz))
263350 end
351+ range = _function_range (data)
352+ if range > data. threshold_dynamic_range_single
353+ push! (
354+ data. large_dynamic_range_constraints,
355+ LargeDynamicRangeConstraint (
356+ ref,
357+ data. _small_coefficient[1 ][2 ],
358+ data. _large_coefficient[1 ][2 ],
359+ range,
360+ ),
361+ )
362+ end
363+ _reset_function_range (data)
264364 data. matrix_nnz += nnz
265365 return
266366end
@@ -290,8 +390,8 @@ function _get_constraint_matrix_data(
290390 LargeMatrixQuadraticCoefficient (ref, v1, v2, coefficient),
291391 )
292392 end
293- push! (data. variables_in_constraints , v1)
294- push! (data. variables_in_constraints , v2)
393+ push! (data. _variables_in_constraints , v1)
394+ push! (data. _variables_in_constraints , v2)
295395 end
296396 data. has_quadratic_constraints = true
297397 _get_constraint_matrix_data (
@@ -307,15 +407,19 @@ function _get_constraint_matrix_data(
307407 data,
308408 ref:: MOI.ConstraintIndex ,
309409 func:: MOI.VectorAffineFunction{T} ,
410+ ignore_extras:: Bool = false ,
310411) where {T}
412+ nnz = 0
413+ _reset_function_range (data)
311414 for term in func. terms
312415 variable = term. scalar_term. variable
313416 coefficient = term. scalar_term. coefficient
314417 # index = term.output_index
315418 if iszero (coefficient)
316419 continue
317420 end
318- _update_range (data. matrix_range, coefficient)
421+ # _update_range(data.matrix_range, coefficient)
422+ nnz += _update_constraint_range (data, coefficient, variable, ref)
319423 if abs (coefficient) < data. threshold_small
320424 push! (
321425 data. matrix_small,
@@ -327,8 +431,34 @@ function _get_constraint_matrix_data(
327431 LargeMatrixCoefficient (ref, variable, coefficient),
328432 )
329433 end
330- push! (data. variables_in_constraints, variable)
434+ push! (data. _variables_in_constraints, variable)
435+ end
436+ if nnz == 0
437+ if ! ignore_extras
438+ push! (data. empty_rows, EmptyConstraint (ref))
439+ end
440+ return
441+ end
442+ # this computation for vector constraint can be more complicated
443+ # as this might need to be per index
444+ # if nnz / data.number_of_variables > data.threshold_dense_fill_in &&
445+ # nnz > data.threshold_dense_entries
446+ # push!(data.dense_rows, DenseConstraint(ref, nnz))
447+ # end
448+ range = _function_range (data)
449+ if range > data. threshold_dynamic_range_single
450+ push! (
451+ data. large_dynamic_range_constraints,
452+ LargeDynamicRangeConstraint (
453+ ref,
454+ data. _small_coefficient[1 ][2 ],
455+ data. _large_coefficient[1 ][2 ],
456+ range,
457+ ),
458+ )
331459 end
460+ _reset_function_range (data)
461+ data. matrix_nnz += nnz
332462 return
333463end
334464
@@ -337,14 +467,15 @@ function _get_constraint_matrix_data(
337467 ref:: MOI.ConstraintIndex ,
338468 func:: MOI.VectorQuadraticFunction{T} ,
339469) where {T}
470+ nnz = 0
340471 for term in func. quadratic_terms
341472 v1 = term. scalar_term. variable_1
342473 v2 = term. scalar_term. variable_2
343474 coefficient = term. scalar_term. coefficient
344475 if iszero (coefficient)
345476 continue
346477 end
347- _update_range (data. matrix_quadratic_range, coefficient)
478+ nnz += _update_range (data. matrix_quadratic_range, coefficient)
348479 if abs (coefficient) < data. threshold_small
349480 push! (
350481 data. matrix_quadratic_small,
@@ -356,14 +487,14 @@ function _get_constraint_matrix_data(
356487 LargeMatrixQuadraticCoefficient (ref, v1, v2, coefficient),
357488 )
358489 end
359- push! (data. variables_in_constraints , v1)
360- push! (data. variables_in_constraints , v2)
490+ push! (data. _variables_in_constraints , v1)
491+ push! (data. _variables_in_constraints , v2)
361492 end
362493 _get_constraint_matrix_data (
363494 data,
364495 ref,
365496 MOI. VectorAffineFunction {T} (func. affine_terms, func. constants),
366- # ignore_extras = nnz > 0,
497+ ignore_extras = nnz > 0 ,
367498 )
368499 return
369500end
@@ -373,7 +504,7 @@ function _get_constraint_matrix_data(
373504 ref:: MOI.ConstraintIndex ,
374505 func:: MOI.VariableIndex ,
375506)
376- # push!(data.variables_in_constraints , func)
507+ # push!(data._variables_in_constraints , func)
377508 return
378509end
379510
@@ -386,7 +517,7 @@ function _get_constraint_matrix_data(
386517 return
387518 end
388519 for var in func. variables
389- push! (data. variables_in_constraints , var)
520+ push! (data. _variables_in_constraints , var)
390521 end
391522 return
392523end
0 commit comments