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