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