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