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