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