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
67typedef 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
140static int numstrongbranchmaxiterup = 0;
141static int numstrongbranchmaxiterdo = 0;
142static int numprimalmaxiter = 0;
143static int numdualmaxiter = 0;
144static int numstrongbranchobjup = 0;
145static int numstrongbranchobjdo = 0;
146static int numprimalobj = 0;
147static int numdualobj = 0;
148#endif
149
150#if DEBUG_PRINT_STAT > 0
151static int numstrongbranchmaxiterup = 0;
152static int numstrongbranchmaxiterdo = 0;
153static int numprimalmaxiter = 0;
154static int numdualmaxiter = 0;
155static int numstrongbranchobjup = 0;
156static int numstrongbranchobjdo = 0;
157static int numprimalobj = 0;
158static int numdualobj = 0;
159#endif
160
161
162/** internal data for Mosek LPI */
163struct 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
196typedef SCIP_DUALPACKET COLPACKET; /* each column needs two bits of information (basic/on_lower/on_upper) */
197#define COLS_PER_PACKET SCIP_DUALPACKETSIZE
198typedef 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 */
202struct 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 */
221static
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 */
248static
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 */
257static
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 */
266static
267void 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 */
284static
285SCIP_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 */
403static
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 */
422static
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 */
441static
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 */
460static
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 */
471static
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 */
522static
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 */
556static
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 */
578static
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 */
621static
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 */
636static
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 */
679static
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 */
708static
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 */
727static
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
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 */
1810static
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 */
2154static
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 */
2171static
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 */
2205static
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 */
2859static
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
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
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 */
3879static
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 {
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 */
3909static
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 */
3985static
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 */
4052static
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 {
4065 resstat[i] = MSK_SK_LOW;
4066 break;
4068 resstat[i] = MSK_SK_BAS;
4069 break;
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 */
4083static
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 {
4098 resstat[i] = MSK_SK_UPR; /* Reversed */
4099 break;
4101 resstat[i] = MSK_SK_BAS;
4102 break;
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 */
4565static
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 */
4591static
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 */
4611static
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 */
4686static
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 */
4707static
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 */
4731static
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 */
5096static 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 */
5121static
5122const 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 */
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 {