forked from XiongPengNUS/rsome
-
Notifications
You must be signed in to change notification settings - Fork 0
/
clp_solver.py
111 lines (91 loc) · 2.76 KB
/
clp_solver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
"""
This module is used as an interface to call the CyLP solver for solving
(mixed-integer) linear programming problems.
"""
from cylp.cy import CyClpSimplex
from cylp.py.modeling.CyLPModel import CyLPArray
import numpy as np
import warnings
import time
from .lp import Solution
def solve(formula, display=True, export=False, params={}):
try:
if formula.qmat:
warnings.warn('SOC constriants are ignored in the LP solver. ')
except AttributeError:
pass
obj = formula.obj.flatten()
linear = formula.linear
sense = formula.sense
const = formula.const
ub = formula.ub
lb = formula.lb
vtype = formula.vtype
eq_linear = linear[sense == 1, :]
eq_const = const[sense == 1]
ineq_linear = linear[sense == 0, :]
ineq_const = const[sense == 0]
is_con = vtype == 'C'
is_int = vtype == 'I'
is_bin = vtype == 'B'
s = CyClpSimplex()
obj_expr = 0
ncv = sum(is_con)
if ncv:
cv = s.addVariable('cv', ncv)
s += cv <= ub[is_con]
s += cv >= lb[is_con]
obj_expr += CyLPArray(obj[is_con]) * cv
niv = sum(is_int)
if niv:
iv = s.addVariable('iv', niv, isInt=True)
s += iv <= ub[is_int]
s += iv >= lb[is_int]
obj_expr += CyLPArray(obj[is_int]) * iv
nbv = sum(is_bin)
if nbv:
bv = s.addVariable('bv', nbv)
s += bv <= 1
s += bv >= 0
obj_expr += CyLPArray(obj[is_bin]) * bv
s.objective = obj_expr
if eq_linear.shape[0] > 0:
left = 0
if ncv:
left += eq_linear[:, is_con] * cv
if niv:
left += eq_linear[:, is_int] * iv
if nbv:
left += eq_linear[:, is_bin] * bv
s += left == eq_const
if ineq_linear.shape[0] > 0:
left = 0
if ncv:
left += ineq_linear[:, is_con] * cv
if niv:
left += ineq_linear[:, is_int] * iv
if nbv:
left += ineq_linear[:, is_bin] * bv
s += left <= ineq_const
if display:
print('Being solved by CyLP...', flush=True)
time.sleep(0.2)
t0 = time.time()
status = s.primal()
stime = time.time() - t0
if display:
print('Solution status: {0}'.format(status))
print('Running time: {0:0.4f}s'.format(stime))
try:
x_sol = np.zeros(linear.shape[1])
if ncv:
x_sol[is_con] = s.primalVariableSolution['cv']
if niv:
x_sol[is_int] = s.primalVariableSolution['iv'].round()
if nbv:
x_sol[is_bin] = s.primalVariableSolution['bv'].round()
solution = Solution(s.objectiveValue, x_sol, status)
except AttributeError:
warnings.warn('No feasible solution can be found.')
solution = None
return solution