113
113
114
114
mutable struct PresolvedData{T, S}
115
115
xps:: S
116
+ c:: S # copy of c
117
+ z:: S # c + Qx for postsolve PrimalConstraints
116
118
arows:: Vector{Row{T}}
117
119
acols:: Vector{Col{T}}
118
120
hcols:: Vector{Col{T}}
@@ -289,6 +291,26 @@ function presolve(
289
291
psdata. c0 = qmp. c0
290
292
end
291
293
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
+
292
314
# form meta
293
315
nnzh = length (psdata. H. vals)
294
316
if ! (nnzh == length (psdata. H. rows) == length (psdata. H. cols))
@@ -318,16 +340,20 @@ function presolve(
318
340
solver_specific = Dict (:presolvedQM => nothing ),
319
341
)
320
342
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)
321
345
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
323
347
return GenericExecutionStats (
324
348
qm,
325
349
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,
331
357
iter = 0 ,
332
358
elapsed_time = time () - start_time,
333
359
solver_specific = Dict (:presolvedQM => nothing , :psoperations => operations),
@@ -349,19 +375,6 @@ function presolve(
349
375
minimize = qm. meta. minimize,
350
376
kwargs... ,
351
377
)
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
- )
365
378
ps = PresolvedQuadraticModel (psmeta, Counters (), psdata, psd)
366
379
return GenericExecutionStats (
367
380
ps,
@@ -374,13 +387,11 @@ function presolve(
374
387
end
375
388
376
389
function postsolve! (
377
- qm:: QuadraticModel{T, S} ,
378
- psqm:: PresolvedQuadraticModel{T, S} ,
390
+ psd:: PresolvedData{T, S} ,
379
391
sol:: QMSolution{S} ,
380
392
sol_in:: QMSolution{S} ,
381
393
) where {T, S}
382
394
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
384
395
n_operations = length (psd. operations)
385
396
nvar = psd. nvar
386
397
@assert nvar == length (sol. x)
@@ -389,13 +400,34 @@ function postsolve!(
389
400
@assert ncon == length (sol. y)
390
401
restore_y! (psd. kept_rows, y_in, sol. y, ncon)
391
402
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
392
404
393
405
for i = n_operations: - 1 : 1
394
406
operation_i = psd. operations[i]
395
407
postsolve! (sol, operation_i, psd)
396
408
end
397
409
end
398
410
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
+
399
431
"""
400
432
sol = postsolve(qm::QuadraticModel{T, S}, psqm::PresolvedQuadraticModel{T, S},
401
433
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
404
436
`sol_in` of type [`QMSolution`](@ref).
405
437
`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.
406
438
"""
407
- function postsolve (
439
+ postsolve (
408
440
qm:: QuadraticModel{T, S} ,
409
441
psqm:: PresolvedQuadraticModel{T, S} ,
410
442
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