# Best way to convert a generic QCQP into standard form in JuMP

**URL:** <https://discourse.julialang.org/t/best-way-to-convert-a-generic-qcqp-into-standard-form-in-jump/77593>\
**Category:** Optimization (Mathematical)\
**Tags:** jump\
**Created:** [March 8, 2022, 3:39pm UTC](https://discourse.julialang.org/t/best-way-to-convert-a-generic-qcqp-into-standard-form-in-jump/77593 "2022-03-08T15:39:56Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Shuvomoy\_Das\_Gupta](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shuvomoy_das_gupta/32/10069_2.png) [@Shuvomoy\_Das\_Gupta](https://discourse.julialang.org/u/Shuvomoy_Das_Gupta)\
**Post date:** [March 8, 2022, 3:39pm UTC](https://discourse.julialang.org/t/best-way-to-convert-a-generic-qcqp-into-standard-form-in-jump/77593/1 "2022-03-08T15:39:56Z")

</div>

Dear All,

I am solving nonconvex quadratically constrained quadratic optimization problems (QCQPs) in `JuMP`+`Gurobi` for teaching a recitation class on power system course at MIT (I am a teaching assistant for the course). I am using SDP relaxations of these QCQPs to compute a lower bound. This nonconvex QCQP can be formulated and solved via `JuMP+Gurobi` without any problem. However, to compute the SDP relaxation of the QCQP, I need to go through the following steps. While these might be trivial to many in `JuMP` community, for completeness, I describing my steps as follows.

**Step 1. Convert the original QCQP into a standard form:** Convert the original QCQP model (with the problem modeling real life constraints and objective) to the standard form nonconvex QCQP (the matrices are just symmetric and not PSD):

p^\star = \min\_{x}\{x^{\top}A\_{0}x+b\_{0}^{\top}x+c\_{0}\mid x^{\top}A\_{i}x+b\_{i}^{\top}x+c\_{i}\leq0,\quad i=1,\ldots,m.\}\quad (1)

by manually vectorizing the original decision variables of the original QCQP (note that the matrices $A\_i$​ for i=0,\ldots,m are only symmetric and not positive-semidefinite).

**Step 2. Convert (1)​​ into rank-1 nonconvex SDP.** After that, I define X= xx ^T ​​​​, which leads to the equivalent rank-1 nonconvex SDP:

p^{\star}=\min\_{X,x}\{\mathbf{tr}A\_{0}X+b\_{0}^{\top}x+c\_{0}\mid X=xx^{\top},\quad\mathbf{tr}A\_{i}X+b\_{i}^{\top}x+c\_{i}\leq0,\quad i=1,\ldots,m\}\quad(2)

**Step 3. Construct convex SDP by dropping the rank constraint.** Finally dropping the rank-1 constraint and using the Schur’s complement I construct the convex SDP relaxation of (1):

p\_{\textrm{lower}}^{\star}=\min\_{X,x}\{\mathbf{tr}A\_{0}X+b\_{0}^{\top}x+c\_{0}\mid\begin{bmatrix}X & x\\ x^{\top} & 1 \end{bmatrix}\succeq0,\;\mathbf{tr}A\_{i}X+b\_{i}^{\top}x+c\_{i}\leq0,\quad i=1,\ldots,m\}\quad(3)

which gives us a lower bound on the original problem, i.e., p^\star\_\textrm{lower} \leq p^\star.

While the process is straightforward, Step 1, where I need to vectorize the original variables to take into form (1), is very very tedious. The manual vectorization for different problem setups is also prone to human errors. My question is what is the best way to code converting an ugly-looking QCQP into the standard form QCQP such as (1)​​​​? Is there any tips/tricks that I could do to automate this process? Any tips/suggestions from the `JuMP` community will be much appreciated!

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [March 9, 2022, 12:03am UTC](https://discourse.julialang.org/t/best-way-to-convert-a-generic-qcqp-into-standard-form-in-jump/77593/2 "2022-03-09T00:03:14Z")

</div>

I don’t think there’s an easy way to do this in JuMP.

There are two complicated ways:

- Write functions to parse the JuMP model and extract the coefficient matrices. Look here for inspiration: [https://github.com/jump-dev/JuMP.jl/blob/2875bd1a0d336215a63ffb0fe74ffaaad0a6979a/src/lp\_sensitivity2.jl#L302-L350](https://github.com/jump-dev/JuMP.jl/blob/2875bd1a0d336215a63ffb0fe74ffaaad0a6979a/src/lp_sensitivity2.jl#L302-L350)
- Create a MOI model that supports quadratic objective and quadratic-in-less than, then write a function to extract the matrices from the MOI model. Look here for something similar with LPs: [cplex - Standard Form for LP and MPS - Operations Research Stack Exchange](https://or.stackexchange.com/questions/6982/standard-form-for-lp-and-mps/7003#7003)

---

<div class="post-metadata">

**Author:** ![Shuvomoy\_Das\_Gupta](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shuvomoy_das_gupta/32/10069_2.png) [@Shuvomoy\_Das\_Gupta](https://discourse.julialang.org/u/Shuvomoy_Das_Gupta)\
**Post date:** [March 9, 2022, 8:33am UTC](https://discourse.julialang.org/t/best-way-to-convert-a-generic-qcqp-into-standard-form-in-jump/77593/3 "2022-03-09T08:33:11Z")

</div>

I see, okay thanks @odow ! Both are very interesting approaches, so I will definitely go through them in detail!

---

<div class="post-metadata">

**Author:** ![miles.lubin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/miles.lubin/32/279_2.png) [@miles.lubin](https://discourse.julialang.org/u/miles.lubin)\
**Post date:** [March 9, 2022, 10:16pm UTC](https://discourse.julialang.org/t/best-way-to-convert-a-generic-qcqp-into-standard-form-in-jump/77593/4 "2022-03-09T22:16:41Z")

</div>

There’s no super easy way, but if it’s just for the purposes of demonstration, then the route of extracting the coefficients from the JuMP model (Oscar’s first suggestion) is likely more direct than working at the MOI level.

---

<div class="post-metadata">

**Author:** ![Shuvomoy\_Das\_Gupta](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shuvomoy_das_gupta/32/10069_2.png) [@Shuvomoy\_Das\_Gupta](https://discourse.julialang.org/u/Shuvomoy_Das_Gupta)\
**Post date:** [March 9, 2022, 11:46pm UTC](https://discourse.julialang.org/t/best-way-to-convert-a-generic-qcqp-into-standard-form-in-jump/77593/5 "2022-03-09T23:46:55Z")

</div>

Okay, thanks @miles.lubin !

I taught the SDP relaxation thing yesterday in my recitation session. Basically, I picked a simple QCQP that can be converted to SDP by hand, and then solved the QCQP using Gurobi and the SDP using Mosek. For the purpose of the course probably it suffices.

That being said, for a research project I am using somewhat of a similar process (converting a QCQP into rank-1 SDP), so your suggestion will be useful in automating the process!
