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