Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/numerical/backends/cplex_backend.pyx
4057 views
1
"""
2
CPLEX Backend
3
4
AUTHORS:
5
6
- Nathann Cohen (2010-10): initial implementation
7
8
"""
9
10
##############################################################################
11
# Copyright (C) 2010 Nathann Cohen <[email protected]>
12
# Distributed under the terms of the GNU General Public License (GPL)
13
# The full text of the GPL is available at:
14
# http://www.gnu.org/licenses/
15
##############################################################################
16
17
18
from sage.numerical.mip import MIPSolverException
19
20
cdef class CPLEXBackend(GenericBackend):
21
22
def __cinit__(self, maximization = True):
23
"""
24
Constructor
25
26
EXAMPLE::
27
28
sage: p = MixedIntegerLinearProgram(solver="CPLEX") # optional - CPLEX
29
"""
30
31
cdef int status
32
self.env = CPXopenCPLEX (&status)
33
check(status)
34
35
cdef char * tmp = ""
36
self.lp = CPXcreateprob (self.env, &status, tmp);
37
check(status)
38
39
if maximization:
40
self.set_sense(+1)
41
else:
42
self.set_sense(-1)
43
44
self.obj_constant_term = 0.0
45
46
cpdef int add_variable(self, lower_bound=0.0, upper_bound=None, binary=False, continuous=False, integer=False, obj=0.0, name=None) except -1:
47
"""
48
Add a variable.
49
50
This amounts to adding a new column to the matrix. By default,
51
the variable is both positive and real.
52
53
INPUT:
54
55
- ``lower_bound`` - the lower bound of the variable (default: 0)
56
57
- ``upper_bound`` - the upper bound of the variable (default: ``None``)
58
59
- ``binary`` - ``True`` if the variable is binary (default: ``False``).
60
61
- ``continuous`` - ``True`` if the variable is binary (default: ``True``).
62
63
- ``integer`` - ``True`` if the variable is binary (default: ``False``).
64
65
- ``obj`` - (optional) coefficient of this variable in the objective function (default: 0.0)
66
67
- ``name`` - an optional name for the newly added variable (default: ``None``).
68
69
OUTPUT: The index of the newly created variable
70
71
EXAMPLE::
72
73
sage: from sage.numerical.backends.generic_backend import get_solver
74
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
75
sage: p.ncols() # optional - CPLEX
76
0
77
sage: p.add_variable() # optional - CPLEX
78
0
79
sage: p.ncols() # optional - CPLEX
80
1
81
sage: p.add_variable(binary=True) # optional - CPLEX
82
1
83
sage: p.add_variable(lower_bound=-2.0, integer=True) # optional - CPLEX
84
2
85
sage: p.add_variable(continuous=True, integer=True) # optional - CPLEX
86
Traceback (most recent call last):
87
...
88
ValueError: ...
89
sage: p.add_variable(name='x',obj=1.0) # optional - CPLEX
90
3
91
sage: p.col_name(3) # optional - CPLEX
92
'x'
93
sage: p.objective_coefficient(3) # optional - CPLEX
94
1.0
95
96
"""
97
cdef char * c_name
98
cdef double c_coeff = obj
99
cdef int vtype = int(bool(binary)) + int(bool(continuous)) + int(bool(integer))
100
if vtype == 0:
101
continuous = True
102
elif vtype != 1:
103
raise ValueError("Exactly one parameter of 'binary', 'integer' and 'continuous' must be 'True'.")
104
105
cdef int status
106
status = CPXnewcols(self.env, self.lp, 1, NULL, NULL, NULL, NULL, NULL)
107
check(status)
108
109
cdef int n
110
n = CPXgetnumcols(self.env, self.lp) - 1
111
112
if lower_bound != 0.0:
113
self.variable_lower_bound(n, lower_bound)
114
if upper_bound is not None:
115
self.variable_upper_bound(n, upper_bound)
116
117
if binary:
118
self.set_variable_type(n,0)
119
elif integer:
120
self.set_variable_type(n,1)
121
122
if name is not None:
123
c_name = name
124
status = CPXchgcolname(self.env, self.lp, 1, &n, &c_name)
125
check(status)
126
127
if c_coeff:
128
status = CPXchgobj(self.env, self.lp, 1, &n, &c_coeff)
129
check(status)
130
131
return n
132
133
cpdef int add_variables(self, int number, lower_bound=0.0, upper_bound=None, binary=False, continuous=False, integer=False, obj=0.0, names=None) except -1:
134
"""
135
Add ``number`` new variables.
136
137
This amounts to adding new columns to the matrix. By default,
138
the variables are both positive and real.
139
140
INPUT:
141
142
- ``n`` - the number of new variables (must be > 0)
143
144
- ``lower_bound`` - the lower bound of the variable (default: 0)
145
146
- ``upper_bound`` - the upper bound of the variable (default: ``None``)
147
148
- ``binary`` - ``True`` if the variable is binary (default: ``False``).
149
150
- ``continuous`` - ``True`` if the variable is binary (default: ``True``).
151
152
- ``integer`` - ``True`` if the variable is binary (default: ``False``).
153
154
- ``obj`` - (optional) coefficient of all variables in the objective function (default: 0.0)
155
156
- ``names`` - optional list of names (default: ``None``)
157
158
OUTPUT: The index of the variable created last.
159
160
EXAMPLE::
161
162
sage: from sage.numerical.backends.generic_backend import get_solver
163
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
164
sage: p.ncols() # optional - CPLEX
165
0
166
sage: p.add_variables(5) # optional - CPLEX
167
4
168
sage: p.ncols() # optional - CPLEX
169
5
170
sage: p.add_variables(2, lower_bound=-2.0, integer=True, names=['a','b']) # optional - CPLEX
171
6
172
"""
173
cdef char * c_name
174
cdef double c_coeff = obj
175
cdef int vtype = int(bool(binary)) + int(bool(continuous)) + int(bool(integer))
176
if vtype == 0:
177
continuous = True
178
elif vtype != 1:
179
raise ValueError("Exactly one parameter of 'binary', 'integer' and 'continuous' must be 'True'.")
180
181
cdef int status
182
status = CPXnewcols(self.env, self.lp, number, NULL, NULL, NULL, NULL, NULL)
183
check(status)
184
185
cdef int n
186
n = CPXgetnumcols(self.env, self.lp) - 1
187
188
cdef int i, j
189
190
for 0<= i < number:
191
if lower_bound != 0.0:
192
self.variable_lower_bound(n - i, lower_bound)
193
if upper_bound is not None:
194
self.variable_upper_bound(n - i, upper_bound)
195
196
if binary:
197
self.set_variable_type(n - i,0)
198
elif integer:
199
self.set_variable_type(n - i,1)
200
201
if names:
202
j = n - i
203
c_name = names[i]
204
status = CPXchgcolname(self.env, self.lp, 1, &j, &c_name)
205
check(status)
206
207
if c_coeff:
208
j = n - i
209
status = CPXchgobj(self.env, self.lp, 1, &j, &c_coeff)
210
check(status)
211
212
return n
213
214
cpdef set_variable_type(self, int variable, int vtype):
215
r"""
216
Sets the type of a variable
217
218
INPUT:
219
220
- ``variable`` (integer) -- the variable's id
221
222
- ``vtype`` (integer) :
223
224
* 1 Integer
225
* 0 Binary
226
* -1 Real
227
228
EXAMPLE::
229
230
sage: from sage.numerical.backends.generic_backend import get_solver
231
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
232
sage: p.ncols() # optional - CPLEX
233
0
234
sage: p.add_variable() # optional - CPLEX
235
0
236
sage: p.set_variable_type(0,1) # optional - CPLEX
237
sage: p.is_variable_integer(0) # optional - CPLEX
238
True
239
"""
240
241
cdef int status
242
243
cdef char type
244
if vtype == 1:
245
type = 'I'
246
elif vtype == 0:
247
type = 'B'
248
else:
249
type = 'C'
250
251
status = CPXchgctype(self.env, self.lp, 1, &variable, &type)
252
check(status)
253
254
cpdef set_sense(self, int sense):
255
r"""
256
Sets the direction (maximization/minimization).
257
258
INPUT:
259
260
- ``sense`` (integer) :
261
262
* +1 => Maximization
263
* -1 => Minimization
264
265
EXAMPLE::
266
267
sage: from sage.numerical.backends.generic_backend import get_solver
268
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
269
sage: p.is_maximization() # optional - CPLEX
270
True
271
sage: p.set_sense(-1) # optional - CPLEX
272
sage: p.is_maximization() # optional - CPLEX
273
False
274
"""
275
276
CPXchgobjsen(self.env, self.lp, -sense)
277
278
cpdef objective_coefficient(self, int variable, coeff=None):
279
"""
280
Set or get the coefficient of a variable in the objective function
281
282
INPUT:
283
284
- ``variable`` (integer) -- the variable's id
285
286
- ``coeff`` (double) -- its coefficient or ``None`` for
287
reading (default: ``None``)
288
289
EXAMPLE::
290
291
sage: from sage.numerical.backends.generic_backend import get_solver
292
sage: p = get_solver(solver = "CPLEX") # optional -- CPLEX
293
sage: p.add_variable() # optional -- CPLEX
294
0
295
sage: p.objective_coefficient(0) # optional -- CPLEX
296
0.0
297
sage: p.objective_coefficient(0,2) # optional -- CPLEX
298
sage: p.objective_coefficient(0) # optional -- CPLEX
299
2.0
300
"""
301
302
cdef int status
303
cdef double value
304
305
if coeff is None:
306
status = CPXgetobj(self.env, self.lp, &value, variable, variable)
307
check(status)
308
return value
309
310
else:
311
value = coeff
312
status = CPXchgobj(self.env, self.lp, 1, &variable, &value)
313
check(status)
314
315
cpdef problem_name(self, char * name = NULL):
316
r"""
317
Returns or defines the problem's name
318
319
INPUT:
320
321
- ``name`` (``char *``) -- the problem's name. When set to
322
``NULL`` (default), the method returns the problem's name.
323
324
EXAMPLE::
325
326
sage: from sage.numerical.backends.generic_backend import get_solver
327
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
328
sage: p.problem_name("There once was a french fry") # optional - CPLEX
329
sage: print p.problem_name() # optional - CPLEX
330
There once was a french fry
331
"""
332
333
cdef int status
334
cdef int zero
335
cdef char * n
336
if name == NULL:
337
338
n = <char*> sage_malloc(500*sizeof(char))
339
status = CPXgetprobname(self.env, self.lp, n, 500, &zero)
340
check(status)
341
s = str(n)
342
sage_free(n)
343
return s
344
345
346
else:
347
status = CPXchgprobname(self.env, self.lp, name)
348
check(status)
349
350
351
cpdef set_objective(self, list coeff, double d = 0.0):
352
r"""
353
Sets the objective function.
354
355
INPUT:
356
357
- ``coeff`` -- a list of real values, whose ith element is the
358
coefficient of the ith variable in the objective function.
359
360
- ``d`` (double) -- the constant term in the linear function (set to `0` by default)
361
362
EXAMPLE::
363
364
sage: from sage.numerical.backends.generic_backend import get_solver
365
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
366
sage: p.add_variables(5) # optional - CPLEX
367
4
368
sage: p.set_objective([1, 1, 2, 1, 3]) # optional - CPLEX
369
sage: map(lambda x :p.objective_coefficient(x), range(5)) # optional - CPLEX
370
[1.0, 1.0, 2.0, 1.0, 3.0]
371
372
Constants in the objective function are respected::
373
374
sage: p = MixedIntegerLinearProgram(solver='CPLEX') # optional - CPLEX
375
sage: x,y = p[0], p[1] # optional - CPLEX
376
sage: p.add_constraint(2*x + 3*y, max = 6) # optional - CPLEX
377
sage: p.add_constraint(3*x + 2*y, max = 6) # optional - CPLEX
378
sage: p.set_objective(x + y + 7) # optional - CPLEX
379
sage: p.set_integer(x); p.set_integer(y) # optional - CPLEX
380
sage: p.solve() # optional - CPLEX
381
9.0
382
"""
383
384
cdef int status
385
cdef int n = self.ncols()
386
cdef double * c_coeff = <double *> sage_malloc(n * sizeof(double))
387
cdef int * c_indices = <int *> sage_malloc(n * sizeof(int))
388
389
for i,v in enumerate(coeff):
390
c_coeff[i] = v
391
c_indices[i] = i
392
393
status = CPXchgobj(self.env, self.lp, n, c_indices, c_coeff)
394
check(status)
395
396
sage_free(c_coeff)
397
sage_free(c_indices)
398
399
self.obj_constant_term = d
400
401
402
cpdef set_verbosity(self, int level):
403
r"""
404
Sets the log (verbosity) level
405
406
INPUT:
407
408
- ``level`` (integer) -- From 0 (no verbosity) to 3.
409
410
EXAMPLE::
411
412
sage: from sage.numerical.backends.generic_backend import get_solver
413
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
414
sage: p.set_verbosity(2) # optional - CPLEX
415
416
"""
417
418
cdef int status
419
if level == 0:
420
status = CPXsetintparam (self.env, CPX_PARAM_SCRIND, 0)
421
check(status)
422
else:
423
status = CPXsetintparam (self.env, CPX_PARAM_SCRIND, CPX_ON)
424
check(status)
425
426
cpdef remove_constraint(self, int i):
427
r"""
428
Remove a constraint from self.
429
430
INPUT:
431
432
- ``i`` -- index of the constraint to remove
433
434
EXAMPLE::
435
436
sage: p = MixedIntegerLinearProgram(solver='CPLEX')# optional - CPLEX
437
sage: x,y = p[0], p[1] # optional - CPLEX
438
sage: p.add_constraint(2*x + 3*y, max = 6) # optional - CPLEX
439
sage: p.add_constraint(3*x + 2*y, max = 6) # optional - CPLEX
440
sage: p.set_objective(x + y + 7) # optional - CPLEX
441
sage: p.set_integer(x); p.set_integer(y) # optional - CPLEX
442
sage: p.solve() # optional - CPLEX
443
9.0
444
sage: p.remove_constraint(0) # optional - CPLEX
445
sage: p.solve() # optional - CPLEX
446
10.0
447
sage: p.get_values([x,y]) # optional - CPLEX
448
[0.0, 3.0]
449
"""
450
cdef int status
451
status = CPXdelrows(self.env, self.lp, i, i)
452
check(status)
453
454
cpdef add_linear_constraints(self, int number, lower_bound, upper_bound, names = None):
455
"""
456
Add ``'number`` linear constraints.
457
458
INPUT:
459
460
- ``number`` (integer) -- the number of constraints to add.
461
462
- ``lower_bound`` - a lower bound, either a real value or ``None``
463
464
- ``upper_bound`` - an upper bound, either a real value or ``None``
465
466
- ``names`` - an optional list of names (default: ``None``)
467
468
EXAMPLE::
469
470
sage: from sage.numerical.backends.generic_backend import get_solver
471
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
472
sage: p.add_variables(5) # optional - CPLEX
473
4
474
sage: p.add_linear_constraints(5, None, 2) # optional - CPLEX
475
sage: p.row(4) # optional - CPLEX
476
([], [])
477
sage: p.row_bounds(4) # optional - CPLEX
478
(None, 2.0)
479
sage: p.add_linear_constraints(2, None, 2, names=['foo','bar']) # optional - Coin
480
"""
481
if lower_bound is None and upper_bound is None:
482
raise ValueError("At least one of 'upper_bound' or 'lower_bound' must be set.")
483
484
cdef int status
485
cdef char * sense = <char *> sage_malloc(number * sizeof(char))
486
cdef double * bound = <double *> sage_malloc(number * sizeof(double))
487
cdef double * rng = NULL
488
cdef int i
489
cdef char ** c_names = <char **> sage_malloc(number * sizeof(char *))
490
491
if upper_bound == lower_bound:
492
sense[0] = 'E'
493
bound[0] = lower_bound
494
495
elif upper_bound is not None and lower_bound is not None:
496
if upper_bound < lower_bound:
497
raise ValueError("The upper bound must be at least equal to the lower bound !")
498
499
rng = <double *> sage_malloc(number * sizeof(double))
500
501
sense[0] = 'R'
502
bound[0] = lower_bound
503
rng[0] = upper_bound - lower_bound
504
505
elif upper_bound is not None:
506
sense[0] = 'L'
507
bound[0] = upper_bound
508
509
elif lower_bound is not None:
510
sense[0] = 'G'
511
bound[0] = lower_bound
512
513
if names:
514
c_names[0] = names[0]
515
516
for 1<= i <number:
517
sense[i] = sense[0]
518
bound[i] = bound[0]
519
if rng != NULL:
520
rng[i] = rng[0]
521
if names:
522
c_names[i] = names[i]
523
524
status = CPXnewrows(self.env, self.lp, number, bound, sense, rng, c_names if names else NULL)
525
526
sage_free(sense)
527
sage_free(bound)
528
sage_free(c_names)
529
check(status)
530
531
cpdef add_linear_constraint(self, coefficients, lower_bound, upper_bound, name = None):
532
"""
533
Add a linear constraint.
534
535
INPUT:
536
537
- ``coefficients`` an iterable with ``(c,v)`` pairs where ``c``
538
is a variable index (integer) and ``v`` is a value (real
539
value).
540
541
- ``lower_bound`` - a lower bound, either a real value or ``None``
542
543
- ``upper_bound`` - an upper bound, either a real value or ``None``
544
545
- ``name`` - an optional name for this row (default: ``None``)
546
547
EXAMPLE::
548
549
sage: from sage.numerical.backends.generic_backend import get_solver
550
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
551
sage: p.add_variables(5) # optional - CPLEX
552
4
553
sage: p.add_linear_constraint( zip(range(5), range(5)), 2.0, 2.0) # optional - CPLEX
554
sage: p.row(0) # optional - CPLEX
555
([1, 2, 3, 4], [1.0, 2.0, 3.0, 4.0])
556
sage: p.row_bounds(0) # optional - CPLEX
557
(2.0, 2.0)
558
sage: p.add_linear_constraint( zip(range(5), range(5)), 1.0, 1.0, name='foo') # optional - CPLEX
559
sage: p.row_name(1) # optional - CPLEX
560
'foo'
561
562
"""
563
if lower_bound is None and upper_bound is None:
564
raise ValueError("At least one of 'upper_bound' or 'lower_bound' must be set.")
565
566
cdef int status
567
cdef int i, j
568
cdef int n = len(coefficients)
569
cdef int nrows = self.nrows()
570
cdef char sense
571
572
cdef char * c_name
573
574
cdef double * c_coeff
575
cdef int * c_indices
576
cdef int * c_row
577
cdef double bound
578
cdef double rng
579
cdef double c
580
581
c_coeff = <double *> sage_malloc(n * sizeof(double))
582
c_indices = <int *> sage_malloc(n * sizeof(int))
583
c_row = <int *> sage_malloc(n * sizeof(int))
584
585
for i, (j, c) in enumerate(coefficients):
586
c_coeff[i] = c
587
c_indices[i] = j
588
c_row[i] = nrows
589
590
if upper_bound is None and lower_bound is None:
591
pass
592
593
elif upper_bound == lower_bound:
594
sense = 'E'
595
bound = lower_bound
596
597
elif upper_bound is not None and lower_bound is not None:
598
if upper_bound < lower_bound:
599
raise ValueError("The upper bound must be at least equal to the lower bound !")
600
601
sense = 'R'
602
bound = lower_bound
603
rng = upper_bound - lower_bound
604
605
elif upper_bound is not None:
606
sense = 'L'
607
bound = upper_bound
608
609
elif lower_bound is not None:
610
sense = 'G'
611
bound = lower_bound
612
613
if name:
614
c_name = name
615
616
status = CPXnewrows(self.env, self.lp, 1, &bound, &sense, &rng, NULL if (name is None) else &c_name)
617
618
check(status)
619
status = CPXchgcoeflist(self.env, self.lp, n, c_row, c_indices, c_coeff)
620
check(status)
621
622
# Free memory
623
sage_free(c_coeff)
624
sage_free(c_indices)
625
sage_free(c_row)
626
627
cpdef row(self, int index):
628
r"""
629
Returns a row
630
631
INPUT:
632
633
- ``index`` (integer) -- the constraint's id.
634
635
OUTPUT:
636
637
A pair ``(indices, coeffs)`` where ``indices`` lists the
638
entries whose coefficient is nonzero, and to which ``coeffs``
639
associates their coefficient on the model of the
640
``add_linear_constraint`` method.
641
642
EXAMPLE::
643
644
sage: from sage.numerical.backends.generic_backend import get_solver
645
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
646
sage: p.add_variables(5) # optional - CPLEX
647
4
648
sage: p.add_linear_constraint(zip(range(5), range(5)), 2, 2) # optional - CPLEX
649
sage: p.row(0) # optional - CPLEX
650
([1, 2, 3, 4], [1.0, 2.0, 3.0, 4.0])
651
sage: p.row_bounds(0) # optional - CPLEX
652
(2.0, 2.0)
653
"""
654
655
cdef int status
656
cdef int n,i
657
cdef int zero
658
cdef list indices = []
659
cdef list values = []
660
661
cdef double * c_coeff = <double *> sage_malloc((self.ncols()+10) * sizeof(double))
662
cdef int * c_indices = <int *> sage_malloc((self.ncols()+10) * sizeof(int))
663
664
status = CPXgetrows(self.env, self.lp, &n, &zero, c_indices, c_coeff, self.ncols()+3, &zero, index, index)
665
666
check(status)
667
668
for 0<= i<n:
669
indices.append(c_indices[i])
670
values.append(c_coeff[i])
671
672
sage_free(c_coeff)
673
sage_free(c_indices)
674
675
return (indices, values)
676
677
cpdef row_bounds(self, int index):
678
r"""
679
Returns the bounds of a specific constraint.
680
681
INPUT:
682
683
- ``index`` (integer) -- the constraint's id.
684
685
OUTPUT:
686
687
A pair ``(lower_bound, upper_bound)``. Each of them can be set
688
to ``None`` if the constraint is not bounded in the
689
corresponding direction, and is a real value otherwise.
690
691
EXAMPLE::
692
693
sage: from sage.numerical.backends.generic_backend import get_solver
694
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
695
sage: p.add_variables(5) # optional - CPLEX
696
4
697
sage: p.add_linear_constraint(zip(range(5), range(5)), 2, 2) # optional - CPLEX
698
sage: p.row(0) # optional - CPLEX
699
([1, 2, 3, 4], [1.0, 2.0, 3.0, 4.0])
700
sage: p.row_bounds(0) # optional - CPLEX
701
(2.0, 2.0)
702
"""
703
704
cdef int status
705
cdef double rng
706
cdef double value
707
status = CPXgetrhs(self.env, self.lp, &value, index, index)
708
check(status)
709
710
cdef char direction
711
status = CPXgetsense(self.env, self.lp, &direction, index, index)
712
check(status)
713
714
if direction == 'L':
715
return (None, value)
716
elif direction == 'G':
717
return (value, None)
718
elif direction == 'E':
719
return (value, value)
720
elif direction == 'R':
721
status = CPXgetrngval(self.env, self.lp, &rng, index, index)
722
check(status)
723
return (value, value + rng)
724
725
cpdef col_bounds(self, int index):
726
r"""
727
Returns the bounds of a specific variable.
728
729
INPUT:
730
731
- ``index`` (integer) -- the variable's id.
732
733
OUTPUT:
734
735
A pair ``(lower_bound, upper_bound)``. Each of them can be set
736
to ``None`` if the variable is not bounded in the
737
corresponding direction, and is a real value otherwise.
738
739
EXAMPLE::
740
741
sage: from sage.numerical.backends.generic_backend import get_solver
742
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
743
sage: p.add_variable() # optional - CPLEX
744
0
745
sage: p.col_bounds(0) # optional - CPLEX
746
(0.0, None)
747
sage: p.variable_upper_bound(0, 5) # optional - CPLEX
748
sage: p.col_bounds(0) # optional - CPLEX
749
(0.0, 5.0)
750
"""
751
752
cdef int status
753
cdef double ub
754
cdef double lb
755
756
status = CPXgetub(self.env, self.lp, &ub, index, index)
757
check(status)
758
759
status = CPXgetlb(self.env, self.lp, &lb, index, index)
760
check(status)
761
762
return (None if lb <= -int(CPX_INFBOUND) else lb,
763
None if ub >= +int(CPX_INFBOUND) else ub)
764
765
cpdef add_col(self, list indices, list coeffs):
766
r"""
767
Adds a column.
768
769
INPUT:
770
771
- ``indices`` (list of integers) -- this list constains the
772
indices of the constraints in which the variable's
773
coefficient is nonzero
774
775
- ``coeffs`` (list of real values) -- associates a coefficient
776
to the variable in each of the constraints in which it
777
appears. Namely, the ith entry of ``coeffs`` corresponds to
778
the coefficient of the variable in the constraint
779
represented by the ith entry in ``indices``.
780
781
.. NOTE::
782
783
``indices`` and ``coeffs`` are expected to be of the same
784
length.
785
786
EXAMPLE::
787
788
sage: from sage.numerical.backends.generic_backend import get_solver
789
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
790
sage: p.ncols() # optional - CPLEX
791
0
792
sage: p.nrows() # optional - CPLEX
793
0
794
sage: p.add_linear_constraints(5, 0, None) # optional - CPLEX
795
sage: p.add_col(range(5), range(5)) # optional - CPLEX
796
sage: p.nrows() # optional - CPLEX
797
5
798
"""
799
800
cdef int status
801
cdef int i
802
cdef int n = len(indices)
803
cdef int ncols = self.ncols()
804
805
status = CPXnewcols(self.env, self.lp, 1, NULL, NULL, NULL, NULL, NULL)
806
807
808
check(status)
809
810
cdef double * c_coeff = <double *> sage_malloc(n * sizeof(double))
811
cdef int * c_indices = <int *> sage_malloc(n * sizeof(int))
812
cdef int * c_col = <int *> sage_malloc(n * sizeof(int))
813
814
for 0<= i < n:
815
c_coeff[i] = coeffs[i]
816
c_indices[i] = indices[i]
817
c_col[i] = ncols
818
819
820
status = CPXchgcoeflist(self.env, self.lp, n, c_indices, c_col, c_coeff)
821
check(status)
822
823
sage_free(c_coeff)
824
sage_free(c_indices)
825
sage_free(c_col)
826
827
828
cpdef int solve(self) except -1:
829
r"""
830
Solves the problem.
831
832
.. NOTE::
833
834
This method raises ``MIPSolverException`` exceptions when
835
the solution can not be computed for any reason (none
836
exists, or the LP solver was not able to find it, etc...)
837
838
EXAMPLE::
839
840
sage: from sage.numerical.backends.generic_backend import get_solver
841
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
842
sage: p.add_linear_constraints(5, 0, None) # optional - CPLEX
843
sage: p.add_col(range(5), range(5)) # optional - CPLEX
844
sage: p.solve() # optional - CPLEX
845
0
846
sage: p.objective_coefficient(0,1) # optional - CPLEX
847
sage: p.solve() # optional - CPLEX
848
Traceback (most recent call last):
849
...
850
MIPSolverException: ...
851
"""
852
853
cdef int status
854
cdef int ptype
855
cdef int solnmethod_p, solntype_p, pfeasind_p, dfeasind_p
856
857
ptype = CPXgetprobtype(self.env, self.lp)
858
859
if ptype == 1:
860
status = CPXmipopt(self.env, self.lp)
861
elif ptype == 0:
862
status = CPXlpopt(self.env, self.lp)
863
else:
864
raise MIPSolverException("CPLEX: Unknown problem type")
865
866
check(status)
867
868
status = CPXsolninfo(self.env, self.lp, &solnmethod_p, &solntype_p, &pfeasind_p, &dfeasind_p)
869
check(status)
870
871
if not pfeasind_p:
872
raise MIPSolverException("CPLEX: The primal has no feasible solution")
873
if not dfeasind_p:
874
raise MIPSolverException("CPLEX: The problem is unbounded")
875
876
877
return 0
878
879
880
cpdef double get_objective_value(self):
881
r"""
882
Returns the value of the objective function.
883
884
.. NOTE::
885
886
Has no meaning unless ``solve`` has been called before.
887
888
EXAMPLE::
889
890
sage: from sage.numerical.backends.generic_backend import get_solver
891
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
892
sage: p.add_variables(2) # optional - CPLEX
893
1
894
sage: p.add_linear_constraint([(0,1), (1,2)], None, 3) # optional - CPLEX
895
sage: p.set_objective([2, 5]) # optional - CPLEX
896
sage: p.solve() # optional - CPLEX
897
0
898
sage: p.get_objective_value() # optional - CPLEX
899
7.5
900
sage: p.get_variable_value(0) # optional - CPLEX
901
0.0
902
sage: p.get_variable_value(1) # optional - CPLEX
903
1.5
904
"""
905
906
cdef int status
907
cdef double value
908
status = CPXgetobjval (self.env, self.lp, &value)
909
check(status)
910
911
return value + self.obj_constant_term
912
913
914
cpdef double get_variable_value(self, int variable):
915
r"""
916
Returns the value of a variable given by the solver.
917
918
.. NOTE::
919
920
Has no meaning unless ``solve`` has been called before.
921
922
EXAMPLE::
923
924
sage: from sage.numerical.backends.generic_backend import get_solver
925
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
926
sage: p.add_variables(2) # optional - CPLEX
927
1
928
sage: p.add_linear_constraint([(0,1), (1,2)], None, 3) # optional - CPLEX
929
sage: p.set_objective([2, 5]) # optional - CPLEX
930
sage: p.solve() # optional - CPLEX
931
0
932
sage: p.get_objective_value() # optional - CPLEX
933
7.5
934
sage: p.get_variable_value(0) # optional - CPLEX
935
0.0
936
sage: p.get_variable_value(1) # optional - CPLEX
937
1.5
938
"""
939
940
cdef int status
941
cdef int zero
942
cdef char ctype
943
cdef double value
944
status = CPXgetx(self.env, self.lp, &value, variable, variable)
945
check(status)
946
947
status = CPXgetctype(self.env, self.lp, &ctype, variable, variable)
948
949
return value if (status == 3003 or ctype=='C') else round(value)
950
951
cpdef int ncols(self):
952
r"""
953
Returns the number of columns/variables.
954
955
EXAMPLE::
956
957
sage: from sage.numerical.backends.generic_backend import get_solver
958
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
959
sage: p.ncols() # optional - CPLEX
960
0
961
sage: p.add_variables(2) # optional - CPLEX
962
1
963
sage: p.ncols() # optional - CPLEX
964
2
965
"""
966
967
return CPXgetnumcols(self.env, self.lp)
968
969
cpdef int nrows(self):
970
r"""
971
Returns the number of rows/constraints.
972
973
EXAMPLE::
974
975
sage: from sage.numerical.backends.generic_backend import get_solver
976
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
977
sage: p.nrows() # optional - CPLEX
978
0
979
sage: p.add_linear_constraints(2, 2, None) # optional - CPLEX
980
sage: p.nrows() # optional - CPLEX
981
2
982
"""
983
984
return CPXgetnumrows(self.env, self.lp)
985
986
cpdef row_name(self, int index):
987
r"""
988
Return the ``index`` th row name
989
990
INPUT:
991
992
- ``index`` (integer) -- the row's id
993
994
EXAMPLE::
995
996
sage: from sage.numerical.backends.generic_backend import get_solver
997
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
998
sage: p.add_linear_constraints(1, 2, None, names=['Empty constraint 1']) # optional - CPLEX
999
sage: p.row_name(0) # optional - CPLEX
1000
'Empty constraint 1'
1001
"""
1002
1003
cdef int status
1004
cdef int zero
1005
cdef char * n
1006
1007
n = <char *>sage_malloc(500*sizeof(char))
1008
status = CPXgetrowname(self.env, self.lp, &n, n, 500, &zero, index, index)
1009
if status == 1219:
1010
sage_free(n)
1011
return ""
1012
check(status)
1013
1014
s = str(n)
1015
sage_free(n)
1016
1017
return s
1018
1019
cpdef col_name(self, int index):
1020
r"""
1021
Returns the ``index`` th col name.
1022
1023
INPUT:
1024
1025
- ``index`` (integer) -- the col's id
1026
1027
EXAMPLE::
1028
1029
sage: from sage.numerical.backends.generic_backend import get_solver
1030
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
1031
sage: p.add_variable(name='I am a variable') # optional - CPLEX
1032
0
1033
sage: p.col_name(0) # optional - CPLEX
1034
'I am a variable'
1035
"""
1036
1037
cdef int status
1038
cdef char * n
1039
cdef int zero
1040
1041
n = <char *>sage_malloc(500*sizeof(char))
1042
status = CPXgetcolname(self.env, self.lp, &n, n, 500, &zero, index, index)
1043
if status == 1219:
1044
sage_free(n)
1045
return ""
1046
check(status)
1047
1048
s = str(n)
1049
sage_free(n)
1050
return s
1051
1052
cpdef bint is_variable_binary(self, int index):
1053
r"""
1054
Tests whether the given variable is of binary type.
1055
1056
INPUT:
1057
1058
- ``index`` (integer) -- the variable's id
1059
1060
EXAMPLE::
1061
1062
sage: from sage.numerical.backends.generic_backend import get_solver
1063
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
1064
sage: p.ncols() # optional - CPLEX
1065
0
1066
sage: p.add_variable() # optional - CPLEX
1067
0
1068
sage: p.set_variable_type(0,0) # optional - CPLEX
1069
sage: p.is_variable_binary(0) # optional - CPLEX
1070
True
1071
1072
"""
1073
1074
cdef int status
1075
cdef char ctype
1076
1077
status = CPXgetctype(self.env, self.lp, &ctype, index, index)
1078
1079
# status = 3003 when the problem is a LP and not a MILP
1080
if status == 3003:
1081
return False
1082
1083
check(status)
1084
1085
return ctype == 'B'
1086
1087
1088
cpdef bint is_variable_integer(self, int index):
1089
r"""
1090
Tests whether the given variable is of integer type.
1091
1092
INPUT:
1093
1094
- ``index`` (integer) -- the variable's id
1095
1096
EXAMPLE::
1097
1098
sage: from sage.numerical.backends.generic_backend import get_solver
1099
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
1100
sage: p.ncols() # optional - CPLEX
1101
0
1102
sage: p.add_variable() # optional - CPLEX
1103
0
1104
sage: p.set_variable_type(0,1) # optional - CPLEX
1105
sage: p.is_variable_integer(0) # optional - CPLEX
1106
True
1107
"""
1108
1109
cdef int status
1110
cdef char ctype
1111
1112
status = CPXgetctype(self.env, self.lp, &ctype, index, index)
1113
1114
# status = 3003 when the problem is a LP and not a MILP
1115
if status == 3003:
1116
return False
1117
1118
check(status)
1119
1120
return ctype == 'I'
1121
1122
1123
cpdef bint is_variable_continuous(self, int index):
1124
r"""
1125
Tests whether the given variable is of continuous/real type.
1126
1127
INPUT:
1128
1129
- ``index`` (integer) -- the variable's id
1130
1131
EXAMPLE::
1132
1133
sage: from sage.numerical.backends.generic_backend import get_solver
1134
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
1135
sage: p.ncols() # optional - CPLEX
1136
0
1137
sage: p.add_variable() # optional - CPLEX
1138
0
1139
sage: p.is_variable_continuous(0) # optional - CPLEX
1140
True
1141
sage: p.set_variable_type(0,1) # optional - CPLEX
1142
sage: p.is_variable_continuous(0) # optional - CPLEX
1143
False
1144
1145
"""
1146
1147
cdef int status
1148
cdef char ctype
1149
1150
status = CPXgetctype(self.env, self.lp, &ctype, index, index)
1151
1152
# status = 3003 when the problem is a LP and not a MILP
1153
if status == 3003:
1154
return True
1155
1156
check(status)
1157
1158
return ctype == 'C'
1159
1160
1161
cpdef bint is_maximization(self):
1162
r"""
1163
Tests whether the problem is a maximization
1164
1165
EXAMPLE::
1166
1167
sage: from sage.numerical.backends.generic_backend import get_solver
1168
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
1169
sage: p.is_maximization() # optional - CPLEX
1170
True
1171
sage: p.set_sense(-1) # optional - CPLEX
1172
sage: p.is_maximization() # optional - CPLEX
1173
False
1174
"""
1175
1176
return -1 == CPXgetobjsen(self.env, self.lp)
1177
1178
cpdef variable_upper_bound(self, int index, value = False):
1179
r"""
1180
Returns or defines the upper bound on a variable
1181
1182
INPUT:
1183
1184
- ``index`` (integer) -- the variable's id
1185
1186
- ``value`` -- real value, or ``None`` to mean that the
1187
variable has not upper bound. When set to ``False``
1188
(default), the method returns the current value.
1189
1190
EXAMPLE::
1191
1192
sage: from sage.numerical.backends.generic_backend import get_solver
1193
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
1194
sage: p.add_variable() # optional - CPLEX
1195
0
1196
sage: p.col_bounds(0) # optional - CPLEX
1197
(0.0, None)
1198
sage: p.variable_upper_bound(0, 5) # optional - CPLEX
1199
sage: p.col_bounds(0) # optional - CPLEX
1200
(0.0, 5.0)
1201
"""
1202
cdef int status
1203
cdef double ub
1204
cdef char x
1205
cdef double c_value
1206
1207
if value == False:
1208
1209
status = CPXgetub(self.env, self.lp, &ub, index, index)
1210
check(status)
1211
1212
return ub if ub < int(CPX_INFBOUND) else None
1213
1214
else:
1215
1216
x = 'U'
1217
c_value = value if value is not None else +CPX_INFBOUND
1218
status = CPXchgbds(self.env, self.lp, 1, &index, &x, &c_value)
1219
check(status)
1220
1221
cpdef variable_lower_bound(self, int index, value = False):
1222
r"""
1223
Returns or defines the lower bound on a variable
1224
1225
INPUT:
1226
1227
- ``index`` (integer) -- the variable's id
1228
1229
- ``value`` -- real value, or ``None`` to mean that the
1230
variable has not lower bound. When set to ``False``
1231
(default), the method returns the current value.
1232
1233
EXAMPLE::
1234
1235
sage: from sage.numerical.backends.generic_backend import get_solver
1236
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
1237
sage: p.add_variable() # optional - CPLEX
1238
0
1239
sage: p.col_bounds(0) # optional - CPLEX
1240
(0.0, None)
1241
sage: p.variable_lower_bound(0, 5) # optional - CPLEX
1242
sage: p.col_bounds(0) # optional - CPLEX
1243
(5.0, None)
1244
"""
1245
cdef int status
1246
cdef double lb
1247
cdef char x
1248
cdef double c_value
1249
1250
if value == False:
1251
status = CPXgetlb(self.env, self.lp, &lb, index, index)
1252
check(status)
1253
return None if lb <= int(-CPX_INFBOUND) else lb
1254
1255
else:
1256
x = 'L'
1257
c_value = value if value is not None else -CPX_INFBOUND
1258
status = CPXchgbds(self.env, self.lp, 1, &index, &x, &c_value)
1259
check(status)
1260
1261
cpdef write_lp(self, char * filename):
1262
r"""
1263
Writes the problem to a .lp file
1264
1265
INPUT:
1266
1267
- ``filename`` (string)
1268
1269
EXAMPLE::
1270
1271
sage: from sage.numerical.backends.generic_backend import get_solver
1272
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
1273
sage: p.add_variables(2) # optional - CPLEX
1274
1
1275
sage: p.add_linear_constraint([(0, 1), (1, 2)], None, 3) # optional - CPLEX
1276
sage: p.set_objective([2, 5]) # optional - CPLEX
1277
sage: p.write_lp(SAGE_TMP+"/lp_problem.lp") # optional - CPLEX
1278
"""
1279
1280
cdef int status
1281
cdef char * ext = "LP"
1282
status = CPXwriteprob(self.env, self.lp, filename, ext)
1283
check(status)
1284
1285
cpdef write_mps(self, char * filename, int modern):
1286
r"""
1287
Writes the problem to a .mps file
1288
1289
INPUT:
1290
1291
- ``filename`` (string)
1292
1293
EXAMPLE::
1294
1295
sage: from sage.numerical.backends.generic_backend import get_solver
1296
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
1297
sage: p.add_variables(2) # optional - CPLEX
1298
1
1299
sage: p.add_linear_constraint([(0, 1), (1, 2)], None, 3) # optional - CPLEX
1300
sage: p.set_objective([2, 5]) # optional - CPLEX
1301
sage: p.write_lp(SAGE_TMP+"/lp_problem.lp") # optional - CPLEX
1302
"""
1303
1304
cdef int status
1305
cdef char * ext = "MPS"
1306
status = CPXwriteprob(self.env, self.lp, filename, ext)
1307
check(status)
1308
1309
cpdef CPLEXBackend copy(self):
1310
r"""
1311
Returns a copy of self.
1312
1313
EXAMPLE::
1314
1315
sage: from sage.numerical.backends.generic_backend import get_solver
1316
sage: p = MixedIntegerLinearProgram(solver = "CPLEX") # optional - CPLEX
1317
sage: b = p.new_variable() # optional - CPLEX
1318
sage: p.add_constraint(b[1] + b[2] <= 6) # optional - CPLEX
1319
sage: p.set_objective(b[1] + b[2]) # optional - CPLEX
1320
sage: copy(p).solve() # optional - CPLEX
1321
6.0
1322
"""
1323
cdef CPLEXBackend p = CPLEXBackend()
1324
1325
p.lp = CPXcloneprob(p.env, self.lp, &status)
1326
check(status)
1327
1328
p._mixed = self._mixed
1329
p.current_sol = self.current_sol
1330
1331
status = CPXchgprobtype(p.env, p.lp, CPXgetprobtype(self.env, self.lp))
1332
check(status)
1333
1334
return p
1335
1336
cpdef solver_parameter(self, name, value = None):
1337
"""
1338
Return or define a solver parameter
1339
1340
INPUT:
1341
1342
- ``name`` (string) -- the parameter
1343
1344
- ``value`` -- the parameter's value if it is to be defined,
1345
or ``None`` (default) to obtain its current value.
1346
1347
.. NOTE::
1348
1349
The list of available parameters is available at
1350
:meth:`sage.numerical.mip.MixedIntegerlinearProgram.solver_parameter`
1351
1352
EXAMPLE::
1353
1354
sage: from sage.numerical.backends.generic_backend import get_solver
1355
sage: p = get_solver(solver = "CPLEX") # optional - CPLEX
1356
sage: p.solver_parameter("timelimit", 60) # optional - CPLEX
1357
sage: p.solver_parameter("timelimit") # optional - CPLEX
1358
60.0
1359
"""
1360
cdef int intv
1361
cdef double doublev
1362
cdef char * strv
1363
1364
# If the name has to be translated to a CPLEX parameter ID
1365
if name == "timelimit":
1366
name = "CPX_PARAM_TILIM"
1367
1368
cdef int paramid = parameters.get(name,-1)
1369
1370
if paramid == -1:
1371
raise ValueError("This parameter is not available.")
1372
1373
# Type of the parameter. Can be INT (1), Double(2) or String(3)
1374
cdef int paramtype
1375
CPXgetparamtype(self.env, paramid, &paramtype)
1376
1377
if value is None:
1378
if paramtype == 1:
1379
CPXgetintparam(self.env, paramid, &intv)
1380
return intv
1381
elif paramtype == 2:
1382
CPXgetdblparam(self.env, paramid, &doublev)
1383
return doublev
1384
else:
1385
strv = <char *>sage_malloc(500*sizeof(char))
1386
CPXgetstrparam(self.env, paramid, strv)
1387
s = str(strv)
1388
sage_free(strv)
1389
return s
1390
else:
1391
if paramtype == 1:
1392
CPXsetintparam(self.env, paramid, value)
1393
elif paramtype == 2:
1394
CPXsetdblparam(self.env, paramid, value)
1395
else:
1396
CPXsetstrparam(self.env, paramid, value)
1397
1398
def __dealloc__(self):
1399
r"""
1400
Destructor for the class
1401
"""
1402
cdef int status
1403
1404
if self.lp != NULL:
1405
status = CPXfreeprob(self.env, &self.lp)
1406
1407
if self.env != NULL:
1408
status = CPXcloseCPLEX(&self.env)
1409
1410
cdef check(number):
1411
r"""
1412
Given a number, raises the corresponding exception or does nothing
1413
if ``number == 0``.
1414
1415
- ``number`` (integer) -- number corresponding to the error. If
1416
this number is unknown, the message contained in the raised
1417
exception will mention it.
1418
"""
1419
1420
# Below 1000 are 0 (no error), and some quality reports (but the
1421
# ERR* codes are above 1000)
1422
if number > 1000:
1423
from sage.numerical.mip import MIPSolverException
1424
default = "Error reported by the solver (unknown error number : "+str(number)+")"
1425
raise MIPSolverException("CPLEX: "+errors.get(number,default))
1426
1427
# Error codes
1428
#
1429
# Todo : when common error codes are returned, rewrite the message to
1430
# be more meaningful
1431
1432
cdef dict errors
1433
1434
errors = {
1435
1001 : "CPXERR_NO_MEMORY",
1436
1002 : "CPXERR_NO_ENVIRONMENT",
1437
1003 : "CPXERR_BAD_ARGUMENT",
1438
1004 : "CPXERR_NULL_POINTER",
1439
1006 : "CPXERR_CALLBACK",
1440
1009 : "CPXERR_NO_PROBLEM",
1441
1012 : "CPXERR_LIMITS_TOO_BIG",
1442
1013 : "CPXERR_BAD_PARAM_NUM",
1443
1014 : "CPXERR_PARAM_TOO_SMALL",
1444
1015 : "CPXERR_PARAM_TOO_BIG",
1445
1016 : "CPXERR_RESTRICTED_VERSION",
1446
1017 : "CPXERR_NOT_FOR_MIP",
1447
1018 : "CPXERR_NOT_FOR_QP",
1448
1019 : "CPXERR_CHILD_OF_CHILD",
1449
1020 : "CPXERR_TOO_MANY_THREADS",
1450
1021 : "CPXERR_CANT_CLOSE_CHILD",
1451
1022 : "CPXERR_BAD_PROB_TYPE",
1452
1023 : "CPXERR_NOT_ONE_PROBLEM",
1453
1024 : "CPXERR_NOT_MILPCLASS",
1454
1026 : "CPXERR_STR_PARAM_TOO_LONG",
1455
1027 : "CPXERR_DECOMPRESSION",
1456
1028 : "CPXERR_BAD_PARAM_NAME",
1457
1029 : "CPXERR_NOT_MIQPCLASS",
1458
1031 : "CPXERR_NOT_FOR_QCP",
1459
1051 : "CPXERR_MSG_NO_CHANNEL",
1460
1052 : "CPXERR_MSG_NO_FILEPTR",
1461
1053 : "CPXERR_MSG_NO_FUNCTION",
1462
1101 : "CPXERR_PRESLV_INForUNBD",
1463
1103 : "CPXERR_PRESLV_NO_PROB",
1464
1106 : "CPXERR_PRESLV_ABORT",
1465
1107 : "CPXERR_PRESLV_BASIS_MEM",
1466
1108 : "CPXERR_PRESLV_COPYSOS",
1467
1109 : "CPXERR_PRESLV_COPYORDER",
1468
1110 : "CPXERR_PRESLV_SOLN_MIP",
1469
1111 : "CPXERR_PRESLV_SOLN_QP",
1470
1112 : "CPXERR_PRESLV_START_LP",
1471
1114 : "CPXERR_PRESLV_FAIL_BASIS",
1472
1115 : "CPXERR_PRESLV_NO_BASIS",
1473
1117 : "CPXERR_PRESLV_INF",
1474
1118 : "CPXERR_PRESLV_UNBD",
1475
1119 : "CPXERR_PRESLV_DUAL",
1476
1120 : "CPXERR_PRESLV_UNCRUSHFORM",
1477
1121 : "CPXERR_PRESLV_CRUSHFORM",
1478
1122 : "CPXERR_PRESLV_BAD_PARAM",
1479
1123 : "CPXERR_PRESLV_TIME_LIM",
1480
1200 : "CPXERR_INDEX_RANGE",
1481
1201 : "CPXERR_COL_INDEX_RANGE",
1482
1203 : "CPXERR_ROW_INDEX_RANGE",
1483
1205 : "CPXERR_INDEX_RANGE_LOW",
1484
1206 : "CPXERR_INDEX_RANGE_HIGH",
1485
1207 : "CPXERR_NEGATIVE_SURPLUS",
1486
1208 : "CPXERR_ARRAY_TOO_LONG",
1487
1209 : "CPXERR_NAME_CREATION",
1488
1210 : "CPXERR_NAME_NOT_FOUND",
1489
1211 : "CPXERR_NO_RHS_IN_OBJ",
1490
1215 : "CPXERR_BAD_SENSE",
1491
1216 : "CPXERR_NO_RNGVAL",
1492
1217 : "CPXERR_NO_SOLN",
1493
1219 : "CPXERR_NO_NAMES",
1494
1221 : "CPXERR_NOT_FIXED",
1495
1222 : "CPXERR_DUP_ENTRY",
1496
1223 : "CPXERR_NO_BARRIER_SOLN",
1497
1224 : "CPXERR_NULL_NAME",
1498
1225 : "CPXERR_NAN",
1499
1226 : "CPXERR_ARRAY_NOT_ASCENDING",
1500
1227 : "CPXERR_COUNT_RANGE",
1501
1228 : "CPXERR_COUNT_OVERLAP",
1502
1229 : "CPXERR_BAD_LUB",
1503
1230 : "CPXERR_NODE_INDEX_RANGE",
1504
1231 : "CPXERR_ARC_INDEX_RANGE",
1505
1232 : "CPXERR_NO_DUAL_SOLN",
1506
1233 : "CPXERR_DBL_MAX",
1507
1234 : "CPXERR_THREAD_FAILED",
1508
1251 : "CPXERR_INDEX_NOT_BASIC",
1509
1252 : "CPXERR_NEED_OPT_SOLN",
1510
1253 : "CPXERR_BAD_STATUS",
1511
1254 : "CPXERR_NOT_UNBOUNDED",
1512
1255 : "CPXERR_SBASE_INCOMPAT",
1513
1256 : "CPXERR_SINGULAR",
1514
1257 : "CPXERR_PRIIND",
1515
1258 : "CPXERR_NO_LU_FACTOR",
1516
1260 : "CPXERR_NO_SENSIT",
1517
1261 : "CPXERR_NO_BASIC_SOLN",
1518
1262 : "CPXERR_NO_BASIS",
1519
1263 : "CPXERR_ABORT_STRONGBRANCH",
1520
1264 : "CPXERR_NO_NORMS",
1521
1265 : "CPXERR_NOT_DUAL_UNBOUNDED",
1522
1266 : "CPXERR_TILIM_STRONGBRANCH",
1523
1267 : "CPXERR_BAD_PIVOT",
1524
1268 : "CPXERR_TILIM_CONDITION_NO",
1525
1292 : "CPXERR_BAD_METHOD",
1526
1421 : "CPXERR_NO_FILENAME",
1527
1422 : "CPXERR_FAIL_OPEN_WRITE",
1528
1423 : "CPXERR_FAIL_OPEN_READ",
1529
1424 : "CPXERR_BAD_FILETYPE",
1530
1425 : "CPXERR_XMLPARSE",
1531
1431 : "CPXERR_TOO_MANY_ROWS",
1532
1432 : "CPXERR_TOO_MANY_COLS",
1533
1433 : "CPXERR_TOO_MANY_COEFFS",
1534
1434 : "CPXERR_BAD_NUMBER",
1535
1435 : "CPXERR_BAD_EXPO_RANGE",
1536
1436 : "CPXERR_NO_OBJ_SENSE",
1537
1437 : "CPXERR_QCP_SENSE_FILE",
1538
1438 : "CPXERR_BAD_LAZY_UCUT",
1539
1439 : "CPXERR_BAD_INDCONSTR",
1540
1441 : "CPXERR_NO_NAME_SECTION",
1541
1442 : "CPXERR_BAD_SOS_TYPE",
1542
1443 : "CPXERR_COL_ROW_REPEATS",
1543
1444 : "CPXERR_RIM_ROW_REPEATS",
1544
1445 : "CPXERR_ROW_REPEATS",
1545
1446 : "CPXERR_COL_REPEATS",
1546
1447 : "CPXERR_RIM_REPEATS",
1547
1448 : "CPXERR_ROW_UNKNOWN",
1548
1449 : "CPXERR_COL_UNKNOWN",
1549
1453 : "CPXERR_NO_ROW_SENSE",
1550
1454 : "CPXERR_EXTRA_FX_BOUND",
1551
1455 : "CPXERR_EXTRA_FR_BOUND",
1552
1456 : "CPXERR_EXTRA_BV_BOUND",
1553
1457 : "CPXERR_BAD_BOUND_TYPE",
1554
1458 : "CPXERR_UP_BOUND_REPEATS",
1555
1459 : "CPXERR_LO_BOUND_REPEATS",
1556
1460 : "CPXERR_NO_BOUND_TYPE",
1557
1461 : "CPXERR_NO_QMATRIX_SECTION",
1558
1462 : "CPXERR_BAD_SECTION_ENDATA",
1559
1463 : "CPXERR_INT_TOO_BIG_INPUT",
1560
1464 : "CPXERR_NAME_TOO_LONG",
1561
1465 : "CPXERR_LINE_TOO_LONG",
1562
1471 : "CPXERR_NO_ROWS_SECTION",
1563
1472 : "CPXERR_NO_COLUMNS_SECTION",
1564
1473 : "CPXERR_BAD_SECTION_BOUNDS",
1565
1474 : "CPXERR_RANGE_SECTION_ORDER",
1566
1475 : "CPXERR_BAD_SECTION_QMATRIX",
1567
1476 : "CPXERR_NO_OBJECTIVE",
1568
1477 : "CPXERR_ROW_REPEAT_PRINT",
1569
1478 : "CPXERR_COL_REPEAT_PRINT",
1570
1479 : "CPXERR_RIMNZ_REPEATS",
1571
1480 : "CPXERR_EXTRA_INTORG",
1572
1481 : "CPXERR_EXTRA_INTEND",
1573
1482 : "CPXERR_EXTRA_SOSORG",
1574
1483 : "CPXERR_EXTRA_SOSEND",
1575
1484 : "CPXERR_TOO_MANY_RIMS",
1576
1485 : "CPXERR_TOO_MANY_RIMNZ",
1577
1486 : "CPXERR_NO_ROW_NAME",
1578
1487 : "CPXERR_BAD_OBJ_SENSE",
1579
1550 : "CPXERR_BAS_FILE_SHORT",
1580
1551 : "CPXERR_BAD_INDICATOR",
1581
1552 : "CPXERR_NO_ENDATA",
1582
1553 : "CPXERR_FILE_ENTRIES",
1583
1554 : "CPXERR_SBASE_ILLEGAL",
1584
1555 : "CPXERR_BAS_FILE_SIZE",
1585
1556 : "CPXERR_NO_VECTOR_SOLN",
1586
1560 : "CPXERR_NOT_SAV_FILE",
1587
1561 : "CPXERR_SAV_FILE_DATA",
1588
1562 : "CPXERR_SAV_FILE_WRITE",
1589
1563 : "CPXERR_FILE_FORMAT",
1590
1602 : "CPXERR_ADJ_SIGNS",
1591
1603 : "CPXERR_RHS_IN_OBJ",
1592
1604 : "CPXERR_ADJ_SIGN_SENSE",
1593
1605 : "CPXERR_QUAD_IN_ROW",
1594
1606 : "CPXERR_ADJ_SIGN_QUAD",
1595
1607 : "CPXERR_NO_OPERATOR",
1596
1608 : "CPXERR_NO_OP_OR_SENSE",
1597
1609 : "CPXERR_NO_ID_FIRST",
1598
1610 : "CPXERR_NO_RHS_COEFF",
1599
1611 : "CPXERR_NO_NUMBER_FIRST",
1600
1612 : "CPXERR_NO_QUAD_EXP",
1601
1613 : "CPXERR_QUAD_EXP_NOT_2",
1602
1614 : "CPXERR_NO_QP_OPERATOR",
1603
1615 : "CPXERR_NO_NUMBER",
1604
1616 : "CPXERR_NO_ID",
1605
1617 : "CPXERR_BAD_ID",
1606
1618 : "CPXERR_BAD_EXPONENT",
1607
1619 : "CPXERR_Q_DIVISOR",
1608
1621 : "CPXERR_NO_BOUND_SENSE",
1609
1622 : "CPXERR_BAD_BOUND_SENSE",
1610
1623 : "CPXERR_NO_NUMBER_BOUND",
1611
1627 : "CPXERR_NO_SOS_SEPARATOR",
1612
1650 : "CPXERR_INVALID_NUMBER",
1613
1660 : "CPXERR_PRM_DATA",
1614
1661 : "CPXERR_PRM_HEADER",
1615
1719 : "CPXERR_NO_CONFLICT",
1616
1720 : "CPXERR_CONFLICT_UNSTABLE",
1617
1801 : "CPXERR_WORK_FILE_OPEN",
1618
1802 : "CPXERR_WORK_FILE_READ",
1619
1803 : "CPXERR_WORK_FILE_WRITE",
1620
1804 : "CPXERR_IN_INFOCALLBACK",
1621
1805 : "CPXERR_MIPSEARCH_WITH_CALLBACKS",
1622
1806 : "CPXERR_LP_NOT_IN_ENVIRONMENT",
1623
1807 : "CPXERR_PARAM_INCOMPATIBLE",
1624
32000 : "CPXERR_LICENSE_MIN",
1625
32201 : "CPXERR_ILOG_LICENSE",
1626
32301 : "CPXERR_NO_MIP_LIC",
1627
32302 : "CPXERR_NO_BARRIER_LIC",
1628
32305 : "CPXERR_NO_MIQP_LIC",
1629
32018 : "CPXERR_BADLDWID",
1630
32023 : "CPXERR_BADPRODUCT",
1631
32024 : "CPXERR_ALGNOTLICENSED",
1632
32999 : "CPXERR_LICENSE_MAX",
1633
1701 : "CPXERR_IIS_NO_INFO",
1634
1702 : "CPXERR_IIS_NO_SOLN",
1635
1703 : "CPXERR_IIS_FEAS",
1636
1704 : "CPXERR_IIS_NOT_INFEAS",
1637
1705 : "CPXERR_IIS_OPT_INFEAS",
1638
1706 : "CPXERR_IIS_DEFAULT",
1639
1707 : "CPXERR_IIS_NO_BASIC",
1640
1709 : "CPXERR_IIS_NO_LOAD",
1641
1710 : "CPXERR_IIS_SUB_OBJ_LIM",
1642
1711 : "CPXERR_IIS_SUB_IT_LIM",
1643
1712 : "CPXERR_IIS_SUB_TIME_LIM",
1644
1713 : "CPXERR_IIS_NUM_BEST",
1645
1714 : "CPXERR_IIS_SUB_ABORT",
1646
3003 : "CPXERR_NOT_MIP",
1647
3006 : "CPXERR_BAD_PRIORITY",
1648
3007 : "CPXERR_ORDER_BAD_DIRECTION",
1649
3009 : "CPXERR_ARRAY_BAD_SOS_TYPE",
1650
3010 : "CPXERR_UNIQUE_WEIGHTS",
1651
3012 : "CPXERR_BAD_DIRECTION",
1652
3015 : "CPXERR_NO_SOS",
1653
3016 : "CPXERR_NO_ORDER",
1654
3018 : "CPXERR_INT_TOO_BIG",
1655
3019 : "CPXERR_SUBPROB_SOLVE",
1656
3020 : "CPXERR_NO_MIPSTART",
1657
3021 : "CPXERR_BAD_CTYPE",
1658
3023 : "CPXERR_NO_INT_X",
1659
3024 : "CPXERR_NO_SOLNPOOL",
1660
3301 : "CPXERR_MISS_SOS_TYPE",
1661
3412 : "CPXERR_NO_TREE",
1662
3413 : "CPXERR_TREE_MEMORY_LIMIT",
1663
3414 : "CPXERR_FILTER_VARIABLE_TYPE",
1664
3504 : "CPXERR_NODE_ON_DISK",
1665
3601 : "CPXERR_PTHREAD_MUTEX_INIT",
1666
3603 : "CPXERR_PTHREAD_CREATE",
1667
1212 : "CPXERR_UNSUPPORTED_CONSTRAINT_TYPE",
1668
1213 : "CPXERR_ILL_DEFINED_PWL",
1669
1530 : "CPXERR_NET_DATA",
1670
1531 : "CPXERR_NOT_MIN_COST_FLOW",
1671
1532 : "CPXERR_BAD_ROW_ID",
1672
1537 : "CPXERR_BAD_CHAR",
1673
1538 : "CPXERR_NET_FILE_SHORT",
1674
5002 : "CPXERR_Q_NOT_POS_DEF",
1675
5004 : "CPXERR_NOT_QP",
1676
5011 : "CPXERR_Q_DUP_ENTRY",
1677
5012 : "CPXERR_Q_NOT_SYMMETRIC",
1678
5014 : "CPXERR_Q_NOT_INDEF",
1679
6002 : "CPXERR_QCP_SENSE"
1680
}
1681
1682
cdef dict parameters
1683
parameters = {
1684
"CPX_PARAMTYPE_NONE" : 0,
1685
"CPX_PARAMTYPE_INT" : 1,
1686
"CPX_PARAMTYPE_DOUBLE" : 2,
1687
"CPX_PARAMTYPE_STRING" : 3,
1688
"CPX_PARAM_ADVIND" : 1001,
1689
"CPX_PARAM_AGGFILL" : 1002,
1690
"CPX_PARAM_AGGIND" : 1003,
1691
"CPX_PARAM_BASINTERVAL" : 1004,
1692
"CPX_PARAM_CFILEMUL" : 1005,
1693
"CPX_PARAM_CLOCKTYPE" : 1006,
1694
"CPX_PARAM_CRAIND" : 1007,
1695
"CPX_PARAM_DEPIND" : 1008,
1696
"CPX_PARAM_DPRIIND" : 1009,
1697
"CPX_PARAM_PRICELIM" : 1010,
1698
"CPX_PARAM_EPMRK" : 1013,
1699
"CPX_PARAM_EPOPT" : 1014,
1700
"CPX_PARAM_EPPER" : 1015,
1701
"CPX_PARAM_EPRHS" : 1016,
1702
"CPX_PARAM_FASTMIP" : 1017,
1703
"CPX_PARAM_SIMDISPLAY" : 1019,
1704
"CPX_PARAM_ITLIM" : 1020,
1705
"CPX_PARAM_ROWREADLIM" : 1021,
1706
"CPX_PARAM_NETFIND" : 1022,
1707
"CPX_PARAM_COLREADLIM" : 1023,
1708
"CPX_PARAM_NZREADLIM" : 1024,
1709
"CPX_PARAM_OBJLLIM" : 1025,
1710
"CPX_PARAM_OBJULIM" : 1026,
1711
"CPX_PARAM_PERIND" : 1027,
1712
"CPX_PARAM_PERLIM" : 1028,
1713
"CPX_PARAM_PPRIIND" : 1029,
1714
"CPX_PARAM_PREIND" : 1030,
1715
"CPX_PARAM_REINV" : 1031,
1716
"CPX_PARAM_REVERSEIND" : 1032,
1717
"CPX_PARAM_RFILEMUL" : 1033,
1718
"CPX_PARAM_SCAIND" : 1034,
1719
"CPX_PARAM_SCRIND" : 1035,
1720
"CPX_PARAM_SINGLIM" : 1037,
1721
"CPX_PARAM_SINGTOL" : 1038,
1722
"CPX_PARAM_TILIM" : 1039,
1723
"CPX_PARAM_XXXIND" : 1041,
1724
"CPX_PARAM_PREDUAL" : 1044,
1725
"CPX_PARAM_EPOPT_H" : 1049,
1726
"CPX_PARAM_EPRHS_H" : 1050,
1727
"CPX_PARAM_PREPASS" : 1052,
1728
"CPX_PARAM_DATACHECK" : 1056,
1729
"CPX_PARAM_REDUCE" : 1057,
1730
"CPX_PARAM_PRELINEAR" : 1058,
1731
"CPX_PARAM_LPMETHOD" : 1062,
1732
"CPX_PARAM_QPMETHOD" : 1063,
1733
"CPX_PARAM_WORKDIR" : 1064,
1734
"CPX_PARAM_WORKMEM" : 1065,
1735
"CPX_PARAM_THREADS" : 1067,
1736
"CPX_PARAM_CONFLICTDISPLAY" : 1074,
1737
"CPX_PARAM_SIFTDISPLAY" : 1076,
1738
"CPX_PARAM_SIFTALG" : 1077,
1739
"CPX_PARAM_SIFTITLIM" : 1078,
1740
"CPX_PARAM_MPSLONGNUM" : 1081,
1741
"CPX_PARAM_MEMORYEMPHASIS" : 1082,
1742
"CPX_PARAM_NUMERICALEMPHASIS" : 1083,
1743
"CPX_PARAM_FEASOPTMODE" : 1084,
1744
"CPX_PARAM_PARALLELMODE" : 1109,
1745
"CPX_PARAM_TUNINGMEASURE" : 1110,
1746
"CPX_PARAM_TUNINGREPEAT" : 1111,
1747
"CPX_PARAM_TUNINGTILIM" : 1112,
1748
"CPX_PARAM_TUNINGDISPLAY" : 1113,
1749
"CPX_PARAM_WRITELEVEL" : 1114,
1750
"CPX_PARAM_ALL_MIN" : 1000,
1751
"CPX_PARAM_ALL_MAX" : 6000,
1752
"CPX_PARAM_BARDSTART" : 3001,
1753
"CPX_PARAM_BAREPCOMP" : 3002,
1754
"CPX_PARAM_BARGROWTH" : 3003,
1755
"CPX_PARAM_BAROBJRNG" : 3004,
1756
"CPX_PARAM_BARPSTART" : 3005,
1757
"CPX_PARAM_BARALG" : 3007,
1758
"CPX_PARAM_BARCOLNZ" : 3009,
1759
"CPX_PARAM_BARDISPLAY" : 3010,
1760
"CPX_PARAM_BARITLIM" : 3012,
1761
"CPX_PARAM_BARMAXCOR" : 3013,
1762
"CPX_PARAM_BARORDER" : 3014,
1763
"CPX_PARAM_BARSTARTALG" : 3017,
1764
"CPX_PARAM_BARCROSSALG" : 3018,
1765
"CPX_PARAM_BARQCPEPCOMP" : 3020,
1766
"CPX_PARAM_BRDIR" : 2001,
1767
"CPX_PARAM_BTTOL" : 2002,
1768
"CPX_PARAM_CLIQUES" : 2003,
1769
"CPX_PARAM_COEREDIND" : 2004,
1770
"CPX_PARAM_COVERS" : 2005,
1771
"CPX_PARAM_CUTLO" : 2006,
1772
"CPX_PARAM_CUTUP" : 2007,
1773
"CPX_PARAM_EPAGAP" : 2008,
1774
"CPX_PARAM_EPGAP" : 2009,
1775
"CPX_PARAM_EPINT" : 2010,
1776
"CPX_PARAM_MIPDISPLAY" : 2012,
1777
"CPX_PARAM_MIPINTERVAL" : 2013,
1778
"CPX_PARAM_INTSOLLIM" : 2015,
1779
"CPX_PARAM_NODEFILEIND" : 2016,
1780
"CPX_PARAM_NODELIM" : 2017,
1781
"CPX_PARAM_NODESEL" : 2018,
1782
"CPX_PARAM_OBJDIF" : 2019,
1783
"CPX_PARAM_MIPORDIND" : 2020,
1784
"CPX_PARAM_RELOBJDIF" : 2022,
1785
"CPX_PARAM_STARTALG" : 2025,
1786
"CPX_PARAM_SUBALG" : 2026,
1787
"CPX_PARAM_TRELIM" : 2027,
1788
"CPX_PARAM_VARSEL" : 2028,
1789
"CPX_PARAM_BNDSTRENIND" : 2029,
1790
"CPX_PARAM_HEURFREQ" : 2031,
1791
"CPX_PARAM_MIPORDTYPE" : 2032,
1792
"CPX_PARAM_CUTSFACTOR" : 2033,
1793
"CPX_PARAM_RELAXPREIND" : 2034,
1794
"CPX_PARAM_PRESLVND" : 2037,
1795
"CPX_PARAM_BBINTERVAL" : 2039,
1796
"CPX_PARAM_FLOWCOVERS" : 2040,
1797
"CPX_PARAM_IMPLBD" : 2041,
1798
"CPX_PARAM_PROBE" : 2042,
1799
"CPX_PARAM_GUBCOVERS" : 2044,
1800
"CPX_PARAM_STRONGCANDLIM" : 2045,
1801
"CPX_PARAM_STRONGITLIM" : 2046,
1802
"CPX_PARAM_FRACCAND" : 2048,
1803
"CPX_PARAM_FRACCUTS" : 2049,
1804
"CPX_PARAM_FRACPASS" : 2050,
1805
"CPX_PARAM_FLOWPATHS" : 2051,
1806
"CPX_PARAM_MIRCUTS" : 2052,
1807
"CPX_PARAM_DISJCUTS" : 2053,
1808
"CPX_PARAM_AGGCUTLIM" : 2054,
1809
"CPX_PARAM_MIPCBREDLP" : 2055 ,
1810
"CPX_PARAM_CUTPASS" : 2056,
1811
"CPX_PARAM_MIPEMPHASIS" : 2058,
1812
"CPX_PARAM_SYMMETRY" : 2059,
1813
"CPX_PARAM_DIVETYPE" : 2060,
1814
"CPX_PARAM_RINSHEUR" : 2061,
1815
"CPX_PARAM_SUBMIPNODELIM" : 2062,
1816
"CPX_PARAM_LBHEUR" : 2063,
1817
"CPX_PARAM_REPEATPRESOLVE" : 2064,
1818
"CPX_PARAM_PROBETIME" : 2065,
1819
"CPX_PARAM_POLISHTIME" : 2066,
1820
"CPX_PARAM_REPAIRTRIES" : 2067,
1821
"CPX_PARAM_EPLIN" : 2068,
1822
"CPX_PARAM_EPRELAX" : 2073,
1823
"CPX_PARAM_FPHEUR" : 2098,
1824
"CPX_PARAM_EACHCUTLIM" : 2102,
1825
"CPX_PARAM_SOLNPOOLCAPACITY" : 2103 ,
1826
"CPX_PARAM_SOLNPOOLREPLACE" : 2104 ,
1827
"CPX_PARAM_SOLNPOOLGAP" : 2105 ,
1828
"CPX_PARAM_SOLNPOOLAGAP" : 2106 ,
1829
"CPX_PARAM_SOLNPOOLINTENSITY" : 2107,
1830
"CPX_PARAM_POPULATELIM" : 2108,
1831
"CPX_PARAM_MIPSEARCH" : 2109,
1832
"CPX_PARAM_MIQCPSTRAT" : 2110,
1833
"CPX_PARAM_ZEROHALFCUTS" : 2111,
1834
"CPX_PARAM_POLISHAFTEREPAGAP" : 2126,
1835
"CPX_PARAM_POLISHAFTEREPGAP" : 2127,
1836
"CPX_PARAM_POLISHAFTERNODE" : 2128,
1837
"CPX_PARAM_POLISHAFTERINTSOL" : 2129,
1838
"CPX_PARAM_POLISHAFTERTIME" : 2130,
1839
"CPX_PARAM_MCFCUTS" : 2134,
1840
"CPX_PARAM_NETITLIM" : 5001,
1841
"CPX_PARAM_NETEPOPT" : 5002,
1842
"CPX_PARAM_NETEPRHS" : 5003,
1843
"CPX_PARAM_NETPPRIIND" : 5004,
1844
"CPX_PARAM_NETDISPLAY" : 5005,
1845
"CPX_PARAM_QPNZREADLIM" : 4001,
1846
"CPX_PARAM_QPMAKEPSDIND" : 4010,
1847
}
1848
1849