Scippy

SCIP

Solving Constraint Integer Programs

lpi_msk.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2020 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file lpi_msk.c
17  * @ingroup LPIS
18  * @brief LP interface for MOSEK
19  * @author Bo Jensen
20  * @author Tristan Gally
21  * @author Marc Pfetsch
22  *
23  * @todo Check whether MSK_IPAR_{SIM_DUAL|PRIMAL}_RESTRICT_SELECTION should be used if problem is solved from scratch or
24  * if no basis is available.
25  * @todo Revise handling of the MSK_RES_TRM_MAX_NUM_SETBACKS return value: Remove it form the check of MOSEK_CALL and
26  * include it in filterTRMrescode().
27  * @todo Check whether SCIPlpiGetSolFeasibility() should also return primal/dual feasible if the status is
28  * MSK_SOL_STA_NEAR_PRIM_FEAS, MSK_SOL_STA_NEAR_DUAL_FEAS.
29  * @todo Check why it can happen that the termination code is MSK_RES_OK, but the solution status is MSK_SOL_STA_UNKNOWN.
30  */
31 
32 #include <assert.h>
33 
34 #define MSKCONST const
35 #include "mosek.h"
36 
37 #include "lpi/lpi.h"
38 #include "scip/bitencode.h"
39 #include "scip/pub_message.h"
40 #include <string.h>
41 
42 /* do defines for windows directly here to make the lpi more independent */
43 #if defined(_WIN32) || defined(_WIN64)
44 #define snprintf _snprintf
45 #endif
46 
47 #if ( MSK_VERSION_MAJOR < 7 )
48 #error "The MOSEK interface only works for MOSEK versions 7.0.0.0 and newer"
49 #endif
50 
51 #define scipmskobjsen MSKobjsensee
52 #define SENSE2MOSEK(objsen) (((objsen)==SCIP_OBJSEN_MINIMIZE)?(MSK_OBJECTIVE_SENSE_MINIMIZE):(MSK_OBJECTIVE_SENSE_MAXIMIZE))
53 
54 typedef enum MSKoptimizertype_enum MSKoptimizertype;
55 
56 #define MOSEK_CALL(x) do \
57  { /*lint --e{641}*/ \
58  MSKrescodee _restat_; \
59  _restat_ = (x); \
60  if( (_restat_) != MSK_RES_OK && (_restat_ ) != MSK_RES_TRM_MAX_NUM_SETBACKS ) \
61  { \
62  SCIPerrorMessage("LP Error: MOSEK returned %d.\n", (int)_restat_); \
63  return SCIP_LPERROR; \
64  } \
65  } \
66  while( FALSE )
67 
68 /* this macro is only called in functions returning SCIP_Bool; thus, we return FALSE if there is an error in optimized mode */
69 #define SCIP_ABORT_FALSE(x) do \
70  { \
71  SCIP_RETCODE _restat_; \
72  if( (_restat_ = (x)) != SCIP_OKAY ) \
73  { \
74  SCIPerrorMessage("LP Error: MOSEK returned %d.\n", (int)_restat_); \
75  SCIPABORT(); \
76  return FALSE; \
77  } \
78  } \
79  while( FALSE )
80 
81 #define IS_POSINF(x) ((x) >= MSK_INFINITY)
82 #define IS_NEGINF(x) ((x) <= -MSK_INFINITY)
83 
84 /* global variables */
85 static MSKenv_t MosekEnv = NULL;
86 static int numlp = 0;
87 
88 static int optimizecount = 0;
89 static int nextlpid = 1;
90 
91 #if MSK_VERSION_MAJOR >= 9
92 #define NEAR_REL_TOLERANCE 1.0 /* MOSEK will multiply all tolerances with this factor after stalling */
93 #endif
94 #define DEBUG_PRINT_STAT 0
95 #define DEBUG_PARAM_SETTING 0
96 #define DEBUG_CHECK_DATA 0
97 #define DEBUG_EASY_REPRODUCE 0
98 #define DEBUG_DO_INTPNT_FEAS_CHECK 0
99 #define DEBUG_CHECK_STATE_TOL 1e-5
100 #define SHOW_ERRORS 0
101 #define SHOW_RELATIVE_OPTIMAL_GAP 0
102 #define ASSERT_ON_NUMERICAL_TROUBLES 0
103 #define ASSERT_ON_WARNING 0
104 #define FORCE_MOSEK_LOG 0 /* note that changing this AND setting lpinfo will lead to asserts in lpCheckIntpar */
105 #define FORCE_MOSEK_SUMMARY 0
106 #define FORCE_NO_MAXITER 0
107 #define SETBACK_LIMIT 250
108 #define STRONGBRANCH_PRICING MSK_SIM_SELECTION_SE
109 #define SUPRESS_NAME_ERROR 1
110 #define WRITE_DUAL 0
111 #define WRITE_PRIMAL 0
112 #define WRITE_INTPNT 0
113 #if WRITE_DUAL > 0 || WRITE_PRIMAL > 0 || WRITE_INTPNT > 0 || FORCE_MOSEK_LOG > 0 || FORCE_MOSEK_SUMMARY > 0
114 #define WRITE_ABOVE 0
115 #endif
116 #define DEGEN_LEVEL MSK_SIM_DEGEN_FREE
117 #define ALWAYS_SOLVE_PRIMAL_FORM 1
118 #if DEBUG_PRINT_STAT > 0
119 static int numstrongbranchmaxiterup = 0;
120 static int numstrongbranchmaxiterdo = 0;
121 static int numprimalmaxiter = 0;
122 static int numdualmaxiter = 0;
123 static int numstrongbranchobjup = 0;
124 static int numstrongbranchobjdo = 0;
125 static int numprimalobj = 0;
126 static int numdualobj = 0;
127 #endif
128 
129 #if DEBUG_PRINT_STAT > 0
130 static int numstrongbranchmaxiterup = 0;
131 static int numstrongbranchmaxiterdo = 0;
132 static int numprimalmaxiter = 0;
133 static int numdualmaxiter = 0;
134 static int numstrongbranchobjup = 0;
135 static int numstrongbranchobjdo = 0;
136 static int numprimalobj = 0;
137 static int numdualobj = 0;
138 #endif
139 
140 
141 /** internal data for Mosek LPI */
142 struct SCIP_LPi
143 {
144  MSKtask_t task; /**< Mosek task */
145  MSKrescodee termcode; /**< termination code of last optimization run */
146  int itercount; /**< iteration count of last optimization run */
147  SCIP_PRICING pricing; /**< SCIP pricing setting */
148  int lpid; /**< id for LP within same task */
149  MSKoptimizertype lastalgo; /**< algorithm type of last solving call */
150  MSKstakeye* skx; /**< basis status for columns */
151  MSKstakeye* skc; /**< basis status for rows */
152  MSKboundkeye* bkx; /**< bound keys for columns */
153  MSKboundkeye* bkc; /**< bound keys for rows */
154  MSKint32t* aptre; /**< row or column end pointers */
155  int skxsize; /**< size of skx array */
156  int skcsize; /**< size of skc array */
157  int bkxsize; /**< size of bkx */
158  int bkcsize; /**< size of bkx */
159  int aptresize; /**< size of aptre */
160  MSKsoltypee lastsolvetype; /**< Which solver was called last and which solution should be returned? */
161  SCIP_Bool solved; /**< was the current LP solved? */
162  SCIP_Bool fromscratch; /**< Shall solves be performed with MSK_IPAR_SIM_HOTSTART turned off? */
163  SCIP_Bool clearstate; /**< Shall next solve be performed with MSK_IPAR_SIM_HOTSTART turned off? */
164  SCIP_Bool lpinfo; /**< Should LP solver output information to the screen? */
165  int restrictselectdef; /**< default value for MSK_IPAR_SIM_DUAL_RESTRICT_SELECTION */
166  SCIP_MESSAGEHDLR* messagehdlr; /**< messagehdlr handler to printing messages, or NULL */
167 };
168 
169 typedef SCIP_DUALPACKET COLPACKET; /* each column needs two bits of information (basic/on_lower/on_upper) */
170 #define COLS_PER_PACKET SCIP_DUALPACKETSIZE
171 typedef SCIP_DUALPACKET ROWPACKET; /* each row needs two bit of information (basic/on_lower/on_upper) */
172 #define ROWS_PER_PACKET SCIP_DUALPACKETSIZE
173 
174 /** basis status */
175 struct SCIP_LPiState
176 {
177  int num;
178  MSKsolstae solsta; /**< solution status */
179  int ncols; /**< number of columns */
180  int nrows; /**< number of rows */
181  COLPACKET* skx; /**< basis status for columns */
182  ROWPACKET* skc; /**< basis status for rows */
183 };
184 
185 
186 /*
187  * Local functions
188  */
189 
190 /** gives problem and solution status for a Mosek Task
191  *
192  * With Mosek 7.0, the routine MSK_getsolutionstatus was replaced by MSK_getprosta and MSK_getsolsta.
193  */
194 static
196  MSKtask_t task, /**< Mosek Task */
197  MSKsoltypee whichsol, /**< for which type of solution a status is requested */
198  MSKprostae* prosta, /**< buffer to store problem status, or NULL if not needed */
199  MSKsolstae* solsta /**< buffer to store solution status, or NULL if not needed */
200  )
201 {
202  MSKrescodee res;
203 
204  if( prosta != NULL )
205  {
206  res = MSK_getprosta(task, whichsol, prosta);
207  if ( res != MSK_RES_OK )
208  return res;
209  }
210  if( solsta != NULL )
211  {
212  res = MSK_getsolsta(task, whichsol, solsta);
213  if ( res != MSK_RES_OK )
214  return res;
215  }
216 
217  return MSK_RES_OK;
218 }
219 
220 /** returns the number of packets needed to store column packet information */
221 static
223  int ncols /**< number of columns to store */
224  )
225 {
226  return (ncols+(int)COLS_PER_PACKET-1)/(int)COLS_PER_PACKET;
227 }
228 
229 /** returns the number of packets needed to store row packet information */
230 static
232  int nrows /**< number of rows to store */
233  )
234 {
235  return (nrows+(int)ROWS_PER_PACKET-1)/(int)ROWS_PER_PACKET;
236 }
237 
238 /** print string using message handler of SCIP */
239 static
240 void MSKAPI printstr(
241  MSKuserhandle_t handle, /**< error handle */
242  const char* str /**< string that contains string on output */
243  )
244 { /*lint --e{715}*/
245 #if SUPRESS_NAME_ERROR
246  char errstr[32];
247  snprintf(errstr, 32, "MOSEK Error %d", MSK_RES_ERR_DUP_NAME);
248  if (0 == strncmp(errstr, str, strlen(errstr)))
249  return;
250 #endif
251 
252  SCIPmessagePrintInfo((SCIP_MESSAGEHDLR *) handle, "MOSEK: %s", str);
253 }
254 
255 #if DEBUG_CHECK_DATA > 0
256 /** check data */
257 static
258 SCIP_RETCODE scip_checkdata(
259  SCIP_LPI* lpi, /**< pointer to an LP interface structure */
260  const char* functionname /**< function name */
261  )
262 {
263  int i;
264  int numcon;
265  int numvar;
266  int gotbasicsol;
267  MSKboundkeye* tbkc;
268  MSKboundkeye* tbkx;
269  MSKstakeye *tskc;
270  MSKstakeye* tskx;
271  double* tblc;
272  double* tbuc;
273  double* tblx;
274  double* tbux;
275 
276  assert(MosekEnv != NULL);
277  assert(lpi != NULL);
278  assert(lpi->task != NULL);
279 
280  MOSEK_CALL( MSK_solutiondef(lpi->task, MSK_SOL_BAS, &gotbasicsol) );
281 
282  MOSEK_CALL( MSK_getnumvar(lpi->task, &numvar) );
283  MOSEK_CALL( MSK_getnumcon(lpi->task, &numcon) );
284 
285  /* allocate memory */
286  SCIP_ALLOC( BMSallocMemoryArray(&tbkc, numcon) );
287  SCIP_ALLOC( BMSallocMemoryArray(&tskc, numcon) );
288  SCIP_ALLOC( BMSallocMemoryArray(&tblc, numcon) );
289  SCIP_ALLOC( BMSallocMemoryArray(&tbuc, numcon) );
290 
291  SCIP_ALLOC( BMSallocMemoryArray(&tbkx, numvar) );
292  SCIP_ALLOC( BMSallocMemoryArray(&tskx, numvar) );
293  SCIP_ALLOC( BMSallocMemoryArray(&tblx, numvar) );
294  SCIP_ALLOC( BMSallocMemoryArray(&tbux, numvar) );
295 
296  /* Check bounds */
297  if( gotbasicsol )
298  {
299  MOSEK_CALL( MSK_getsolution(lpi->task, MSK_SOL_BAS, NULL, NULL, tskc, tskx,
300  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
301  }
302 
303  for( i = 0; i < numvar; i++ )
304  {
305  MOSEK_CALL( MSK_getbound(lpi->task, MSK_ACC_VAR, i, &tbkx[i], &tblx[i], &tbux[i]) );
306  }
307 
308  for( i = 0; i < numcon; i++ )
309  {
310  MOSEK_CALL( MSK_getbound(lpi->task, MSK_ACC_CON, i, &tbkc[i], &tblc[i], &tbuc[i]) );
311  }
312 
313  for( i = 0; i < numcon; ++i )
314  {
315  if( gotbasicsol )
316  {
317  if( ( tskc[i] == MSK_SK_FIX && tbkc[i] != MSK_BK_FX ) ||
318  ( tskc[i] == MSK_SK_LOW && !(tbkc[i] == MSK_BK_FX || tbkc[i] == MSK_BK_LO || tbkc[i] == MSK_BK_RA ) ) ||
319  ( tskc[i] == MSK_SK_UPR && !(tbkc[i] == MSK_BK_FX || tbkc[i] == MSK_BK_UP || tbkc[i] == MSK_BK_RA ) ) )
320  {
321  SCIPerrorMessage("STATUS KEY ERROR i %d bkc %d skc %d %s\n", i, tbkc[i], tskc[i], functionname);
322  }
323  }
324 
325  if( tbkc[i] == MSK_BK_LO || tbkc[i] == MSK_BK_FX || tbkc[i] == MSK_BK_RA )
326  {
327  if( isnan(tblc[i]) )
328  {
329  SCIPdebugMessage("nan in blc : %s\n", functionname);
330  }
331  }
332 
333  if( tbkc[i] == MSK_BK_UP || tbkc[i] == MSK_BK_FX || tbkc[i] == MSK_BK_RA )
334  {
335  if( isnan(tbuc[i]) )
336  {
337  SCIPdebugMessage("nan in bux : %s\n", functionname);
338  }
339  }
340  }
341 
342  for( i = 0; i < numvar; ++i )
343  {
344  if( tbkx[i] == MSK_BK_LO || tbkx[i] == MSK_BK_FX || tbkx[i] == MSK_BK_RA )
345  {
346  if( isnan(tblx[i]) )
347  {
348  SCIPdebugMessage("nan in blx : %s\n", functionname);
349  }
350  }
351 
352  if( tbkx[i] == MSK_BK_UP || tbkx[i] == MSK_BK_FX || tbkx[i] == MSK_BK_RA )
353  {
354  if( isnan(tbux[i]) )
355  {
356  SCIPdebugMessage("nan in bux : %s\n", functionname);
357  getchar();
358  }
359  }
360  }
361 
362  BMSfreeMemoryArray(&tbkc);
363  BMSfreeMemoryArray(&tskc);
364  BMSfreeMemoryArray(&tblc);
365  BMSfreeMemoryArray(&tbuc);
366  BMSfreeMemoryArray(&tbkx);
367  BMSfreeMemoryArray(&tskx);
368  BMSfreeMemoryArray(&tblx);
369  BMSfreeMemoryArray(&tbux);
370 
371  return SCIP_OKAY;
372 }
373 #endif
374 
375 /** resizes bound keys array bkx to have at least ncols entries */
376 static
378  SCIP_LPI* lpi, /**< pointer to an LP interface structure */
379  int ncols /**< number of columns */
380  )
381 {
382  if ( lpi->bkxsize < ncols )
383  {
384  int newsize;
385  newsize = MAX(2*lpi->bkxsize, ncols);
386 
387  SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->bkx), newsize) );
388  lpi->bkxsize = newsize;
389  }
390 
391  return SCIP_OKAY;
392 }
393 
394 /** resizes bound keys array bkc to have at least nrows entries */
395 static
397  SCIP_LPI* lpi, /**< pointer to an LP interface structure */
398  int nrows /**< number of rows */
399  )
400 {
401  if ( lpi->bkcsize < nrows )
402  {
403  int newsize;
404  newsize = MAX(2*lpi->bkcsize, nrows);
405 
406  SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->bkc), newsize) );
407  lpi->bkcsize = newsize;
408  }
409 
410  return SCIP_OKAY;
411 }
412 
413 /** resizes aptre array to have at least n entries */
414 static
416  SCIP_LPI* lpi, /**< pointer to an LP interface structure */
417  int n /**< number of entries */
418  )
419 {
420  if ( lpi->aptresize < n )
421  {
422  int newsize;
423  newsize = MAX(2*lpi->aptresize, n);
424 
425  SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->aptre), newsize) );
426  lpi->aptresize = newsize;
427  }
428 
429  return SCIP_OKAY;
430 }
431 
432 /** marks the current LP to be unsolved */
433 static
435  SCIP_LPI* lpi /**< pointer to an LP interface structure */
436  )
437 {
438  assert(lpi != NULL);
439 
440  lpi->solved = FALSE;
441 }
442 
443 /** compute boundkeys to inform MOSEK about fixed/free/ranged/lower bounded/upper bounded variables or constraints */
444 static
446  int n, /**< array size */
447  const double* lb, /**< lower bounds of variables or left-hand sides of ranged rows */
448  const double* ub, /**< upper bounds of variables or right-hand sides of ranged rows */
449  MSKboundkeye* bk /**< pointer to store boundkeys to inform MOSEK about status of var/row */
450  )
451 {
452  int i;
453 
454  assert(lb != NULL);
455  assert(ub != NULL);
456  assert(bk != NULL);
457 
458  for( i = 0; i < n; i++ )
459  {
460  if (IS_NEGINF(lb[i]))
461  {
462  if (IS_POSINF(ub[i]))
463  {
464  bk[i] = MSK_BK_FR;
465  }
466  else
467  {
468  assert(!IS_NEGINF(ub[i]));
469  bk[i] = MSK_BK_UP;
470  }
471  }
472  else
473  {
474  assert(!IS_POSINF(lb[i]));
475  if (IS_POSINF(ub[i]))
476  {
477  bk[i] = MSK_BK_LO;
478  }
479  else if (lb[i] == ub[i])/*lint !e777*/ /* No epsilon-test since MOSEK will also test for exact equality */
480  {
481  assert(lb[i] - ub[i] == 0);
482  assert(ub[i] - lb[i] == 0);
483  bk[i] = MSK_BK_FX;
484  }
485  else
486  {
487  assert(lb[i] < ub[i]);
488  bk[i] = MSK_BK_RA;
489  }
490  }
491  }
492 }
493 
494 /** get end pointers of arrays */
495 static
497  int n, /**< array size */
498  const int* beg, /**< array of beginning indices */
499  int nnonz, /**< number of nonzeros */
500  MSKint32t* aptre /**< array to store the result */
501  )
502 {
503  int i;
504 
505  assert(beg != NULL || nnonz == 0);
506 
507  if (nnonz > 0)
508  {
509  assert(beg != NULL);
510  for(i = 0; i < n-1; i++)
511  {
512  aptre[i] = beg[i+1];
513  assert(aptre[i] >= beg[i]);
514  }
515 
516  aptre[n-1] = nnonz;
517  assert(aptre[n-1] >= beg[n-1]);
518  }
519  else
520  {
521  for( i = 0; i < n; i++ )
522  aptre[i] = 0;
523  }
524 
525  return SCIP_OKAY;
526 }
527 
528 /** compute indices from range */
529 static
531  int first, /**< first index */
532  int last, /**< last index */
533  int** sub /**< pointer to store the indices ranges */
534  )
535 {
536  int i;
537 
538  assert(first <= last);
539 
540  SCIP_ALLOC( BMSallocMemoryArray(sub, (last - first + 1)) );
541 
542  for( i = first; i <= last; i++ )
543  {
544  (*sub)[i-first] = i;
545  }
546 
547  return SCIP_OKAY;
548 }
549 
550 /** compute indices from dense array */
551 static
553  int* dstat, /**< array */
554  int n, /**< size of array */
555  int* count, /**< array of counts (sizes) */
556  int** sub /**< pointer to store array of indices */
557  )
558 {
559  int i;
560  int j;
561 
562  assert(dstat != NULL);
563  assert(count != NULL);
564 
565  *count = 0;
566  for( i = 0; i < n; i++ )
567  {
568  if (dstat[i] == 1)
569  {
570  (*count)++;
571  }
572  }
573 
574  if( (*count) > 0 )
575  {
576  SCIP_ALLOC( BMSallocMemoryArray(sub, (*count)) );
577  }
578  else
579  return SCIP_OKAY;
580 
581  j = 0;
582  for( i = 0; i < n; i++ )
583  {
584  if (dstat[i] == 1)
585  {
586  (*sub)[j++] = i;
587  }
588  }
589 
590  return SCIP_OKAY;
591 }
592 
593 /** scale a vector */
594 static
596  int len, /**< length of vector */
597  double* vec, /**< vector to be scaled */
598  double s /**< scaling factor */
599  )
600 {
601  int i;
602  for( i = 0; i < len; i++ )
603  {
604  vec[i] *= s;
605  }
606 }
607 
608 /** scale lower and upper bound */
609 static
611  MSKboundkeye* bk, /**< pointer to store boundkeys to inform MOSEK about status of var/row */
612  double* bl, /**< lower bound */
613  double* bu, /**< upper bound */
614  double s /**< scaling factor */
615  )
616 {
617  switch( *bk )
618  {
619  case MSK_BK_LO:
620  *bl *= s;
621  if ( s < 0.0 )
622  *bk = MSK_BK_UP;
623  break;
624  case MSK_BK_UP:
625  *bu *= s;
626  if ( s < 0.0 )
627  *bk = MSK_BK_LO;
628  break;
629  case MSK_BK_FX:
630  case MSK_BK_RA:
631  *bl *= s;
632  *bu *= s;
633  break;
634  case MSK_BK_FR:
635  break;
636  default:
637  assert(FALSE);
638  break;
639  } /*lint !e788*/
640 
641  /* switch bounds if scaling is negative */
642  if ( s < 0.0 )
643  {
644  double tmp;
645  tmp = *bl;
646  *bl = *bu;
647  *bu = tmp;
648  }
649 }
650 
651 /** resizes state arrays to have at least ncols/nrows entries */
652 static
654  SCIP_LPI* lpi, /**< pointer to an LP interface structure */
655  int ncols, /**< number of columns */
656  int nrows /**< number of rows */
657  )
658 {
659  if ( lpi->skxsize < ncols )
660  {
661  int newsize;
662  newsize = MAX(2*lpi->skxsize, ncols);
663 
664  SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->skx), newsize) );
665  lpi->skxsize = newsize;
666  }
667 
668  if ( lpi->skcsize < nrows )
669  {
670  int newsize;
671  newsize = MAX(2*lpi->skcsize, nrows);
672 
673  SCIP_ALLOC( BMSreallocMemoryArray(&(lpi->skc), newsize) );
674  lpi->skcsize = newsize;
675  }
676 
677  return SCIP_OKAY;
678 }
679 
680 /** get base and store in skc/skx arrays */
681 static
683  SCIP_LPI* lpi, /**< pointer to an LP interface structure */
684  int ncols, /**< number of columns */
685  int nrows /**< number of rows */
686  )
687 {
688  assert(lpi->lastsolvetype == MSK_SOL_BAS);
689 
690  SCIPdebugMessage("Calling getbase (%d)\n", lpi->lpid);
691 
692  SCIP_CALL( ensureStateMem(lpi, ncols, nrows) );
693  MOSEK_CALL( MSK_getsolution(lpi->task, MSK_SOL_BAS, NULL, NULL, lpi->skc, lpi->skx,
694  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
695 
696  return SCIP_OKAY;
697 }
698 
699 /** set base to the values given in skc/skx arrays */
700 static
702  SCIP_LPI* lpi /**< pointer to an LP interface structure */
703  )
704 {
705  SCIPdebugMessage("Calling setbase (%d)\n", lpi->lpid);
706 
707  lpi->lastsolvetype = MSK_SOL_BAS;
708  lpi->solved = FALSE;
709 
710  MOSEK_CALL( MSK_putsolution(lpi->task, MSK_SOL_BAS, lpi->skc, lpi->skx, NULL, NULL,
711  NULL, NULL, NULL, NULL, NULL, NULL, NULL) );
712 
713  return SCIP_OKAY;
714 }
715 
716 
717 
718 /*
719  * Miscellaneous Methods
720  */
721 
722 static char mskname[100];
723 
724 /**@name Miscellaneous Methods */
725 /**@{ */
726 
727 /** gets name and version of LP solver */
729  void
730  )
731 {
732 #if MSK_VERSION_MAJOR < 9
733  sprintf(mskname, "MOSEK %d.%d.%d.%d", MSK_VERSION_MAJOR, MSK_VERSION_MINOR, MSK_VERSION_BUILD, MSK_VERSION_REVISION);
734 #else
735  sprintf(mskname, "MOSEK %d.%d.%d", MSK_VERSION_MAJOR, MSK_VERSION_MINOR, MSK_VERSION_REVISION);
736 #endif
737  return mskname;
738 }
739 
740 /** gets description of LP solver (developer, webpage, ...) */
742  void
743  )
744 {
745  return "Linear Programming Solver developed by MOSEK Optimization Software (www.mosek.com)";
746 }
747 
748 /** gets pointer for LP solver - use only with great care */
750  SCIP_LPI* lpi /**< pointer to an LP interface structure */
751  )
752 {
753  assert(MosekEnv != NULL);
754  assert(lpi != NULL);
755  assert(lpi->task != NULL);
756 
757  return (void*) lpi->task;
758 }
759 
760 /** pass integrality information to LP solver */
762  SCIP_LPI* lpi, /**< pointer to an LP interface structure */
763  int ncols, /**< length of integrality array */
764  int* intInfo /**< integrality array (0: continuous, 1: integer). May be NULL iff ncols is 0. */
765  )
766 { /*lint --e{715}*/
767  SCIPerrorMessage("SCIPlpiSetIntegralityInformation() has not been implemented yet.\n");
768  return SCIP_LPERROR;
769 }
770 
771 /** informs about availability of a primal simplex solving method */
773  void
774  )
775 {
776  return TRUE;
777 }
778 
779 /** informs about availability of a dual simplex solving method */
781  void
782  )
783 {
784  return TRUE;
785 }
786 
787 /** informs about availability of a barrier solving method */
789  void
790  )
791 {
792  return TRUE;
793 }
794 
795 /**@} */
796 
797 
798 /*
799  * LPI Creation and Destruction Methods
800  */
801 
802 /**@name LPI Creation and Destruction Methods */
803 /**@{ */
804 
805 /** creates an LP problem object */
807  SCIP_LPI** lpi, /**< pointer to an LP interface structure */
808  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler to use for printing messages, or NULL */
809  const char* name, /**< problem name */
810  SCIP_OBJSEN objsen /**< objective sense */
811  )
812 {
813  assert(lpi != NULL);
814  assert(name != NULL);
815  assert(numlp >= 0);
816 
817  SCIPdebugMessage("Calling SCIPlpiCreate\n");
818 
819  if (MosekEnv == NULL)
820  {
821  MOSEK_CALL( MSK_makeenv(&MosekEnv, NULL) );
822  MOSEK_CALL( MSK_linkfunctoenvstream(MosekEnv, MSK_STREAM_LOG, (MSKuserhandle_t) messagehdlr, printstr) );
823 #if MSK_VERSION_MAJOR < 8
824  MOSEK_CALL( MSK_initenv(MosekEnv) );
825 #endif
826  }
827 
828  numlp++;
829 
830  SCIP_ALLOC( BMSallocMemory(lpi) );
831 
832  MOSEK_CALL( MSK_makeemptytask(MosekEnv, &((*lpi)->task)) );
833 
834  MOSEK_CALL( MSK_linkfunctotaskstream((*lpi)->task, MSK_STREAM_LOG, (MSKuserhandle_t) messagehdlr, printstr) );
835 
836  MOSEK_CALL( MSK_putobjsense((*lpi)->task, SENSE2MOSEK(objsen)) );
837  MOSEK_CALL( MSK_putintparam((*lpi)->task, MSK_IPAR_SIM_MAX_NUM_SETBACKS, SETBACK_LIMIT) );
838  MOSEK_CALL( MSK_putintparam((*lpi)->task, MSK_IPAR_OPTIMIZER, MSK_OPTIMIZER_FREE_SIMPLEX) );
839  MOSEK_CALL( MSK_putintparam((*lpi)->task, MSK_IPAR_SIM_DEGEN, DEGEN_LEVEL) );
840  MOSEK_CALL( MSK_putintparam((*lpi)->task, MSK_IPAR_SIM_SWITCH_OPTIMIZER, MSK_ON) );
841  MOSEK_CALL( MSK_puttaskname((*lpi)->task, (char*) name) );
842 
843  /* disable errors for huge values */
844  MOSEK_CALL( MSK_putdouparam((*lpi)->task, MSK_DPAR_DATA_TOL_AIJ_HUGE, MSK_INFINITY * 2)); /* not clear why the *2 is needed */
845  MOSEK_CALL( MSK_putdouparam((*lpi)->task, MSK_DPAR_DATA_TOL_C_HUGE, MSK_INFINITY));
846 
847  /* disable warnings for large values */
848  MOSEK_CALL( MSK_putdouparam((*lpi)->task, MSK_DPAR_DATA_TOL_AIJ_LARGE, MSK_INFINITY * 2));
849  MOSEK_CALL( MSK_putdouparam((*lpi)->task, MSK_DPAR_DATA_TOL_CJ_LARGE, MSK_INFINITY));
850 
851  /* disable warnings for large bounds */
852  MOSEK_CALL( MSK_putdouparam((*lpi)->task, MSK_DPAR_DATA_TOL_BOUND_WRN, MSK_INFINITY));
853 
854  (*lpi)->termcode = MSK_RES_OK;
855  (*lpi)->itercount = 0;
856  (*lpi)->pricing = SCIP_PRICING_LPIDEFAULT;
857  (*lpi)->lpid = nextlpid++;
858  (*lpi)->lastalgo = MSK_OPTIMIZER_FREE;
859  (*lpi)->skx = NULL;
860  (*lpi)->skc = NULL;
861  (*lpi)->bkx = NULL;
862  (*lpi)->bkc = NULL;
863  (*lpi)->aptre = NULL;
864  (*lpi)->skxsize = 0;
865  (*lpi)->skcsize = 0;
866  (*lpi)->bkxsize = 0;
867  (*lpi)->bkcsize = 0;
868  (*lpi)->aptresize = 0;
869  (*lpi)->lastsolvetype = (MSKsoltypee) -1;
870  (*lpi)->lpinfo = FALSE;
871  (*lpi)->restrictselectdef = 50;
872  (*lpi)->fromscratch = FALSE;
873  (*lpi)->clearstate = FALSE;
874  (*lpi)->messagehdlr = messagehdlr;
875 
876  invalidateSolution(*lpi);
877 
878  MOSEK_CALL( MSK_putintparam((*lpi)->task, MSK_IPAR_LOG, MSK_OFF) );
879  MOSEK_CALL( MSK_putintparam((*lpi)->task, MSK_IPAR_LOG_SIM, MSK_OFF) );
880 
881  return SCIP_OKAY;
882 }
883 
884 /** deletes an LP problem object */
886  SCIP_LPI** lpi /**< pointer to an LP interface structure */
887  )
888 {
889  assert(lpi != NULL);
890  assert(*lpi != NULL);
891  assert(numlp > 0);
892 
893  SCIPdebugMessage("Calling SCIPlpiFree (%d)\n", (*lpi)->lpid);
894 
895  MOSEK_CALL( MSK_deletetask(&(*lpi)->task) );
896 
897  BMSfreeMemoryArrayNull(&(*lpi)->aptre);
898  BMSfreeMemoryArrayNull(&(*lpi)->bkx);
899  BMSfreeMemoryArrayNull(&(*lpi)->bkc);
900  BMSfreeMemoryArrayNull(&(*lpi)->skx);
901  BMSfreeMemoryArrayNull(&(*lpi)->skc);
902  BMSfreeMemory(lpi);
903 
904  numlp--;
905  if (numlp == 0)
906  {
907  MOSEK_CALL( MSK_deleteenv(&MosekEnv) );
908  MosekEnv = NULL;
909  }
910 
911  return SCIP_OKAY;
912 }
913 
914 /*
915  * Modification Methods
916  */
917 
918 
919 /** copies LP data with column matrix into LP solver */
921  SCIP_LPI* lpi, /**< LP interface structure */
922  SCIP_OBJSEN objsen, /**< objective sense */
923  int ncols, /**< number of columns */
924  const SCIP_Real* obj, /**< objective function values of columns */
925  const SCIP_Real* lb, /**< lower bounds of columns */
926  const SCIP_Real* ub, /**< upper bounds of columns */
927  char** colnames, /**< column names, or NULL */
928  int nrows, /**< number of rows */
929  const SCIP_Real* lhs, /**< left hand sides of rows */
930  const SCIP_Real* rhs, /**< right hand sides of rows */
931  char** rownames, /**< row names, or NULL */
932  int nnonz, /**< number of nonzero elements in the constraint matrix */
933  const int* beg, /**< start index of each column in ind- and val-array */
934  const int* ind, /**< row indices of constraint matrix entries */
935  const SCIP_Real* val /**< values of constraint matrix entries */
936  )
937 {
938 #ifndef NDEBUG
939  {
940  int j;
941  for( j = 0; j < nnonz; j++ )
942  assert( val[j] != 0.0 );
943  }
944 #endif
945 
946  assert(MosekEnv != NULL);
947  assert(lpi != NULL);
948  assert(lpi->task != NULL);
949  assert(lhs != NULL);
950  assert(rhs != NULL);
951  assert(obj != NULL);
952  assert(lb != NULL);
953  assert(ub != NULL);
954  assert(beg != NULL);
955  assert(ind != NULL);
956  assert(val != NULL);
957 
958  SCIPdebugMessage("Calling SCIPlpiLoadColLP (%d)\n", lpi->lpid);
959 
960  invalidateSolution(lpi);
961 
962 #if DEBUG_CHECK_DATA > 0
963  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiLoadColLP") );
964 #endif
965 
966  if (nrows > 0)
967  {
968  SCIP_CALL( ensureBkcMem(lpi, nrows) );
969  generateMskBoundkeys(nrows, lhs, rhs, lpi->bkc);
970  }
971 
972  if (ncols > 0)
973  {
974  SCIP_CALL( ensureBkxMem(lpi, ncols) );
975  generateMskBoundkeys(ncols, lb, ub, lpi->bkx);
976 
977  SCIP_CALL( ensureAptreMem(lpi, ncols) );
978  SCIP_CALL( getEndptrs(ncols, beg, nnonz, lpi->aptre) );
979  }
980 
981  MOSEK_CALL( MSK_inputdata(lpi->task, nrows, ncols, nrows, ncols, obj, 0.0, beg, lpi->aptre, ind, val,
982  lpi->bkc, lhs, rhs, lpi->bkx, lb, ub) );
983 
984  MOSEK_CALL( MSK_putobjsense(lpi->task, SENSE2MOSEK(objsen)) );
985 
986  if( colnames != NULL )
987  {
988  int c;
989 
990  for( c = 0; c < ncols; c++ )
991  {
992  MOSEK_CALL( MSK_putvarname(lpi->task, c, colnames[c]) );
993  }
994  }
995 
996  if( rownames != NULL )
997  {
998  int r;
999 
1000  for( r = 0; r < nrows; r++ )
1001  {
1002  MOSEK_CALL( MSK_putconname(lpi->task, r, rownames[r]) );
1003  }
1004  }
1005 
1006 #if DEBUG_CHECK_DATA > 0
1007  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiLoadColLP") );
1008 #endif
1009 
1010  return SCIP_OKAY;
1011 }
1012 
1013 /** adds columns to the LP */
1015  SCIP_LPI* lpi, /**< LP interface structure */
1016  int ncols, /**< number of columns to be added */
1017  const SCIP_Real* obj, /**< objective function values of new columns */
1018  const SCIP_Real* lb, /**< lower bounds of new columns */
1019  const SCIP_Real* ub, /**< upper bounds of new columns */
1020  char** colnames, /**< column names, or NULL */
1021  int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
1022  const int* beg, /**< start index of each column in ind- and val-array, or NULL if nnonz == 0 */
1023  const int* ind, /**< row indices of constraint matrix entries, or NULL if nnonz == 0 */
1024  const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
1025  )
1026 {
1027 #if MSK_VERSION_MAJOR < 7
1028  const int* aptrb;
1029 #endif
1030 
1031  int oldcols;
1032 
1033  assert(MosekEnv != NULL);
1034  assert(lpi != NULL);
1035  assert(lpi->task != NULL);
1036  assert(obj != NULL);
1037  assert(lb != NULL);
1038  assert(ub != NULL);
1039  assert(nnonz == 0 || beg != NULL);
1040  assert(nnonz == 0 || ind != NULL);
1041  assert(nnonz == 0 || val != NULL);
1042  assert(nnonz >= 0);
1043  assert(ncols >= 0);
1044 
1045  SCIPdebugMessage("Calling SCIPlpiAddCols (%d)\n", lpi->lpid);
1046 
1047  invalidateSolution(lpi);
1048 
1049 #if DEBUG_CHECK_DATA > 0
1050  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiAddCols") );
1051 #endif
1052 
1053  if (ncols == 0)
1054  return SCIP_OKAY;
1055 
1056  SCIP_CALL( ensureBkxMem(lpi, ncols) );
1057  generateMskBoundkeys(ncols, lb, ub, lpi->bkx);
1058 
1059  MOSEK_CALL( MSK_getnumvar(lpi->task, &oldcols) );
1060 
1061  MOSEK_CALL( MSK_appendvars(lpi->task, ncols) );
1062  MOSEK_CALL( MSK_putcslice(lpi->task, oldcols, oldcols+ncols, obj) );
1063  MOSEK_CALL( MSK_putvarboundslice(lpi->task, oldcols, oldcols+ncols, lpi->bkx, lb, ub) );
1064 
1065  if( nnonz > 0 )
1066  {
1067 #ifndef NDEBUG
1068  /* perform check that no new rows are added - this is forbidden */
1069  int nrows;
1070  int j;
1071 
1072  MOSEK_CALL( MSK_getnumcon(lpi->task, &nrows) );
1073  for (j = 0; j < nnonz; ++j)
1074  {
1075  assert( 0 <= ind[j] && ind[j] < nrows );
1076  assert( val[j] != 0.0 );
1077  }
1078 #endif
1079 
1080  SCIP_CALL( ensureAptreMem(lpi, ncols) );
1081  SCIP_CALL( getEndptrs(ncols, beg, nnonz, lpi->aptre) );
1082  MOSEK_CALL( MSK_putacolslice(lpi->task, oldcols, oldcols+ncols, beg, lpi->aptre, ind, val) );
1083  }
1084 
1085  if( colnames != NULL )
1086  {
1087  int c;
1088 
1089  for( c = 0; c < ncols; c++ )
1090  {
1091  MOSEK_CALL( MSK_putvarname(lpi->task, c, colnames[c]) );
1092  }
1093  }
1094 
1095 #if DEBUG_CHECK_DATA > 0
1096  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiAddCols") );
1097 #endif
1098 
1099  return SCIP_OKAY;
1100 }
1101 
1102 /** deletes all columns in the given range from LP */
1104  SCIP_LPI* lpi, /**< LP interface structure */
1105  int firstcol, /**< first column to be deleted */
1106  int lastcol /**< last column to be deleted */
1107  )
1108 {
1109  int* sub;
1110 
1111  assert(MosekEnv != NULL);
1112  assert(lpi != NULL);
1113  assert(lpi->task != NULL);
1114 
1115  SCIPdebugMessage("Calling SCIPlpiDelCols (%d)\n", lpi->lpid);
1116 
1117  invalidateSolution(lpi);
1118 
1119 #if DEBUG_CHECK_DATA > 0
1120  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiDelCols") );
1121 #endif
1122 
1123  SCIP_CALL( getIndicesRange(firstcol, lastcol, &sub) );
1124 
1125  MOSEK_CALL( MSK_removevars(lpi->task, lastcol-firstcol+1, sub) );
1126 
1127  BMSfreeMemoryArray(&sub);
1128 
1129 #if DEBUG_CHECK_DATA > 0
1130  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiDelCols") );
1131 #endif
1132 
1133  return SCIP_OKAY;
1134 }
1135 
1136 /** deletes columns from SCIP_LP; the new position of a column must not be greater that its old position */
1138  SCIP_LPI* lpi, /**< LP interface structure */
1139  int* dstat /**< deletion status of columns
1140  * input: 1 if column should be deleted, 0 if not
1141  * output: new position of column, -1 if column was deleted */
1142  )
1143 {
1144  int* sub = NULL;
1145  int count;
1146  int ncols;
1147  int col;
1148  int i;
1149 
1150  assert(MosekEnv != NULL);
1151  assert(lpi != NULL);
1152  assert(lpi->task != NULL);
1153  assert(dstat != NULL);
1154 
1155  SCIPdebugMessage("Calling SCIPlpiDelColset (%d)\n", lpi->lpid);
1156 
1157  invalidateSolution(lpi);
1158 
1159 #if DEBUG_CHECK_DATA > 0
1160  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiDelColset") );
1161 #endif
1162 
1163  MOSEK_CALL( MSK_getnumvar(lpi->task, &ncols) );
1164 
1165  SCIP_CALL( getIndicesFromDense(dstat, ncols, &count, &sub) );
1166 
1167  col = 0;
1168  for( i = 0; i < ncols; i++)
1169  {
1170  if (dstat[i] == 1)
1171  {
1172  dstat[i] = -1;
1173  }
1174  else
1175  {
1176  dstat[i] = col;
1177  col++;
1178  }
1179  }
1180 
1181  if (count > 0)
1182  {
1183  SCIPdebugMessage("Deleting %d vars %d, ...\n", count, sub[0]);
1184  MOSEK_CALL( MSK_removevars(lpi->task, count, sub) );
1185  BMSfreeMemoryArray(&sub);
1186  }
1187 
1188 #if DEBUG_CHECK_DATA > 0
1189  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiDelColset") );
1190 #endif
1191 
1192  return SCIP_OKAY;
1193 }
1194 
1195 /** adds rows to the LP */
1197  SCIP_LPI* lpi, /**< LP interface structure */
1198  int nrows, /**< number of rows to be added */
1199  const SCIP_Real* lhs, /**< left hand sides of new rows */
1200  const SCIP_Real* rhs, /**< right hand sides of new rows */
1201  char** rownames, /**< row names, or NULL */
1202  int nnonz, /**< number of nonzero elements to be added to the constraint matrix */
1203  const int* beg, /**< start index of each row in ind- and val-array, or NULL if nnonz == 0 */
1204  const int* ind, /**< column indices of constraint matrix entries, or NULL if nnonz == 0 */
1205  const SCIP_Real* val /**< values of constraint matrix entries, or NULL if nnonz == 0 */
1206  )
1207 {
1208  int oldrows;
1209 
1210  assert(MosekEnv != NULL);
1211  assert(lpi != NULL);
1212  assert(lpi->task != NULL);
1213  assert(nnonz == 0 || beg != NULL);
1214  assert(nnonz == 0 || ind != NULL);
1215  assert(nnonz == 0 || val != NULL);
1216 
1217  SCIPdebugMessage("Calling SCIPlpiAddRows (%d)\n", lpi->lpid);
1218 
1219  invalidateSolution(lpi);
1220 
1221 #if DEBUG_CHECK_DATA > 0
1222  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiAddRows") );
1223 #endif
1224 
1225  if (nrows == 0)
1226  return SCIP_OKAY;
1227 
1228  SCIP_CALL( ensureBkcMem(lpi, nrows) );
1229 
1230  generateMskBoundkeys(nrows, lhs, rhs, lpi->bkc);
1231 
1232  MOSEK_CALL( MSK_getnumcon(lpi->task, &oldrows) );
1233 
1234  MOSEK_CALL( MSK_appendcons(lpi->task, nrows) );
1235  MOSEK_CALL( MSK_putconboundslice(lpi->task, oldrows, oldrows+nrows, lpi->bkc, lhs, rhs) );
1236 
1237  if( nnonz > 0 )
1238  {
1239 #ifndef NDEBUG
1240  /* perform check that no new cols are added - this is forbidden */
1241  int ncols;
1242  int j;
1243 
1244  MOSEK_CALL( MSK_getnumvar(lpi->task, &ncols) );
1245  for (j = 0; j < nnonz; ++j)
1246  {
1247  assert( val[j] != 0.0 );
1248  assert( 0 <= ind[j] && ind[j] < ncols );
1249  }
1250 #endif
1251 
1252  SCIP_CALL( ensureAptreMem(lpi, nrows) );
1253  SCIP_CALL( getEndptrs(nrows, beg, nnonz, lpi->aptre) );
1254  MOSEK_CALL( MSK_putarowslice(lpi->task, oldrows, oldrows+nrows, beg, lpi->aptre, ind, val) );
1255  }
1256 
1257  if( rownames != NULL )
1258  {
1259  int r;
1260 
1261  for( r = 0; r < nrows; r++ )
1262  {
1263  MOSEK_CALL( MSK_putconname(lpi->task, r, rownames[r]) );
1264  }
1265  }
1266 
1267 #if DEBUG_CHECK_DATA > 0
1268  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiAddRows") );
1269 #endif
1270 
1271  return SCIP_OKAY;
1272 }
1273 
1274 /** deletes all rows in the given range from LP */
1276  SCIP_LPI* lpi, /**< LP interface structure */
1277  int firstrow, /**< first row to be deleted */
1278  int lastrow /**< last row to be deleted */
1279  )
1280 {
1281  int* sub;
1282 
1283  assert(MosekEnv != NULL);
1284  assert(lpi != NULL);
1285  assert(lpi->task != NULL);
1286 
1287  SCIPdebugMessage("Calling SCIPlpiDelRows (%d)\n", lpi->lpid);
1288 
1289  invalidateSolution(lpi);
1290 
1291 #if DEBUG_CHECK_DATA > 0
1292  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiDelRows") );
1293 #endif
1294 
1295  SCIP_CALL( getIndicesRange(firstrow, lastrow, &sub) );
1296 
1297  SCIPdebugMessage("Deleting cons %d to %d\n", firstrow, lastrow);
1298 
1299  MOSEK_CALL( MSK_removecons(lpi->task, lastrow-firstrow+1, sub) );
1300 
1301  BMSfreeMemoryArray(&sub);
1302 
1303 #if DEBUG_CHECK_DATA > 0
1304  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiDelRows") );
1305 #endif
1306 
1307  return SCIP_OKAY;
1308 }
1309 
1310 /** deletes rows from SCIP_LP; the new position of a row must not be greater that its old position */
1312  SCIP_LPI* lpi, /**< LP interface structure */
1313  int* dstat /**< deletion status of rows
1314  * input: 1 if row should be deleted, 0 if not
1315  * output: new position of row, -1 if row was deleted */
1316  )
1317 {
1318  int* sub;
1319  int count;
1320  int nrows;
1321  int row;
1322  int i;
1323 
1324  assert(MosekEnv != NULL);
1325  assert(lpi != NULL);
1326  assert(lpi->task != NULL);
1327 
1328  SCIPdebugMessage("Calling SCIPlpiDelRowset (%d)\n", lpi->lpid);
1329 
1330  invalidateSolution(lpi);
1331 
1332 #if DEBUG_CHECK_DATA > 0
1333  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiDelRowset") );
1334 #endif
1335 
1336  MOSEK_CALL( MSK_getnumcon(lpi->task, &nrows) );
1337 
1338  sub = NULL;
1339  SCIP_CALL( getIndicesFromDense(dstat, nrows, &count, &sub) );
1340 
1341  row = 0;
1342  for( i = 0; i < nrows; i++ )
1343  {
1344  if (dstat[i] == 1)
1345  {
1346  dstat[i] = -1;
1347  }
1348  else
1349  {
1350  dstat[i] = row;
1351  row++;
1352  }
1353  }
1354 
1355  if (count > 0)
1356  {
1357  SCIPdebugMessage("Deleting %d cons %d, ...\n", count, sub[0]);
1358  MOSEK_CALL( MSK_removecons(lpi->task, count, sub) );
1359  BMSfreeMemoryArray(&sub);
1360  }
1361 
1362 #if DEBUG_CHECK_DATA > 0
1363  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiDelRowset end") );
1364 #endif
1365 
1366  return SCIP_OKAY;
1367 }
1368 
1369 /** clears the whole LP */
1371  SCIP_LPI* lpi /**< LP interface structure */
1372  )
1373 {
1374  int nrows;
1375  int ncols;
1376 
1377  assert(MosekEnv != NULL);
1378  assert(lpi != NULL);
1379  assert(lpi->task != NULL);
1380 
1381  SCIPdebugMessage("Calling SCIPlpiClear (%d)\n", lpi->lpid);
1382 
1383  invalidateSolution(lpi);
1384 
1385  MOSEK_CALL( MSK_getnumcon(lpi->task, &nrows) );
1386  MOSEK_CALL( MSK_getnumvar(lpi->task, &ncols) );
1387 
1388  SCIP_CALL( SCIPlpiDelRows(lpi, 0, nrows - 1) );
1389  SCIP_CALL( SCIPlpiDelCols(lpi, 0, ncols - 1) );
1390 
1391  return SCIP_OKAY;
1392 }
1393 
1394 /** changes lower and upper bounds of columns */
1396  SCIP_LPI* lpi, /**< LP interface structure */
1397  int ncols, /**< number of columns to change bounds for */
1398  const int* ind, /**< column indices or NULL if ncols is zero */
1399  const SCIP_Real* lb, /**< values for the new lower bounds or NULL if ncols is zero */
1400  const SCIP_Real* ub /**< values for the new upper bounds or NULL if ncols is zero */
1401  )
1402 {
1403  int i;
1404 
1405  assert(MosekEnv != NULL);
1406  assert(lpi != NULL);
1407  assert(lpi->task != NULL);
1408  assert(ncols == 0 || (ind != NULL && lb != NULL && ub != NULL));
1409 
1410  SCIPdebugMessage("Calling SCIPlpiChgBounds (%d)\n", lpi->lpid);
1411  if( ncols <= 0 )
1412  return SCIP_OKAY;
1413 
1414  invalidateSolution(lpi);
1415 
1416 #if DEBUG_CHECK_DATA > 0
1417  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiChgBounds") );
1418 #endif
1419 
1420  /* @todo This test could be integrated into generateMskBoundkeys, but then this function needs to be able to return an
1421  * error, which requires some rewriting. */
1422  for (i = 0; i < ncols; ++i)
1423  {
1424  if ( SCIPlpiIsInfinity(lpi, lb[i]) )
1425  {
1426  SCIPerrorMessage("LP Error: fixing lower bound for variable %d to infinity.\n", ind[i]);
1427  return SCIP_LPERROR;
1428  }
1429  if ( SCIPlpiIsInfinity(lpi, -ub[i]) )
1430  {
1431  SCIPerrorMessage("LP Error: fixing upper bound for variable %d to -infinity.\n", ind[i]);
1432  return SCIP_LPERROR;
1433  }
1434  }
1435 
1436  SCIP_CALL( ensureBkxMem(lpi, ncols) );
1437 
1438  generateMskBoundkeys(ncols, lb, ub, lpi->bkx);
1439 #if MSK_VERSION_MAJOR < 9
1440  MOSEK_CALL( MSK_putboundlist(lpi->task, MSK_ACC_VAR, ncols, ind, lpi->bkx, lb, ub) );
1441 #else
1442  MOSEK_CALL( MSK_putvarboundlist(lpi->task, ncols, ind, lpi->bkx, lb, ub) );
1443 #endif
1444 
1445 #if DEBUG_CHECK_DATA > 0
1446  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiChgBounds") );
1447 #endif
1448 
1449  return SCIP_OKAY;
1450 }
1451 
1452 /** changes left and right hand sides of rows */
1454  SCIP_LPI* lpi, /**< LP interface structure */
1455  int nrows, /**< number of rows to change sides for */
1456  const int* ind, /**< row indices */
1457  const SCIP_Real* lhs, /**< new values for left hand sides */
1458  const SCIP_Real* rhs /**< new values for right hand sides */
1459  )
1460 {
1461  assert(MosekEnv != NULL);
1462  assert(lpi != NULL);
1463  assert(lpi->task != NULL);
1464  assert(ind != NULL);
1465 
1466  if( nrows <= 0 )
1467  return SCIP_OKAY;
1468 
1469  invalidateSolution(lpi);
1470 
1471  SCIPdebugMessage("Calling SCIPlpiChgSides (%d)\n", lpi->lpid);
1472 
1473 #if DEBUG_CHECK_DATA > 0
1474  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiChgSides") );
1475 #endif
1476 
1477  SCIP_CALL( ensureBkcMem(lpi, nrows) );
1478 
1479  generateMskBoundkeys(nrows, lhs, rhs, lpi->bkc);
1480 #if MSK_VERSION_MAJOR < 9
1481  MOSEK_CALL( MSK_putboundlist(lpi->task, MSK_ACC_CON, nrows, ind, lpi->bkc, lhs, rhs) );
1482 #else
1483  MOSEK_CALL( MSK_putconboundlist(lpi->task, nrows, ind, lpi->bkc, lhs, rhs) );
1484 #endif
1485 
1486 #if DEBUG_CHECK_DATA > 0
1487  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiChgSides") );
1488 #endif
1489 
1490  return SCIP_OKAY;
1491 }
1492 
1493 /** changes a single coefficient */
1495  SCIP_LPI* lpi, /**< LP interface structure */
1496  int row, /**< row number of coefficient to change */
1497  int col, /**< column number of coefficient to change */
1498  SCIP_Real newval /**< new value of coefficient */
1499  )
1500 {
1501  assert(MosekEnv != NULL);
1502  assert(lpi != NULL);
1503  assert(lpi->task != NULL);
1504 
1505  SCIPdebugMessage("Calling SCIPlpiChgCoef (%d)\n", lpi->lpid);
1506 
1507  invalidateSolution(lpi);
1508 
1509 #if DEBUG_CHECK_DATA > 0
1510  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiChgCoef") );
1511 #endif
1512 
1513  MOSEK_CALL( MSK_putaij(lpi->task, row, col, newval) );
1514 
1515 #if DEBUG_CHECK_DATA > 0
1516  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiChgCoef") );
1517 #endif
1518 
1519  return SCIP_OKAY;
1520 }
1521 
1522 /** changes the objective sense */
1524  SCIP_LPI* lpi, /**< LP interface structure */
1525  SCIP_OBJSEN objsen /**< new objective sense */
1526  )
1527 {
1528  assert(MosekEnv != NULL);
1529  assert(lpi != NULL);
1530  assert(lpi->task != NULL);
1531 
1532  SCIPdebugMessage("Calling SCIPlpiChgObjsen (%d)\n", lpi->lpid);
1533 
1534  invalidateSolution(lpi);
1535 
1536  MOSEK_CALL( MSK_putobjsense(lpi->task, SENSE2MOSEK(objsen)) );
1537 
1538  return SCIP_OKAY;
1539 }
1540 
1541 /** changes objective values of columns in the LP */
1543  SCIP_LPI* lpi, /**< LP interface structure */
1544  int ncols, /**< number of columns to change objective value for */
1545  const int* ind, /**< column indices to change objective value for */
1546  const SCIP_Real* obj /**< new objective values for columns */
1547  )
1548 {
1549  assert(MosekEnv != NULL);
1550  assert(lpi != NULL);
1551  assert(lpi->task != NULL);
1552  assert(ind != NULL);
1553  assert(obj != NULL);
1554 
1555  SCIPdebugMessage("Calling SCIPlpiChgObj (%d)\n", lpi->lpid);
1556 
1557  invalidateSolution(lpi);
1558 
1559 #if DEBUG_CHECK_DATA > 0
1560  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiChgObj") );
1561 #endif
1562 
1563  MOSEK_CALL( MSK_putclist(lpi->task, ncols, ind, obj) );
1564 
1565 #if DEBUG_CHECK_DATA > 0
1566  SCIP_CALL( scip_checkdata(lpi,"SCIPlpiChgObj") );
1567 #endif
1568 
1569  return SCIP_OKAY;
1570 }
1571 
1572 /** multiplies a row with a non-zero scalar; for negative scalars, the row's sense is switched accordingly */
1574  SCIP_LPI* lpi, /**< LP interface structure */
1575  int row, /**< row number to scale */
1576  SCIP_Real scaleval /**< scaling multiplier */
1577  )
1578 {
1579  int nnonz;
1580  int* sub;
1581  double* val;
1582  MSKboundkeye bkc;
1583  double blc;
1584  double buc;
1585 
1586  assert(MosekEnv != NULL);
1587  assert(lpi != NULL);
1588  assert(lpi->task != NULL);
1589 
1590  SCIPdebugMessage("Calling SCIPlpiScaleRow (%d)\n", lpi->lpid);
1591 
1592  invalidateSolution(lpi);
1593 
1594 #if DEBUG_CHECK_DATA > 0
1595  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiScaleRow") );
1596 #endif
1597 
1598  assert(scaleval != 0);
1599 
1600  MOSEK_CALL( MSK_getarownumnz(lpi->task, row, &nnonz) );
1601 
1602  if (nnonz != 0)
1603  {
1604  SCIP_ALLOC( BMSallocMemoryArray(&sub, nnonz) );
1605  SCIP_ALLOC( BMSallocMemoryArray(&val, nnonz) );
1606 
1607  MOSEK_CALL( MSK_getarow(lpi->task, row, &nnonz, sub, val) );
1608  scale_vec(nnonz, val, scaleval);
1609  MOSEK_CALL( MSK_putarow(lpi->task, row, nnonz, sub, val) );
1610 
1611  BMSfreeMemoryArray(&val);
1612  BMSfreeMemoryArray(&sub);
1613  }
1614 
1615 #if MSK_VERSION_MAJOR < 9
1616  MOSEK_CALL( MSK_getbound(lpi->task, MSK_ACC_CON, row, &bkc, &blc, &buc) );
1617  scale_bound(&bkc, &blc, &buc, scaleval);
1618  MOSEK_CALL( MSK_putbound(lpi->task, MSK_ACC_CON, row, bkc, blc, buc) );
1619 #else
1620  MOSEK_CALL( MSK_getconbound(lpi->task, row, &bkc, &blc, &buc) );
1621  scale_bound(&bkc, &blc, &buc, scaleval);
1622  MOSEK_CALL( MSK_putconbound(lpi->task, row, bkc, blc, buc) );
1623 #endif
1624 
1625 #if DEBUG_CHECK_DATA > 0
1626  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiScaleRow") );
1627 #endif
1628 
1629  return SCIP_OKAY;
1630 }
1631 
1632 /** multiplies a column with a non-zero scalar; the objective value is multiplied with the scalar, and the bounds
1633  * are divided by the scalar; for negative scalars, the column's bounds are switched
1634  */
1636  SCIP_LPI* lpi, /**< LP interface structure */
1637  int col, /**< column number to scale */
1638  SCIP_Real scaleval /**< scaling multiplier */
1639  )
1640 {
1641  int nnonz;
1642  int *sub = NULL;
1643  double *val = NULL;
1644  MSKboundkeye bkx;
1645  double blx, bux, c;
1646 
1647  assert(MosekEnv != NULL);
1648  assert(lpi != NULL);
1649  assert(lpi->task != NULL);
1650 
1651  SCIPdebugMessage("Calling SCIPlpiScaleCol (%d)\n", lpi->lpid);
1652 
1653  invalidateSolution(lpi);
1654 
1655 #if DEBUG_CHECK_DATA > 0
1656  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiScaleCol") );
1657 #endif
1658 
1659  assert(scaleval != 0);
1660  MOSEK_CALL( MSK_getacolnumnz(lpi->task, col, &nnonz) );
1661 
1662  if (nnonz != 0)
1663  {
1664  SCIP_ALLOC( BMSallocMemoryArray(&sub, nnonz) );
1665  SCIP_ALLOC( BMSallocMemoryArray(&val, nnonz) );
1666 
1667  MOSEK_CALL( MSK_getacol(lpi->task, col, &nnonz, sub, val) );
1668  scale_vec(nnonz, val, scaleval);
1669  MOSEK_CALL( MSK_putacol(lpi->task, col, nnonz, sub, val) );
1670 
1671  BMSfreeMemoryArray(&val);
1672  BMSfreeMemoryArray(&sub);
1673  }
1674 
1675 #if MSK_VERSION_MAJOR < 9
1676  MOSEK_CALL( MSK_getbound(lpi->task, MSK_ACC_VAR, col, &bkx, &blx, &bux) );
1677  scale_bound(&bkx, &blx, &bux, 1.0/scaleval);
1678  MOSEK_CALL( MSK_putbound(lpi->task, MSK_ACC_VAR, col, bkx, blx, bux) );
1679 #else
1680  MOSEK_CALL( MSK_getvarbound(lpi->task, col, &bkx, &blx, &bux) );
1681  scale_bound(&bkx, &blx, &bux, 1.0/scaleval);
1682  MOSEK_CALL( MSK_putvarbound(lpi->task, col, bkx, blx, bux) );
1683 #endif
1684 
1685  MOSEK_CALL( MSK_getcslice(lpi->task, col, col+1, &c) );
1686  MOSEK_CALL( MSK_putcj(lpi->task, col, c*scaleval) );
1687 
1688 #if DEBUG_CHECK_DATA > 0
1689  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiScaleCol") );
1690 #endif
1691 
1692  return SCIP_OKAY;
1693 }
1694 
1695 
1696 /*
1697  * Data Accessing Methods
1698  */
1699 
1700 
1701 /** gets the number of rows in the LP */
1703  SCIP_LPI* lpi, /**< LP interface structure */
1704  int* nrows /**< pointer to store the number of rows */
1705  )
1706 {
1707  assert(MosekEnv != NULL);
1708  assert(lpi != NULL);
1709  assert(lpi->task != NULL);
1710  assert(nrows != NULL);
1711 
1712  SCIPdebugMessage("Calling SCIPlpiGetNRows (%d)\n", lpi->lpid);
1713 
1714  MOSEK_CALL( MSK_getnumcon(lpi->task, nrows) );
1715 
1716  return SCIP_OKAY;
1717 }
1718 
1719 /** gets the number of columns in the LP */
1721  SCIP_LPI* lpi, /**< LP interface structure */
1722  int* ncols /**< pointer to store the number of cols */
1723  )
1724 {
1725  assert(MosekEnv != NULL);
1726  assert(lpi != NULL);
1727  assert(lpi->task != NULL);
1728  assert(ncols != NULL);
1729 
1730  SCIPdebugMessage("Calling SCIPlpiGetNCols (%d)\n", lpi->lpid);
1731 
1732  MOSEK_CALL( MSK_getnumvar(lpi->task, ncols) );
1733 
1734  return SCIP_OKAY;
1735 }
1736 
1737 /** gets the number of nonzero elements in the LP constraint matrix */
1739  SCIP_LPI* lpi, /**< LP interface structure */
1740  int* nnonz /**< pointer to store the number of nonzeros */
1741  )
1742 {
1743  assert(MosekEnv != NULL);
1744  assert(lpi != NULL);
1745  assert(lpi->task != NULL);
1746  assert(nnonz != NULL);
1747 
1748  SCIPdebugMessage("Calling SCIPlpiGetNNonz (%d)\n", lpi->lpid);
1749 
1750  MOSEK_CALL( MSK_getnumanz(lpi->task, nnonz) );
1751 
1752  return SCIP_OKAY;
1753 }
1754 
1755 /** get a slice of a row or column */
1756 static
1758  SCIP_LPI* lpi, /**< LP interface structure */
1759  SCIP_Bool iscon, /**< whether we are requesting a slice of a constraint or column */
1760  int first, /**< first index */
1761  int last, /**< last index */
1762  int* nnonz, /**< pointer to store the number of nonzeros */
1763  int* beg, /**< array for begins of indices/values */
1764  int* ind, /**< array of row/column indices */
1765  double* val /**< array of values */
1766  )
1767 {
1768  assert(MosekEnv != NULL);
1769  assert(lpi != NULL);
1770  assert(lpi->task != NULL);
1771  assert(first <= last);
1772 
1773  SCIPdebugMessage("Calling SCIPlpiGetNNonz (%d)\n", lpi->lpid);
1774 
1775 #if DEBUG_CHECK_DATA > 0
1776  SCIP_CALL( scip_checkdata(lpi, "getASlice") );
1777 #endif
1778 
1779  if( nnonz != 0 )
1780  {
1781  int surplus;
1782 
1783  assert(beg != NULL);
1784  assert(ind != NULL);
1785  assert(val != NULL);
1786 
1787  SCIP_CALL( ensureAptreMem(lpi, last - first + 1) );
1788 
1789 #if MSK_VERSION_MAJOR < 9
1790  MOSEK_CALL( MSK_getaslicenumnz(lpi->task, iscon ? MSK_ACC_CON : MSK_ACC_VAR, first, last+1, nnonz) );
1791  surplus = *nnonz;
1792  MOSEK_CALL( MSK_getaslice(lpi->task, iscon ? MSK_ACC_CON : MSK_ACC_VAR, first, last+1, *nnonz, &surplus, beg, lpi->aptre, ind, val) );
1793 #else
1794  if( iscon )
1795  {
1796  MOSEK_CALL( MSK_getarowslicenumnz(lpi->task, first, last+1, nnonz) );
1797  surplus = *nnonz;
1798  MOSEK_CALL( MSK_getarowslice(lpi->task, first, last+1, *nnonz, &surplus, beg, lpi->aptre, ind, val) );
1799  }
1800  else
1801  {
1802  MOSEK_CALL( MSK_getacolslicenumnz(lpi->task, first, last+1, nnonz) );
1803  surplus = *nnonz;
1804  MOSEK_CALL( MSK_getacolslice(lpi->task, first, last+1, *nnonz, &surplus, beg, lpi->aptre, ind, val) );
1805  }
1806 #endif
1807 
1808  assert(surplus == 0);
1809  }
1810 
1811 #if DEBUG_CHECK_DATA > 0
1812  SCIP_CALL( scip_checkdata(lpi, "getASlice") );
1813 #endif
1814 
1815  return SCIP_OKAY;
1816 }
1817 
1818 /** gets columns from LP problem object; the arrays have to be large enough to store all values;
1819  * Either both, lb and ub, have to be NULL, or both have to be non-NULL,
1820  * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
1821  */
1823  SCIP_LPI* lpi, /**< LP interface structure */
1824  int firstcol, /**< first column to get from LP */
1825  int lastcol, /**< last column to get from LP */
1826  SCIP_Real* lb, /**< buffer to store the lower bound vector, or NULL */
1827  SCIP_Real* ub, /**< buffer to store the upper bound vector, or NULL */
1828  int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
1829  int* beg, /**< buffer to store start index of each column in ind- and val-array, or NULL */
1830  int* ind, /**< buffer to store row indices of constraint matrix entries, or NULL */
1831  SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
1832  )
1833 {
1834  assert(MosekEnv != NULL);
1835  assert(lpi != NULL);
1836  assert(lpi->task != NULL);
1837  assert((lb != NULL && ub != NULL) || (lb == NULL && ub == NULL));
1838  assert((nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL));
1839 
1840 #ifndef NDEBUG
1841  {
1842  int ncols;
1843  SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) );
1844  assert(0 <= firstcol && firstcol <= lastcol && lastcol < ncols);
1845  }
1846 #endif
1847 
1848  SCIPdebugMessage("Calling SCIPlpiGetCols (%d)\n", lpi->lpid);
1849 
1850  SCIP_CALL( SCIPlpiGetBounds(lpi, firstcol, lastcol, lb, ub) );
1851  SCIP_CALL( getASlice(lpi, FALSE, firstcol, lastcol, nnonz, beg, ind, val) );
1852 
1853  return SCIP_OKAY;
1854 }
1855 
1856 /** gets rows from LP problem object; the arrays have to be large enough to store all values.
1857  * Either both, lhs and rhs, have to be NULL, or both have to be non-NULL,
1858  * either nnonz, beg, ind, and val have to be NULL, or all of them have to be non-NULL.
1859  */
1861  SCIP_LPI* lpi, /**< LP interface structure */
1862  int firstrow, /**< first row to get from LP */
1863  int lastrow, /**< last row to get from LP */
1864  SCIP_Real* lhs, /**< buffer to store left hand side vector, or NULL */
1865  SCIP_Real* rhs, /**< buffer to store right hand side vector, or NULL */
1866  int* nnonz, /**< pointer to store the number of nonzero elements returned, or NULL */
1867  int* beg, /**< buffer to store start index of each row in ind- and val-array, or NULL */
1868  int* ind, /**< buffer to store column indices of constraint matrix entries, or NULL */
1869  SCIP_Real* val /**< buffer to store values of constraint matrix entries, or NULL */
1870  )
1871 {
1872  assert(MosekEnv != NULL);
1873  assert(lpi != NULL);
1874  assert(lpi->task != NULL);
1875  assert((lhs != NULL && rhs != NULL) || (lhs == NULL && rhs == NULL));
1876  assert((nnonz != NULL && beg != NULL && ind != NULL && val != NULL) || (nnonz == NULL && beg == NULL && ind == NULL && val == NULL));
1877 
1878 #ifndef NDEBUG
1879  {
1880  int nrows;
1881  SCIP_CALL( SCIPlpiGetNRows(lpi, &nrows) );
1882  assert(0 <= firstrow && firstrow <= lastrow && lastrow < nrows);
1883  }
1884 #endif
1885 
1886  SCIPdebugMessage("Calling SCIPlpiGetRows (%d)\n", lpi->lpid);
1887 
1888 #if DEBUG_CHECK_DATA > 0
1889  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiGetRows") );
1890 #endif
1891 
1892  SCIP_CALL( SCIPlpiGetSides(lpi, firstrow, lastrow, lhs, rhs) );
1893  SCIP_CALL( getASlice(lpi, TRUE, firstrow, lastrow, nnonz, beg, ind, val) );
1894 
1895 #if DEBUG_CHECK_DATA > 0
1896  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiGetRows") );
1897 #endif
1898 
1899  return SCIP_OKAY;
1900 }
1901 
1902 /** gets column names */
1904  SCIP_LPI* lpi, /**< LP interface structure */
1905  int firstcol, /**< first column to get name from LP */
1906  int lastcol, /**< last column to get name from LP */
1907  char** colnames, /**< pointers to column names (of size at least lastcol-firstcol+1) or NULL if namestoragesize is zero */
1908  char* namestorage, /**< storage for col names or NULL if namestoragesize is zero */
1909  int namestoragesize, /**< size of namestorage (if 0, storageleft returns the storage needed) */
1910  int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
1911  )
1912 { /*lint --e{715}*/
1913  assert(MosekEnv != NULL);
1914  assert(lpi != NULL);
1915  assert(lpi->task != NULL);
1916  assert(colnames != NULL || namestoragesize == 0);
1917  assert(namestorage != NULL || namestoragesize == 0);
1918  assert(namestoragesize >= 0);
1919  assert(storageleft != NULL);
1920 
1921  SCIPerrorMessage("SCIPlpiGetColNames() has not been implemented yet.\n");
1922 
1923  return SCIP_LPERROR;
1924 }
1925 
1926 /** gets row names */
1928  SCIP_LPI* lpi, /**< LP interface structure */
1929  int firstrow, /**< first row to get name from LP */
1930  int lastrow, /**< last row to get name from LP */
1931  char** rownames, /**< pointers to row names (of size at least lastrow-firstrow+1) or NULL if namestoragesize is zero */
1932  char* namestorage, /**< storage for row names or NULL if namestoragesize is zero */
1933  int namestoragesize, /**< size of namestorage (if 0, -storageleft returns the storage needed) */
1934  int* storageleft /**< amount of storage left (if < 0 the namestorage was not big enough) or NULL if namestoragesize is zero */
1935  )
1936 { /*lint --e{715}*/
1937  assert(MosekEnv != NULL);
1938  assert(lpi != NULL);
1939  assert(lpi->task != NULL);
1940  assert(rownames != NULL || namestoragesize == 0);
1941  assert(namestorage != NULL || namestoragesize == 0);
1942  assert(namestoragesize >= 0);
1943  assert(storageleft != NULL);
1944 
1945  SCIPerrorMessage("SCIPlpiGetRowNames() has not been implemented yet.\n");
1946 
1947  return SCIP_LPERROR;
1948 }
1949 
1950 /** gets the objective sense of the LP */
1952  SCIP_LPI* lpi, /**< LP interface structure */
1953  SCIP_OBJSEN* objsen /**< pointer to store objective sense */
1954  )
1955 {
1956  MSKobjsensee mskobjsen;
1957 
1958  assert(MosekEnv != NULL);
1959  assert(lpi != NULL);
1960  assert(lpi->task != NULL);
1961  assert(objsen != NULL);
1962 
1963  SCIPdebugMessage("Calling SCIPlpiGetObjsen (%d)\n", lpi->lpid);
1964 
1965  MOSEK_CALL( MSK_getobjsense(lpi->task, &mskobjsen) );
1966  *objsen = (mskobjsen == MSK_OBJECTIVE_SENSE_MINIMIZE ? SCIP_OBJSEN_MINIMIZE : SCIP_OBJSEN_MAXIMIZE);
1967 
1968  return SCIP_OKAY;
1969 }
1970 
1971 /** gets objective coefficients from LP problem object */
1973  SCIP_LPI* lpi, /**< LP interface structure */
1974  int firstcol, /**< first column to get objective coefficient for */
1975  int lastcol, /**< last column to get objective coefficient for */
1976  SCIP_Real* vals /**< array to store objective coefficients */
1977  )
1978 {
1979  assert(MosekEnv != NULL);
1980  assert(lpi != NULL);
1981  assert(lpi->task != NULL);
1982  assert(firstcol <= lastcol);
1983  assert(vals != NULL);
1984 
1985  SCIPdebugMessage("Calling SCIPlpiGetObj (%d)\n", lpi->lpid);
1986 
1987  MOSEK_CALL( MSK_getcslice(lpi->task, firstcol, lastcol+1, vals) );
1988 
1989  return SCIP_OKAY;
1990 }
1991 
1992 /** gets current bounds from LP problem object */
1994  SCIP_LPI* lpi, /**< LP interface structure */
1995  int firstcol, /**< first column to get bounds for */
1996  int lastcol, /**< last column to get bounds for */
1997  SCIP_Real* lbs, /**< array to store lower bound values, or NULL */
1998  SCIP_Real* ubs /**< array to store upper bound values, or NULL */
1999  )
2000 {
2001  assert(MosekEnv != NULL);
2002  assert(lpi != NULL);
2003  assert(lpi->task != NULL);
2004  assert(firstcol <= lastcol);
2005 
2006  SCIPdebugMessage("Calling SCIPlpiGetBounds (%d)\n", lpi->lpid);
2007 
2008 #if DEBUG_CHECK_DATA > 0
2009  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiGetBounds") );
2010 #endif
2011 
2012 #if MSK_VERSION_MAJOR < 9
2013  MOSEK_CALL( MSK_getboundslice(lpi->task, MSK_ACC_VAR, firstcol, lastcol+1, NULL, lbs, ubs) );
2014 #else
2015  MOSEK_CALL( MSK_getvarboundslice(lpi->task, firstcol, lastcol+1, NULL, lbs, ubs) );
2016 #endif
2017 
2018  return SCIP_OKAY;
2019 }
2020 
2021 /** gets current row sides from LP problem object */
2023  SCIP_LPI* lpi, /**< LP interface structure */
2024  int firstrow, /**< first row to get sides for */
2025  int lastrow, /**< last row to get sides for */
2026  SCIP_Real* lhss, /**< array to store left hand side values, or NULL */
2027  SCIP_Real* rhss /**< array to store right hand side values, or NULL */
2028  )
2029 {
2030  assert(MosekEnv != NULL);
2031  assert(lpi != NULL);
2032  assert(lpi->task != NULL);
2033  assert(firstrow <= lastrow);
2034 
2035  SCIPdebugMessage("Calling SCIPlpiGetSides (%d)\n", lpi->lpid);
2036 
2037 #if DEBUG_CHECK_DATA > 0
2038  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiGetSides") );
2039 #endif
2040 
2041 #if MSK_VERSION_MAJOR < 9
2042  MOSEK_CALL( MSK_getboundslice(lpi->task, MSK_ACC_CON, firstrow, lastrow+1, NULL, lhss, rhss) );
2043 #else
2044  MOSEK_CALL( MSK_getconboundslice(lpi->task, firstrow, lastrow+1, NULL, lhss, rhss) );
2045 #endif
2046 
2047 #if DEBUG_CHECK_DATA > 0
2048  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiGetSides") );
2049 #endif
2050 
2051  return SCIP_OKAY;
2052 }
2053 
2054 /** gets a single coefficient */
2056  SCIP_LPI* lpi, /**< LP interface structure */
2057  int row, /**< row number of coefficient */
2058  int col, /**< column number of coefficient */
2059  SCIP_Real* val /**< pointer to store the value of the coefficient */
2060  )
2061 {
2062  assert(MosekEnv != NULL);
2063  assert(lpi != NULL);
2064  assert(lpi->task != NULL);
2065  assert(val != NULL);
2066 
2067  SCIPdebugMessage("Calling SCIPlpiGetCoef (%d)\n", lpi->lpid);
2068 
2069 #if DEBUG_CHECK_DATA > 0
2070  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiGetCoef") );
2071 #endif
2072 
2073  MOSEK_CALL( MSK_getaij(lpi->task, row, col, val) );
2074 
2075 #if DEBUG_CHECK_DATA > 0
2076  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiGetCoef") );
2077 #endif
2078 
2079  return SCIP_OKAY;
2080 }
2081 
2082 /*
2083  * Solving Methods
2084  */
2085 
2086 
2087 /** gets the internal solution status of the solver */
2088 static
2090  SCIP_LPI* lpi, /**< LP interface structure */
2091  MSKprostae* prosta, /**< pointer to store the problem status */
2092  MSKsolstae* solsta /**< pointer to store the solution status */
2093  )
2094 {
2095  assert(MosekEnv != NULL);
2096  assert(lpi != NULL);
2097  assert(lpi->task != NULL);
2098 
2099  MOSEK_CALL( MSK_getsolutionstatus(lpi->task, lpi->lastsolvetype, prosta, solsta) );
2100 
2101  return SCIP_OKAY;
2102 }
2103 
2104 /** helper method to filter out numerical problems */
2105 static
2106 MSKrescodee filterTRMrescode(
2107  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2108  MSKrescodee* termcode, /**< pointer to store output termination code */
2109  MSKrescodee res /**< input result of call to Mosek function */
2110  )
2111 { /*lint --e{715}*/
2112  assert( termcode != NULL );
2113 
2114 #if ASSERT_ON_NUMERICAL_TROUBLES > 0
2115  if ( res == MSK_RES_TRM_MAX_NUM_SETBACKS || res == MSK_RES_TRM_NUMERICAL_PROBLEM )
2116  {
2117  SCIPmessagePrintWarning(messagehdlr, "Return code %d in [%d]\n", res, optimizecount);
2118  assert(0);
2119  *termcode = res;
2120  return MSK_RES_OK;
2121  }
2122 #endif
2123 
2124  if ( res == MSK_RES_TRM_MAX_ITERATIONS || res == MSK_RES_TRM_MAX_TIME
2125  || res == MSK_RES_TRM_OBJECTIVE_RANGE || res == MSK_RES_TRM_STALL )
2126  {
2127  *termcode = res;
2128  res = MSK_RES_OK;
2129  }
2130  else
2131  *termcode = MSK_RES_OK;
2132 
2133  return res;
2134 }
2135 
2136 /** solve problem with the simplex algorithm */
2137 static
2139  SCIP_LPI* lpi /**< LP interface structure */
2140  )
2141 {
2142  int itercount_primal;
2143  int itercount_dual;
2144  int gotbasicsol;
2145  int presolve;
2146  int maxiter;
2147  MSKprostae prosta;
2148  MSKsolstae solsta;
2149  double pobj, dobj;
2150 
2151  assert(MosekEnv != NULL);
2152  assert(lpi != NULL);
2153  assert(lpi->task != NULL);
2154 
2155  invalidateSolution(lpi);
2156  lpi->lastsolvetype = MSK_SOL_BAS;
2157 
2158  /* store original settings */
2159  MOSEK_CALL( MSK_getintparam(lpi->task, MSK_IPAR_PRESOLVE_USE, &presolve) );
2160  MOSEK_CALL( MSK_getintparam(lpi->task, MSK_IPAR_SIM_MAX_ITERATIONS, &maxiter) );
2161 
2162  /* set some paramters */
2163 #if DEBUG_EASY_REPRODUCE
2164  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_AUTO_SORT_A_BEFORE_OPT, MSK_ON) );
2165  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_HOTSTART_LU, MSK_OFF) );
2166 #else
2167  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_HOTSTART_LU, MSK_ON) );
2168 #endif
2169 
2170  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_AUTO_UPDATE_SOL_INFO, MSK_OFF) );
2171 
2172 #if FORCE_MOSEK_LOG
2173  if( optimizecount > WRITE_ABOVE )
2174  {
2175  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_LOG_SIM, 4) );
2176  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_LOG_SIM_FREQ, 1) );
2177  }
2178  else
2179  {
2180  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_LOG_SIM, 4) );
2181  }
2182 #endif
2183 
2184  MOSEK_CALL( MSK_solutiondef(lpi->task, MSK_SOL_BAS, &gotbasicsol) );
2185 
2186  if( gotbasicsol )
2187  {
2188  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_PRESOLVE_USE, MSK_PRESOLVE_MODE_OFF) );
2189  }
2190  else
2191  {
2192  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_PRESOLVE_USE, MSK_PRESOLVE_MODE_ON) );
2193  }
2194 
2195 #if ALWAYS_SOLVE_PRIMAL_FORM > 0
2196  /* always solve the primal formulation */
2197  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_SOLVE_FORM, MSK_SOLVE_PRIMAL) );
2198 #endif
2199 
2200 #if DEBUG_CHECK_DATA > 0
2201  SCIP_CALL( scip_checkdata(lpi, "SolveWSimplex") );
2202 #endif
2203 
2204  if( gotbasicsol && maxiter < 20000 )
2205  {
2206  /* Since max iter often is set, we switch off restricted pricing */
2207  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_DUAL_RESTRICT_SELECTION, 0) );
2208  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_PRIMAL_RESTRICT_SELECTION, 0) );
2209  }
2210  else
2211  {
2212  /* otherwise use default value */
2213  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_DUAL_RESTRICT_SELECTION, lpi->restrictselectdef) );
2214  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_PRIMAL_RESTRICT_SELECTION, lpi->restrictselectdef) );
2215  }
2216 
2217 #if FORCE_NO_MAXITER > 0
2218  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_MAX_ITERATIONS, 2000000000) );
2219 #endif
2220 
2221 
2222 #if DEBUG_CHECK_DATA > 0
2223  SCIP_CALL( scip_checkdata(lpi, "Begin optimize with simplex") );
2224 #endif
2225 
2226 #if FORCE_MOSEK_SUMMARY > 1
2227  if( optimizecount > WRITE_ABOVE )
2228  {
2229  MOSEK_CALL( MSK_solutionsummary(lpi->task, MSK_STREAM_LOG) );
2230  }
2231 #endif
2232 
2233  /* perform actual optimization */
2234  MOSEK_CALL( filterTRMrescode(lpi->messagehdlr, &lpi->termcode, MSK_optimize(lpi->task)) );
2235 
2236  /* resolve with aggresive scaling if the maximal number of setbacks has been reached */
2237  if( lpi->termcode == MSK_RES_TRM_MAX_NUM_SETBACKS )
2238  {
2239  int scaling;
2240 
2241  MOSEK_CALL( MSK_getintparam(lpi->task, MSK_IPAR_SIM_SCALING, &scaling) );
2242  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_SCALING, MSK_SCALING_AGGRESSIVE) );
2243  MOSEK_CALL( filterTRMrescode(lpi->messagehdlr, &lpi->termcode, MSK_optimize(lpi->task)) );
2244  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_SCALING, scaling) );
2245  }
2246 
2247 #if FORCE_MOSEK_SUMMARY
2248  if( optimizecount > WRITE_ABOVE )
2249  {
2250  MOSEK_CALL( MSK_solutionsummary(lpi->task, MSK_STREAM_LOG) );
2251  }
2252 #else
2253  if( lpi->lpinfo )
2254  {
2255  MOSEK_CALL( MSK_solutionsummary(lpi->task, MSK_STREAM_LOG) );
2256  }
2257 #endif
2258 
2259 #if DEBUG_CHECK_DATA > 0
2260  SCIP_CALL( scip_checkdata(lpi, "End optimize with simplex") );
2261 #endif
2262 
2263  /* set paramaters to their original values */
2264  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_PRESOLVE_USE, presolve) );
2265  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_MAX_ITERATIONS, maxiter) );
2266 
2267  /* obtain iteration count */
2268  MOSEK_CALL( MSK_getintinf(lpi->task, MSK_IINF_SIM_PRIMAL_ITER, &itercount_primal) );
2269  MOSEK_CALL( MSK_getintinf(lpi->task, MSK_IINF_SIM_DUAL_ITER, &itercount_dual) );
2270 
2271  lpi->itercount = itercount_primal + itercount_dual;
2272 
2273  /* get solution information */
2274  MOSEK_CALL( MSK_getprimalobj(lpi->task, MSK_SOL_BAS, &pobj) );
2275  MOSEK_CALL( MSK_getdualobj(lpi->task, MSK_SOL_BAS, &dobj) );
2276 
2277  MOSEK_CALL( MSK_getsolutionstatus(lpi->task, MSK_SOL_BAS, &prosta, &solsta) );
2278 
2279  SCIPdebugMessage("maxiter = %d, termcode = %d, prosta = %d, solsta = %d, objval = %g : %g, iter = %d+%d\n",
2280  maxiter, lpi->termcode, prosta, solsta, pobj, dobj, itercount_primal, itercount_dual);
2281 
2282  switch (solsta)
2283  {
2284  case MSK_SOL_STA_OPTIMAL:
2285  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
2286  case MSK_SOL_STA_PRIM_FEAS:
2287  case MSK_SOL_STA_DUAL_FEAS:
2288  case MSK_SOL_STA_PRIM_INFEAS_CER:
2289  case MSK_SOL_STA_DUAL_INFEAS_CER:
2290  if (lpi->termcode == MSK_RES_OK)
2291  lpi->solved = TRUE;
2292  break;
2293 
2294  case MSK_SOL_STA_UNKNOWN:
2295  /* Mosek seems to have status unknown on the following termination codes */
2296  assert( lpi->termcode == MSK_RES_TRM_MAX_ITERATIONS || lpi->termcode == MSK_RES_TRM_MAX_TIME ||
2297  lpi->termcode == MSK_RES_TRM_OBJECTIVE_RANGE || lpi->termcode == MSK_RES_TRM_STALL ||
2298  lpi->termcode == MSK_RES_OK );
2299 
2300  if ( lpi->termcode != MSK_RES_TRM_MAX_ITERATIONS && lpi->termcode != MSK_RES_TRM_MAX_TIME &&
2301  lpi->termcode != MSK_RES_TRM_OBJECTIVE_RANGE )
2302  {
2303  SCIPmessagePrintWarning(lpi->messagehdlr, "Numerical problem: simplex[%d] returned solsta = %d.\n", optimizecount, solsta);
2304  lpi->termcode = MSK_RES_TRM_NUMERICAL_PROBLEM;
2305 #if ASSERT_ON_WARNING
2306  assert(0);
2307 #endif
2308  }
2309  break;
2310 
2311 #if MSK_VERSION_MAJOR < 9
2312  case MSK_SOL_STA_NEAR_OPTIMAL:
2313  case MSK_SOL_STA_NEAR_PRIM_FEAS:
2314  case MSK_SOL_STA_NEAR_DUAL_FEAS:
2315  case MSK_SOL_STA_NEAR_PRIM_AND_DUAL_FEAS:
2316  case MSK_SOL_STA_NEAR_PRIM_INFEAS_CER:
2317  case MSK_SOL_STA_NEAR_DUAL_INFEAS_CER:
2318 
2319  assert(lpi->termcode == MSK_RES_OK);
2320 
2321  SCIPmessagePrintWarning(lpi->messagehdlr, "Simplex[%d] returned solsta = %d (numerical problem).\n", optimizecount, solsta);
2322  lpi->termcode = MSK_RES_TRM_NUMERICAL_PROBLEM;
2323 #if ASSERT_ON_WARNING
2324  assert(0);
2325 #endif
2326  break;
2327 #endif
2328 
2329  case MSK_SOL_STA_INTEGER_OPTIMAL:
2330 #if MSK_VERSION_MAJOR < 9
2331  case MSK_SOL_STA_NEAR_INTEGER_OPTIMAL:
2332 #endif
2333  default:
2334 #if SHOW_ERRORS
2335  SCIPerrorMessage("Simplex[%d] returned solsta = %d\n", optimizecount, solsta);
2336 #endif
2337 
2338 #if ASSERT_ON_WARNING
2339  assert(0);
2340 #endif
2341 
2342  return SCIP_LPERROR;
2343  } /*lint !e788*/
2344 
2345  switch (prosta)
2346  {
2347  /* already handled above */
2348  case MSK_PRO_STA_PRIM_AND_DUAL_FEAS:
2349  case MSK_PRO_STA_PRIM_FEAS:
2350  case MSK_PRO_STA_DUAL_FEAS:
2351  case MSK_PRO_STA_PRIM_AND_DUAL_INFEAS:
2352  case MSK_PRO_STA_PRIM_INFEAS:
2353  case MSK_PRO_STA_DUAL_INFEAS:
2354  case MSK_PRO_STA_UNKNOWN:
2355  break;
2356 
2357 #if MSK_VERSION_MAJOR < 9
2358  case MSK_PRO_STA_NEAR_PRIM_AND_DUAL_FEAS:
2359  case MSK_PRO_STA_NEAR_PRIM_FEAS:
2360  case MSK_PRO_STA_NEAR_DUAL_FEAS:
2361 #endif
2362  case MSK_PRO_STA_ILL_POSED:
2363  case MSK_PRO_STA_PRIM_INFEAS_OR_UNBOUNDED:
2364  assert(lpi->termcode == MSK_RES_OK);
2365 
2366  SCIPmessagePrintWarning(lpi->messagehdlr, "Simplex[%d] returned prosta = %d\n", optimizecount, prosta);
2367  lpi->termcode = MSK_RES_TRM_NUMERICAL_PROBLEM;
2368  invalidateSolution(lpi);
2369 #if ASSERT_ON_WARNING
2370  assert(0);
2371 #endif
2372  break;
2373 
2374  default:
2375 #if SHOW_ERRORS
2376  SCIPerrorMessage("Simplex[%d] returned prosta = %d\n", optimizecount, prosta);
2377 #endif
2378 
2379 #if ASSERT_ON_WARNING
2380  assert(0);
2381 #endif
2382 
2383  return SCIP_LPERROR;
2384  } /*lint !e788*/
2385 
2386  /* todo: replace numbers by constants, e.g., tolerances */
2387 #if SHOW_RELATIVE_OPTIMAL_GAP
2388  if ( solsta == MSK_SOL_STA_OPTIMAL && fabs(pobj) + fabs(dobj) > 1.0e-6 && fabs(pobj-dobj) > 0.0001*(fabs(pobj) + fabs(dobj)))
2389  {
2390  SCIPerrorMessage("Simplex[%d] returned optimal solution with different objvals %g != %g reldiff %.2g%%\n",
2391  optimizecount, pobj, dobj, 100.0 * fabs(pobj-dobj)/ MAX(fabs(pobj), fabs(dobj))); /*lint !e666*/
2392  }
2393 #endif
2394 
2395  /* The optimizer terminated with an objective value outside the objective range. */
2396  if (lpi->termcode == MSK_RES_TRM_OBJECTIVE_RANGE)
2397  {
2398  if (solsta != MSK_SOL_STA_DUAL_FEAS && solsta != MSK_SOL_STA_OPTIMAL && solsta != MSK_SOL_STA_PRIM_AND_DUAL_FEAS)
2399  {
2400  SCIPerrorMessage("[%d] Terminated on objective range without dual feasible solsta.\n", optimizecount);
2401 
2402  /* solve again with barrier */
2404  }
2405  else
2406  {
2407  scipmskobjsen objsen;
2408  double bound;
2409 
2410  MOSEK_CALL( MSK_getobjsense(lpi->task, &objsen) );
2411 
2412  if (objsen == MSK_OBJECTIVE_SENSE_MINIMIZE)
2413  {
2414  MOSEK_CALL( MSK_getdouparam(lpi->task, MSK_DPAR_UPPER_OBJ_CUT, &bound) );
2415 
2416  if (1.0e-6*(fabs(bound) + fabs(dobj)) < bound-dobj)
2417  {
2418  SCIPerrorMessage("[%d] Terminated on obj range, dobj = %g, bound = %g\n", optimizecount, dobj, bound);
2419 
2421  }
2422  }
2423  else /* objsen == MSK_OBJECTIVE_SENSE_MAX */
2424  {
2425  MOSEK_CALL( MSK_getdouparam(lpi->task, MSK_DPAR_LOWER_OBJ_CUT, &bound) );
2426 
2427  if (1.0e-6*(fabs(bound) + fabs(dobj)) < dobj-bound)
2428  {
2429  SCIPerrorMessage("[%d] Terminated on obj range, dobj = %g, bound = %g\n", optimizecount, dobj, bound);
2430 
2432  }
2433  }
2434  }
2435  }
2436 
2437  /* if the simplex took too many iterations, solve again with barrier */
2438  if (maxiter >= 2000000000)
2439  {
2440  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_MAX_ITERATIONS, maxiter) );
2441 
2442  if (lpi->termcode == MSK_RES_TRM_MAX_ITERATIONS)
2443  {
2444  SCIPmessagePrintWarning(lpi->messagehdlr, "Simplex[%d] failed to terminate in 10000 iterations, switching to interior point\n",
2445  optimizecount);
2446 
2448  }
2449  }
2450 
2451 #if DEBUG_DO_INTPNT_FEAS_CHECK
2452  if (solsta == MSK_SOL_STA_PRIM_INFEAS_CER || solsta == MSK_SOL_STA_DUAL_INFEAS_CER)
2453  {
2454  SCIPdebugMessage("Checking infeasibility[%d]... ", optimizecount);
2455 
2456  SCIP_CALL( SCIPlpiSolveBarrier(lpi, true) );
2457 
2458  MOSEK_CALL( MSK_getsolutionstatus(lpi->task, MSK_SOL_BAS, &prosta, &solsta) );
2459 
2460  if (solsta == MSK_SOL_STA_PRIM_INFEAS_CER || solsta == MSK_SOL_STA_DUAL_INFEAS_CER)
2461  {
2462  SCIPdebugPrintf("ok\n");
2463  }
2464  else
2465  {
2466  SCIPdebugPrintf("wrong [%d] prosta = %d, solsta = %d\n", optimizecount, prosta, solsta);
2467  }
2468  }
2469 #endif
2470 
2471 
2472 #if DEBUG_PRINT_STAT > 0
2473  SCIPdebugMessage("Max iter stat : Count %d branchup = %d branchlo = %d primal %d dual %d\n",
2474  optimizecount, numstrongbranchmaxiterup, numstrongbranchmaxiterdo, numprimalmaxiter, numdualmaxiter);
2475  SCIPdebugMessage("Objcut iter stat : Count %d branchup = %d branchlo = %d primal %d dual %d\n",
2476  optimizecount, numstrongbranchobjup, numstrongbranchobjdo, numprimalobj, numdualobj);
2477 #endif
2478 
2479 #if DEBUG_CHECK_DATA > 0
2480  SCIP_CALL( scip_checkdata(lpi, "SolveWSimplex") );
2481 #endif
2482 
2483  return SCIP_OKAY;
2484 }
2485 
2486 /** calls primal simplex to solve the LP */
2488  SCIP_LPI* lpi /**< LP interface structure */
2489  )
2490 {
2491  assert(MosekEnv != NULL);
2492  assert(lpi != NULL);
2493  assert(lpi->task != NULL);
2494 
2495  optimizecount++;
2496 
2497  SCIPdebugMessage("Calling SCIPlpiSolvePrimal[%d] (%d) ", optimizecount, lpi->lpid);
2498 
2499  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_HOTSTART_LU, MSK_ON) );
2500 
2501  /* Set warmstarting information in MOSEK. We only have status keys (recalculate dual solution without dual superbasics) */
2502  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_HOTSTART, lpi->fromscratch || lpi->clearstate ?
2503  MSK_SIM_HOTSTART_NONE : MSK_SIM_HOTSTART_STATUS_KEYS) );
2504  lpi->clearstate = FALSE;
2505 
2506 #if DEBUG_CHECK_DATA > 0
2507  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiSolvePrimal") );
2508 #endif
2509 
2510  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_OPTIMIZER, MSK_OPTIMIZER_PRIMAL_SIMPLEX) );
2511  lpi->lastalgo = MSK_OPTIMIZER_PRIMAL_SIMPLEX;
2512 
2513 #if WRITE_PRIMAL > 0
2514  if( optimizecount > WRITE_ABOVE )
2515  {
2516  char fname[40];
2517  snprintf(fname, 40, "primal_%d.lp", optimizecount);
2518  SCIPdebugMessage("\nWriting lp %s\n", fname);
2519  /*MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_WRITE_GENERIC_NAMES, MSK_ON) );*/
2520  MSK_writedata(lpi->task, fname);
2521  }
2522 #endif
2523 
2524  SCIP_CALL( SolveWSimplex(lpi) );
2525 
2526 #ifdef SCIP_DISABLED_CODE
2527  /* the following code is unclear: Why should the resolve change anything ?????? */
2528  if ( lpi->termcode == MSK_RES_TRM_OBJECTIVE_RANGE )
2529  {
2530  MSKsolstae solsta;
2531 
2532  MOSEK_CALL( MSK_getsolutionstatus(lpi->task, MSK_SOL_BAS, NULL, &solsta) );
2533 
2534  if( solsta != MSK_SOL_STA_PRIM_FEAS )
2535  {
2536  SCIP_CALL( SolveWSimplex(lpi) );
2537  }
2538  }
2539 #endif
2540 
2541 #if DEBUG_PRINT_STAT > 0
2542  if (lpi->termcode == MSK_RES_TRM_OBJECTIVE_RANGE)
2543  ++numprimalobj;
2544 #endif
2545 
2546 #if DEBUG_PRINT_STAT > 0
2547  if (lpi->termcode == MSK_RES_TRM_MAX_ITERATIONS)
2548  ++numprimalmaxiter;
2549 #endif
2550 
2551 #if DEBUG_CHECK_DATA > 0
2552  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiSolvePrimal") );
2553 #endif
2554 
2555  return SCIP_OKAY;
2556 }
2557 
2558 /** calls dual simplex to solve the LP */
2560  SCIP_LPI* lpi /**< LP interface structure */
2561  )
2562 {
2563  assert(MosekEnv != NULL);
2564  assert(lpi != NULL);
2565  assert(lpi->task != NULL);
2566 
2567  optimizecount++;
2568 
2569  SCIPdebugMessage("Calling SCIPlpiSolveDual[%d] (%d)\n", optimizecount, lpi->lpid);
2570 
2571 /* MSK_IPAR_SIM_INTEGER is removed in Mosek 8.1 */
2572 #if (MSK_VERSION_MAJOR < 8) || (MSK_VERSION_MAJOR == 8 && MSK_VERSION_MINOR == 0)
2573  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_INTEGER, MSK_ON) );
2574 #endif
2575  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_HOTSTART_LU, MSK_ON) );
2576 
2577  /* Set warmstarting information in MOSEK. We only have status keys (recalculate dual solution without dual superbasics) */
2578  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_HOTSTART, (lpi->fromscratch || lpi->clearstate) ?
2579  MSK_SIM_HOTSTART_NONE : MSK_SIM_HOTSTART_STATUS_KEYS) );
2580  lpi->clearstate = FALSE;
2581 
2582  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_OPTIMIZER, MSK_OPTIMIZER_DUAL_SIMPLEX) );
2583  lpi->lastalgo = MSK_OPTIMIZER_DUAL_SIMPLEX;
2584 
2585 #if WRITE_DUAL > 0
2586  if( optimizecount > WRITE_ABOVE )
2587  {
2588  char fname[40];
2589  snprintf(fname,40,"dual_%d.lp", optimizecount);
2590  SCIPdebugMessage("\nWriting lp %s\n", fname);
2591  MSK_writedata(lpi->task, fname);
2592  }
2593 #endif
2594 
2595  SCIP_CALL( SolveWSimplex(lpi) );
2596 
2597 #ifdef SCIP_DISABLED_CODE
2598  /* the following code is unclear: Why should the resolve change anything ?????? */
2599  if ( lpi->termcode == MSK_RES_TRM_OBJECTIVE_RANGE )
2600  {
2601  MSKsolstae solsta;
2602 
2603  MOSEK_CALL( MSK_getsolutionstatus(lpi->task, MSK_SOL_BAS, NULL, &solsta) );
2604 
2605  if( solsta != MSK_SOL_STA_DUAL_FEAS )
2606  {
2607  SCIP_CALL( SolveWSimplex(lpi) );
2608  }
2609  }
2610 #endif
2611 
2612 #if DEBUG_PRINT_STAT > 0
2613  if (lpi->termcode == MSK_RES_TRM_OBJECTIVE_RANGE)
2614  ++numdualobj;
2615 #endif
2616 
2617 #if DEBUG_PRINT_STAT > 0
2618  if (lpi->termcode == MSK_RES_TRM_MAX_ITERATIONS)
2619  ++numdualmaxiter;
2620 #endif
2621 
2622  return SCIP_OKAY;
2623 }
2624 
2625 /** calls barrier or interior point algorithm to solve the LP with crossover to simplex basis */
2627  SCIP_LPI* lpi, /**< LP interface structure */
2628  SCIP_Bool crossover /**< perform crossover */
2629  )
2630 {
2631  MSKprostae prosta;
2632  MSKsolstae solsta;
2633 
2634  assert(MosekEnv != NULL);
2635  assert(lpi != NULL);
2636  assert(lpi->task != NULL);
2637 
2638  optimizecount++;
2639 
2640  invalidateSolution(lpi);
2641  lpi->lastsolvetype = crossover ? MSK_SOL_BAS : MSK_SOL_ITR;
2642 
2643 #if FORCE_MOSEK_LOG
2644  if( optimizecount > WRITE_ABOVE )
2645  {
2646  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_LOG, 4) );
2647  }
2648  else
2649  {
2650  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_LOG, 0) );
2651  }
2652 #endif
2653 
2654  SCIPdebugMessage("Calling SCIPlpiSolveBarrier[%d] (%d) ", optimizecount, lpi->lpid);
2655 
2656 #if DEBUG_CHECK_DATA > 0
2657  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiSolveBarrier") );
2658 #endif
2659 
2660 #ifdef SCIP_DISABLED_CODE
2661  /* The parameter exists in MOSEK, but as of version 8, it is not in use and the interior-point solver is never warmstarted */
2662  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_INTPNT_HOTSTART, (lpi->fromscratch || lpi->clearstate) ?
2663  MSK_SIM_HOTSTART_NONE : MSK_INTPNT_HOTSTART_PRIMAL_DUAL) );
2664 #endif
2665  lpi->clearstate = FALSE;
2666 
2667  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_INTPNT_BASIS, crossover ? MSK_BI_ALWAYS : MSK_BI_NEVER) );
2668  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_OPTIMIZER, MSK_OPTIMIZER_INTPNT) );
2669  lpi->lastalgo = MSK_OPTIMIZER_INTPNT;
2670 
2671 #if MSK_VERSION_MAJOR >= 9
2672  MOSEK_CALL( MSK_putdouparam(lpi->task, MSK_DPAR_INTPNT_CO_TOL_NEAR_REL, NEAR_REL_TOLERANCE) );
2673 #endif
2674 
2675 #if WRITE_INTPNT > 0
2676  if( optimizecount > WRITE_ABOVE )
2677  {
2678  char fname[40];
2679  snprintf(fname,40,"intpnt_%d.lp", optimizecount);
2680  SCIPdebugMessage("\nWriting lp %s\n", fname);
2681  /*MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_WRITE_GENERIC_NAMES, MSK_ON) );*/
2682  MSK_writedata(lpi->task, fname);
2683  }
2684 #endif
2685 
2686  MOSEK_CALL( filterTRMrescode(lpi->messagehdlr, &lpi->termcode, MSK_optimize(lpi->task)) );
2687 
2688 #if DEBUG_PRINT_STAT > 0
2689  if (lpi->termcode == MSK_RES_TRM_MAX_ITERATIONS)
2690  ++numdualmaxiter;
2691 #endif
2692 
2693  MOSEK_CALL( MSK_getintinf(lpi->task, MSK_IINF_INTPNT_ITER, &lpi->itercount) );
2694 
2695  MOSEK_CALL( MSK_getsolutionstatus(lpi->task, lpi->lastsolvetype, &prosta, &solsta) );
2696  SCIPdebugMessage("termcode = %d, prosta = %d, solsta = %d, iter = %d\n",
2697  lpi->termcode, prosta, solsta, lpi->itercount);
2698 
2699  switch (solsta)
2700  {
2701  case MSK_SOL_STA_OPTIMAL:
2702  case MSK_SOL_STA_PRIM_AND_DUAL_FEAS:
2703  case MSK_SOL_STA_PRIM_FEAS:
2704  case MSK_SOL_STA_DUAL_FEAS:
2705  case MSK_SOL_STA_PRIM_INFEAS_CER:
2706  case MSK_SOL_STA_DUAL_INFEAS_CER:
2707  if (lpi->termcode == MSK_RES_OK)
2708  lpi->solved = TRUE;
2709  break;
2710  case MSK_SOL_STA_UNKNOWN:
2711 #if MSK_VERSION_MAJOR < 9
2712  case MSK_SOL_STA_NEAR_OPTIMAL:
2713  case MSK_SOL_STA_NEAR_PRIM_FEAS:
2714  case MSK_SOL_STA_NEAR_DUAL_FEAS:
2715  case MSK_SOL_STA_NEAR_PRIM_AND_DUAL_FEAS:
2716  case MSK_SOL_STA_NEAR_PRIM_INFEAS_CER:
2717  case MSK_SOL_STA_NEAR_DUAL_INFEAS_CER:
2718 #endif
2719  SCIPmessagePrintWarning(lpi->messagehdlr, "Barrier[%d] returned solsta = %d\n", optimizecount, solsta);
2720 
2721  if (lpi->termcode == MSK_RES_OK)
2722  lpi->termcode = MSK_RES_TRM_NUMERICAL_PROBLEM;
2723 
2724 #if ASSERT_ON_WARNING
2725  assert(0);
2726 #endif
2727  break;
2728  case MSK_SOL_STA_INTEGER_OPTIMAL:
2729 #if MSK_VERSION_MAJOR < 9
2730  case MSK_SOL_STA_NEAR_INTEGER_OPTIMAL:
2731 #endif
2732  default:
2733 #if SHOW_ERRORS
2734  SCIPerrorMessage("Barrier[%d] returned solsta = %d\n", optimizecount, solsta);
2735 #endif
2736 
2737 #if ASSERT_ON_WARNING
2738  assert(0);
2739 #endif
2740 
2741  return SCIP_LPERROR;
2742  } /*lint !e788*/
2743 
2744  switch (prosta)
2745  {
2746  case MSK_PRO_STA_PRIM_AND_DUAL_FEAS:
2747  case MSK_PRO_STA_PRIM_FEAS:
2748  case MSK_PRO_STA_DUAL_FEAS:
2749  case MSK_PRO_STA_PRIM_AND_DUAL_INFEAS:
2750  case MSK_PRO_STA_PRIM_INFEAS:
2751  case MSK_PRO_STA_DUAL_INFEAS:
2752  break;
2753  case MSK_PRO_STA_UNKNOWN:
2754 #if MSK_VERSION_MAJOR < 9
2755  case MSK_PRO_STA_NEAR_PRIM_AND_DUAL_FEAS:
2756  case MSK_PRO_STA_NEAR_PRIM_FEAS:
2757  case MSK_PRO_STA_NEAR_DUAL_FEAS:
2758 #endif
2759  case MSK_PRO_STA_ILL_POSED:
2760  case MSK_PRO_STA_PRIM_INFEAS_OR_UNBOUNDED:
2761  SCIPmessagePrintWarning(lpi->messagehdlr, "Barrier[%d] returned prosta = %d\n", optimizecount, prosta);
2762 
2763  if (lpi->termcode == MSK_RES_OK)
2764  lpi->termcode = MSK_RES_TRM_NUMERICAL_PROBLEM;
2765 
2766  invalidateSolution(lpi);
2767 
2768 #if ASSERT_ON_WARNING
2769  assert(0);
2770 #endif
2771  break;
2772  default:
2773 #if SHOW_ERRORS
2774  SCIPerrorMessage("Barrier[%d] returned prosta = %d\n", optimizecount, prosta);
2775 #endif
2776 
2777 #if ASSERT_ON_WARNING
2778  assert(0);
2779 #endif
2780 
2781  return SCIP_LPERROR;
2782  } /*lint !e788*/
2783 
2784 #if DEBUG_CHECK_DATA > 0
2785  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiSolveBarrier") );
2786 #endif
2787 
2788  return SCIP_OKAY;
2789 }
2790 
2791 /** start strong branching - call before any strong branching */
2793  SCIP_LPI* lpi /**< LP interface structure */
2794  )
2795 { /*lint --e{715}*/
2796  assert(MosekEnv != NULL);
2797  assert(lpi != NULL);
2798  assert(lpi->task != NULL);
2799 
2800  /* currently do nothing */
2801  return SCIP_OKAY;
2802 }
2803 
2804 /** end strong branching - call after any strong branching */
2806  SCIP_LPI* lpi /**< LP interface structure */
2807  )
2808 { /* lint --e{715}*/
2809  assert(lpi != NULL);
2810  /* assert(MosekEnv != NULL);
2811  assert(lpi->task != NULL); */
2812 
2813  /* currently do nothing */
2814  return SCIP_OKAY;
2815 }
2816 
2817 /** performs strong branching iterations on all candidates
2818  *
2819  * @note last solve call must have been either simplex or barrier with crossover or base must have been set manually
2820  */
2821 static
2823  SCIP_LPI* lpi, /**< LP interface structure */
2824  int col, /**< column to apply strong branching on */
2825  SCIP_Real psol, /**< current primal solution value of column */
2826  int itlim, /**< iteration limit for strong branchings */
2827  SCIP_Real* down, /**< stores dual bound after branching column down */
2828  SCIP_Real* up, /**< stores dual bound after branching column up */
2829  SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
2830  * otherwise, it can only be used as an estimate value */
2831  SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
2832  * otherwise, it can only be used as an estimate value */
2833  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
2834  )
2835 {
2836  MSKobjsensee objsen;
2837  int olditerlim;
2838  int oldselection;
2839  int oldhotstart;
2840 
2841  double bound;
2842  int ncols;
2843  int nrows;
2844  MSKboundkeye bkx;
2845  double blx;
2846  double bux;
2847  double newub;
2848  double newlb;
2849 
2850  assert(MosekEnv != NULL);
2851  assert(lpi != NULL);
2852  assert(lpi->task != NULL);
2853 
2854  SCIPdebugMessage("Calling SCIPlpiStrongbranch (%d)\n", lpi->lpid);
2855 
2856 #if DEBUG_CHECK_DATA > 0
2857  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiStrongbranch") );
2858 #endif
2859 
2860  if (lpi->termcode != MSK_RES_OK)
2861  {
2862  SCIPmessagePrintWarning(lpi->messagehdlr, "SB Warning: Previous termcode is %d\n", lpi->termcode);
2863  }
2864 
2865  MOSEK_CALL( MSK_getnumvar(lpi->task, &ncols) );
2866  MOSEK_CALL( MSK_getnumcon(lpi->task, &nrows) );
2867 
2868  SCIP_CALL( getbase(lpi, ncols, nrows) );
2869 
2870  MOSEK_CALL( MSK_getobjsense(lpi->task, &objsen) );
2871  MOSEK_CALL( MSK_getintparam(lpi->task, MSK_IPAR_SIM_MAX_ITERATIONS, &olditerlim) );
2872  MOSEK_CALL( MSK_getintparam(lpi->task, MSK_IPAR_SIM_DUAL_SELECTION, &oldselection) );
2873  MOSEK_CALL( MSK_getintparam(lpi->task, MSK_IPAR_SIM_HOTSTART, &oldhotstart) );
2874 
2875  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_MAX_ITERATIONS, itlim) );
2876  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_DUAL_SELECTION, STRONGBRANCH_PRICING) );
2877 
2878  if (objsen == MSK_OBJECTIVE_SENSE_MINIMIZE)
2879  {
2880  MOSEK_CALL( MSK_getdouparam(lpi->task, MSK_DPAR_UPPER_OBJ_CUT, &bound) );
2881  }
2882  else /* objsen == MSK_OBJECTIVE_SENSE_MAX */
2883  {
2884  MOSEK_CALL( MSK_getdouparam(lpi->task, MSK_DPAR_LOWER_OBJ_CUT, &bound) );
2885  }
2886 
2887 #if MSK_VERSION_MAJOR < 9
2888  MOSEK_CALL( MSK_getbound(lpi->task, MSK_ACC_VAR, col, &bkx, &blx, &bux) );
2889 #else
2890  MOSEK_CALL( MSK_getvarbound(lpi->task, col, &bkx, &blx, &bux) );
2891 #endif
2892 
2893  *iter = 0;
2894 
2895  newub = EPSCEIL(psol-1.0, 1e-06);
2896 
2897  if (newub < blx - 0.5) /* infeasible */
2898  {
2899  *down = bound;
2900  *downvalid = TRUE;
2901  }
2902  else
2903  {
2904  MSKboundkeye newbk;
2905 
2906  if (IS_NEGINF(blx))
2907  newbk = MSK_BK_UP;
2908  else if (EPSEQ(blx, newub,1.0e-6))
2909  {
2910  newbk = MSK_BK_FX;
2911  newub = blx;
2912  }
2913  else
2914  newbk = MSK_BK_RA;
2915 
2916 #if MSK_VERSION_MAJOR < 9
2917  MOSEK_CALL( MSK_putbound(lpi->task, MSK_ACC_VAR, col, newbk, blx, newub) );
2918 #else
2919  MOSEK_CALL( MSK_putvarbound(lpi->task, col, newbk, blx, newub) );
2920 #endif
2921 
2922  SCIP_CALL( SCIPlpiSolveDual(lpi) );
2923 
2924  *iter += lpi->itercount;
2925 
2926  if (SCIPlpiIsStable(lpi))
2927  *downvalid = TRUE;
2928  else
2929  *downvalid = FALSE;
2930 
2931  if (SCIPlpiExistsPrimalRay(lpi))
2932  {
2933  SCIPmessagePrintWarning(lpi->messagehdlr, "SB ERROR: Lp [%d] is dual infeasible\n", optimizecount);
2934 
2935  *down = -1e20;
2936  *downvalid = FALSE;
2937  }
2938  else if (SCIPlpiExistsDualRay(lpi))
2939  {
2940  *down = bound;
2941  }
2942  else
2943  {
2944  SCIP_Bool pfeas;
2945  SCIP_Bool dfeas;
2946 
2947  SCIP_CALL( SCIPlpiGetSolFeasibility(lpi, &pfeas, &dfeas) );
2948 
2949  if (!dfeas)
2950  {
2951  SCIPmessagePrintWarning(lpi->messagehdlr, "SB ERROR: Lp [%d] is not dual feasible\n", optimizecount);
2952 
2953  *down = -1e20;
2954  *downvalid = FALSE;
2955  }
2956  else
2957  {
2958  MOSEK_CALL( MSK_getdualobj(lpi->task, lpi->lastsolvetype, down) );
2959  }
2960  }
2961 
2962 #if DEBUG_PRINT_STAT > 0
2963  if (lpi->termcode == MSK_RES_TRM_OBJECTIVE_RANGE)
2964  ++numstrongbranchobjup;
2965 
2966  if (lpi->termcode == MSK_RES_TRM_MAX_ITERATIONS)
2967  ++numstrongbranchmaxiterup;
2968 #endif
2969  }
2970 
2971  /* Reset basis solution before doing the up branch */
2972 #if MSK_VERSION_MAJOR < 9
2973  MOSEK_CALL( MSK_putbound(lpi->task, MSK_ACC_VAR, col, bkx, blx, bux) );
2974 #else
2975  MOSEK_CALL( MSK_putvarbound(lpi->task, col, bkx, blx, bux) );
2976 #endif
2977  SCIP_CALL( setbase(lpi) );
2978 
2979  newlb = EPSFLOOR(psol+1.0, 1e-06);
2980  if (newlb > bux + 0.5) /* infeasible */
2981  {
2982  *up = bound;
2983  *upvalid = TRUE;
2984  }
2985  else
2986  {
2987  MSKboundkeye newbk;
2988 
2989  if (IS_POSINF(bux))
2990  newbk = MSK_BK_LO;
2991  else if (EPSEQ(bux, newlb,1.0e-6))
2992  {
2993  newbk = MSK_BK_FX;
2994  newlb = bux;
2995  }
2996  else
2997  newbk = MSK_BK_RA;
2998 
2999 #if MSK_VERSION_MAJOR < 9
3000  MOSEK_CALL( MSK_putbound(lpi->task, MSK_ACC_VAR, col, newbk, newlb, bux) );
3001 #else
3002  MOSEK_CALL( MSK_putvarbound(lpi->task, col, newbk, newlb, bux) );
3003 #endif
3004  SCIP_CALL( SCIPlpiSolveDual(lpi) );
3005 
3006  *iter += lpi->itercount;
3007 
3008  if (SCIPlpiIsStable(lpi))
3009  *upvalid = TRUE;
3010  else
3011  *upvalid = FALSE;
3012 
3013  if (SCIPlpiExistsPrimalRay(lpi))
3014  {
3015  *up = -1e20;
3016  *upvalid = FALSE;
3017  }
3018  else if (SCIPlpiExistsDualRay(lpi))
3019  {
3020  *up = bound;
3021  }
3022  else
3023  {
3024  SCIP_Bool pfeas;
3025  SCIP_Bool dfeas;
3026 
3027  SCIP_CALL( SCIPlpiGetSolFeasibility(lpi, &pfeas, &dfeas) );
3028 
3029  if (!dfeas)
3030  {
3031  SCIPmessagePrintWarning(lpi->messagehdlr, "SB ERROR: Lp [%d] is not dual feasible\n", optimizecount);
3032 
3033  *up = -1e20;
3034  *upvalid = FALSE;
3035  }
3036  else
3037  {
3038  MOSEK_CALL( MSK_getdualobj(lpi->task, lpi->lastsolvetype, up) );
3039  }
3040  }
3041 
3042 #if DEBUG_PRINT_STAT > 0
3043  if (lpi->termcode == MSK_RES_TRM_OBJECTIVE_RANGE)
3044  ++numstrongbranchobjdo;
3045 
3046  if (lpi->termcode == MSK_RES_TRM_MAX_ITERATIONS)
3047  ++numstrongbranchmaxiterdo;
3048 #endif
3049  }
3050 
3051 #if MSK_VERSION_MAJOR < 9
3052  MOSEK_CALL( MSK_putbound(lpi->task, MSK_ACC_VAR, col, bkx, blx, bux) );
3053 #else
3054  MOSEK_CALL( MSK_putvarbound(lpi->task, col, bkx, blx, bux) );
3055 #endif
3056  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_MAX_ITERATIONS, olditerlim) );
3057  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_DUAL_SELECTION, oldselection) );
3058  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_HOTSTART, oldhotstart) );
3059 
3060  SCIP_CALL( setbase(lpi) );
3061 
3062  invalidateSolution(lpi);
3063 
3064  lpi->termcode = MSK_RES_OK;
3065  lpi->itercount = 0;
3066 
3067 #if DEBUG_CHECK_DATA > 0
3068  SCIP_CALL( scip_checkdata(lpi, "SCIPlpiStrongbranch") );
3069 #endif
3070 
3071  SCIPdebugMessage("End SCIPlpiStrongbranch (%d)\n", lpi->lpid);
3072 
3073  return SCIP_OKAY;
3074 }
3075 
3076 /** performs strong branching iterations on one @b fractional candidate
3077  *
3078  * @note last solve call must have been either simplex or barrier with crossover or base must have been set manually
3079  */
3081  SCIP_LPI* lpi, /**< LP interface structure */
3082  int col, /**< column to apply strong branching on */
3083  SCIP_Real psol, /**< fractional current primal solution value of column */
3084  int itlim, /**< iteration limit for strong branchings */
3085  SCIP_Real* down, /**< stores dual bound after branching column down */
3086  SCIP_Real* up, /**< stores dual bound after branching column up */
3087  SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
3088  * otherwise, it can only be used as an estimate value */
3089  SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
3090  * otherwise, it can only be used as an estimate value */
3091  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3092  )
3093 {
3094  /* pass call on to lpiStrongbranch() */
3095  SCIP_CALL( SCIPlpiStrongbranch(lpi, col, psol, itlim, down, up, downvalid, upvalid, iter) );
3096 
3097  return SCIP_OKAY;
3098 }
3099 
3100 /** performs strong branching iterations on given @b fractional candidates
3101  *
3102  * @note last solve call must have been either simplex or barrier with crossover or base must have been set manually
3103  */
3105  SCIP_LPI* lpi, /**< LP interface structure */
3106  int* cols, /**< columns to apply strong branching on */
3107  int ncols, /**< number of columns */
3108  SCIP_Real* psols, /**< fractional current primal solution values of columns */
3109  int itlim, /**< iteration limit for strong branchings */
3110  SCIP_Real* down, /**< stores dual bounds after branching columns down */
3111  SCIP_Real* up, /**< stores dual bounds after branching columns up */
3112  SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
3113  * otherwise, they can only be used as an estimate values */
3114  SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
3115  * otherwise, they can only be used as an estimate values */
3116  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3117  )
3118 {
3119  int j;
3120 
3121  assert( cols != NULL );
3122  assert( psols != NULL );
3123  assert( down != NULL );
3124  assert( up != NULL );
3125  assert( downvalid != NULL );
3126  assert( upvalid != NULL );
3127  assert( down != NULL );
3128 
3129  if ( iter != NULL )
3130  *iter = 0;
3131 
3132  for (j = 0; j < ncols; ++j)
3133  {
3134  /* pass call on to lpiStrongbranch() */
3135  SCIP_CALL( SCIPlpiStrongbranch(lpi, cols[j], psols[j], itlim, &(down[j]), &(up[j]), &(downvalid[j]), &(upvalid[j]), iter) );
3136  }
3137  return SCIP_OKAY;
3138 }
3139 
3140 /** performs strong branching iterations on one candidate with @b integral value
3141  *
3142  * @note last solve call must have been either simplex or barrier with crossover or base must have been set manually
3143  */
3145  SCIP_LPI* lpi, /**< LP interface structure */
3146  int col, /**< column to apply strong branching on */
3147  SCIP_Real psol, /**< current integral primal solution value of column */
3148  int itlim, /**< iteration limit for strong branchings */
3149  SCIP_Real* down, /**< stores dual bound after branching column down */
3150  SCIP_Real* up, /**< stores dual bound after branching column up */
3151  SCIP_Bool* downvalid, /**< stores whether the returned down value is a valid dual bound;
3152  * otherwise, it can only be used as an estimate value */
3153  SCIP_Bool* upvalid, /**< stores whether the returned up value is a valid dual bound;
3154  * otherwise, it can only be used as an estimate value */
3155  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3156  )
3157 {
3158  /* pass call on to lpiStrongbranch() */
3159  SCIP_CALL( SCIPlpiStrongbranch(lpi, col, psol, itlim, down, up, downvalid, upvalid, iter) );
3160 
3161  return SCIP_OKAY;
3162 }
3163 
3164 /** performs strong branching iterations on given candidates with @b integral values
3165  *
3166  * @note last solve call must have been either simplex or barrier with crossover or base must have been set manually
3167  */
3169  SCIP_LPI* lpi, /**< LP interface structure */
3170  int* cols, /**< columns to apply strong branching on */
3171  int ncols, /**< number of columns */
3172  SCIP_Real* psols, /**< current integral primal solution values of columns */
3173  int itlim, /**< iteration limit for strong branchings */
3174  SCIP_Real* down, /**< stores dual bounds after branching columns down */
3175  SCIP_Real* up, /**< stores dual bounds after branching columns up */
3176  SCIP_Bool* downvalid, /**< stores whether the returned down values are valid dual bounds;
3177  * otherwise, they can only be used as an estimate values */
3178  SCIP_Bool* upvalid, /**< stores whether the returned up values are a valid dual bounds;
3179  * otherwise, they can only be used as an estimate values */
3180  int* iter /**< stores total number of strong branching iterations, or -1; may be NULL */
3181  )
3182 {
3183  int j;
3184 
3185  assert( cols != NULL );
3186  assert( psols != NULL );
3187  assert( down != NULL );
3188  assert( up != NULL );
3189  assert( downvalid != NULL );
3190  assert( upvalid != NULL );
3191  assert( down != NULL );
3192 
3193  if ( iter != NULL )
3194  *iter = 0;
3195 
3196  for (j = 0; j < ncols; ++j)
3197  {
3198  /* pass call on to lpiStrongbranch() */
3199  SCIP_CALL( SCIPlpiStrongbranch(lpi, cols[j], psols[j], itlim, &(down[j]), &(up[j]), &(downvalid[j]), &(upvalid[j]), iter) );
3200  }
3201  return SCIP_OKAY;
3202 }
3203 
3204 
3205 /*
3206  * Solution Information Methods
3207  */
3208 
3209 
3210 /** returns whether a solve method was called after the last modification of the LP */
3212  SCIP_LPI* lpi /**< LP interface structure */
3213  )
3214 {
3215  assert(lpi != NULL);
3216 
3217  return lpi->solved;
3218 }
3219 
3220 /** gets information about primal and dual feasibility of the current LP solution
3221  *
3222  * The feasibility information is with respect to the last solving call and it is only relevant if SCIPlpiWasSolved()
3223  * returns true. If the LP is changed, this information might be invalidated.
3224  *
3225  * Note that @a primalfeasible and @a dualfeasible should only return true if the solver has proved the respective LP to
3226  * be feasible. Thus, the return values should be equal to the values of SCIPlpiIsPrimalFeasible() and
3227  * SCIPlpiIsDualFeasible(), respectively. Note that if feasibility cannot be proved, they should return false (even if
3228  * the problem might actually be feasible).
3229  */
3231  SCIP_LPI* lpi, /**< LP interface structure */
3232  SCIP_Bool* primalfeasible, /**< pointer to store primal feasibility status */
3233  SCIP_Bool* dualfeasible /**< pointer to store dual feasibility status */
3234  )
3235 {
3236  MSKprostae prosta;
3237 
3238  assert( MosekEnv != NULL );
3239  assert( lpi != NULL );
3240  assert( lpi->task != NULL );
3241  assert( primalfeasible != NULL );
3242  assert( dualfeasible != NULL );
3243 
3244  SCIPdebugMessage("Calling SCIPlpiGetSolFeasibility (%d)\n", lpi->lpid);
3245 
3246  MOSEK_CALL( MSK_getsolutionstatus(lpi->task, lpi->lastsolvetype, &prosta, NULL) );
3247 
3248  switch (prosta)
3249  {
3250  case MSK_PRO_STA_PRIM_AND_DUAL_FEAS:
3251  *primalfeasible = TRUE;
3252  *dualfeasible = TRUE;
3253  break;
3254  case MSK_PRO_STA_PRIM_FEAS:
3255  *primalfeasible = TRUE;
3256  *dualfeasible = FALSE;
3257  break;
3258  case MSK_PRO_STA_DUAL_FEAS:
3259  *primalfeasible = FALSE;
3260  *dualfeasible = TRUE;
3261  break;
3262  case MSK_PRO_STA_DUAL_INFEAS:
3263  /* assume that we have a primal solution if we used the primal simplex */
3264  *primalfeasible = (lpi->lastalgo == MSK_OPTIMIZER_PRIMAL_SIMPLEX);
3265  *dualfeasible = FALSE;
3266  break;
3267  case MSK_PRO_STA_UNKNOWN:
3268  case MSK_PRO_STA_PRIM_INFEAS:
3269  case MSK_PRO_STA_PRIM_AND_DUAL_INFEAS:
3270  case MSK_PRO_STA_ILL_POSED:
3271 #if MSK_VERSION_MAJOR < 9
3272  case MSK_PRO_STA_NEAR_PRIM_AND_DUAL_FEAS:
3273  case MSK_PRO_STA_NEAR_PRIM_FEAS:
3274  case MSK_PRO_STA_NEAR_DUAL_FEAS:
3275 #endif
3276  case MSK_PRO_STA_PRIM_INFEAS_OR_UNBOUNDED:
3277  *primalfeasible = FALSE;
3278  *dualfeasible = FALSE;
3279  break;
3280  default:
3281  return SCIP_LPERROR;
3282  } /*lint !e788*/
3283 
3284  return SCIP_OKAY;
3285 }
3286 
3287 /** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point);
3288  * this does not necessarily mean, that the solver knows and can return the primal ray
3289  */
3291  SCIP_LPI* lpi /**< LP interface structure */
3292  )
3293 {
3294  MSKprostae prosta;
3295  MSKsolstae solsta;
3296 
3297  assert(MosekEnv != NULL);
3298  assert(lpi != NULL);
3299  assert(lpi->task != NULL);
3300 
3301  SCIPdebugMessage("Calling SCIPlpiExistsPrimalRay (%d)\n", lpi->lpid);
3302 
3303  SCIP_ABORT_FALSE( getSolutionStatus(lpi, &prosta, &solsta) );
3304 
3305  return ( solsta == MSK_SOL_STA_DUAL_INFEAS_CER
3306  || prosta == MSK_PRO_STA_DUAL_INFEAS
3307  || prosta == MSK_PRO_STA_PRIM_AND_DUAL_INFEAS );
3308 }
3309 
3310 /** returns TRUE iff LP is proven to have a primal unbounded ray (but not necessary a primal feasible point),
3311  * and the solver knows and can return the primal ray
3312  */
3314  SCIP_LPI* lpi /**< LP interface structure */
3315  )
3316 {
3317  MSKsolstae solsta;
3318 
3319  assert(MosekEnv != NULL);
3320  assert(lpi != NULL);
3321  assert(lpi->task != NULL);
3322 
3323  SCIPdebugMessage("Calling SCIPlpiHasPrimalRay (%d)\n", lpi->lpid);
3324 
3325  SCIP_ABORT_FALSE( getSolutionStatus(lpi, NULL, &solsta) );
3326 
3327  return (solsta == MSK_SOL_STA_DUAL_INFEAS_CER);
3328 }
3329 
3330 /** returns TRUE iff LP is proven to be primal unbounded */
3332  SCIP_LPI* lpi /**< LP interface structure */
3333  )
3334 { /*lint --e{715}*/
3335  MSKsolstae solsta;
3336 
3337  assert(MosekEnv != NULL);
3338  assert(lpi != NULL);
3339  assert(lpi->task != NULL);
3340 
3341  SCIP_ABORT_FALSE( getSolutionStatus(lpi, NULL, &solsta) );
3342 
3343  /* assume primal solution and ray is available if we used the primal simplex and the dual is proven to be infeasible */
3344  return (solsta == MSK_SOL_STA_DUAL_INFEAS_CER && lpi->lastalgo == MSK_OPTIMIZER_PRIMAL_SIMPLEX);
3345 }
3346 
3347 /** returns TRUE iff LP is proven to be primal infeasible */
3349  SCIP_LPI* lpi /**< LP interface structure */
3350  )
3351 {
3352  assert(MosekEnv != NULL);
3353  assert(lpi != NULL);
3354  assert(lpi->task != NULL);
3355 
3356  return SCIPlpiExistsDualRay(lpi);
3357 }
3358 
3359 /** returns TRUE iff LP is proven to be primal feasible */
3361  SCIP_LPI* lpi /**< LP interface structure */
3362  )
3363 {
3364  MSKprostae prosta;
3365 
3366  assert(MosekEnv != NULL);
3367  assert(lpi != NULL);
3368  assert(lpi->task != NULL);
3369 
3370  SCIPdebugMessage("Calling SCIPlpiIsPrimalFeasible (%d)\n", lpi->lpid);
3371 
3372  SCIP_ABORT_FALSE( getSolutionStatus(lpi, &prosta, NULL) );
3373 
3374  return (prosta == MSK_PRO_STA_PRIM_FEAS || prosta == MSK_PRO_STA_PRIM_AND_DUAL_FEAS || (prosta == MSK_PRO_STA_DUAL_INFEAS && lpi->lastalgo == MSK_OPTIMIZER_PRIMAL_SIMPLEX));
3375 }
3376 
3377 /** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point);
3378  * this does not necessarily mean, that the solver knows and can return the dual ray
3379  */
3381  SCIP_LPI* lpi /**< LP interface structure */
3382  )
3383 {
3384  MSKprostae prosta;
3385  MSKsolstae solsta;
3386 
3387  assert(MosekEnv != NULL);
3388  assert(lpi != NULL);
3389  assert(lpi->task != NULL);
3390 
3391  SCIPdebugMessage("Calling SCIPlpiExistsDualRay (%d)\n", lpi->lpid);
3392 
3393  SCIP_ABORT_FALSE( getSolutionStatus(lpi, &prosta, &solsta) );
3394 
3395  return ( solsta == MSK_SOL_STA_PRIM_INFEAS_CER
3396  || prosta == MSK_PRO_STA_PRIM_INFEAS
3397  || prosta == MSK_PRO_STA_PRIM_AND_DUAL_INFEAS );
3398 }
3399 
3400 /** returns TRUE iff LP is proven to have a dual unbounded ray (but not necessary a dual feasible point),
3401  * and the solver knows and can return the dual ray
3402  */
3404  SCIP_LPI* lpi /**< LP interface structure */
3405  )
3406 {
3407  MSKsolstae solsta;
3408 
3409  assert(MosekEnv != NULL);
3410  assert(lpi != NULL);
3411  assert(lpi->task != NULL);
3412 
3413  SCIPdebugMessage("Calling SCIPlpiHasDualRay (%d)\n", lpi->lpid);
3414 
3415  SCIP_ABORT_FALSE( getSolutionStatus(lpi, NULL, &solsta) );
3416 
3417  return (solsta == MSK_SOL_STA_PRIM_INFEAS_CER);
3418 }
3419 
3420 /** returns TRUE iff LP is proven to be dual unbounded */
3422  SCIP_LPI* lpi /**< LP interface structure */
3423  )
3424 { /*lint --e{715}*/
3425  assert(MosekEnv != NULL);
3426  assert(lpi != NULL);
3427  assert(lpi->task != NULL);
3428 
3429  return FALSE;
3430 }
3431 
3432 /** returns TRUE iff LP is proven to be dual infeasible */
3434  SCIP_LPI* lpi /**< LP interface structure */
3435  )
3436 {
3437  assert(MosekEnv != NULL);
3438  assert(lpi != NULL);
3439  assert(lpi->task != NULL);
3440 
3441  return SCIPlpiExistsPrimalRay(lpi);
3442 }
3443 
3444 /** returns TRUE iff LP is proven to be dual feasible */
3446  SCIP_LPI* lpi /**< LP interface structure */
3447  )
3448 {
3449  MSKprostae prosta;
3450 
3451  assert(MosekEnv != NULL);
3452  assert(lpi != NULL);
3453  assert(lpi->task != NULL);
3454 
3455  SCIPdebugMessage("Calling SCIPlpiIsDualFeasible (%d)\n", lpi->lpid);
3456 
3457  SCIP_ABORT_FALSE( getSolutionStatus(lpi, &prosta, NULL) );
3458 
3459  return (prosta == MSK_PRO_STA_DUAL_FEAS || prosta == MSK_PRO_STA_PRIM_AND_DUAL_FEAS);
3460 }
3461 
3462 /** returns TRUE iff LP was solved to optimality */
3464  SCIP_LPI* lpi /**< LP interface structure */
3465  )
3466 {
3467  MSKsolstae solsta;
3468 
3469  assert(MosekEnv != NULL);
3470  assert(lpi != NULL);
3471  assert(lpi->task != NULL);
3472 
3473  SCIPdebugMessage("Calling SCIPlpiIsOptimal (%d)\n", lpi->lpid);
3474 
3475  SCIP_ABORT_FALSE( getSolutionStatus(lpi, NULL, &solsta) );
3476 
3477  return (solsta == MSK_SOL_STA_OPTIMAL);
3478 }
3479 
3480 /** returns TRUE iff current LP solution is stable
3481  *
3482  * This function should return true if the solution is reliable, i.e., feasible and optimal (or proven
3483  * infeasible/unbounded) with respect to the original problem. The optimality status might be with respect to a scaled
3484  * version of the problem, but the solution might not be feasible to the unscaled original problem; in this case,
3485  * SCIPlpiIsStable() should return false.
3486  */
3488  SCIP_LPI* lpi /**< LP interface structure */
3489  )
3490 {
3491  assert(MosekEnv != NULL);
3492  assert(lpi != NULL);
3493  assert(lpi->task != NULL);
3494 
3495  return ( lpi->termcode == MSK_RES_OK
3496  || lpi->termcode == MSK_RES_TRM_MAX_ITERATIONS
3497  || lpi->termcode == MSK_RES_TRM_MAX_TIME
3498  || lpi->termcode == MSK_RES_TRM_OBJECTIVE_RANGE );
3499 }
3500 
3501 /** returns TRUE iff the objective limit was reached */
3503  SCIP_LPI* lpi /**< LP interface structure */
3504  )
3505 {
3506  assert(MosekEnv != NULL);
3507  assert(lpi != NULL);
3508  assert(lpi->task != NULL);
3509 
3510  return ( lpi->termcode == MSK_RES_TRM_OBJECTIVE_RANGE );
3511 }
3512 
3513 /** returns TRUE iff the iteration limit was reached */
3515  SCIP_LPI* lpi /**< LP interface structure */
3516  )
3517 {
3518  assert(MosekEnv != NULL);
3519  assert(lpi != NULL);
3520  assert(lpi->task != NULL);
3521 
3522  return ( lpi->termcode == MSK_RES_TRM_MAX_ITERATIONS );
3523 }
3524 
3525 /** returns TRUE iff the time limit was reached */
3527  SCIP_LPI* lpi /**< LP interface structure */
3528  )
3529 {
3530  assert(MosekEnv != NULL);
3531  assert(lpi != NULL);
3532  assert(lpi->task != NULL);
3533 
3534  return ( lpi->termcode == MSK_RES_TRM_MAX_TIME );
3535 }
3536 
3537 /** returns the internal solution status of the solver */
3539  SCIP_LPI* lpi /**< LP interface structure */
3540  )
3541 {
3542  MSKsolstae solsta;
3543  SCIP_RETCODE retcode;
3544 
3545  assert(MosekEnv != NULL);
3546  assert(lpi != NULL);
3547  assert(lpi->task != NULL);
3548 
3549  SCIPdebugMessage("Calling SCIPlpiGetInternalStatus (%d)\n", lpi->lpid);
3550 
3551  retcode = getSolutionStatus(lpi, NULL, &solsta);
3552  if ( retcode != SCIP_OKAY )
3553  return 0;
3554 
3555  return (int) solsta;
3556 }
3557 
3558 /** tries to reset the internal status of the LP solver in order to ignore an instability of the last solving call */
3560  SCIP_LPI* lpi, /**< LP interface structure */
3561  SCIP_Bool* success /**< pointer to store, whether the instability could be ignored */
3562  )
3563 {
3564  assert(MosekEnv != NULL);
3565  assert(lpi != NULL);
3566  assert(lpi->task != NULL);
3567  assert(success != NULL);
3568 
3569  SCIPdebugMessage("Calling SCIPlpiIgnoreInstability (%d)\n", lpi->lpid);
3570 
3571  *success = FALSE;
3572 
3573  return SCIP_OKAY;
3574 }
3575 
3576 /** gets objective value of solution */
3578  SCIP_LPI* lpi, /**< LP interface structure */
3579  SCIP_Real* objval /**< stores the objective value */
3580  )
3581 {
3582  assert(MosekEnv != NULL);
3583  assert(lpi != NULL);
3584  assert(lpi->task != NULL);
3585  assert(objval != NULL);
3586 
3587  SCIPdebugMessage("Calling SCIPlpiGetObjval (%d)\n", lpi->lpid);
3588 
3589  MOSEK_CALL( MSK_getprimalobj(lpi->task, lpi->lastsolvetype, objval) );
3590 
3591  /* TODO: tjek lighed med dual objektiv i de fleste tilfaelde. */
3592 
3593  return SCIP_OKAY;
3594 }
3595 
3596 /** gets primal and dual solution vectors for feasible LPs
3597  *
3598  * Before calling this function, the caller must ensure that the LP has been solved to optimality, i.e., that
3599  * SCIPlpiIsOptimal() returns true.
3600  */
3602  SCIP_LPI* lpi, /**< LP interface structure */
3603  SCIP_Real* objval, /**< stores the objective value, may be NULL if not needed */
3604  SCIP_Real* primsol, /**< primal solution vector, may be NULL if not needed */
3605  SCIP_Real* dualsol, /**< dual solution vector, may be NULL if not needed */
3606  SCIP_Real* activity, /**< row activity vector, may be NULL if not needed */
3607  SCIP_Real* redcost /**< reduced cost vector, may be NULL if not needed */
3608  )
3609 {
3610  MSKsolstae solsta;
3611  double* sux = NULL;
3612  int ncols = 0;
3613  int i;
3614 
3615  assert(MosekEnv != NULL);
3616  assert(lpi != NULL);
3617  assert(lpi->task != NULL);
3618 
3619  SCIPdebugMessage("Calling SCIPlpiGetSol (%d)\n", lpi->lpid);
3620 
3621  if ( objval != NULL )
3622  {
3623  MOSEK_CALL( MSK_getprimalobj(lpi->task, lpi->lastsolvetype, objval) );
3624  }
3625 
3626  if( redcost )
3627  {
3628  MOSEK_CALL( MSK_getnumvar(lpi->task, &ncols) );
3629  SCIP_ALLOC( BMSallocMemoryArray(&sux, ncols) );
3630  }
3631 
3632  if ( primsol != NULL && lpi->lastalgo == MSK_OPTIMIZER_PRIMAL_SIMPLEX )
3633  {
3634  /* If the status shows that the dual is infeasible this is due to the primal being unbounded. In this case, we need
3635  * to compute a feasible solution by setting the objective to 0.
3636  */
3637  MOSEK_CALL( MSK_getsolutionstatus(lpi->task, MSK_SOL_BAS, NULL, &solsta) );
3638  if ( solsta == MSK_SOL_STA_DUAL_INFEAS_CER )
3639  {
3640  SCIP_Real* objcoefs;
3641  int j;
3642 
3643  MOSEK_CALL( MSK_getnumvar(lpi->task, &ncols) );
3644  SCIP_ALLOC( BMSallocMemoryArray(&objcoefs, ncols) );
3645 
3646  /* store old objective coefficients and set them to 0 */
3647  for (j = 0; j < ncols; ++j)
3648  {
3649  MOSEK_CALL( MSK_getcj(lpi->task, j, &objcoefs[j]) );
3650  MOSEK_CALL( MSK_putcj(lpi->task, j, 0.0) );
3651  }
3652 
3653  /* solve problem again */
3654  SCIP_CALL( SolveWSimplex(lpi) );
3655 
3656  /* At this point we assume that the problem is feasible, since we previously ran the primal simplex and it
3657  * produced a ray.
3658  */
3659 
3660  /* get primal solution */
3661  MOSEK_CALL( MSK_getsolution(lpi->task, lpi->lastsolvetype, NULL, NULL, NULL, NULL, NULL, activity,
3662  primsol, NULL, NULL, NULL, NULL, NULL, NULL) );
3663 
3664  /* restore objective */
3665  MOSEK_CALL( MSK_putcslice(lpi->task, 0, ncols, objcoefs) );
3666 
3667  /* resolve to restore original status */
3668  SCIP_CALL( SolveWSimplex(lpi) );
3669 
3670  BMSfreeMemoryArray(&objcoefs);
3671  }
3672  else
3673  {
3674  MOSEK_CALL( MSK_getsolution(lpi->task, lpi->lastsolvetype, NULL, NULL, NULL, NULL, NULL, activity,
3675  primsol, dualsol, NULL, NULL, redcost, sux, NULL) );
3676  }
3677  }
3678  else
3679  {
3680  MOSEK_CALL( MSK_getsolution(lpi->task, lpi->lastsolvetype, NULL, NULL, NULL, NULL, NULL, activity,
3681  primsol, dualsol, NULL, NULL, redcost, sux, NULL) );
3682  }
3683 
3684  /* the reduced costs are given by the difference of the slx and sux variables (third and second to last parameters) */
3685  if( redcost )
3686  {
3687  for( i = 0; i < ncols; i++ )
3688  {
3689  assert(sux != NULL);
3690  redcost[i] -= sux[i];
3691  }
3692  BMSfreeMemoryArray(&sux);
3693  }
3694 
3695  return SCIP_OKAY;
3696 }
3697 
3698 /** gets primal ray for unbounded LPs */
3700  SCIP_LPI* lpi, /**< LP interface structure */
3701  SCIP_Real* ray /**< primal ray */
3702  )
3703 {
3704  assert(MosekEnv != NULL);
3705  assert(lpi != NULL);
3706  assert(lpi->task != NULL);
3707  assert(ray != NULL);
3708 
3709  SCIPdebugMessage("Calling SCIPlpiGetPrimalRay (%d)\n", lpi->lpid);
3710 
3711  MOSEK_CALL( MSK_getsolution(lpi->task, lpi->lastsolvetype, NULL, NULL, NULL, NULL, NULL, NULL, ray,
3712  NULL, NULL, NULL, NULL, NULL, NULL) );
3713 
3714  return SCIP_OKAY;
3715 }
3716 
3717 /** gets dual Farkas proof for infeasibility */
3719  SCIP_LPI* lpi, /**< LP interface structure */
3720  SCIP_Real* dualfarkas /**< dual Farkas row multipliers */
3721  )
3722 {
3723  assert(MosekEnv != NULL);
3724  assert(lpi != NULL);
3725  assert(lpi->task != NULL);
3726  assert(dualfarkas != NULL);
3727 
3728  SCIPdebugMessage("Calling SCIPlpiGetDualfarkas (%d)\n", lpi->lpid);
3729 
3730  MOSEK_CALL( MSK_getsolution(lpi->task, lpi->lastsolvetype, NULL, NULL, NULL, NULL, NULL, NULL, NULL, dualfarkas,
3731  NULL, NULL, NULL, NULL, NULL) );
3732 
3733  return SCIP_OKAY;
3734 }
3735 
3736 /** gets the number of LP iterations of the last solve call */
3738  SCIP_LPI* lpi, /**< LP interface structure */
3739  int* iterations /**< pointer to store the number of iterations of the last solve call */
3740  )
3741 {
3742  assert(MosekEnv != NULL);
3743  assert(lpi != NULL);
3744  assert(lpi->task != NULL);
3745  assert(iterations != NULL);
3746 
3747  SCIPdebugMessage("Calling SCIPlpiGetIterations (%d)\n", lpi->lpid);
3748 
3749  *iterations = lpi->itercount;
3750 
3751  return SCIP_OKAY;
3752 }
3753 
3754 /** gets information about the quality of an LP solution
3755  *
3756  * Such information is usually only available, if also a (maybe not optimal) solution is available.
3757  * The LPI should return SCIP_INVALID for @p quality, if the requested quantity is not available.
3758  */
3760  SCIP_LPI* lpi, /**< LP interface structure */
3761  SCIP_LPSOLQUALITY qualityindicator, /**< indicates which quality should be returned */
3762  SCIP_Real* quality /**< pointer to store quality number */
3763  )
3764 { /*lint --e{715}*/
3765  assert(MosekEnv != NULL);
3766  assert(lpi != NULL);
3767  assert(lpi->task != NULL);
3768  assert(quality != NULL);
3769 
3770  *quality = SCIP_INVALID;
3771 
3772  return SCIP_OKAY;
3773 }
3774 
3775 /** handle singular basis */
3776 static
3778  SCIP_LPI* lpi, /**< LP interface structure */
3779  int* basis, /**< array of basis indices */
3780  MSKrescodee res /**< result */
3781  )
3782 {
3783  if (res == MSK_RES_ERR_BASIS_SINGULAR)
3784  {
3785  SCIP_CALL( SCIPlpiSolvePrimal(lpi) );
3786 
3787  MOSEK_CALL( MSK_initbasissolve(lpi->task, basis) );
3788  }
3789  else
3790  {
3791  MOSEK_CALL( res );
3792  }
3793 
3794  return SCIP_OKAY;
3795 }
3796 
3797 
3798 /*
3799  * LP Basis Methods
3800  */
3801 
3802 /** convert Mosek basis status to SCIP basis status
3803  *
3804  * @note last solve call must have been either simplex or barrier with crossover or base must have been set manually
3805  */
3806 static
3808  SCIP_LPI* lpi, /**< LP interface structure */
3809  SCIP_Bool iscon, /**< whether constraints/variables are considered */
3810  MSKstakeye* sk, /**< status array of Mosek */
3811  int n, /**< size */
3812  int* stat /**< status array of SCIP */
3813  )
3814 {
3815  int i;
3816 
3817  assert(lpi->lastsolvetype == MSK_SOL_BAS);
3818 
3819  for( i = 0; i < n; i++ )
3820  {
3821  double sl;
3822  double su;
3823 
3824  switch (sk[i])
3825  {
3826  case MSK_SK_BAS:
3827  stat[i] = (int)SCIP_BASESTAT_BASIC;
3828  break;
3829  case MSK_SK_SUPBAS:
3830  stat[i] = (int)SCIP_BASESTAT_ZERO;
3831  break;
3832  case MSK_SK_FIX:
3833 #if MSK_VERSION_MAJOR < 9
3834  MOSEK_CALL( MSK_getsolutioni(lpi->task, iscon ? MSK_ACC_CON : MSK_ACC_VAR, i, MSK_SOL_BAS, NULL, NULL, &sl, &su, NULL) );
3835 #else
3836  if( iscon )
3837  {
3838  MOSEK_CALL( MSK_getslcslice(lpi->task, MSK_SOL_BAS, i, i+1, &sl ) );
3839  MOSEK_CALL( MSK_getsucslice(lpi->task, MSK_SOL_BAS, i, i+1, &su ) );
3840  }
3841  else
3842  {
3843  MOSEK_CALL( MSK_getslxslice(lpi->task, MSK_SOL_BAS, i, i+1, &sl ) );
3844  MOSEK_CALL( MSK_getsuxslice(lpi->task, MSK_SOL_BAS, i, i+1, &su ) );
3845  }
3846 #endif
3847 
3848  if (sl < su) /* Negative reduced cost */
3849  stat[i] = (int)SCIP_BASESTAT_UPPER;
3850  else
3851  stat[i] = (int)SCIP_BASESTAT_LOWER;
3852  break;
3853  case MSK_SK_UNK:
3854  stat[i] = (int)SCIP_BASESTAT_LOWER;
3855  break;
3856  case MSK_SK_INF:
3857  stat[i] = (int)SCIP_BASESTAT_LOWER;
3858  break;
3859  case MSK_SK_LOW:
3860  stat[i] = (int)SCIP_BASESTAT_LOWER;
3861  break;
3862  case MSK_SK_UPR:
3863  stat[i] = (int)SCIP_BASESTAT_UPPER;
3864  break;
3865  case MSK_SK_END:
3866  break;
3867  default:
3868  SCIPABORT();
3869  return SCIP_INVALIDDATA; /*lint !e527*/
3870  } /*lint !e788*/
3871  }
3872 
3873  return SCIP_OKAY;
3874 }
3875 
3876 /** convert Mosek to SCIP basis status - slack variables
3877  *
3878  * @note last solve call must have been either simplex or barrier with crossover or base must have been set manually
3879  */
3880 static
3882  SCIP_LPI* lpi, /**< LP interface structure */
3883  SCIP_Bool iscon, /**< whether constraints or variables are accessed */
3884  MSKstakeye* sk, /**< Mosek basis status */
3885  int m, /**< size */
3886  int* stat /**< status array */
3887  )
3888 {
3889  int i;
3890 
3891  assert(lpi->lastsolvetype == MSK_SOL_BAS);
3892 
3893  for( i = 0; i < m; i++ )
3894  {
3895  double sl;
3896  double su;
3897  switch (sk[i])
3898  {
3899  case MSK_SK_BAS:
3900  stat[i] = (int)SCIP_BASESTAT_BASIC;
3901  break;
3902  case MSK_SK_SUPBAS:
3903  stat[i] = (int)SCIP_BASESTAT_ZERO;
3904  break;
3905  case MSK_SK_FIX:
3906 #if MSK_VERSION_MAJOR < 9
3907  MOSEK_CALL( MSK_getsolutioni(lpi->task, iscon ? MSK_ACC_CON : MSK_ACC_VAR, i, MSK_SOL_BAS, NULL, NULL, &sl, &su, NULL) );
3908 #else
3909  if( iscon )
3910  {
3911  MOSEK_CALL( MSK_getslcslice(lpi->task, MSK_SOL_BAS, i, i+1, &sl ) );
3912  MOSEK_CALL( MSK_getsucslice(lpi->task, MSK_SOL_BAS, i, i+1, &su ) );
3913  }
3914  else
3915  {
3916  MOSEK_CALL( MSK_getslxslice(lpi->task, MSK_SOL_BAS, i, i+1, &sl ) );
3917  MOSEK_CALL( MSK_getsuxslice(lpi->task, MSK_SOL_BAS, i, i+1, &su ) );
3918  }
3919 #endif
3920 
3921  if (sl < su) /* Negative reduced cost */
3922  stat[i] = (int)SCIP_BASESTAT_UPPER;
3923  else
3924  stat[i] = (int)SCIP_BASESTAT_LOWER;
3925  break;
3926  case MSK_SK_UNK:
3927  case MSK_SK_INF:
3928  case MSK_SK_UPR:
3929  stat[i] = (int)SCIP_BASESTAT_UPPER;
3930  break;
3931  case MSK_SK_LOW:
3932  stat[i] = (int)SCIP_BASESTAT_LOWER;
3933  break;
3934  case MSK_SK_END:
3935  default:
3936  SCIPABORT();
3937  return SCIP_INVALIDDATA; /*lint !e527*/
3938  } /*lint !e788*/
3939  }
3940 
3941  return SCIP_OKAY;
3942 }
3943 
3944 /** convert SCIP to Mosek basis status */
3945 static
3947  const int* stat, /**< SCIP status array */
3948  int n, /**< size of array */
3949  MSKstakeye* resstat /**< resulting Mosek status array */
3950  )
3951 {
3952  int i;
3953  for( i = 0; i < n; i++ )
3954  {
3955  switch (stat[i])
3956  {
3957  case SCIP_BASESTAT_LOWER:
3958  resstat[i] = MSK_SK_LOW;
3959  break;
3960  case SCIP_BASESTAT_BASIC:
3961  resstat[i] = MSK_SK_BAS;
3962  break;
3963  case SCIP_BASESTAT_UPPER:
3964  resstat[i] = MSK_SK_UPR;
3965  break;
3966  case SCIP_BASESTAT_ZERO:
3967  resstat[i] = MSK_SK_SUPBAS;
3968  break;
3969  default:
3970  SCIPABORT();
3971  }
3972  }
3973 }
3974 
3975 /** convert SCIP to Mosek basis status - slack variables */
3976 static
3978  const int* stat, /**< SCIP status array */
3979  int n, /**< size of array */
3980  MSKstakeye* resstat /**< resulting Mosek status array */
3981  )
3982 {
3983  /* slacks are stored as -1 in Mosek, i.e., bounds are reversed compared to SCIP */
3984  int i;
3985 
3986  for( i = 0; i < n; i++ )
3987  {
3988  switch (stat[i])
3989  {
3990  case SCIP_BASESTAT_LOWER:
3991  resstat[i] = MSK_SK_UPR; /* Reversed */
3992  break;
3993  case SCIP_BASESTAT_BASIC:
3994  resstat[i] = MSK_SK_BAS;
3995  break;
3996  case SCIP_BASESTAT_UPPER:
3997  resstat[i] = MSK_SK_LOW; /* Reversed */
3998  break;
3999  case SCIP_BASESTAT_ZERO:
4000  resstat[i] = MSK_SK_SUPBAS;
4001  break;
4002  default:
4003  SCIPABORT();
4004  }
4005  }
4006 }
4007 
4008 /** gets current basis status for columns and rows; arrays must be large enough to store the basis status
4009  *
4010  * @note last solve call must have been either simplex or barrier with crossover or base must have been set manually
4011  */
4013  SCIP_LPI* lpi, /**< LP interface structure */
4014  int* cstat, /**< array to store column basis status, or NULL */
4015  int* rstat /**< array to store row basis status, or NULL */
4016  )
4017 {
4018  int nrows;
4019  int ncols;
4020 
4021  assert(MosekEnv != NULL);
4022  assert(lpi != NULL);
4023  assert(lpi->task != NULL);
4024  assert(lpi->lastsolvetype == MSK_SOL_BAS);
4025 
4026  SCIPdebugMessage("Calling SCIPlpiGetBase (%d)\n", lpi->lpid);
4027 
4028  MOSEK_CALL( MSK_getnumvar(lpi->task, &ncols) );
4029  MOSEK_CALL( MSK_getnumcon(lpi->task, &nrows) );
4030 
4031  SCIP_CALL( getbase(lpi, ncols, nrows) );
4032 
4033  if (cstat)
4034  {
4035  SCIP_CALL( convertstat_mosek2scip(lpi, FALSE, lpi->skx, ncols, cstat) );
4036  }
4037 
4038  if (rstat)
4039  {
4040  SCIP_CALL( convertstat_mosek2scip_slack(lpi, TRUE, lpi->skc, nrows, rstat) );
4041  }
4042 
4043  return SCIP_OKAY;
4044 }
4045 
4046 /** sets current basis status for columns and rows */
4048  SCIP_LPI* lpi, /**< LP interface structure */
4049  const int* cstat, /**< array with column basis status */
4050  const int* rstat /**< array with row basis status */
4051  )
4052 {
4053  int nrows;
4054  int ncols;
4055 
4056  assert(MosekEnv != NULL);
4057  assert(lpi != NULL);
4058  assert(lpi->task != NULL);
4059 
4060  SCIP_CALL( SCIPlpiGetNRows(lpi, &nrows) );
4061  SCIP_CALL( SCIPlpiGetNCols(lpi, &ncols) );
4062 
4063  assert(cstat != NULL || ncols == 0);
4064  assert(rstat != NULL || nrows == 0);
4065 
4066  SCIPdebugMessage("Calling SCIPlpiSetBase (%d)\n", lpi->lpid);
4067 
4068  SCIP_CALL( ensureStateMem(lpi, ncols, nrows) );
4069 
4070  convertstat_scip2mosek(cstat, ncols, lpi->skx);
4071  convertstat_scip2mosek_slack(rstat, nrows, lpi->skc);
4072 
4073  SCIP_CALL( setbase(lpi) );
4074 
4075  invalidateSolution(lpi);
4076 
4077  return SCIP_OKAY;
4078 }
4079 
4080 /** returns the indices of the basic columns and rows; basic column n gives value n, basic row m gives value -1-m */
4082  SCIP_LPI* lpi, /**< LP interface structure */
4083  int* bind /**< pointer to store basis indices ready to keep number of rows entries */
4084  )
4085 {
4086  int nrows;
4087  int i;
4088 
4089  assert(MosekEnv != NULL);
4090  assert(lpi != NULL);
4091  assert(lpi->task != NULL);
4092  assert(bind != NULL);
4093 
4094  SCIPdebugMessage("Calling SCIPlpiGetBasisInd (%d)\n", lpi->lpid);
4095 
4096  MOSEK_CALL( MSK_getnumcon(lpi->task, &nrows) );
4097 
4098  SCIP_CALL( handle_singular(lpi, bind, MSK_initbasissolve(lpi->task, bind)) );
4099 
4100  for (i = 0; i < nrows; i++ )
4101  {
4102  if (bind[i] < nrows) /* row bind[i] is basic */
4103  bind[i] = -1 - bind[i];
4104  else /* column bind[i]-nrows is basic */
4105  bind[i] = bind[i] - nrows;
4106  }
4107 
4108  return SCIP_OKAY;
4109 }
4110 
4111 /** get row of inverse basis matrix B^-1
4112  *
4113  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
4114  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
4115  * see also the explanation in lpi.h.
4116  *
4117  * @todo check that the result is in terms of the LP interface definition
4118  *
4119  * @todo check if this should invalidate the solution
4120  */
4122  SCIP_LPI* lpi, /**< LP interface structure */
4123  int r, /**< row number */
4124  SCIP_Real* coef, /**< pointer to store the coefficients of the row */
4125  int* inds, /**< array to store the non-zero indices, or NULL */
4126  int* ninds /**< pointer to store the number of non-zero indices, or NULL
4127  * (-1: if we do not store sparsity information) */
4128  )
4129 {
4130  int nrows;
4131  int i;
4132 
4133  assert(MosekEnv != NULL);
4134  assert(lpi != NULL);
4135  assert(lpi->task != NULL);
4136  assert(coef != NULL);
4137 
4138  SCIPdebugMessage("Calling SCIPlpiGetBInvRow (%d)\n", lpi->lpid);
4139 
4140  MOSEK_CALL( MSK_getnumcon(lpi->task, &nrows) );
4141 
4142  /* set coefficient for slack variables to be 1 instead of -1 */
4143  MOSEK_CALL( MSK_putnaintparam(lpi->task, MSK_IPAR_BASIS_SOLVE_USE_PLUS_ONE_, MSK_ON) );
4144 
4145  /* prepare basis in Mosek, since we do not need the basis ourselves, we set the return parameter to NULL */
4146  SCIP_CALL( handle_singular(lpi, NULL, MSK_initbasissolve(lpi->task, NULL)) );
4147 
4148  /* initialize rhs of system to be a dense +/- unit vector (needed for MSK_solvewithbasis()) */
4149  for (i = 0; i < nrows; ++i)
4150  coef[i] = 0.0;
4151  coef[r] = 1.0; /* unit vector e_r */
4152 
4153  /* check whether we require a dense or sparse result vector */
4154  if ( ninds != NULL && inds != NULL )
4155  {
4156  *ninds = 1;
4157  inds[0]= r;
4158 
4159  /* solve transposed system */
4160  MOSEK_CALL( MSK_solvewithbasis(lpi->task, 1, ninds, inds, coef) );
4161  assert( *ninds <= nrows );
4162  }
4163  else
4164  {
4165  int* sub;
4166  int numnz;
4167 
4168  SCIP_ALLOC( BMSallocMemoryArray(&sub, nrows) );
4169 
4170  numnz = 1;
4171  sub[0] = r;
4172 
4173  /* solve transposed system */
4174  MOSEK_CALL( MSK_solvewithbasis(lpi->task, 1, &numnz, sub, coef) );
4175  assert( numnz <= nrows );
4176 
4177  BMSfreeMemoryArray(&sub);
4178  }
4179  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_HOTSTART_LU, MSK_ON) );
4180 
4181  SCIPdebugMessage("End SCIPlpiGetBInvRow (%d)\n", lpi->lpid);
4182 
4183  return SCIP_OKAY;
4184 }
4185 
4186 /** get column of inverse basis matrix B^-1
4187  *
4188  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
4189  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
4190  * see also the explanation in lpi.h.
4191  *
4192  * @todo check that the result is in terms of the LP interface definition
4193  *
4194  * @todo check if this should invalidate the solution
4195  */
4197  SCIP_LPI* lpi, /**< LP interface structure */
4198  int c, /**< column number of B^-1; this is NOT the number of the column in the LP;
4199  * you have to call SCIPlpiGetBasisInd() to get the array which links the
4200  * B^-1 column numbers to the row and column numbers of the LP!
4201  * c must be between 0 and nrows-1, since the basis has the size
4202  * nrows * nrows */
4203  SCIP_Real* coef, /**< pointer to store the coefficients of the column */
4204  int* inds, /**< array to store the non-zero indices, or NULL */
4205  int* ninds /**< pointer to store the number of non-zero indices, or NULL
4206  * (-1: if we do not store sparsity information) */
4207  )
4208 {
4209  int nrows;
4210  int i;
4211 
4212  assert(MosekEnv != NULL);
4213  assert(lpi != NULL);
4214  assert(lpi->task != NULL);
4215  assert(coef != NULL);
4216 
4217  SCIPdebugMessage("Calling SCIPlpiGetBInvCol (%d)\n", lpi->lpid);
4218 
4219  MOSEK_CALL( MSK_getnumcon(lpi->task, &nrows) );
4220 
4221  /* set coefficient for slack variables to be 1 instead of -1 */
4222  MOSEK_CALL( MSK_putnaintparam(lpi->task, MSK_IPAR_BASIS_SOLVE_USE_PLUS_ONE_, MSK_ON) );
4223 
4224  /* prepare basis in Mosek, since we do not need the basis ourselves, we set the return parameter to NULL */
4225  SCIP_CALL( handle_singular(lpi, NULL, MSK_initbasissolve(lpi->task, NULL)) );
4226 
4227  /* initialize rhs of system to be a dense +/- unit vector (needed for MSK_solvewithbasis()) */
4228  for (i = 0; i < nrows; ++i)
4229  coef[i] = 0.0;
4230  coef[c] = 1.0; /* unit vector e_c */
4231 
4232  /* check whether we require a dense or sparse result vector */
4233  if ( ninds != NULL && inds != NULL )
4234  {
4235  *ninds = 1;
4236  inds[0]= c;
4237 
4238  MOSEK_CALL( MSK_solvewithbasis(lpi->task, 0, ninds, inds, coef) );
4239  assert( *ninds <= nrows );
4240  }
4241  else
4242  {
4243  int* sub;
4244  int numnz;
4245 
4246  SCIP_ALLOC( BMSallocMemoryArray(&sub, nrows) );
4247 
4248  numnz = 1;
4249  sub[0]= c;
4250 
4251  MOSEK_CALL( MSK_solvewithbasis(lpi->task, 0, &numnz, sub, coef) );
4252  assert( numnz <= nrows );
4253 
4254  BMSfreeMemoryArray(&sub);
4255  }
4256  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_HOTSTART_LU, MSK_ON) );
4257 
4258  return SCIP_OKAY;
4259 }
4260 
4261 /** get row of inverse basis matrix times constraint matrix B^-1 * A
4262  *
4263  * @note The LP interface defines slack variables to have coefficient +1. This means that if, internally, the LP solver
4264  * uses a -1 coefficient, then rows associated with slacks variables whose coefficient is -1, should be negated;
4265  * see also the explanation in lpi.h.
4266  *
4267  * @todo check that the result is in terms of the LP interface definition
4268  *
4269  * @todo check if this should invalidate the solution
4270  */
4272  SCIP_LPI* lpi, /**< LP interface structure */
4273  int row, /**< row number */
4274  const SCIP_Real* binvrow, /**< row in (A_B)^-1 from prior call to SCIPlpiGetBInvRow(), or NULL */
4275  SCIP_Real* coef, /**< vector to return coefficients of the row */
4276  int* inds, /**< array to store the non-zero indices, or NULL */
4277  int* ninds /**< pointer to store the number of non-zero indices, or NULL
4278  * (-1: if we do not store sparsity information) */
4279  )
4280 { /*lint --e{715}*/
4281  int nrows;
4282  int ncols;
4283  int numnz;
4284  int* csub;
4285  int didalloc = 0;
4286  double* cval;
4287  double* binv;
4288  int i;
4289  int k;
4290 
4291  assert(MosekEnv != NULL);
4292  assert(lpi != NULL);
4293  assert(lpi->task != NULL);
4294  assert(coef != NULL);
4295 
4296  SCIPdebugMessage("Calling SCIPlpiGetBInvARow (%d)\n", lpi->lpid);
4297 
4298  /* can currently only return dense result */
4299  if ( ninds != NULL )
4300  *ninds = -1;
4301 
4302  MOSEK_CALL( MSK_getnumcon(lpi->task, &nrows) );
4303  MOSEK_CALL( MSK_getnumvar(lpi->task, &ncols) );
4304 
4305  SCIP_ALLOC( BMSallocMemoryArray(&csub, nrows) );
4306  SCIP_ALLOC( BMSallocMemoryArray(&cval, nrows) );
4307 
4308  if( binvrow == NULL )
4309  {
4310  didalloc = 1;
4311 
4312  /* get dense vector */
4313  SCIP_ALLOC( BMSallocMemoryArray(&binv, nrows) );
4314  SCIP_CALL( SCIPlpiGetBInvRow(lpi, row, binv, NULL, NULL) );
4315  }
4316  else
4317  binv = (SCIP_Real*)binvrow;
4318 
4319  /* binvrow*A */
4320  for (i = 0; i < ncols; ++i)
4321  {
4322  MOSEK_CALL( MSK_getacol(lpi->task, i, &numnz, csub, cval) );
4323 
4324  /* compute dense vector */
4325  coef[i] = 0.0;
4326  for (k = 0; k < numnz; ++k)
4327  {
4328  assert( 0 <= csub[k] && csub[k] < nrows );
4329  coef[i] += binv[csub[k]] * cval[k];
4330  }
4331  }
4332 
4333  /* free memory arrays */
4334  BMSfreeMemoryArray(&cval);
4335  BMSfreeMemoryArray(&csub);
4336 
4337  if ( didalloc > 0 )
4338  {
4339  BMSfreeMemoryArray(&binv);
4340  }
4341 
4342  return SCIP_OKAY;
4343 }
4344 
4345 /** get column of inverse basis matrix times constraint matrix B^-1 * A
4346  *
4347  * @todo check if this should invalidate the solution
4348  */
4350  SCIP_LPI* lpi, /**< LP interface structure */
4351  int c, /**< column number */
4352  SCIP_Real* coef, /**< vector to return coefficients of the columnn */
4353  int* inds, /**< array to store the non-zero indices, or NULL */
4354  int* ninds /**< pointer to store the number of non-zero indices, or NULL
4355  * (-1: if we do not store sparsity information) */
4356  )
4357 { /*lint --e{715}*/
4358  SCIP_Real* val;
4359  int nrows;
4360  int numnz;
4361  int i;
4362 
4363  assert(MosekEnv != NULL);
4364  assert(lpi != NULL);
4365  assert(lpi->task != NULL);
4366  assert(coef != NULL);
4367 
4368  SCIPdebugMessage("Calling SCIPlpiGetBInvACol (%d)\n", lpi->lpid);
4369 
4370  MOSEK_CALL( MSK_getnumcon(lpi->task, &nrows) );
4371  MOSEK_CALL( MSK_getacolnumnz(lpi->task, c, &numnz) );
4372  SCIP_ALLOC( BMSallocMemoryArray(&val, numnz+1) );
4373 
4374  /* set coefficient for slack variables to be 1 instead of -1 */
4375  MOSEK_CALL( MSK_putnaintparam(lpi->task, MSK_IPAR_BASIS_SOLVE_USE_PLUS_ONE_, MSK_ON) );
4376 
4377  /* prepare basis in Mosek, since we do not need the basis ourselves, we set the return parameter to NULL */
4378  SCIP_CALL( handle_singular(lpi, NULL, MSK_initbasissolve(lpi->task, NULL)) );
4379 
4380  /* init coefficients */
4381  for (i = 0; i < nrows; ++i)
4382  coef[i] = 0.0;
4383 
4384  /* check whether we require a dense or sparse result vector */
4385  if ( ninds != NULL && inds != NULL )
4386  {
4387  /* fill column into dense vector */
4388  MOSEK_CALL( MSK_getacol(lpi->task, c, &numnz, inds, val) );
4389  for (i = 0; i < numnz; ++i)
4390  {
4391  assert( 0 <= inds[i] && inds[i] < nrows );
4392  coef[inds[i]] = val[i];
4393  }
4394 
4395  *ninds = numnz;
4396 
4397  MOSEK_CALL( MSK_solvewithbasis(lpi->task, 0, ninds, inds, coef) );
4398  assert( *ninds <= nrows );
4399  }
4400  else
4401  {
4402  int* sub;
4403  SCIP_ALLOC( BMSallocMemoryArray(&sub, nrows) );
4404 
4405  /* fill column into dense vector */
4406  MOSEK_CALL( MSK_getacol(lpi->task, c, &numnz, sub, val) );
4407  for (i = 0; i < numnz; ++i)
4408  {
4409  assert( 0 <= sub[i] && sub[i] < nrows );
4410  coef[sub[i]] = val[i];
4411  }
4412 
4413  MOSEK_CALL( MSK_solvewithbasis(lpi->task, 0, &numnz, sub, coef) );
4414 
4415  if ( ninds != NULL )
4416  *ninds = numnz;
4417 
4418  BMSfreeMemoryArray(&sub);
4419  }
4420 
4421  BMSfreeMemoryArray(&val);
4422  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_HOTSTART_LU, MSK_ON) );
4423 
4424  return SCIP_OKAY;
4425 }
4426 
4427 
4428 /*
4429  * LP State Methods
4430  */
4431 
4432 /** creates LPi state information object */
4433 static
4435  SCIP_LPISTATE** lpistate, /**< pointer to LPi state */
4436  BMS_BLKMEM* blkmem, /**< block memory */
4437  int ncols, /**< number of columns to store */
4438  int nrows /**< number of rows to store */
4439  )
4440 {
4441  assert(lpistate != NULL);
4442  assert(blkmem != NULL);
4443  assert(ncols >= 0);
4444  assert(nrows >= 0);
4445 
4446  SCIP_ALLOC( BMSallocBlockMemory(blkmem, lpistate) );
4447  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->skx, colpacketNum(ncols)) );
4448  SCIP_ALLOC( BMSallocBlockMemoryArray(blkmem, &(*lpistate)->skc, rowpacketNum(nrows)) );
4449 
4450  (*lpistate)->solsta = MSK_SOL_STA_UNKNOWN;
4451  (*lpistate)->num = -1;
4452  (*lpistate)->ncols = ncols;
4453  (*lpistate)->nrows = nrows;
4454 
4455  return SCIP_OKAY;
4456 }
4457 
4458 /** frees LPi state information */
4459 static
4461  SCIP_LPISTATE** lpistate, /**< pointer to LPi state information (like basis information) */
4462  BMS_BLKMEM* blkmem /**< block memory */
4463  )
4464 {
4465  assert(blkmem != NULL);
4466  assert(lpistate != NULL);
4467  assert(*lpistate != NULL);
4468 
4469  BMSfreeBlockMemoryArray(blkmem, &(*lpistate)->skx, colpacketNum((*lpistate)->ncols));
4470  BMSfreeBlockMemoryArray(blkmem, &(*lpistate)->skc, rowpacketNum((*lpistate)->nrows));
4471  BMSfreeBlockMemory(blkmem, lpistate);
4472 }
4473 
4474 #ifndef NDEBUG
4475 /** check state
4476  *
4477  * @note last solve call must have been either simplex or barrier with crossover or base must have been set manually
4478  */
4479 static
4481  SCIP_LPI* lpi, /**< LP interface structure */
4482  int n, /**< number of rows or columns */
4483  MSKstakeye* sk, /**< basis status */
4484  SCIP_Bool isrow /**< whether rows/columns are considered */
4485  )
4486 {
4487  char xc;
4488  int i;
4489 
4490  assert(lpi != NULL);
4491  assert(lpi->lastsolvetype == MSK_SOL_BAS);
4492 
4493  if( !isrow )
4494  xc = 'x';
4495  else
4496  xc = 'c';
4497 
4498  /* printout for all except LOW, UPR, FIX and BAS with sl[xc]==su[xc] */
4499  for( i = 0; i < n; i++ )
4500  {
4501  double sl;
4502  double su;
4503  switch (sk[i])
4504  {
4505  case MSK_SK_UNK:
4506  SCIPdebugMessage("STATE[%d]: %c[%d] = unk\n", optimizecount, xc, i);
4507  break;
4508  case MSK_SK_BAS:
4509  /* the following function is deprecated */
4510 #if MSK_VERSION_MAJOR < 9
4511  MOSEK_CALL( MSK_getsolutioni(lpi->task, isrow ? MSK_ACC_CON : MSK_ACC_VAR, i, MSK_SOL_BAS, NULL, NULL, &sl, &su, NULL) );
4512 #else
4513  if( isrow )
4514  {
4515  MOSEK_CALL( MSK_getslcslice(lpi->task, MSK_SOL_BAS, i, i+1, &sl ) );
4516  MOSEK_CALL( MSK_getsucslice(lpi->task, MSK_SOL_BAS, i, i+1, &su ) );
4517  }
4518  else
4519  {
4520  MOSEK_CALL( MSK_getslxslice(lpi->task, MSK_SOL_BAS, i, i+1, &sl ) );
4521  MOSEK_CALL( MSK_getsuxslice(lpi->task, MSK_SOL_BAS, i, i+1, &su ) );
4522  }
4523 #endif
4524  if (fabs(sl-su) > DEBUG_CHECK_STATE_TOL)
4525  {
4526  SCIPdebugMessage("STATE[%d]: %c[%d] = bas, sl%c = %g, su%c = %g\n", optimizecount, xc, i, xc, sl, xc, su);
4527  }
4528  break;
4529  case MSK_SK_SUPBAS:
4530  SCIPdebugMessage("STATE[%d]: %c[%d] = supbas\n", optimizecount, xc, i);
4531  break;
4532  case MSK_SK_LOW:
4533  case MSK_SK_UPR:
4534  case MSK_SK_FIX:
4535  break;
4536  case MSK_SK_INF:
4537  SCIPdebugMessage("STATE[%d]: %c[%d] = inf\n", optimizecount, xc, i);
4538  break;
4539  default:
4540  SCIPdebugMessage("STATE[%d]: %c[%d] = unknown status <%d>\n", optimizecount, xc, i, sk[i]);
4541  break;
4542  } /*lint !e788*/
4543  }
4544 
4545  return SCIP_OKAY;
4546 }
4547 
4548 /** check state
4549  *
4550  * @note last solve call must have been either simplex or barrier with crossover or base must have been set manually
4551  */
4552 static
4554  SCIP_LPI* lpi, /**< LP interface structure */
4555  int ncols, /**< number of columns */
4556  int nrows /**< number of rows */
4557  )
4558 {
4559  assert(lpi != NULL);
4560  assert(lpi->lastsolvetype == MSK_SOL_BAS);
4561 
4562  SCIP_CALL( checkState1(lpi, ncols, lpi->skx, FALSE) );
4563  SCIP_CALL( checkState1(lpi, nrows, lpi->skc, TRUE) );
4564 
4565  return SCIP_OKAY;
4566  }
4567 #endif
4568 
4569 /** store row and column basis status in a packed LPi state object
4570  *
4571  * @note last solve call must have been either simplex or barrier with crossover or base must have been set manually
4572  */
4573 static
4575  SCIP_LPI* lpi, /**< LP interface structure */
4576  SCIP_LPISTATE* lpistate /**< pointer to LPi state data */
4577  )
4578 {
4579  int *skxi = (int *) lpi->skx; /* Used as temp. buffer */
4580  int *skci = (int *) lpi->skc; /* Used as temp. buffer */
4581 
4582  assert(sizeof(int) == sizeof(MSKstakeye));
4583  assert(lpi != NULL);
4584  assert(lpistate != NULL);
4585  assert(lpi->lastsolvetype == MSK_SOL_BAS);
4586 
4587  SCIP_CALL( convertstat_mosek2scip(lpi, FALSE, lpi->skx, lpistate->ncols, skxi) );
4588  SCIP_CALL( convertstat_mosek2scip_slack(lpi, TRUE, lpi->skc, lpistate->nrows, skci) );
4589 
4590  SCIPencodeDualBit(skxi, lpistate->skx, lpistate->ncols);
4591  SCIPencodeDualBit(skci, lpistate->skc, lpistate->nrows);
4592 
4593  return SCIP_OKAY;
4594 }
4595 
4596 /** unpacks row and column basis status from a packed LPi state object */
4597 static
4599  const SCIP_LPISTATE* lpistate, /**< pointer to LPi state data */
4600  MSKstakeye* skx, /**< basis status for columns */
4601  MSKstakeye* skc /**< basis status for rows */
4602  )
4603 {
4604  assert(sizeof(int) == sizeof(MSKstakeye));
4605 
4606  SCIPdecodeDualBit(lpistate->skx, (int*) skx, lpistate->ncols);
4607  SCIPdecodeDualBit(lpistate->skc, (int*) skc, lpistate->nrows);
4608 
4609  convertstat_scip2mosek((int*) skx, lpistate->ncols, skx);
4610  convertstat_scip2mosek_slack((int*) skc, lpistate->nrows, skc);
4611 }
4612 
4613 /** stores LP state (like basis information) into lpistate object
4614  *
4615  * @note last solve call must have been either simplex or barrier with crossover or base must have been set manually
4616  */
4618  SCIP_LPI* lpi, /**< LP interface structure */
4619  BMS_BLKMEM* blkmem, /**< block memory */
4620  SCIP_LPISTATE** lpistate /**< pointer to LP state information (like basis information) */
4621  )
4622 {
4623  int gotbasicsol;
4624  int nrows;
4625  int ncols;
4626 
4627  assert(MosekEnv != NULL);
4628  assert(lpi != NULL);
4629  assert(lpi->task != NULL);
4630  assert(lpistate != NULL);
4631  assert(blkmem != NULL);
4632  assert(lpi->lastsolvetype == MSK_SOL_BAS);
4633 
4634  SCIPdebugMessage("Calling SCIPlpiGetState (%d)\n", lpi->lpid);
4635 
4636  *lpistate = NULL;
4637 
4638  MOSEK_CALL( MSK_solutiondef(lpi->task, MSK_SOL_BAS, &gotbasicsol) );
4639 
4640  if ( gotbasicsol == 0 || SCIPlpiExistsDualRay(lpi) || lpi->clearstate )
4641  return SCIP_OKAY;
4642 
4643  MOSEK_CALL( MSK_getnumcon(lpi->task, &nrows) );
4644  MOSEK_CALL( MSK_getnumvar(lpi->task, &ncols) );
4645 
4646  /* allocate lpistate data */
4647  SCIP_CALL( lpistateCreate(lpistate, blkmem, ncols, nrows) );
4648 
4649  lpistate[0]->num = optimizecount;
4650 
4651  MOSEK_CALL( MSK_getsolutionstatus(lpi->task, MSK_SOL_BAS, NULL, &lpistate[0]->solsta) );
4652 
4653  SCIP_CALL( getbase(lpi, ncols, nrows) );
4654 
4655 #ifndef NDEBUG
4656  SCIP_CALL( checkState(lpi, ncols, nrows) );
4657 #endif
4658 
4659  SCIP_CALL( lpistatePack(lpi, lpistate[0]) );
4660 
4661  SCIPdebugMessage("Store into state from iter : %d\n", optimizecount);
4662 
4663  /* if (r != SCIP_OKAY)
4664  * lpistateFree(lpistate, blkmem );
4665  */
4666 
4667  return SCIP_OKAY;
4668 }
4669 
4670 /** loads LPi state (like basis information) into solver; note that the LP might have been extended with additional
4671  * columns and rows since the state was stored with SCIPlpiGetState()
4672  */
4674  SCIP_LPI* lpi, /**< LP interface structure */
4675  BMS_BLKMEM* blkmem, /**< block memory */
4676  const SCIP_LPISTATE* lpistate /**< LP state information (like basis information), or NULL */
4677  )
4678 { /*lint --e{715}*/
4679  int nrows;
4680  int ncols;
4681  int i;
4682 
4683  assert(MosekEnv != NULL);
4684  assert(lpi != NULL);
4685  assert(lpi->task != NULL);
4686  assert(blkmem != NULL);
4687 #ifdef SCIP_DISABLED_CODE
4688  assert(lpi->lastsolvetype == MSK_SOL_BAS);
4689 #endif
4690 
4691  if (lpistate == NULL)
4692  {
4693  SCIPdebugMessage("Setting NULL state\n");
4694  return SCIP_OKAY;
4695  }
4696 
4697  if (lpistate->nrows == 0 || lpistate->ncols == 0)
4698  return SCIP_OKAY;
4699 
4700  MOSEK_CALL( MSK_getnumcon(lpi->task, &nrows) );
4701  MOSEK_CALL( MSK_getnumvar(lpi->task, &ncols) );
4702  assert(lpistate->nrows <= nrows);
4703  assert(lpistate->ncols <= ncols);
4704 
4705  SCIP_CALL( ensureStateMem(lpi, ncols, nrows) );
4706 
4707 #ifdef SCIP_DISABLED_CODE
4708  SCIP_CALL( getbase(lpi, ncols, nrows) ); /* Why do we need to get the basis ????? */
4709 #endif
4710 
4711  lpistateUnpack(lpistate, lpi->skx, lpi->skc);
4712 
4713  /* extend the basis to the current LP beyond the previously existing columns */
4714  for (i = lpistate->ncols; i < ncols; ++i)
4715  {
4716  SCIP_Real lb;
4717  SCIP_Real ub;
4718 #if MSK_VERSION_MAJOR < 9
4719  MOSEK_CALL( MSK_getboundslice(lpi->task, MSK_ACC_VAR, i, i, NULL, &lb, &ub) );
4720 #else
4721  MOSEK_CALL( MSK_getvarboundslice(lpi->task, i, i, NULL, &lb, &ub) );
4722 #endif
4723  if ( SCIPlpiIsInfinity(lpi, REALABS(lb)) )
4724  {
4725  /* if lower bound is +/- infinity -> try upper bound */
4726  if ( SCIPlpiIsInfinity(lpi, REALABS(ub)) )
4727  lpi->skx[i] = MSK_SK_SUPBAS; /* variable is free (super basic) */
4728  else
4729  lpi->skx[i] = MSK_SK_UPR; /* use finite upper bound */
4730  }
4731  else
4732  lpi->skx[i] = MSK_SK_LOW; /* use finite lower bound */
4733  }
4734  for (i = lpistate->nrows; i < nrows; ++i)
4735  lpi->skc[i] = MSK_SK_BAS;
4736 
4737  /* load basis information into MOSEK */
4738  SCIP_CALL( setbase(lpi) );
4739 
4740  invalidateSolution(lpi);
4741 
4742  SCIPdebugMessage("Store from state into task iter : %d with solsta : %d\n", lpistate->num, lpistate->solsta);
4743 
4744  return SCIP_OKAY;
4745 }
4746 
4747 /** clears current LPi state (like basis information) of the solver */
4749  SCIP_LPI* lpi /**< LP interface structure */
4750  )
4751 {
4752  assert(MosekEnv != NULL);
4753  assert(lpi != NULL);
4754  assert(lpi->task != NULL);
4755 
4756  lpi->clearstate = TRUE;
4757 
4758  return SCIP_OKAY;
4759 }
4760 
4761 /** frees LP state information */
4763  SCIP_LPI* lpi, /**< LP interface structure */
4764  BMS_BLKMEM* blkmem, /**< block memory */
4765  SCIP_LPISTATE** lpistate /**< pointer to LP state information (like basis information) */
4766  )
4767 { /*lint --e{715}*/
4768  assert(MosekEnv != NULL);
4769  assert(lpi != NULL);
4770  assert(lpi->task != NULL);
4771  assert(lpistate != NULL);
4772  assert(blkmem != NULL);
4773 
4774  SCIPdebugMessage("Calling SCIPlpiFreeState (%d)\n", lpi->lpid);
4775 
4776  if( *lpistate != NULL )
4777  {
4778  lpistateFree(lpistate, blkmem);
4779  }
4780 
4781  return SCIP_OKAY;
4782 }
4783 
4784 /** checks, whether the given LP state contains simplex basis information */
4786  SCIP_LPI* lpi, /**< LP interface structure */
4787  SCIP_LPISTATE* lpistate /**< LP state information (like basis information), or NULL */
4788  )
4789 { /*lint --e{715}*/
4790  assert(MosekEnv != NULL);
4791  assert(lpi != NULL);
4792  assert(lpi->task != NULL);
4793 
4794  SCIPdebugMessage("Calling SCIPlpiHasStateBasis (%d)\n", lpi->lpid);
4795 
4796  return ( lpistate != NULL && lpistate->num >= 0);
4797 }
4798 
4799 /** reads LP state (like basis information) from a file
4800  *
4801  * @note last solve call must have been either simplex or barrier with crossover or base must have been set manually
4802  */
4804  SCIP_LPI* lpi, /**< LP interface structure */
4805  const char* fname /**< file name */
4806  )
4807 {
4808  assert(MosekEnv != NULL);
4809  assert(lpi != NULL);
4810  assert(lpi->task != NULL);
4811  assert(fname != NULL);
4812 
4813  SCIPdebugMessage("reading LP state from file <%s>\n", fname);
4814 
4815  lpi->clearstate = FALSE;
4816 
4817  MOSEK_CALL( MSK_readsolution(lpi->task, MSK_SOL_BAS, fname) );
4818 
4819  return SCIP_OKAY;
4820 }
4821 
4822 /** writes LPi state (i.e. basis information) to a file */
4824  SCIP_LPI* lpi, /**< LP interface structure */
4825  const char* fname /**< file name */
4826  )
4827 {
4828  int v;
4829  int nvars;
4830  int c = 0;
4831  int nconss;
4832  SCIP_Bool emptyname = FALSE;
4833  char name[SCIP_MAXSTRLEN];
4834 
4835  assert(MosekEnv != NULL);
4836  assert(lpi != NULL);
4837  assert(lpi->task != NULL);
4838  assert(fname != NULL);
4839  assert(lpi->lastsolvetype == MSK_SOL_BAS);
4840 
4841  SCIPdebugMessage("writing LP state to file <%s>\n", fname);
4842 
4843  if( lpi->clearstate )
4844  {
4845  SCIPdebugMessage("No LP state written, since it was cleared after the last solve \n");
4846  return SCIP_OKAY;
4847  }
4848 
4849  /* If any rows or columns have empty names, MOSEK will make up names like C1 and X1, but will no
4850  * longer recognize them when reading the same state file back in, therefore we return an error in
4851  * this case
4852  */
4853  MOSEK_CALL( MSK_getnumvar(lpi->task, &nvars) );
4854  for( v = 0; v < nvars; v++ )
4855  {
4856  MOSEK_CALL( MSK_getvarname(lpi->task, v, SCIP_MAXSTRLEN, name) );
4857  if( strcmp(name, "") == 0 )
4858  {
4859  emptyname = TRUE;
4860  break;
4861  }
4862  }
4863  if( !emptyname )
4864  {
4865  MOSEK_CALL( MSK_getnumcon(lpi->task, &nconss) );
4866  for( c = 0; c < nconss; c++ )
4867  {
4868  MOSEK_CALL( MSK_getconname(lpi->task, c, SCIP_MAXSTRLEN, name) );
4869  if( strcmp(name, "") == 0 )
4870  {
4871  emptyname = TRUE;
4872  break;
4873  }
4874  }
4875  }
4876 
4877  if( emptyname )
4878  {
4879  SCIPmessagePrintWarning(lpi->messagehdlr, "Writing LP state with unnamed %s %d, using default"
4880  " names instead. Note that this state cannot be read back in later!\n",
4881  v < nvars ? "variable" : "constraint", v < nvars ? v : c);
4882  }
4883 
4884  /* set parameter to be able to write */
4885  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_WRITE_SOL_HEAD, MSK_ON) );
4886  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_WRITE_SOL_VARIABLES, MSK_ON) );
4887  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_WRITE_SOL_CONSTRAINTS, MSK_ON) );
4888 
4889  MOSEK_CALL( MSK_writesolution(lpi->task, MSK_SOL_BAS, fname) );
4890 
4891  return SCIP_OKAY;
4892 }
4893 
4894 /**@} */
4895 
4896 /*
4897  * LP Pricing Norms Methods
4898  */
4899 
4900 /**@name LP Pricing Norms Methods */
4901 /**@{ */
4902 
4903 /** stores LPi pricing norms information
4904  * @todo should we store norm information?
4905  */
4907  SCIP_LPI* lpi, /**< LP interface structure */
4908  BMS_BLKMEM* blkmem, /**< block memory */
4909  SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information */
4910  )
4911 { /*lint --e{715}*/
4912  assert(MosekEnv != NULL);
4913  assert(lpi != NULL);
4914  assert(lpi->task != NULL);
4915  assert(lpinorms != NULL);
4916  assert(blkmem != NULL);
4917 
4918  (*lpinorms) = NULL;
4919 
4920  return SCIP_OKAY;
4921 }
4922 
4923 /** loads LPi pricing norms into solver; note that the LP might have been extended with additional
4924  * columns and rows since the state was stored with SCIPlpiGetNorms()
4925  */
4927  SCIP_LPI* lpi, /**< LP interface structure */
4928  BMS_BLKMEM* blkmem, /**< block memory */
4929  const SCIP_LPINORMS* lpinorms /**< LPi pricing norms information, or NULL */
4930  )
4931 { /*lint --e{715}*/
4932  assert(lpinorms == NULL);
4933 
4934  /* no work necessary */
4935  return SCIP_OKAY;
4936 }
4937 
4938 /** frees pricing norms information */
4940  SCIP_LPI* lpi, /**< LP interface structure */
4941  BMS_BLKMEM* blkmem, /**< block memory */
4942  SCIP_LPINORMS** lpinorms /**< pointer to LPi pricing norms information, or NULL */
4943  )
4944 { /*lint --e{715}*/
4945  assert(lpinorms == NULL);
4946 
4947  /* no work necessary */
4948  return SCIP_OKAY;
4949 }
4950 
4951 /**@} */
4952 
4953 /*
4954  * Parameter Methods
4955  */
4956 
4957 /** constant array containing the parameter names */
4958 static const char* paramname[] = {
4959  "SCIP_LPPAR_FROMSCRATCH", /* solver should start from scratch at next call? */
4960  "SCIP_LPPAR_FASTMIP", /* fast mip setting of LP solver */
4961  "SCIP_LPPAR_SCALING", /* which scaling should LP solver use? */
4962  "SCIP_LPPAR_PRESOLVING", /* should LP solver use presolving? */
4963  "SCIP_LPPAR_PRICING", /* pricing strategy */
4964  "SCIP_LPPAR_LPINFO", /* should LP solver output information to the screen? */
4965  "SCIP_LPPAR_FEASTOL", /* feasibility tolerance for primal variables and slacks */
4966  "SCIP_LPPAR_DUALFEASTOL", /* feasibility tolerance for dual variables and reduced costs */
4967  "SCIP_LPPAR_BARRIERCONVTOL", /* convergence tolerance used in barrier algorithm */
4968  "SCIP_LPPAR_OBJLIM", /* objective limit (stop if objective is known be larger/smaller than limit for min/max-imization) */
4969  "SCIP_LPPAR_LPITLIM", /* LP iteration limit, greater than or equal 0 */
4970  "SCIP_LPPAR_LPTILIM", /* LP time limit, positive */
4971  "SCIP_LPPAR_MARKOWITZ", /* Markowitz tolerance */
4972  "SCIP_LPPAR_ROWREPSWITCH", /* simplex algorithm shall use row representation of the basis
4973  * if number of rows divided by number of columns exceeds this value */
4974  "SCIP_LPPAR_THREADS", /* number of threads used to solve the LP */
4975  "SCIP_LPPAR_CONDITIONLIMIT", /* maximum condition number of LP basis counted as stable */
4976  "SCIP_LPPAR_TIMING", /* type of timer (1 - cpu, 2 - wallclock, 0 - off) */
4977  "SCIP_LPPAR_RANDOMSEED", /* inital random seed, e.g. for perturbations in the simplex (0: LP default) */
4978  "SCIP_LPPAR_POLISHING", /* set solution polishing (0 - disable, 1 - enable) */
4979  "SCIP_LPPAR_REFACTOR" /* set refactorization interval (0 - automatic) */
4980 };
4981 
4982 /** method mapping parameter index to parameter name */
4983 static
4984 const char* paramty2str(
4985  SCIP_LPPARAM type
4986  )
4987 { /*lint --e{641}*/
4988  /* check if the parameters in this order */
4989  assert(SCIP_LPPAR_FROMSCRATCH == 0); /* solver should start from scratch at next call? */
4990  assert(SCIP_LPPAR_FASTMIP == 1); /* fast mip setting of LP solver */
4991  assert(SCIP_LPPAR_SCALING == 2); /* which scaling should LP solver use? */
4992  assert(SCIP_LPPAR_PRESOLVING == 3); /* should LP solver use presolving? */
4993  assert(SCIP_LPPAR_PRICING == 4); /* pricing strategy */
4994  assert(SCIP_LPPAR_LPINFO == 5); /* should LP solver output information to the screen? */
4995  assert(SCIP_LPPAR_FEASTOL == 6); /* feasibility tolerance for primal variables and slacks */
4996  assert(SCIP_LPPAR_DUALFEASTOL == 7); /* feasibility tolerance for dual variables and reduced costs */
4997  assert(SCIP_LPPAR_BARRIERCONVTOL == 8); /* convergence tolerance used in barrier algorithm */
4998  assert(SCIP_LPPAR_OBJLIM == 9); /* objective limit (stop if objective is known be larger/smaller than limit for min/max-imization) */
4999  assert(SCIP_LPPAR_LPITLIM == 10); /* LP iteration limit, greater than or equal 0 */
5000  assert(SCIP_LPPAR_LPTILIM == 11); /* LP time limit, positive */
5001  assert(SCIP_LPPAR_MARKOWITZ == 12); /* Markowitz tolerance */
5002  assert(SCIP_LPPAR_ROWREPSWITCH == 13); /* row representation switch */
5003  assert(SCIP_LPPAR_THREADS == 14); /* number of threads used to solve the LP */
5004  assert(SCIP_LPPAR_CONDITIONLIMIT == 15); /* maximum condition number of LP basis counted as stable */
5005  assert(SCIP_LPPAR_TIMING == 16); /* type of timer (1 - cpu, 2 - wallclock, 0 - off) */
5006  assert(SCIP_LPPAR_RANDOMSEED == 17); /* inital random seed, e.g. for perturbations in the simplex (0: LP default) */
5007  assert(SCIP_LPPAR_POLISHING == 18); /* set solution polishing (0 - disable, 1 - enable) */
5008  assert(SCIP_LPPAR_REFACTOR == 19); /* set refactorization interval (0 - automatic) */
5009 
5010  return paramname[type];
5011 }
5012 
5013 /** gets integer parameter of LP */
5015  SCIP_LPI* lpi, /**< LP interface structure */
5016  SCIP_LPPARAM type, /**< parameter number */
5017  int* ival /**< buffer to store the parameter value */
5018  )
5019 { /*lint --e{641}*/
5020  assert(MosekEnv != NULL);
5021  assert(lpi != NULL);
5022  assert(lpi->task != NULL);
5023  assert(ival != NULL);
5024 
5025  SCIPdebugMessage("getting int parameter %s\n", paramty2str(type));
5026 
5027  switch (type)
5028  {
5029  case SCIP_LPPAR_FROMSCRATCH: /* solver should start from scratch at next call? */
5030  *ival = (int) lpi->fromscratch;
5031  break;
5032  case SCIP_LPPAR_FASTMIP: /* fast mip setting of LP solver */
5033  return SCIP_PARAMETERUNKNOWN;
5034  case SCIP_LPPAR_SCALING: /* should LP solver use scaling? */
5035  MOSEK_CALL( MSK_getintparam(lpi->task, MSK_IPAR_SIM_SCALING, ival) );
5036  if( *ival == MSK_SCALING_NONE )
5037  *ival = 0;
5038  else if( *ival == MSK_SCALING_FREE )
5039  *ival = 1;
5040  else if( *ival == MSK_SCALING_AGGRESSIVE )
5041  *ival = 2;
5042  else /* MSK_SCALING_MODERATE should not be used by the interface */
5043  return SCIP_PARAMETERWRONGVAL;
5044  break;
5045  case SCIP_LPPAR_PRESOLVING: /* should LP solver use presolving? */
5046  MOSEK_CALL( MSK_getintparam(lpi->task, MSK_IPAR_PRESOLVE_USE, ival) );
5047  *ival = (*ival != MSK_PRESOLVE_MODE_OFF);
5048  break;
5049  case SCIP_LPPAR_PRICING: /* pricing strategy */
5050  *ival = lpi->pricing;
5051  break;
5052  case SCIP_LPPAR_LPINFO: /* should LP solver output information to the screen? */
5053  *ival = (int) lpi->lpinfo;
5054  break;
5055  case SCIP_LPPAR_LPITLIM: /* LP iteration limit */
5056  MOSEK_CALL( MSK_getintparam(lpi->task, MSK_IPAR_SIM_MAX_ITERATIONS, ival) );
5057  break;
5058  case SCIP_LPPAR_THREADS: /* number of threads */
5059  MOSEK_CALL( MSK_getintparam(lpi->task, MSK_IPAR_NUM_THREADS, ival) );
5060  break;
5061  case SCIP_LPPAR_REFACTOR: /* refactorization interval */
5062  MOSEK_CALL( MSK_getintparam(lpi->task, MSK_IPAR_SIM_REFACTOR_FREQ, ival) );
5063  break;
5064  default:
5065  return SCIP_PARAMETERUNKNOWN;
5066  } /*lint !e788*/
5067 
5068  return SCIP_OKAY;
5069 }
5070 
5071 /** sets integer parameter of LP */
5073  SCIP_LPI* lpi, /**< LP interface structure */
5074  SCIP_LPPARAM type, /**< parameter number */
5075  int ival /**< parameter value */
5076  )
5077 {
5078  static int pricing[7] =
5079  {
5080  (int)MSK_SIM_SELECTION_SE, /**< mosek pricing for SCIP_PRICING_LPIDEFAULT */
5081  (int)MSK_SIM_SELECTION_FREE, /**< mosek pricing for SCIP_PRICING_AUTO */
5082  (int)MSK_SIM_SELECTION_FULL, /**< mosek pricing for SCIP_PRICING_FULL */
5083  (int)MSK_SIM_SELECTION_PARTIAL, /**< mosek pricing for SCIP_PRICING_PARTIAL */
5084  (int)MSK_SIM_SELECTION_SE, /**< mosek pricing for SCIP_PRICING_STEEP */
5085  (int)MSK_SIM_SELECTION_ASE, /**< mosek pricing for SCIP_PRICING_STEEPQSTART */
5086  (int)MSK_SIM_SELECTION_DEVEX, /**< mosek pricing for SCIP_PRICING_DEVEX */
5087  };
5088 
5089  assert((int)SCIP_PRICING_LPIDEFAULT == 0);
5090  assert((int)SCIP_PRICING_AUTO == 1);
5091  assert((int)SCIP_PRICING_FULL == 2);
5092  assert((int)SCIP_PRICING_PARTIAL == 3);
5093  assert((int)SCIP_PRICING_STEEP == 4);
5094  assert((int)SCIP_PRICING_STEEPQSTART == 5);
5095  assert((int)SCIP_PRICING_DEVEX == 6);
5096 
5097  assert(MosekEnv != NULL);
5098  assert(lpi != NULL);
5099  assert(lpi->task != NULL);
5100 
5101  SCIPdebugMessage("Calling SCIPlpiSetIntpar (%d) Parameter=<%s> Value=<%d>\n", lpi->lpid, paramty2str(type), ival);
5102 
5103  switch (type)
5104  {
5105  case SCIP_LPPAR_FROMSCRATCH: /* solver should start from scratch at next call? */
5106  lpi->fromscratch = (SCIP_Bool) ival;
5107  break;
5108  case SCIP_LPPAR_FASTMIP: /* fast mip setting of LP solver */
5109  return SCIP_PARAMETERUNKNOWN;
5110  case SCIP_LPPAR_SCALING: /* should LP solver use scaling? */
5111  assert( ival >= 0 && ival <= 2 );
5112  if( ival == 0 )
5113  {
5114  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_SCALING, MSK_SCALING_NONE) );
5115  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_INTPNT_SCALING, MSK_SCALING_NONE) );
5116  }
5117  else if( ival == 1 )
5118  {
5119  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_SCALING, MSK_SCALING_FREE) );
5120  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_INTPNT_SCALING, MSK_SCALING_FREE) );
5121  }
5122  else
5123  {
5124  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_SCALING, MSK_SCALING_AGGRESSIVE) );
5125  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_INTPNT_SCALING, MSK_SCALING_AGGRESSIVE) );
5126  }
5127 
5128  break;
5129  case SCIP_LPPAR_PRESOLVING: /* should LP solver use presolving? */
5130  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_PRESOLVE_USE,
5131  ival ? MSK_PRESOLVE_MODE_FREE : MSK_PRESOLVE_MODE_OFF) );
5132  break;
5133  case SCIP_LPPAR_PRICING: /* pricing strategy */
5134  assert(ival >= 0 && ival <= (int)SCIP_PRICING_DEVEX);
5135  lpi->pricing = (SCIP_PRICING)ival;
5136 
5137  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_PRIMAL_SELECTION, pricing[ival]) );
5138  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_DUAL_SELECTION, pricing[ival]) );
5139 
5140  /* for certain pricing values, do not use restricted pricing */
5141  if( lpi->pricing == SCIP_PRICING_PARTIAL || lpi->pricing == SCIP_PRICING_AUTO )
5142  lpi->restrictselectdef = 50;
5143  else
5144  lpi->restrictselectdef = 0;
5145 
5146  break;
5147  case SCIP_LPPAR_LPINFO:
5148  /* should LP solver output information to the screen? */
5149 #if FORCE_MOSEK_LOG
5150  SCIPdebugMessage("Ignoring log setting!\n");
5151 #else
5152  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_LOG, ival ? 4 : MSK_OFF) );
5153  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_LOG_SIM, ival ? 4 : MSK_OFF) );
5154 #endif
5155  lpi->lpinfo = (SCIP_Bool) ival;
5156  break;
5157  case SCIP_LPPAR_LPITLIM: /* LP iteration limit */
5158 #if DEBUG_PARAM_SETTING
5159  if( ival )
5160  {
5161  SCIPdebugMessage("Setting max iter to : %d\n", ival);
5162  }
5163 #endif
5164  /* 0 <= ival, 0 stopping immediately */
5165  assert( ival >= 0 );
5166  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_MAX_ITERATIONS, ival) );
5167  break;
5168  case SCIP_LPPAR_THREADS: /* number of threads (0 => MOSEK chooses) */
5169  assert(ival >= 0);
5170  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_NUM_THREADS, ival) );
5171  break;
5172  case SCIP_LPPAR_REFACTOR: /* refactorization interval */
5173  assert(ival >= 0);
5174  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_SIM_REFACTOR_FREQ, ival) );
5175  break;
5176  default:
5177  return SCIP_PARAMETERUNKNOWN;
5178  } /*lint !e788*/
5179 
5180  return SCIP_OKAY;
5181 }
5182 
5183 /** gets floating point parameter of LP */
5185  SCIP_LPI* lpi, /**< LP interface structure */
5186  SCIP_LPPARAM type, /**< parameter number */
5187  SCIP_Real* dval /**< buffer to store the parameter value */
5188  )
5189 {
5190  assert(MosekEnv != NULL);
5191  assert(lpi != NULL);
5192  assert(lpi->task != NULL);
5193  assert(dval != NULL);
5194 
5195  SCIPdebugMessage("getting real parameter %s\n", paramty2str(type));
5196 
5197  switch (type)
5198  {
5199  case SCIP_LPPAR_FEASTOL: /* feasibility tolerance for primal variables and slacks */
5200  MOSEK_CALL( MSK_getdouparam(lpi->task, MSK_DPAR_BASIS_TOL_X, dval) );
5201  break;
5202  case SCIP_LPPAR_DUALFEASTOL: /* feasibility tolerance for dual variables and reduced costs */
5203  MOSEK_CALL( MSK_getdouparam(lpi->task, MSK_DPAR_BASIS_TOL_S, dval) );
5204  break;
5205  case SCIP_LPPAR_BARRIERCONVTOL: /* convergence tolerance used in barrier algorithm */
5206  MOSEK_CALL( MSK_getdouparam(lpi->task, MSK_DPAR_INTPNT_TOL_REL_GAP, dval) );
5207  break;
5208  case SCIP_LPPAR_OBJLIM: /* objective limit */
5209  {
5210  MSKobjsensee objsen;
5211  MOSEK_CALL( MSK_getobjsense(lpi->task, &objsen) );
5212  if (objsen == MSK_OBJECTIVE_SENSE_MINIMIZE)
5213  {
5214  MOSEK_CALL( MSK_getdouparam(lpi->task, MSK_DPAR_UPPER_OBJ_CUT, dval) );
5215  }
5216  else /* objsen == MSK_OBJECTIVE_SENSE_MAX */
5217  {
5218  MOSEK_CALL( MSK_getdouparam(lpi->task, MSK_DPAR_LOWER_OBJ_CUT, dval) );
5219  }
5220  break;
5221  }
5222  case SCIP_LPPAR_LPTILIM: /* LP time limit */
5223  MOSEK_CALL( MSK_getdouparam(lpi->task, MSK_DPAR_OPTIMIZER_MAX_TIME, dval) );
5224  break;
5225  case SCIP_LPPAR_MARKOWITZ: /* Markowitz tolerance */
5226  default:
5227  return SCIP_PARAMETERUNKNOWN;
5228  } /*lint !e788*/
5229 
5230  return SCIP_OKAY;
5231 }
5232 
5233 /** sets floating point parameter of LP */
5235  SCIP_LPI* lpi, /**< LP interface structure */
5236  SCIP_LPPARAM type, /**< parameter number */
5237  SCIP_Real dval /**< parameter value */
5238  )
5239 {
5240  assert(MosekEnv != NULL);
5241  assert(lpi != NULL);
5242  assert(lpi->task != NULL);
5243 
5244  SCIPdebugMessage("setting real parameter %s to %g\n", paramty2str(type), dval);
5245 
5246  /**@todo Limits shouldn't be hardcoded */
5247 
5248  switch (type)
5249  {
5250  case SCIP_LPPAR_FEASTOL: /* feasibility tolerance for primal variables and slacks */
5251  assert( dval > 0.0 );
5252  /* 1e-9 <= dval <= inf */
5253  if( dval < 1e-9 )
5254  dval = 1e-9;
5255 
5256  MOSEK_CALL( MSK_putdouparam(lpi->task, MSK_DPAR_BASIS_TOL_X, dval) );
5257  break;
5258  case SCIP_LPPAR_DUALFEASTOL: /* feasibility tolerance for dual variables and reduced costs */
5259  assert( dval > 0.0 );
5260  /* 1e-9 <= dval <= inf */
5261  if( dval < 1e-9 )
5262  dval = 1e-9;
5263 
5264  MOSEK_CALL( MSK_putdouparam(lpi->task, MSK_DPAR_BASIS_TOL_S, dval) );
5265  break;
5266  case SCIP_LPPAR_BARRIERCONVTOL: /* convergence tolerance used in barrier algorithm */
5267  /* 1e-14 <= dval <= inf */
5268  assert( dval >= 0.0 );
5269  if( dval < 1e-14 )
5270  dval = 1e-14;
5271 
5272  MOSEK_CALL( MSK_putdouparam(lpi->task, MSK_DPAR_INTPNT_TOL_REL_GAP, dval) );
5273  break;
5274  case SCIP_LPPAR_OBJLIM: /* objective limit */
5275  {
5276  /* no restriction on dval */
5277  MSKobjsensee objsen;
5278  MOSEK_CALL( MSK_getobjsense(lpi->task, &objsen) );
5279  if (objsen == MSK_OBJECTIVE_SENSE_MINIMIZE)
5280  {
5281  MOSEK_CALL( MSK_putdouparam(lpi->task, MSK_DPAR_UPPER_OBJ_CUT, dval) );
5282  }
5283  else /* objsen == MSK_OBJECTIVE_SENSE_MAX */
5284  {
5285  MOSEK_CALL( MSK_putdouparam(lpi->task, MSK_DPAR_LOWER_OBJ_CUT, dval) );
5286  }
5287  break;
5288  }
5289  case SCIP_LPPAR_LPTILIM: /* LP time limit */
5290  assert( dval > 0.0 );
5291  /* mosek requires 0 <= dval
5292  *
5293  * However for consistency we assert the timelimit to be strictly positive.
5294  */
5295  MOSEK_CALL( MSK_putdouparam(lpi->task, MSK_DPAR_OPTIMIZER_MAX_TIME, dval) );
5296  break;
5297  case SCIP_LPPAR_MARKOWITZ: /* Markowitz tolerance */
5298  default:
5299  return SCIP_PARAMETERUNKNOWN;
5300  } /*lint !e788*/
5301 
5302  return SCIP_OKAY;
5303 }
5304 
5305 
5306 /*
5307  * Numerical Methods
5308  */
5309 
5310 
5311 /** returns value treated as infinity in the LP solver */
5313  SCIP_LPI* lpi /**< LP interface structure */
5314  )
5315 { /*lint --e{715}*/
5316  assert(MosekEnv != NULL);
5317  assert(lpi != NULL);
5318  assert(lpi->task != NULL);
5319 
5320  return MSK_INFINITY;
5321 }
5322 
5323 /** checks if given value is treated as infinity in the LP solver */
5325  SCIP_LPI* lpi, /**< LP interface structure */
5326  SCIP_Real val /**< value to be checked for infinity */
5327  )
5328 { /*lint --e{715}*/
5329  assert(MosekEnv != NULL);
5330  assert(lpi != NULL);
5331  assert(lpi->task != NULL);
5332 
5333  return IS_POSINF(val);
5334 }
5335 
5336 
5337 /*
5338  * File Interface Methods
5339  */
5340 
5341 
5342 /** reads LP from a file */
5344  SCIP_LPI* lpi, /**< LP interface structure */
5345  const char* fname /**< file name */
5346  )
5347 {
5348 #if MSK_VERSION_MAJOR < 9
5349  int olddataformat;
5350 #endif
5351 
5352  assert(MosekEnv != NULL);
5353  assert(lpi != NULL);
5354  assert(lpi->task != NULL);
5355  assert(fname != NULL);
5356 
5357  SCIPdebugMessage("Calling SCIPlpiReadLP (%d), filename <%s>\n", lpi->lpid, fname);
5358 
5359 #if MSK_VERSION_MAJOR < 9
5360  MOSEK_CALL( MSK_getintparam(lpi->task, MSK_IPAR_READ_DATA_FORMAT, &olddataformat) );
5361  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_READ_DATA_FORMAT, MSK_DATA_FORMAT_LP) );
5362  MOSEK_CALL( MSK_readdata(lpi->task, fname) );
5363  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_READ_DATA_FORMAT, olddataformat) );
5364 #else
5365  MOSEK_CALL( MSK_readdataformat(lpi->task, fname, MSK_DATA_FORMAT_LP, MSK_COMPRESS_FREE) );
5366 #endif
5367 
5368  return SCIP_OKAY;
5369 }
5370 
5371 /** writes LP to a file */
5373  SCIP_LPI* lpi, /**< LP interface structure */
5374  const char* fname /**< file name */
5375  )
5376 {
5377 #if MSK_VERSION_MAJOR < 9
5378  int olddataformat;
5379 #endif
5380 
5381  assert(MosekEnv != NULL);
5382  assert(lpi != NULL);
5383  assert(lpi->task != NULL);
5384  assert(fname != NULL);
5385 #if MSK_VERSION_MAJOR >= 9
5386  /* Mosek 9 derives file format from given filename */
5387  assert(strstr(fname, ".lp") != NULL);
5388 #endif
5389 
5390  SCIPdebugMessage("Calling SCIPlpiWriteLP (%d), filename <%s>\n", lpi->lpid, fname);
5391 
5392 #if MSK_VERSION_MAJOR < 9
5393  MOSEK_CALL( MSK_getintparam(lpi->task, MSK_IPAR_WRITE_DATA_FORMAT, &olddataformat) );
5394  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_WRITE_DATA_FORMAT, MSK_DATA_FORMAT_LP) );
5395  MOSEK_CALL( MSK_writedata(lpi->task, fname) );
5396  MOSEK_CALL( MSK_putintparam(lpi->task, MSK_IPAR_WRITE_DATA_FORMAT, olddataformat) );
5397 #else
5398  MOSEK_CALL( MSK_writedata(lpi->task, fname) );
5399 #endif
5400 
5401  return SCIP_OKAY;
5402 }
static SCIP_RETCODE ensureBkxMem(SCIP_LPI *lpi, int ncols)
Definition: lpi_msk.c:377
SCIP_RETCODE SCIPlpiCreate(SCIP_LPI **lpi, SCIP_MESSAGEHDLR *messagehdlr, const char *name, SCIP_OBJSEN objsen)
Definition: lpi_msk.c:806
ROWPACKET * skc
Definition: lpi_msk.c:182
SCIP_RETCODE SCIPlpiSetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int ival)
Definition: lpi_msk.c:5072
SCIP_RETCODE SCIPlpiStrongbranchesFrac(SCIP_LPI *lpi, int *cols, int ncols, SCIP_Real *psols, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_msk.c:3104
enum SCIP_LPSolQuality SCIP_LPSOLQUALITY
Definition: type_lpi.h:95
SCIP_Real SCIPlpiInfinity(SCIP_LPI *lpi)
Definition: lpi_msk.c:5312
COLPACKET * skx
Definition: lpi_msk.c:181
const char * SCIPlpiGetSolverName(void)
Definition: lpi_msk.c:728
static void scale_bound(MSKboundkeye *bk, double *bl, double *bu, double s)
Definition: lpi_msk.c:610
int restrictselectdef
Definition: lpi_msk.c:165
static void invalidateSolution(SCIP_LPI *lpi)
Definition: lpi_msk.c:434
#define BMSfreeMemoryArrayNull(ptr)
Definition: memory.h:140
SCIP_RETCODE SCIPlpiGetIntpar(SCIP_LPI *lpi, SCIP_LPPARAM type, int *ival)
Definition: lpi_msk.c:5014
SCIP_RETCODE SCIPlpiSetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, const SCIP_LPINORMS *lpinorms)
Definition: lpi_msk.c:4926
int nrows
Definition: lpi_none.c:39
SCIP_RETCODE SCIPlpiGetDualfarkas(SCIP_LPI *lpi, SCIP_Real *dualfarkas)
Definition: lpi_msk.c:3718
SCIP_RETCODE SCIPlpiChgCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real newval)
Definition: lpi_msk.c:1494
static SCIP_RETCODE checkState1(SCIP_LPI *lpi, int n, MSKstakeye *sk, SCIP_Bool isrow)
Definition: lpi_msk.c:4480
SCIP_PRICING pricing
Definition: lpi_clp.cpp:103
static SCIP_RETCODE ensureBkcMem(SCIP_LPI *lpi, int nrows)
Definition: lpi_msk.c:396
static SCIP_RETCODE ensureAptreMem(SCIP_LPI *lpi, int n)
Definition: lpi_msk.c:415
#define SCIP_MAXSTRLEN
Definition: def.h:273
SCIP_RETCODE SCIPlpiGetBase(SCIP_LPI *lpi, int *cstat, int *rstat)
Definition: lpi_msk.c:4012
SCIP_RETCODE SCIPlpiGetObj(SCIP_LPI *lpi, int firstcol, int lastcol, SCIP_Real *vals)
Definition: lpi_msk.c:1972
enum SCIP_ObjSen SCIP_OBJSEN
Definition: type_lpi.h:36
void * SCIPlpiGetSolverPointer(SCIP_LPI *lpi)
Definition: lpi_msk.c:749
SCIP_Bool SCIPlpiHasStateBasis(SCIP_LPI *lpi, SCIP_LPISTATE *lpistate)
Definition: lpi_msk.c:4785
static long bound
SCIP_Bool solved
Definition: lpi_clp.cpp:105
void SCIPdecodeDualBit(const SCIP_DUALPACKET *inp, int *out, int count)
Definition: bitencode.c:299
SCIP_Bool SCIPlpiHasPrimalRay(SCIP_LPI *lpi)
Definition: lpi_msk.c:3313
interface methods for specific LP solvers
SCIP_RETCODE SCIPlpiSolveBarrier(SCIP_LPI *lpi, SCIP_Bool crossover)
Definition: lpi_msk.c:2626
SCIP_RETCODE SCIPlpiAddRows(SCIP_LPI *lpi, int nrows, const SCIP_Real *lhs, const SCIP_Real *rhs, char **rownames, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
Definition: lpi_msk.c:1196
static void convertstat_scip2mosek_slack(const int *stat, int n, MSKstakeye *resstat)
Definition: lpi_msk.c:3977
SCIP_Bool SCIPlpiIsInfinity(SCIP_LPI *lpi, SCIP_Real val)
Definition: lpi_msk.c:5324
#define FALSE
Definition: def.h:73
int bkxsize
Definition: lpi_msk.c:157
SCIP_Bool SCIPlpiHasPrimalSolve(void)
Definition: lpi_msk.c:772
#define EPSEQ(x, y, eps)
Definition: def.h:188
SCIP_Bool SCIPlpiIsPrimalInfeasible(SCIP_LPI *lpi)
Definition: lpi_msk.c:3348
static SCIP_RETCODE convertstat_mosek2scip_slack(SCIP_LPI *lpi, SCIP_Bool iscon, MSKstakeye *sk, int m, int *stat)
Definition: lpi_msk.c:3881
#define TRUE
Definition: def.h:72
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
SCIP_RETCODE SCIPlpiGetBInvACol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_msk.c:4349
SCIP_RETCODE SCIPlpiStartStrongbranch(SCIP_LPI *lpi)
Definition: lpi_msk.c:2792
static SCIP_RETCODE getASlice(SCIP_LPI *lpi, SCIP_Bool iscon, int first, int last, int *nnonz, int *beg, int *ind, double *val)
Definition: lpi_msk.c:1757
SCIP_RETCODE SCIPlpiGetNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_msk.c:4906
#define IS_NEGINF(x)
Definition: lpi_msk.c:82
enum SCIP_LPParam SCIP_LPPARAM
Definition: type_lpi.h:64
#define BMSallocMemoryArray(ptr, num)
Definition: memory.h:115
SCIP_Bool SCIPlpiIsObjlimExc(SCIP_LPI *lpi)
Definition: lpi_msk.c:3502
SCIP_RETCODE SCIPlpiDelRows(SCIP_LPI *lpi, int firstrow, int lastrow)
Definition: lpi_msk.c:1275
static void MSKAPI printstr(MSKuserhandle_t handle, const char *str)
Definition: lpi_msk.c:240
MSKoptimizertype lastalgo
Definition: lpi_msk.c:149
#define SCIPdebugMessage
Definition: pub_message.h:87
MSKsolstae solsta
Definition: lpi_msk.c:178
#define SETBACK_LIMIT
Definition: lpi_msk.c:107
SCIP_RETCODE SCIPlpiGetCoef(SCIP_LPI *lpi, int row, int col, SCIP_Real *val)
Definition: lpi_msk.c:2055
#define BMSfreeMemory(ptr)
Definition: memory.h:137
enum SCIP_Pricing SCIP_PRICING
Definition: type_lpi.h:77
int lpid
Definition: lpi_msk.c:148
#define scipmskobjsen
Definition: lpi_msk.c:51
SCIP_RETCODE SCIPlpiGetBInvCol(SCIP_LPI *lpi, int c, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_msk.c:4196
SCIP_Bool SCIPlpiIsIterlimExc(SCIP_LPI *lpi)
Definition: lpi_msk.c:3514
SCIP_DUALPACKET COLPACKET
Definition: lpi_clp.cpp:117
SCIP_RETCODE SCIPlpiLoadColLP(SCIP_LPI *lpi, SCIP_OBJSEN objsen, int ncols, const SCIP_Real *obj, const SCIP_Real *lb, const SCIP_Real *ub, char **colnames, int nrows, const SCIP_Real *lhs, const SCIP_Real *rhs, char **rownames, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
Definition: lpi_msk.c:920
SCIP_Bool SCIPlpiIsDualUnbounded(SCIP_LPI *lpi)
Definition: lpi_msk.c:3421
int skcsize
Definition: lpi_msk.c:156
SCIP_RETCODE SCIPlpiScaleCol(SCIP_LPI *lpi, int col, SCIP_Real scaleval)
Definition: lpi_msk.c:1635
SCIP_DUALPACKET COLPACKET
Definition: lpi_msk.c:169
SCIP_RETCODE SCIPlpiReadState(SCIP_LPI *lpi, const char *fname)
Definition: lpi_msk.c:4803
SCIP_RETCODE SCIPlpiStrongbranchFrac(SCIP_LPI *lpi, int col, SCIP_Real psol, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_msk.c:3080
SCIP_RETCODE SCIPlpiGetNRows(SCIP_LPI *lpi, int *nrows)
Definition: lpi_msk.c:1702
packing single and dual bit values
#define BMSfreeMemoryArray(ptr)
Definition: memory.h:139
SCIP_RETCODE SCIPlpiGetSolFeasibility(SCIP_LPI *lpi, SCIP_Bool *primalfeasible, SCIP_Bool *dualfeasible)
Definition: lpi_msk.c:3230
static SCIP_RETCODE checkState(SCIP_LPI *lpi, int ncols, int nrows)
Definition: lpi_msk.c:4553
enum MSKoptimizertype_enum MSKoptimizertype
Definition: lpi_msk.c:54
#define SCIPerrorMessage
Definition: pub_message.h:55
int ncols
Definition: lpi_none.c:40
#define SCIPdebugPrintf
Definition: pub_message.h:90
SCIP_RETCODE SCIPlpiEndStrongbranch(SCIP_LPI *lpi)
Definition: lpi_msk.c:2805
SCIP_Bool SCIPlpiIsTimelimExc(SCIP_LPI *lpi)
Definition: lpi_msk.c:3526
static void convertstat_scip2mosek(const int *stat, int n, MSKstakeye *resstat)
Definition: lpi_msk.c:3946
static int optimizecount
Definition: lpi_msk.c:88
SCIP_RETCODE SCIPlpiSetBase(SCIP_LPI *lpi, const int *cstat, const int *rstat)
Definition: lpi_msk.c:4047
SCIP_RETCODE SCIPlpiWriteLP(SCIP_LPI *lpi, const char *fname)
Definition: lpi_msk.c:5372
SCIP_RETCODE SCIPlpiDelColset(SCIP_LPI *lpi, int *dstat)
Definition: lpi_msk.c:1137
SCIP_RETCODE SCIPlpiGetRowNames(SCIP_LPI *lpi, int firstrow, int lastrow, char **rownames, char *namestorage, int namestoragesize, int *storageleft)
Definition: lpi_msk.c:1927
SCIP_RETCODE SCIPlpiSetIntegralityInformation(SCIP_LPI *lpi, int ncols, int *intInfo)
Definition: lpi_msk.c:761
SCIP_Bool SCIPlpiExistsDualRay(SCIP_LPI *lpi)
Definition: lpi_msk.c:3380
SCIP_RETCODE SCIPlpiChgObjsen(SCIP_LPI *lpi, SCIP_OBJSEN objsen)
Definition: lpi_msk.c:1523
SCIP_RETCODE SCIPlpiGetObjval(SCIP_LPI *lpi, SCIP_Real *objval)
Definition: lpi_msk.c:3577
SCIP_DUALPACKET ROWPACKET
Definition: lpi_clp.cpp:119
static SCIP_RETCODE handle_singular(SCIP_LPI *lpi, int *basis, MSKrescodee res)
Definition: lpi_msk.c:3777
SCIP_Bool SCIPlpiHasDualSolve(void)
Definition: lpi_msk.c:780
SCIP_RETCODE SCIPlpiIgnoreInstability(SCIP_LPI *lpi, SCIP_Bool *success)
Definition: lpi_msk.c:3559
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:418
SCIP_RETCODE SCIPlpiDelCols(SCIP_LPI *lpi, int firstcol, int lastcol)
Definition: lpi_msk.c:1103
SCIP_RETCODE SCIPlpiClearState(SCIP_LPI *lpi)
Definition: lpi_msk.c:4748
#define NULL
Definition: lpi_spx1.cpp:155
int skxsize
Definition: lpi_msk.c:155
int * rstat
Definition: lpi_clp.cpp:99
SCIPInterval fabs(const SCIPInterval &x)
#define REALABS(x)
Definition: def.h:187
static SCIP_RETCODE setbase(SCIP_LPI *lpi)
Definition: lpi_msk.c:701
SCIP_RETCODE SCIPlpiGetSides(SCIP_LPI *lpi, int firstrow, int lastrow, SCIP_Real *lhss, SCIP_Real *rhss)
Definition: lpi_msk.c:2022
int bkcsize
Definition: lpi_msk.c:158
#define DEBUG_CHECK_STATE_TOL
Definition: lpi_msk.c:99
MSKtask_t task
Definition: lpi_msk.c:144
#define SCIP_CALL(x)
Definition: def.h:364
SCIP_Bool fromscratch
Definition: lpi_cpx.c:161
static SCIP_RETCODE getbase(SCIP_LPI *lpi, int ncols, int nrows)
Definition: lpi_msk.c:682
SCIP_RETCODE SCIPlpiChgSides(SCIP_LPI *lpi, int nrows, const int *ind, const SCIP_Real *lhs, const SCIP_Real *rhs)
Definition: lpi_msk.c:1453
SCIP_RETCODE SCIPlpiStrongbranchesInt(SCIP_LPI *lpi, int *cols, int ncols, SCIP_Real *psols, int itlim, SCIP_Real *down, SCIP_Real *up, SCIP_Bool *downvalid, SCIP_Bool *upvalid, int *iter)
Definition: lpi_msk.c:3168
SCIP_RETCODE SCIPlpiAddCols(SCIP_LPI *lpi, int ncols, const SCIP_Real *obj, const SCIP_Real *lb, const SCIP_Real *ub, char **colnames, int nnonz, const int *beg, const int *ind, const SCIP_Real *val)
Definition: lpi_msk.c:1014
void SCIPmessagePrintInfo(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:585
static int nextlpid
Definition: lpi_msk.c:89
static void lpistateFree(SCIP_LPISTATE **lpistate, BMS_BLKMEM *blkmem)
Definition: lpi_msk.c:4460
SCIP_RETCODE SCIPlpiFreeNorms(SCIP_LPI *lpi, BMS_BLKMEM *blkmem, SCIP_LPINORMS **lpinorms)
Definition: lpi_msk.c:4939
static SCIP_RETCODE getEndptrs(int n, const int *beg, int nnonz, MSKint32t *aptre)
Definition: lpi_msk.c:496
SCIP_Bool SCIPlpiIsDualFeasible(SCIP_LPI *lpi)
Definition: lpi_msk.c:3445
void SCIPencodeDualBit(const int *inp, SCIP_DUALPACKET *out, int count)
Definition: bitencode.c:229
SCIP_RETCODE SCIPlpiChgBounds(SCIP_LPI *lpi, int ncols, const int *ind, const SCIP_Real *lb, const SCIP_Real *ub)
Definition: lpi_msk.c:1395
MSKstakeye * skx
Definition: lpi_msk.c:150
#define EPSCEIL(x, eps)
Definition: def.h:197
SCIP_Bool lpinfo
Definition: lpi_msk.c:164
MSKsoltypee lastsolvetype
Definition: lpi_msk.c:160
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:456
static SCIP_RETCODE convertstat_mosek2scip(SCIP_LPI *lpi, SCIP_Bool iscon, MSKstakeye *sk, int n, int *stat)
Definition: lpi_msk.c:3807
static SCIP_RETCODE presolve(SCIP *scip, SCIP_Bool *unbounded, SCIP_Bool *infeasible)
Definition: scip_solve.c:1248
unsigned int SCIP_DUALPACKET
Definition: bitencode.h:33
static void scale_vec(int len, double *vec, double s)
Definition: lpi_msk.c:595
SCIP_RETCODE SCIPlpiGetBInvARow(SCIP_LPI *lpi, int row, const SCIP_Real *binvrow, SCIP_Real *coef, int *inds, int *ninds)
Definition: lpi_msk.c:4271
#define SCIP_ABORT_FALSE(x)
Definition: lpi_msk.c:69
static SCIP_RETCODE ensureStateMem(SCIP_LPI *lpi, int ncols, int nrows)
Definition: lpi_msk.c:653
SCIP_RETCODE SCIPlpiScaleRow(SCIP_LPI *lpi, int row, SCIP_Real scaleval)
Definition: lpi_msk.c:1573
#define MOSEK_CALL(x)
Definition: lpi_msk.c:56
#define SCIP_Bool
Definition: def.h:70
SCIP_RETCODE SCIPlpiSolvePrimal(SCIP_LPI *lpi)
Definition: