diff --git a/include/mp/flat/redef/conic/cones.h b/include/mp/flat/redef/conic/cones.h index 3b540e41f..d3a211769 100644 --- a/include/mp/flat/redef/conic/cones.h +++ b/include/mp/flat/redef/conic/cones.h @@ -141,10 +141,10 @@ class ConicConverter : public MCKeeper { && (MC().NumQC2SOCPAttempted() > MC().NumQC2SOCPSucceeded() || MC().HasQPObjective())) // and quadratics left in || // Some QC -> SOCP but not all - (((MC().NumQC2SOCPAttempted() > MC().NumQC2SOCPSucceeded() - && !MC().IfConvertSOCP2QC()) // and not decided to convert + ((MC().NumQC2SOCPAttempted() > MC().NumQC2SOCPSucceeded() || MC().HasQPObjective()) // or a quadratic obj - && MC().NumQC2SOCPSucceeded()) // Warn only if some succeeded + && MC().NumQC2SOCPSucceeded() // Warn only if some succeeded + && !MC().IfConvertSOCP2QC()) // and not decided to convert ) { MC().AddWarning("Mix QC+cones", "Not all quadratic constraints could " diff --git a/include/mp/flat/redef/conic/qcones2qc.h b/include/mp/flat/redef/conic/qcones2qc.h index bbd4a07b5..5a0375a5a 100644 --- a/include/mp/flat/redef/conic/qcones2qc.h +++ b/include/mp/flat/redef/conic/qcones2qc.h @@ -35,9 +35,18 @@ class QConeConverter : for (auto& coef: c) coef *= coef; c[0] = -c[0]; - GetMC().NarrowVarBounds(x[0], 0.0, GetMC().Infty()); - auto qc {QuadConLE{ {{}, {c, x, x}}, {0.0} }}; - GetMC().AddConstraint(std::move(qc)); + if (!GetMC().is_fixed(x[0])) { + GetMC().NarrowVarBounds(x[0], 0.0, GetMC().Infty()); + auto qc {QuadConLE{ {{}, {c, x, x}}, {0.0} }}; + GetMC().AddConstraint(std::move(qc)); + } else { // produce fixed RHS, better for Mosek + auto rhs = -c[0] * GetMC().fixed_value(x[0]); + c.erase(c.begin()); + auto x0 = x; + x0.erase(x0.begin()); + auto qc {QuadConLE{ {{}, {c, x0, x0}}, {rhs} }}; + GetMC().AddConstraint(std::move(qc)); + } } /// Reuse the stored ModelConverter diff --git a/test/end2end/cases/categorized/fast/conic/modellist.json b/test/end2end/cases/categorized/fast/conic/modellist.json index 1d73b5536..d7d32288f 100644 --- a/test/end2end/cases/categorized/fast/conic/modellist.json +++ b/test/end2end/cases/categorized/fast/conic/modellist.json @@ -61,6 +61,14 @@ "x": 3651.48 } }, + { + "name" : "socp_10_qpobj", + "tags" : ["quadratic"], + "objective" : 0.0, + "values": { + "solve_result_num": 0 + } + }, { "name" : "expcones_01__plain", "objective" : 0.7821882953, diff --git a/test/end2end/cases/categorized/fast/conic/socp_10_qpobj.mod b/test/end2end/cases/categorized/fast/conic/socp_10_qpobj.mod new file mode 100644 index 000000000..adf3674c5 --- /dev/null +++ b/test/end2end/cases/categorized/fast/conic/socp_10_qpobj.mod @@ -0,0 +1,6 @@ +# From #229. +# This is actually convex quadratic, not conic. + +var x {1..7} >= 0; +minimize qobj: sum {j in 1..7} x[j]^2; +subj to qconstr: sum {j in 1..7} x[j]^2 <= 1000;