11 #include "CbcModel.hpp"
13 #include "IpLapack.hpp"
22 #define COUENNE_EIG_RATIO .1 // how much smaller than the largest eigenvalue should the minimum be set at?
24 using namespace Couenne;
32 int PSDize (
int n,
double *A,
double *B,
bool doSqrRoot);
37 OsiSolverInterface *
lp = model -> solver () -> clone ();
46 for (
int i = fp -> Problem () -> nVars (),
j = 0; i--; ++
j) {
55 if (fp -> Problem () -> Var (
j) -> Multiplicity () <= 0)
62 (!isMILP && !intVar)) {
65 lp -> addCol (vec, 0., COIN_DBL_MAX, 1.);
68 match [
j] = lp -> getNumCols () - 1;
77 int objInd = fp -> Problem () -> Obj (0) -> Body () -> Index ();
80 lp -> setObjCoeff (objInd, 0.);
92 int n = fp -> Problem () -> nVars ();
94 CoinPackedVector *
P =
new CoinPackedVector [
n];
117 CoinPackedVector
x0 (n, sol);
121 if (isMILP && (fp -> multObjFMILP () > 0.)) {
123 int objInd = fp -> Problem () -> Obj (0) -> Body () -> Index ();
126 lp -> setObjCoeff (objInd, fp -> multObjFMILP ());
130 (fp -> multHessMILP () > 0.) &&
131 (fp -> nlp () -> optHessian ())) {
146 for (
int i=0; i<
n; i++)
147 if (fp -> Problem () -> Var (i) -> Multiplicity () > 0)
148 P[i].insert (i, 1. / sqrt ((
double) n));
153 for (
int i = 0,
j = n,
k = n;
k--; ++i) {
155 if (match && match [i] < 0)
158 if (fp -> Problem () -> Var (i) -> Multiplicity () <= 0)
170 (!isMILP && !intVar)) {
173 CoinPackedVector &vec = P [i];
175 if (vec.getNumElements () == 0)
179 double PiX0 = sparseDotProduct (vec, x0);
181 assert (!match || match [i] >= 0);
187 vec.insert (
j, -1.); lp -> addRow (vec, -COIN_DBL_MAX, PiX0);
188 vec.setElement (vec.getNumElements () - 1, +1.); lp -> addRow (vec, PiX0, COIN_DBL_MAX);
196 #define INT_LP_BRACKET 0
207 #define GRADIENT_WEIGHT 1
211 CoinPackedVector *
P) {
214 objInd = fp -> Problem () -> Obj (0) -> Body () -> Index (),
215 n = fp -> Problem () -> nVars ();
219 double *val = hessian -> val ();
220 int *row = hessian -> row ();
221 int *col = hessian -> col ();
222 int num = hessian -> num ();
232 for (
int i=num; i--; ++row, ++col, ++val) {
236 if ((*row == objInd) ||
241 else if (fabs (*val) > maxElem)
242 maxElem = fabs (*val);
251 double *A = (
double *) malloc (
n*
n *
sizeof (
double));
252 double *B = (
double *) malloc (
n*
n *
sizeof (
double));
256 double sqrt_trace = 0;
259 for (
int i=0; i<num; ++i, ++row, ++col, ++val)
261 A [*col * n + *row] = fp -> multHessMILP () * *val;
263 sqrt_trace += *val * *val;
270 sqrt_trace = sqrt (sqrt_trace);
274 for (
int i=0; i<num; ++i, ++row, ++col)
275 A [*col * n + *row] /= sqrt_trace;
281 for (
int i=0; i<
n; ++i)
282 if (fp -> Problem () -> Var (i) -> Multiplicity () > 0)
283 A [i * (n+1)] += fp -> multDistMILP () / sqrt (static_cast<double>(n));
294 double *eigenvec = A;
296 for (
int i=0; i<
n; ++i)
297 for (
int j=0;
j<
n; ++
j) {
303 for (
int k=0;
k<
n; ++
k)
304 elem += B [i +
k * n] * eigenvec [
j * n +
k];
307 P [i]. insert (
j, elem);
326 int PSDize (
int n,
double *A,
double *B,
bool doSqrRoot) {
329 double *eigenval = (
double *) malloc (n *
sizeof (
double));
333 Ipopt::IpLapackDsyev (
true, n, A, n, eigenval, status);
335 if (status < 0) printf (
"Couenne: warning, argument %d illegal\n", -status);
336 else if (status > 0) printf (
"Couenne: warning, dsyev did not converge (error code: %d)\n", status);
345 double *eigenvec = A;
355 MinEigVal = eigenval [0],
356 MaxEigVal = eigenval [n-1];
358 for (
int j=1;
j<
n;
j++)
359 assert (eigenval [
j-1] <= eigenval [
j]);
368 for (
int j=0; j<
n; j++)
369 eigenval [j] = 1. / (.1 - eigenval [j]);
378 if (eigenval [0] <= MinEigVal)
379 for (
int j=0; eigenval [
j] <= MinEigVal; j++)
380 eigenval [j] = MinEigVal;
387 for (
int j=0; j<
n; ++
j) {
389 register double multEig = doSqrRoot ? sqrt (eigenval [j]) :
392 for (
int i=0; i<
n; ++i)
393 if (fabs (*B++ = multEig * eigenvec [i*n+j]) >
COUENNE_EPS)
#define COUENNE_EIG_RATIO
static int match(const char **sp, const char *t)
void addDistanceConstraints(const CouenneFeasPump *fp, OsiSolverInterface *lp, double *sol, bool isMILP, int *match)
modify MILP or LP to implement distance by adding extra rows (extra cols were already added by create...
Class for sparse Matrixs (used in modifying distances in FP)
An implementation of the Feasibility pump that uses linearization and Ipopt to find the two sequences...
void fint fint fint real fint real real real real real real real real real fint real fint * lp
void ComputeSquareRoot(const CouenneFeasPump *fp, CouenneSparseMatrix *hessian, CoinPackedVector *P)
computes square root of a CouenneSparseMatrix
OsiSolverInterface * createCloneMILP(const CouenneFeasPump *fp, CbcModel *model, bool isMILP, int *match)
create clone of MILP and add variables for special objective
int nnz
ATTENTION: Filter expect the jacobian to be ordered by row.
int PSDize(int n, double *A, double *B, bool doSqrRoot)
project matrix onto the cone of positive semidefinite matrices (possibly take square root of eigenval...
bool isInteger(CouNumber x)
is this number integer?