Scippy

SCIP

Solving Constraint Integer Programs

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