5 - mult_selection: multiple selection model
6 - convex_comb_sos: model with SOS2 constraints
7 - convex_comb_dis: convex combination with binary variables (disaggregated model)
8 - convex_comb_dis_log: convex combination with a logarithmic number of binary variables
9 - convex_comb_agg: convex combination with binary variables (aggregated model)
10 - convex_comb_agg_log: convex combination with a logarithmic number of binary variables
12 Copyright (c) by Joao Pedro PEDROSO and Mikio KUBO, 2012
16 from pyscipopt
import Model, quicksum
20 """mult_selection -- add piecewise relation with multiple selection formulation
22 - model: a model where to include the piecewise linear relation
23 - a[k]: x-coordinate of the k-th point in the piecewise linear relation
24 - b[k]: y-coordinate of the k-th point in the piecewise linear relation
25 Returns the model with the piecewise linear relation on added variables X, Y, and z.
31 w[k] = model.addVar(lb=-model.infinity())
32 z[k] = model.addVar(vtype=
"B")
33 X = model.addVar(lb=a[0], ub=a[K], vtype=
"C")
34 Y = model.addVar(lb=-model.infinity())
37 model.addCons(w[k] >= a[k] * z[k])
38 model.addCons(w[k] <= a[k + 1] * z[k])
40 model.addCons(
quicksum(z[k]
for k
in range(K)) == 1)
41 model.addCons(X ==
quicksum(w[k]
for k
in range(K)))
43 c = [float(b[k + 1] - b[k]) / (a[k + 1] - a[k])
for k
in range(K)]
44 d = [b[k] - c[k] * a[k]
for k
in range(K)]
45 model.addCons(Y ==
quicksum(d[k] * z[k] + c[k] * w[k]
for k
in range(K)))
51 """convex_comb_sos -- add piecewise relation with gurobi's SOS constraints
53 - model: a model where to include the piecewise linear relation
54 - a[k]: x-coordinate of the k-th point in the piecewise linear relation
55 - b[k]: y-coordinate of the k-th point in the piecewise linear relation
56 Returns the model with the piecewise linear relation on added variables X, Y, and z.
60 for k
in range(K + 1):
61 z[k] = model.addVar(lb=0, ub=1, vtype=
"C")
62 X = model.addVar(lb=a[0], ub=a[K], vtype=
"C")
63 Y = model.addVar(lb=-model.infinity(), vtype=
"C")
65 model.addCons(X ==
quicksum(a[k] * z[k]
for k
in range(K + 1)))
66 model.addCons(Y ==
quicksum(b[k] * z[k]
for k
in range(K + 1)))
68 model.addCons(
quicksum(z[k]
for k
in range(K + 1)) == 1)
69 model.addConsSOS2([z[k]
for k
in range(K + 1)])
75 """convex_comb_dis -- add piecewise relation with convex combination formulation
77 - model: a model where to include the piecewise linear relation
78 - a[k]: x-coordinate of the k-th point in the piecewise linear relation
79 - b[k]: y-coordinate of the k-th point in the piecewise linear relation
80 Returns the model with the piecewise linear relation on added variables X, Y, and z.
83 wL, wR, z = {}, {}, {}
85 wL[k] = model.addVar(lb=0, ub=1, vtype=
"C")
86 wR[k] = model.addVar(lb=0, ub=1, vtype=
"C")
87 z[k] = model.addVar(vtype=
"B")
88 X = model.addVar(lb=a[0], ub=a[K], vtype=
"C")
89 Y = model.addVar(lb=-model.infinity(), vtype=
"C")
91 model.addCons(X ==
quicksum(a[k] * wL[k] + a[k + 1] * wR[k]
for k
in range(K)))
92 model.addCons(Y ==
quicksum(b[k] * wL[k] + b[k + 1] * wR[k]
for k
in range(K)))
94 model.addCons(wL[k] + wR[k] == z[k])
96 model.addCons(
quicksum(z[k]
for k
in range(K)) == 1)
102 """returns i^int(i/2)"""
103 return i ^ (int(i / 2))
107 """convex_comb_dis_log -- add piecewise relation with a logarithmic number of binary variables
108 using the convex combination formulation.
110 - model: a model where to include the piecewise linear relation
111 - a[k]: x-coordinate of the k-th point in the piecewise linear relation
112 - b[k]: y-coordinate of the k-th point in the piecewise linear relation
113 Returns the model with the piecewise linear relation on added variables X, Y, and z.
116 G = int(math.ceil((math.log(K) / math.log(2))))
119 wL, wR, z = {}, {}, {}
121 wL[k] = model.addVar(lb=0, ub=1, vtype=
"C")
122 wR[k] = model.addVar(lb=0, ub=1, vtype=
"C")
123 X = model.addVar(lb=a[0], ub=a[K], vtype=
"C")
124 Y = model.addVar(lb=-model.infinity(), vtype=
"C")
128 g[j] = model.addVar(vtype=
"B")
130 model.addCons(X ==
quicksum(a[k] * wL[k] + a[k + 1] * wR[k]
for k
in range(K)))
131 model.addCons(Y ==
quicksum(b[k] * wL[k] + b[k + 1] * wR[k]
for k
in range(K)))
132 model.addCons(
quicksum(wL[k] + wR[k]
for k
in range(K)) == 1)
143 model.addCons(
quicksum(wL[k] + wR[k]
for k
in ones) <= g[j])
144 model.addCons(
quicksum(wL[k] + wR[k]
for k
in zeros) <= 1 - g[j])
150 """convex_comb_agg -- add piecewise relation convex combination formulation -- non-disaggregated.
152 - model: a model where to include the piecewise linear relation
153 - a[k]: x-coordinate of the k-th point in the piecewise linear relation
154 - b[k]: y-coordinate of the k-th point in the piecewise linear relation
155 Returns the model with the piecewise linear relation on added variables X, Y, and z.
159 for k
in range(K + 1):
160 w[k] = model.addVar(lb=0, ub=1, vtype=
"C")
162 z[k] = model.addVar(vtype=
"B")
163 X = model.addVar(lb=a[0], ub=a[K], vtype=
"C")
164 Y = model.addVar(lb=-model.infinity(), vtype=
"C")
166 model.addCons(X ==
quicksum(a[k] * w[k]
for k
in range(K + 1)))
167 model.addCons(Y ==
quicksum(b[k] * w[k]
for k
in range(K + 1)))
168 model.addCons(w[0] <= z[0])
169 model.addCons(w[K] <= z[K - 1])
170 for k
in range(1, K):
171 model.addCons(w[k] <= z[k - 1] + z[k])
172 model.addCons(
quicksum(w[k]
for k
in range(K + 1)) == 1)
173 model.addCons(
quicksum(z[k]
for k
in range(K)) == 1)
178 """convex_comb_agg_log -- add piecewise relation with a logarithmic number of binary variables
179 using the convex combination formulation -- non-disaggregated.
181 - model: a model where to include the piecewise linear relation
182 - a[k]: x-coordinate of the k-th point in the piecewise linear relation
183 - b[k]: y-coordinate of the k-th point in the piecewise linear relation
184 Returns the model with the piecewise linear relation on added variables X, Y, and z.
187 G = int(math.ceil((math.log(K) / math.log(2))))
189 for k
in range(K + 1):
190 w[k] = model.addVar(lb=0, ub=1, vtype=
"C")
192 g[j] = model.addVar(vtype=
"B")
193 X = model.addVar(lb=a[0], ub=a[K], vtype=
"C")
194 Y = model.addVar(lb=-model.infinity(), vtype=
"C")
196 model.addCons(X ==
quicksum(a[k] * w[k]
for k
in range(K + 1)))
197 model.addCons(Y ==
quicksum(b[k] * w[k]
for k
in range(K + 1)))
198 model.addCons(
quicksum(w[k]
for k
in range(K + 1)) == 1)
202 zeros, ones = [0], []
204 for k
in range(1, K + 1):
206 if (1 &
gray(k) >> j) == 1
and (1 &
gray(k - 1) >> j) == 1:
208 if (1 &
gray(k) >> j) == 0
and (1 &
gray(k - 1) >> j) == 0:
213 model.addCons(
quicksum(w[k]
for k
in ones) <= g[j])
214 model.addCons(
quicksum(w[k]
for k
in zeros) <= 1 - g[j])
219 if __name__ ==
"__main__":
222 a = [-10, 10, 15, 25, 30, 35, 40, 45, 50, 55, 60, 70]
223 b = [-20, -20, 15, -21, 0, 50, 18, 0, 15, 24, 10, 15]
225 print(
"\n\n\npiecewise: multiple selection")
226 model = Model(
"multiple selection")
229 u = model.addVar(vtype=
"C", name=
"u")
231 A = model.addCons(3 * X + 4 * Y <= 250,
"A")
232 B = model.addCons(7 * X - 2 * Y + 3 * u == 170,
"B")
233 model.setObjective(2 * X + 15 * Y + 5 * u,
"maximize")
235 print(
"X:", model.getVal(X))
236 print(
"Y:", model.getVal(Y))
237 print(
"u:", model.getVal(u))
239 print(
"\n\n\npiecewise: disaggregated convex combination")
240 model = Model(
"disaggregated convex combination")
242 u = model.addVar(vtype=
"C", name=
"u")
244 A = model.addCons(3 * X + 4 * Y <= 250,
"A")
245 B = model.addCons(7 * X - 2 * Y + 3 * u == 170,
"B")
246 model.setObjective(2 * X + 15 * Y + 5 * u,
"maximize")
248 print(
"X:", model.getVal(X))
249 print(
"Y:", model.getVal(Y))
250 print(
"u:", model.getVal(u))
252 print(
"\n\n\npiecewise: disaggregated convex combination, logarithmic number of variables")
253 model = Model(
"disaggregated convex combination (log)")
255 u = model.addVar(vtype=
"C", name=
"u")
257 A = model.addCons(3 * X + 4 * Y <= 250,
"A")
258 B = model.addCons(7 * X - 2 * Y + 3 * u == 170,
"B")
259 model.setObjective(2 * X + 15 * Y + 5 * u,
"maximize")
261 print(
"X:", model.getVal(X))
262 print(
"Y:", model.getVal(Y))
263 print(
"u:", model.getVal(u))
265 print(
"\n\n\npiecewise: SOS2 constraint")
266 model = Model(
"SOS2")
268 u = model.addVar(vtype=
"C", name=
"u")
270 A = model.addCons(3 * X + 4 * Y <= 250,
"A")
271 B = model.addCons(7 * X - 2 * Y + 3 * u == 170,
"B")
272 model.setObjective(2 * X + 15 * Y + 5 * u,
"maximize")
274 print(
"X:", model.getVal(X))
275 print(
"Y:", model.getVal(Y))
276 print(
"u:", model.getVal(u))
278 print(
"\n\n\npiecewise: aggregated convex combination")
279 model = Model(
"aggregated convex combination")
281 u = model.addVar(vtype=
"C", name=
"u")
283 A = model.addCons(3 * X + 4 * Y <= 250,
"A")
284 B = model.addCons(7 * X - 2 * Y + 3 * u == 170,
"B")
285 model.setObjective(2 * X + 15 * Y + 5 * u,
"maximize")
287 print(
"X:", model.getVal(X))
288 print(
"Y:", model.getVal(Y))
289 print(
"u:", model.getVal(u))
291 print(
"\n\n\npiecewise: aggregated convex combination, logarithmic number of variables")
292 model = Model(
"aggregated convex combination (log)")
294 u = model.addVar(vtype=
"C", name=
"u")
296 A = model.addCons(3 * X + 4 * Y <= 250,
"A")
297 B = model.addCons(7 * X - 2 * Y + 3 * u == 170,
"B")
298 model.setObjective(2 * X + 15 * Y + 5 * u,
"maximize")
300 print(
"X:", model.getVal(X))
301 print(
"Y:", model.getVal(Y))
302 print(
"u:", model.getVal(u))