113113
114114mutable struct PresolvedData{T, S}
115115 xps:: S
116+ c:: S # copy of c
117+ z:: S # c + Qx for postsolve PrimalConstraints
116118 arows:: Vector{Row{T}}
117119 acols:: Vector{Col{T}}
118120 hcols:: Vector{Col{T}}
@@ -289,6 +291,26 @@ function presolve(
289291 psdata. c0 = qmp. c0
290292 end
291293
294+ # c_ps is the new c padded with zeros to have the same size as the init c
295+ c_ps = fill! (S (undef, nvar), zero (T))
296+ restore_x! (qmp. kept_cols, qmp. c, c_ps, nvar)
297+ # group all presolve info into a struct
298+ psd = PresolvedData {T, S} (
299+ qmp. xps,
300+ c_ps,
301+ copy (c_ps),
302+ qmp. arows,
303+ qmp. acols,
304+ qmp. hcols,
305+ qmp. kept_rows,
306+ qmp. kept_cols,
307+ nvarps,
308+ nconps,
309+ nvar,
310+ ncon,
311+ operations,
312+ )
313+
292314 # form meta
293315 nnzh = length (psdata. H. vals)
294316 if ! (nnzh == length (psdata. H. rows) == length (psdata. H. cols))
@@ -318,16 +340,20 @@ function presolve(
318340 solver_specific = Dict (:presolvedQM => nothing ),
319341 )
320342 elseif nvarps == 0
343+ sol_in = QMSolution (S (undef, 0 ), fill! (S (undef, nconps), zero (T)), S (undef, 0 ), S (undef, 0 ))
344+ sol = postsolve (psd, sol_in)
321345 feasible = all (qm. meta. lcon .<= qm. data. A * qmp. xps .<= qm. meta. ucon)
322- s = qm. data. c .+ Symmetric (qm. data. H, :L ) * qmp. xps
346+ # s = qm.data.c .+ Symmetric(qm.data.H, :L) * qmp.xps
323347 return GenericExecutionStats (
324348 qm,
325349 status = feasible ? :first_order : :infeasible ,
326- solution = qmp. xps,
327- objective = obj (qm, qmp. xps),
328- multipliers = zeros (T, ncon),
329- multipliers_L = max .(s, zero (T)),
330- multipliers_U = max .(.- s, zero (T)),
350+ solution = sol. x,
351+ objective = obj (qm, sol. x),
352+ primal_feas = feasible ? zero (T) : T (Inf ),
353+ dual_feas = feasible ? zero (T) : T (Inf ),
354+ multipliers = sol. y,
355+ multipliers_L = sol. s_l,
356+ multipliers_U = sol. s_u,
331357 iter = 0 ,
332358 elapsed_time = time () - start_time,
333359 solver_specific = Dict (:presolvedQM => nothing , :psoperations => operations),
@@ -349,19 +375,6 @@ function presolve(
349375 minimize = qm. meta. minimize,
350376 kwargs... ,
351377 )
352- psd = PresolvedData {T, S} (
353- qmp. xps,
354- qmp. arows,
355- qmp. acols,
356- qmp. hcols,
357- qmp. kept_rows,
358- qmp. kept_cols,
359- nvarps,
360- nconps,
361- nvar,
362- ncon,
363- operations,
364- )
365378 ps = PresolvedQuadraticModel (psmeta, Counters (), psdata, psd)
366379 return GenericExecutionStats (
367380 ps,
@@ -374,13 +387,11 @@ function presolve(
374387end
375388
376389function postsolve! (
377- qm:: QuadraticModel{T, S} ,
378- psqm:: PresolvedQuadraticModel{T, S} ,
390+ psd:: PresolvedData{T, S} ,
379391 sol:: QMSolution{S} ,
380392 sol_in:: QMSolution{S} ,
381393) where {T, S}
382394 x_in, y_in, s_l_in, s_u_in = sol_in. x, sol_in. y, sol_in. s_l, sol_in. s_u
383- psd = psqm. psd
384395 n_operations = length (psd. operations)
385396 nvar = psd. nvar
386397 @assert nvar == length (sol. x)
@@ -389,13 +400,34 @@ function postsolve!(
389400 @assert ncon == length (sol. y)
390401 restore_y! (psd. kept_rows, y_in, sol. y, ncon)
391402 restore_s! (sol. s_l, sol. s_u, s_l_in, s_u_in, psd. kept_cols)
403+ # add_Hx!(psd.z, psd.hcols, psd.kept_cols) # z = c + Hx
392404
393405 for i = n_operations: - 1 : 1
394406 operation_i = psd. operations[i]
395407 postsolve! (sol, operation_i, psd)
396408 end
397409end
398410
411+ postsolve! (
412+ psqm:: PresolvedQuadraticModel{T, S} ,
413+ sol:: QMSolution{S} ,
414+ sol_in:: QMSolution{S} ,
415+ ) where {T, S} = postsolve! (psqm. psd, sol, sol_in)
416+
417+ function postsolve (
418+ psd:: PresolvedData{T, S} ,
419+ sol_in:: QMSolution{S} ,
420+ ) where {T, S}
421+ x = fill! (S (undef, psd. nvar), zero (T))
422+ y = fill! (S (undef, psd. ncon), zero (T))
423+ s_l = fill! (S (undef, psd. nvar), zero (T))
424+ s_u = fill! (S (undef, psd. nvar), zero (T))
425+
426+ sol = QMSolution (x, y, s_l, s_u)
427+ postsolve! (psd, sol, sol_in)
428+ return sol
429+ end
430+
399431"""
400432 sol = postsolve(qm::QuadraticModel{T, S}, psqm::PresolvedQuadraticModel{T, S},
401433 sol_in::QMSolution{S}) where {T, S}
@@ -404,17 +436,8 @@ Retrieve the solution `sol = (x, y, s_l, s_u)` of the original QP `qm` given the
404436`sol_in` of type [`QMSolution`](@ref).
405437`sol_in.s_l` and `sol_in.s_u` can be sparse or dense vectors, but the output `sol.s_l` and `sol.s_u` are dense vectors.
406438"""
407- function postsolve (
439+ postsolve (
408440 qm:: QuadraticModel{T, S} ,
409441 psqm:: PresolvedQuadraticModel{T, S} ,
410442 sol_in:: QMSolution{S} ,
411- ) where {T, S}
412- x = fill! (S (undef, psqm. psd. nvar), zero (T))
413- y = fill! (S (undef, psqm. psd. ncon), zero (T))
414- s_l = fill! (S (undef, psqm. psd. nvar), zero (T))
415- s_u = fill! (S (undef, psqm. psd. nvar), zero (T))
416-
417- sol = QMSolution (x, y, s_l, s_u)
418- postsolve! (qm, psqm, sol, sol_in)
419- return sol
420- end
443+ ) where {T, S} = postsolve (psqm. psd, sol_in)
0 commit comments