Repository navigation
Expand file tree
/
Copy pathrobustlp.py
More file actions
157 lines (121 loc) · 4.33 KB
/
Copy pathrobustlp.py
File metadata and controls
157 lines (121 loc) · 4.33 KB
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
"""
## GAMSSOURCE: https://www.gams.com/latest/gamslib_ml/libhtml/gamslib_robustlp.html
## LICENSETYPE: Demo
## MODELTYPE: LP, QCP
## KEYWORDS: linear programming, quadratic constraint programming, robust optimization, second order cone programming
Robust linear programming as an SOCP (ROBUSTLP)
Consider a linear optimization problem of the form
min_x c^Tx s.t. a_i^Tx <= b_i, i=1,..,m.
In practice, the coefficient vectors a_i may not be known perfectly,
as they are subject to noise. Assume that we only know that a_i in E_i,
where E_i are given ellipsoids. In robust optimization, we seek to minimize
the original objective, but we insist that each constraint be satisfied,
irrespective of the choice of the corresponding vector a_i in E_i.
We obtain the second-order cone optimization problem
min_x c^Tx s.t. a'_i^Tx + ||R_i^Tx|| <= b_i, i=1,..,m,
where E_i = { a'_i + R_iu | ||u|| <= 1}. In the above, we observe that
the feasible set is smaller than the original one, due to the terms involving
the l_2-norms.
The figure above illustrates the kind of feasible set one obtains in a
particular instance of the above problem, with spherical uncertainties
(that is, all the ellipsoids are spheres, R_i = rho I for some rho >0).
We observe that the robust feasible set is indeed contained in the original
polyhedron.
In this particular example we allow coefficients A(i,*) to vary in an
ellipsoid. The robust LP is reformulated as a SOCP.
Contributed by Michael Ferris, University of Wisconsin, Madison
Lobo, M S, Vandenberghe, L, Boyd, S, and Lebret, H, Applications of
Second Order Cone Programming. Linear Algebra and its Applications,
Special Issue on Linear Algebra in Control, Signals and Image
Processing. 284 (November, 1998).
"""
from __future__ import annotations
from gamspy import (
Alias,
Container,
Equation,
Model,
Parameter,
Problem,
Sense,
Set,
Sum,
Variable,
)
from gamspy.math import uniform
def main():
m = Container()
mu = 1e-2
# Set
i = Set(m, name="i", records=[f"{idx}" for idx in range(1, 8)])
j = Set(m, name="j", records=[f"{idx}" for idx in range(1, 5)])
# Data
a = Parameter(m, name="a", domain=[i, j])
b = Parameter(m, name="b", domain=i)
c = Parameter(m, name="c", domain=j)
b[i] = 1
c[j] = -1
a[i, j] = uniform(0, 1)
# Variable
x = Variable(m, name="x", domain=j)
# Equation
cons = Equation(m, name="cons", domain=i)
defobj = Sum(j, c[j] * x[j])
cons[i] = Sum(j, a[i, j] * x[j]) <= b[i]
lpmod = Model(
m,
name="lpmod",
equations=[cons],
problem="LP",
sense=Sense.MIN,
objective=defobj,
)
lpmod.solve()
results = Parameter(m, name="results", domain=["*", "*"])
results["lp", j] = x.l[j]
results["lp", "obj"] = lpmod.objective_value
lmbda = Variable(m, name="lambda", type="positive", domain=j)
gamma = Variable(m, name="gamma", type="positive", domain=j)
lpcons = Equation(m, name="lpcons", domain=i)
defdual = Equation(m, name="defdual", domain=j)
lpcons[i] = (
mu * Sum(j, lmbda[j] + gamma[j]) + Sum(j, a[i, j] * x[j]) <= b[i]
)
defdual[j] = lmbda[j] - gamma[j] == x[j]
lproblp = Model(
m,
name="lproblp",
equations=[lpcons, defdual],
problem="LP",
sense=Sense.MIN,
objective=defobj,
)
lproblp.solve()
results["roblp", j] = x.l[j]
results["roblp", "obj"] = lproblp.objective_value
k = Alias(m, name="k", alias_with=j)
p = Parameter(m, name="p", domain=[i, j, k])
p[i, j, j] = mu
y = Variable(m, name="y", domain=i)
v = Variable(m, name="v", domain=[i, k])
defrhs = Equation(m, name="defrhs", domain=i)
defv = Equation(m, name="defv", domain=[i, k])
socpqcpcons = Equation(m, name="socpqcpcons", domain=i)
defrhs[i] = y[i] == b[i] - Sum(j, a[i, j] * x[j])
defv[i, k] = v[i, k] == Sum(j, p[i, j, k] * x[j])
socpqcpcons[i] = y[i] ** 2 >= Sum(k, v[i, k] ** 2)
roblpqcp = Model(
m,
name="roblpqcp",
equations=[socpqcpcons, defrhs, defv],
problem=Problem.QCP,
sense=Sense.MIN,
objective=defobj,
)
y.lo[i] = 0
roblpqcp.solve()
results["qcp", j] = x.l[j]
results["qcp", "obj"] = roblpqcp.objective_value
print(results.records)
if __name__ == "__main__":
main()