```/* nag_opt_handle_set_quadmatineq (e04rpc) Example Program.
*
* Copyright 2017 Numerical Algorithms Group.
*
* Mark 26.2, 2017.
*/

/* Read a 'generic' LMI/BMI SDP problem from the input file,
* formulate the problem via a handle and pass it to the solver.
*/
#include <stdio.h>
#include <nag.h>
#include <nag_stdlib.h>
#include <nage04.h>

int main(void)
{
Integer exit_status = 0;
Integer blkidx, dimaq, idblk, idlc, idx, idxend, inform, j, midx, nblk,
nclin, nnzasum, nnzb, nnzc, nnzh, nnzqsum, nq, nvar;
double *a = 0, *b = 0, *bl = 0, *bu = 0, *cvec = 0, *h = 0, *q = 0, *x = 0;
double rinfo[32], stats[32];
Integer *icola = 0, *icolb = 0, *icolh = 0, *icolq = 0, *idxc = 0,
*irowa = 0, *irowb = 0, *irowh = 0, *irowq = 0, *nnza = 0,
*nnzq = 0, *qi = 0, *qj = 0;
void *handle = 0;
/* Nag Types */
NagError fail;

fflush(stdout);

/* Skip heading in the data file. */
scanf("%*[^\n]");

/* Read the problem size. */
scanf("%" NAG_IFMT "%*[^\n]", &nvar);
scanf("%" NAG_IFMT "%*[^\n]", &nnzh);
scanf("%" NAG_IFMT " %" NAG_IFMT "%*[^\n]", &nclin, &nnzb);
scanf("%" NAG_IFMT "%*[^\n]", &nblk);

/* nag_opt_handle_init (e04rac).
* Initialize an empty problem handle with nvar variables. */
nag_opt_handle_init(&handle, nvar, NAGERR_DEFAULT);

/* Read the linear part of the objective function. */
if (!(cvec = NAG_ALLOC(nvar, double)))
{
printf("Allocation failure\n");
exit_status = -1;
goto END;
}
for (j = 0; j < nvar; j++)
scanf("%lf", &cvec[j]);
scanf("%*[^\n]");

if (nnzh == 0) {
/* nag_opt_handle_set_linobj (e04rec).
* Add the linear objective function to the formulation. */
nag_opt_handle_set_linobj(handle, nvar, cvec, NAGERR_DEFAULT);
NAG_FREE(cvec);
}
else {
if (!(irowh = NAG_ALLOC(nnzh, Integer)) ||
!(icolh = NAG_ALLOC(nnzh, Integer)) ||
!(h = NAG_ALLOC(nnzh, double)) || !(idxc = NAG_ALLOC(nvar, Integer)))
{
printf("Allocation failure\n");
exit_status = -1;
goto END;
}

for (idx = 0; idx < nnzh; idx++)
scanf("%lf %" NAG_IFMT " %" NAG_IFMT "%*[^\n]",
&h[idx], &irowh[idx], &icolh[idx]);

/* The linear part of the objective was read in as dense,
* but the sparse format is needed here. */
for (idx = 0; idx < nvar; idx++)
idxc[idx] = idx + 1;
nnzc = nvar;

nag_opt_handle_set_quadobj(handle, nnzc, idxc, cvec, nnzh, icolh, irowh,
h, NAGERR_DEFAULT);
NAG_FREE(idxc);
NAG_FREE(cvec);
NAG_FREE(irowh);
NAG_FREE(icolh);
NAG_FREE(h);
}

/* Read a block of linear constraints and its bounds if present. */
if (nclin > 0 && nnzb > 0) {
if (!(irowb = NAG_ALLOC(nnzb, Integer)) ||
!(icolb = NAG_ALLOC(nnzb, Integer)) ||
!(b = NAG_ALLOC(nnzb, double)) ||
!(bl = NAG_ALLOC(nclin, double)) || !(bu = NAG_ALLOC(nclin, double)))
{
printf("Allocation failure\n");
exit_status = -1;
goto END;
}

/* Read all matrix B nonzeros. */
for (idx = 0; idx < nnzb; idx++)
scanf("%lf %" NAG_IFMT " %" NAG_IFMT "%*[^\n]",
&b[idx], &irowb[idx], &icolb[idx]);

/* Read the lower and upper bounds. */
for (j = 0; j < nclin; j++)
scanf("%lf", &bl[j]);
scanf("%*[^\n]");
for (j = 0; j < nclin; j++)
scanf("%lf", &bu[j]);
scanf("%*[^\n]");
idlc = 0;

/* nag_opt_handle_set_linconstr (e04rjc).
* Add the block of linear constraints to the problem formulation. */
nag_opt_handle_set_linconstr(handle, nclin, bl, bu, nnzb, irowb, icolb,
b, &idlc, NAGERR_DEFAULT);
NAG_FREE(irowb);
NAG_FREE(icolb);
NAG_FREE(b);
NAG_FREE(bl);
NAG_FREE(bu);
}

/* Read all matrix inequalities. */
for (blkidx = 0; blkidx < nblk; blkidx++) {
/* Read the dimension of this matrix inequality. */
scanf("%" NAG_IFMT "%*[^\n]", &dimaq);
/* Read the number of all nonzeros in linear and bilinear parts. */
scanf("%" NAG_IFMT " %" NAG_IFMT "%*[^\n]", &nnzasum, &nnzqsum);
idblk = 0;

if (nnzasum > 0) {
/* Read a linear matrix inequality composed of (nvar+1) matrices. */
if (!(nnza = NAG_ALLOC(nvar + 1, Integer)) ||
!(irowa = NAG_ALLOC(nnzasum, Integer)) ||
!(icola = NAG_ALLOC(nnzasum, Integer)) ||
!(a = NAG_ALLOC(nnzasum, double)))
{
printf("Allocation failure\n");
exit_status = -1;
goto END;
}

idx = 0;
for (midx = 0; midx <= nvar; midx++) {
scanf("%" NAG_IFMT "%*[^\n]", &nnza[midx]);
idxend = idx + nnza[midx];
for ( ; idx < idxend; idx++)
scanf("%lf %" NAG_IFMT " %" NAG_IFMT "%*[^\n]",
&a[idx], &irowa[idx], &icola[idx]);
}
idblk = 0;

/* nag_opt_handle_set_linmatineq (e04rnc).
* Add the linear matrix constraint to the problem formulation. */
nag_opt_handle_set_linmatineq(handle, nvar, dimaq, nnza, nnzasum,
irowa, icola, a, 1, NULL, &idblk,
NAGERR_DEFAULT);

NAG_FREE(nnza);
NAG_FREE(irowa);
NAG_FREE(icola);
NAG_FREE(a);
}

if (nnzqsum > 0) {
/* Read bilinear part of the matrix inequality composed
* of nq matrices. */
scanf("%" NAG_IFMT "%*[^\n]", &nq);
if (!(qi = NAG_ALLOC(nq, Integer)) ||
!(qj = NAG_ALLOC(nq, Integer)) ||
!(nnzq = NAG_ALLOC(nq, Integer)) ||
!(irowq = NAG_ALLOC(nnzqsum, Integer)) ||
!(icolq = NAG_ALLOC(nnzqsum, Integer)) ||
!(q = NAG_ALLOC(nnzqsum, double)))
{
printf("Allocation failure\n");
exit_status = -1;
goto END;
}

idx = 0;
for (midx = 0; midx < nq; midx++) {
/* Read matrix Q_ij where i=qi[midx], j=qj[midx]. */
scanf("%" NAG_IFMT " %" NAG_IFMT "%*[^\n]", &qi[midx], &qj[midx]);
scanf("%" NAG_IFMT "%*[^\n]", &nnzq[midx]);
idxend = idx + nnzq[midx];
for ( ; idx < idxend; idx++)
scanf("%lf %" NAG_IFMT " %" NAG_IFMT "%*[^\n]",
&q[idx], &irowq[idx], &icolq[idx]);
}

* Expand the existing linear matrix inequality with the bilinear
* terms or (if the linear part was not present) create a
* new matrix inequality. */
nag_opt_handle_set_quadmatineq(handle, nq, qi, qj, dimaq, nnzq,
nnzqsum, irowq, icolq, q, &idblk,
NAGERR_DEFAULT);

NAG_FREE(qi);
NAG_FREE(qj);
NAG_FREE(nnzq);
NAG_FREE(irowq);
NAG_FREE(icolq);
NAG_FREE(q);
}
}

/* Problem was successfully decoded. */
printf("SDP problem was read, passing it to the solver.\n\n");
fflush(stdout);

/* nag_opt_handle_print (e04ryc).
* Print overview of the handle. */
nag_opt_handle_print(handle, 6, "Overview, Matrix Constraints",
NAGERR_DEFAULT);

/* Allocate memory for the solver. */
if (!(x = NAG_ALLOC(nvar, double)))
{
printf("Allocation failure\n");
exit_status = -1;
goto END;
}
for (j = 0; j < nvar; j++)
x[j] = 0.0;

/* Call the solver nag_opt_handle_solve_pennon (e04svc),
* ignore Lagrangian multipliers. */
INIT_FAIL(fail);
nag_opt_handle_solve_pennon(handle, nvar, x, 0, NULL, 0, NULL, 0, NULL,
rinfo, stats, &inform, &fail);
if (fail.code != NE_NOERROR) {
printf("Error from nag_opt_handle_solve_pennon (e04svc).\n%s\n",
fail.message);
exit_status = 1;
goto END;
}

END:

/* nag_opt_handle_free (e04rzc).
* Destroy the problem handle and deallocate all the memory. */
if (handle)
nag_opt_handle_free(&handle, NAGERR_DEFAULT);

NAG_FREE(x);

return exit_status;
}
```