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