CONOPT
Loading...
Searching...
No Matches
pinadd.py
Go to the documentation of this file.
7
8import os
9import sys
10import math
11
12import conopt as co
13
14sys.path.append('../common/')
15import std
16
17
18class PinAddModelData(co.ModelData):
19 """ """
20
21 def __init__(self):
22 self.CONS_SEQ = 0
23 self.CONS_DREV = 1
24
25 # index arrays for the variables
26 self.vartd = []
27 self.varcs = []
28 self.vars = []
29 self.vard = []
30 self.varr = []
31 self.varp = []
32 self.varrev = []
33
34 # index arrays for the constraints
35 self.consttdeq = []
36 self.constseq = []
37 self.constcseq = []
38 self.constdeq = []
39 self.constreq = []
40 self.constdrev = []
41
42 self.consmapping = {}
43 super().__init__()
44
45 def buildModel(self, T, xkeep, xstat, estat):
46 """
47 adding the variables and constraints to the model
48 @ingroup PYTHON1THREAD_PINADD
49 """
50
51 demand = [1.0 + 2.3 * pow(1.015, t) for t in range(T)]
52
53 # adding the variables to the model
54 for t in range(T):
55 # td: Lower=0, Upper=inf, Curr=18
56 varidx = self.addVariable(0, co.Conopt.Infinity, 18)
57 self.vartd.append(varidx)
58
59 # cs: Lower=0, Upper=inf, Curr=7*t
60 varidx = self.addVariable(0, co.Conopt.Infinity, 7 * (t + 1))
61 self.varcs.append(varidx)
62
63 # s: Lower=0, Upper=inf, Curr=7
64 varidx = self.addVariable(0, co.Conopt.Infinity, 7)
65 self.vars.append(varidx)
66
67 # d: Lower=0, Upper=inf, Curr=td-s
68 varidx = self.addVariable(
69 0,
70 co.Conopt.Infinity,
71 self.getVariable(self.vartd[t]).curr
72 - self.getVariable(self.vars[t]).curr,
73 )
74 self.vard.append(varidx)
75
76 # r: Lower=1, Upper=inf, Curr=r(t-1)-d
77 if t > 0:
78 varidx = self.addVariable(
79 1,
80 co.Conopt.Infinity,
81 self.getVariable(self.varr[t - 1]).curr
82 - self.getVariable(self.vard[t]).curr,
83 )
84 else:
85 varidx = self.addVariable(
86 1,
87 co.Conopt.Infinity,
88 500 - self.getVariable(self.vard[t]).curr,
89 )
90 self.varr.append(varidx)
91
92 # p: Lower=1, Upper=inf, Curr=14
93 varidx = self.addVariable(1, co.Conopt.Infinity, 14)
94 self.varp.append(varidx)
95
96 # rev: Lower=-inf, Upper=inf, Curr=0
97 varidx = self.addVariable(-co.Conopt.Infinity, co.Conopt.Infinity)
98 self.varrev.append(varidx)
99
100 # This is a restart: Use the initial values from last solve for
101 # the variables in the first periods and extrapolate the last
102 # period using a linear extrapolation between the last two
103 # periods.
104 if len(xkeep) > 0:
105 for i in range(len(xkeep)):
106 self.getVariable(i).curr = xkeep[i]
107
108 # linear extrapolation for the last period of variable td
109 self.getVariable(self.vartd[T - 1]).curr = (
110 2 * self.getVariable(self.vartd[T - 2]).curr
111 - self.getVariable(self.vartd[T - 3]).curr
112 )
113 # cs
114 self.getVariable(self.varcs[T - 1]).curr = (
115 2 * self.getVariable(self.varcs[T - 2]).curr
116 - self.getVariable(self.varcs[T - 3]).curr
117 )
118 # s
119 self.getVariable(self.vars[T - 1]).curr = (
120 2 * self.getVariable(self.vars[T - 2]).curr
121 - self.getVariable(self.vars[T - 3]).curr
122 )
123 # d
124 self.getVariable(self.vard[T - 1]).curr = (
125 2 * self.getVariable(self.vard[T - 2]).curr
126 - self.getVariable(self.vard[T - 3]).curr
127 )
128 # r
129 self.getVariable(self.varr[T - 1]).curr = (
130 2 * self.getVariable(self.varr[T - 2]).curr
131 - self.getVariable(self.varr[T - 3]).curr
132 )
133 # p
134 self.getVariable(self.varp[T - 1]).curr = (
135 2 * self.getVariable(self.varp[T - 2]).curr
136 - self.getVariable(self.varp[T - 3]).curr
137 )
138 # rev
139 self.getVariable(self.varrev[T - 1]).curr = (
140 2 * self.getVariable(self.varrev[T - 2]).curr
141 - self.getVariable(self.varrev[T - 3]).curr
142 )
143
144 # The variables from the last solve are given the old status and
145 # the variables in the new period are given those in the last
146 # period. Similarly with the Equation status:
147 for i in range(len(xstat)):
148 self.getVariable(i).varstatus = xstat[i]
149
150 # td
151 self.getVariable(self.vartd[T - 1]).varstatus = self.getVariable(
152 self.vartd[T - 2]
153 ).varstatus
154 # cs
155 self.getVariable(self.varcs[T - 1]).varstatus = self.getVariable(
156 self.varcs[T - 2]
157 ).varstatus
158 # s
159 self.getVariable(self.vars[T - 1]).varstatus = self.getVariable(
160 self.vars[T - 2]
161 ).varstatus
162 # d
163 self.getVariable(self.vard[T - 1]).varstatus = self.getVariable(
164 self.vard[T - 2]
165 ).varstatus
166 # r
167 self.getVariable(self.varr[T - 1]).varstatus = self.getVariable(
168 self.varr[T - 2]
169 ).varstatus
170 # p
171 self.getVariable(self.varp[T - 1]).varstatus = self.getVariable(
172 self.varp[T - 2]
173 ).varstatus
174 # rev
175 self.getVariable(self.varrev[T - 1]).varstatus = self.getVariable(
176 self.varrev[T - 2]
177 ).varstatus
178
179 # adding the objective
180 objcoeff = [pow(1.05, 1 - (t + 1)) for t in range(T)]
181 objnlflag = [0] * T
182 objidx = self.addConstraint(
183 co.ConstraintType_Free, 0.0, self.varrev, objcoeff, objnlflag
184 )
185
186 # adding the constraints to the model
187 for t in range(T):
188 if t == 0:
189 considx = self.addConstraint(
190 co.ConstraintType_Eq,
191 demand[t] + 0.87 * 18.0,
192 [self.vartd[t], self.varp[t]], # the variables
193 [1.0, 0.13], # the coefficients
194 [0, 0], # nlflags
195 )
196 else:
197 considx = self.addConstraint(
198 co.ConstraintType_Eq,
199 demand[t],
200 [self.vartd[t], self.vartd[t - 1], self.varp[t]],
201 [1.0, -0.87, 0.13],
202 [0, 0, 0],
203 )
204 self.consttdeq.append(considx)
205
206 if t == 0:
207 considx = self.addConstraint(
208 co.ConstraintType_Eq,
209 0.75 * 6.5,
210 [self.vars[t], self.varp[t], self.varcs[t]],
211 [1.0, 0.0, 0.0],
212 [0, 1, 1],
213 )
214 else:
215 considx = self.addConstraint(
216 co.ConstraintType_Eq,
217 0.0,
218 [
219 self.vars[t],
220 self.vars[t - 1],
221 self.varp[t],
222 self.varcs[t],
223 ],
224 [1.0, -0.75, 0.0, 0.0],
225 [0, 0, 1, 1],
226 )
227 self.constseq.append(considx)
228 self.consmapping[considx] = (self.CONS_SEQ, t)
229
230 if t == 0:
231 considx = self.addConstraint(
232 co.ConstraintType_Eq,
233 0.0,
234 [self.varcs[t], self.vars[t]],
235 [1.0, -1.0],
236 [0, 0],
237 )
238 else:
239 considx = self.addConstraint(
240 co.ConstraintType_Eq,
241 0.0,
242 [self.varcs[t], self.varcs[t - 1], self.vars[t]],
243 [1.0, -1.0, -1.0],
244 [0, 0, 0],
245 )
246 self.constcseq.append(considx)
247
248 considx = self.addConstraint(
249 co.ConstraintType_Eq,
250 0.0,
251 [self.vard[t], self.vartd[t], self.vars[t]],
252 [1.0, -1.0, 1.0],
253 [0, 0, 0],
254 )
255 self.constdeq.append(considx)
256
257 if t == 0:
258 considx = self.addConstraint(
259 co.ConstraintType_Eq,
260 500.0,
261 [self.varr[t], self.vard[t]],
262 [1.0, 1.0],
263 [0, 0],
264 )
265 else:
266 considx = self.addConstraint(
267 co.ConstraintType_Eq,
268 0.0,
269 [self.varr[t], self.varr[t - 1], self.vard[t]],
270 [1.0, -1.0, 1.0],
271 [0, 0, 0],
272 )
273 self.constreq.append(considx)
274
275 considx = self.addConstraint(
276 co.ConstraintType_Eq,
277 0.0,
278 [self.varrev[t], self.vard[t], self.varp[t], self.varr[t]],
279 [1.0, 0.0, 0.0, 0.0],
280 [0, 1, 1, 1],
281 )
282 self.constdrev.append(considx)
283 self.consmapping[considx] = (self.CONS_DREV, t)
284
285 # Restore values from previous runs
286 if len(estat) > 0:
287 # the equation status
288 for i in range(len(estat)):
289 self.getConstraint(i).slackstatus = estat[i]
290
291 # tdeq
292 self.getConstraint(
293 self.consttdeq[T - 1]
294 ).slackstatus = self.getConstraint(self.consttdeq[T - 2]).slackstatus
295 # seq
296 self.getConstraint(
297 self.constseq[T - 1]
298 ).slackstatus = self.getConstraint(self.constseq[T - 2]).slackstatus
299 # cseq
300 self.getConstraint(
301 self.constcseq[T - 1]
302 ).slackstatus = self.getConstraint(self.constcseq[T - 2]).slackstatus
303 # deq
304 self.getConstraint(
305 self.constdeq[T - 1]
306 ).slackstatus = self.getConstraint(self.constdeq[T - 2]).slackstatus
307 # req
308 self.getConstraint(
309 self.constreq[T - 1]
310 ).slackstatus = self.getConstraint(self.constreq[T - 2]).slackstatus
311 # drev
312 self.getConstraint(
313 self.constdrev[T - 1]
314 ).slackstatus = self.getConstraint(self.constdrev[T - 2]).slackstatus
315
316 # setting the objective constraint
317 self.setObjectiveElement(co.ObjectiveElement_Constraint, objidx)
318
319 # setting the optimisation direction
320 self.setOptimizationSense(co.Sense_Maximize)
321
322 def evaluateNonlinearTerm(self, x, rowno, ignerr, thread):
323 """
324 @copydoc conopt.ModelData.evaluateNonlinearTerm
325 @ingroup PYTHON1THREAD_PINADD
326 """
327 if rowno not in self.consmapping:
328 return
329
330 # unpack consset and time index
331 consset, t = self.consmapping[rowno]
332 assert consset in (self.CONS_SEQ, self.CONS_DREV)
333
334 g = 0
335 if consset == self.CONS_SEQ:
336 h1 = 1.1 + 0.1 * x[self.varp[t]]
337 h2 = pow(1.02, -x[self.varcs[t]] / 7.0)
338 g = -h1 * h2
339
340 elif consset == self.CONS_DREV:
341 g = -x[self.vard[t]] * (x[self.varp[t]] - 250.0 / x[self.varr[t]])
342
343 return g
344
345 def evaluateNonlinearJacobian(self, x, rowno, jacnum, ignerr, thread):
346 """
347 @copydoc conopt.ModelData.evaluateNonlinearJacobian
348 @ingroup PYTHON1THREAD_PINADD
349 """
350 if rowno not in self.consmapping:
351 return
352
353 # unpack consset and time index
354 consset, t = self.consmapping[rowno]
355 assert consset in (self.CONS_SEQ, self.CONS_DREV)
356
357 jac = []
358 if consset == self.CONS_SEQ:
359 h1 = 1.1 + 0.1 * x[self.varp[t]]
360 h2 = pow(1.02, -x[self.varcs[t]] / 7.0)
361 jac.append(h1 * h2 * math.log(1.02) / 7.0)
362 jac.append(-h2 * 0.1)
363
364 elif consset == self.CONS_DREV:
365 jac.append(-(x[self.varp[t]] - 250.0 / x[self.varr[t]]))
366 jac.append(-x[self.vard[t]] * 250.0 / pow(x[self.varr[t]], 2))
367 jac.append(-x[self.vard[t]])
368
369 return jac
370
371
372if __name__ == '__main__':
373 name = os.path.basename(__file__)[:-3]
374
375 conopt = co.Conopt(name)
376 msghdlr = std.TutMessageHandler(name)
377 conopt.setMessageHandler(msghdlr)
378
379 # getting the license variables
380 license_int_1 = os.environ.get('CONOPT_LICENSE_INT_1', None)
381 license_int_2 = os.environ.get('CONOPT_LICENSE_INT_2', None)
382 license_int_3 = os.environ.get('CONOPT_LICENSE_INT_3', None)
383 license_text = os.environ.get('CONOPT_LICENSE_TEXT', None)
384 if (
385 license_int_1 is not None
386 and license_int_2 is not None
387 and license_int_3 is not None
388 and license_text is not None
389 ):
390 conopt.setLicense(
391 int(license_int_1),
392 int(license_int_2),
393 int(license_int_3),
394 license_text,
395 )
396
397 expected_sols = [1170.49, 1225.86, 1280.28, 1333.74, 1386.24]
398 for i in range(16, 21):
399 model = PinAddModelData()
400
401 xkeep = conopt.getVariableValues()
402 xstat = conopt.getVariableStatus()
403 estat = conopt.getConstraintStatus()
404
405 # building the model
406 model.buildModel(
407 i, xkeep, xstat, estat
408 ) # Add T, and other vectors as parameters
409
410 conopt.loadModel(model)
411
412 coi_error = conopt.solve()
413
414 retcode = std.checkSolve(
415 conopt, expected_sols[i - 16], coi_error, tol=0.01
416 )
417
418 sys.exit(retcode)
static int checkSolve(String name, int model_status, int solution_status, double objective, double expected_objective, double tol)
Definition std.java:20
buildModel(self, T, xkeep, xstat, estat)
adding the variables and constraints to the model
Definition pinadd.py:45
evaluateNonlinearTerm(self, x, rowno, ignerr, thread)
callback method for evaluating the nonlinear terms in a given row
Definition pinadd.py:322
evaluateNonlinearJacobian(self, x, rowno, jacnum, ignerr, thread)
callback method for evaluating the jacobian for the nonlinear terms in a given row
Definition pinadd.py:345