CONOPT
Loading...
Searching...
No Matches
qp4.py
Go to the documentation of this file.
7
8import os
9import sys
10
11import conopt as co
12
13sys.path.append('../common/')
14import std
15
16
17class QPModelData(co.ModelData):
18 def __init__(self):
19 self.NN = 1000
20 self.NQ = self.NN * 2 - 1
21 # only the lower triangle of the Q matrix is stored, since it is
22 # symmetric. The diagonal has the value 10. While the first off diagonal
23 # has the value 0.1. Note, the indices for the lower diagonal is (i + 1,
24 # i)
25 self.target = [10] * self.NN
26 self.Qdiag = [1] * self.NN
27 self.Qlowerdiag = [0.1] * (self.NN - 1)
28
29 super().__init__()
30
31 def buildModel(self):
32 """
33 adding the variables and constraints to the model
34 @ingroup PYTHON1THREAD_QP4
35 """
36 # adding the variables to the model
37 for i in range(self.NN):
38 self.addVariable(0.0, co.Conopt.Infinity)
39
40 # adding the constraints to the model
41 # the first constraint is the quadratic objective
42 varidx = list(range(self.NN))
43 zeros = [0] * self.NN
44 ones = [1] * self.NN
45 self.addConstraint(co.ConstraintType_Free, 0.0, varidx, zeros, ones)
46
47 # the second constraint is the summation constraint: sum(x) = 1
48 self.addConstraint(co.ConstraintType_Eq, 1.0, varidx, ones, zeros)
49
50 # setting the objective constraint
51 self.setObjectiveElement(co.ObjectiveElement_Constraint, 0)
52
53 # setting the optimisation direction
54 self.setOptimizationSense(co.Sense_Minimize)
55
56 # setting the second derivative evaluation type
57 self.setSDEvaluationType(co.SDEvaluationType_Constraint)
58
59 # setting the lagrangian structure for computing the second derivative
61
63 """
64 define the lagrangian structure and supplies it to CONOPT
65
66 @ingroup PYTHON1THREAD_QP4
67 """
68 hessianrow = [f for x in range(self.NN - 1) for f in [x, x + 1]] + [
69 self.NN - 1
70 ]
71 hessiancol = [f for x in range(self.NN - 1) for f in [x, x]] + [
72 self.NN - 1
73 ]
74
75 self.setSDLagrangianStructure(hessianrow, hessiancol)
76
77 def evaluateNonlinearTerm(self, x, rowno, ignerr, thread):
78 """
79 @copydoc conopt.ModelData.evaluateNonlinearTerm
80 @ingroup PYTHON1THREAD_QP4
81 """
82 # only the objective function is nonlinear, so this function will only be
83 # called when rowno == 0
84 g = 0
85 if rowno == 0:
86 g += sum(
87 [
88 (x[i] - self.target[i]) * q * (x[i] - self.target[i])
89 for i, q in enumerate(self.Qdiag)
90 ]
91 )
92 g += 2 * sum(
93 [
94 (x[i + 1] - self.target[i + 1]) * q * (x[i] - self.target[i])
95 for i, q in enumerate(self.Qlowerdiag)
96 ]
97 )
98
99 return g / 2
100
101 def evaluateNonlinearJacobian(self, x, rowno, jacnum, ignerr, thread):
102 """
103 @copydoc conopt.ModelData.evaluateNonlinearJacobian
104 @ingroup PYTHON1THREAD_QP4
105 """
106 jac = [0] * self.NN
107 if rowno == 0:
108 for i in range(self.NN):
109 jac[i] += self.Qdiag[i] * (x[i] - self.target[i])
110 if i < self.NN - 1:
111 jac[i + 1] += self.Qlowerdiag[i] * (x[i] - self.target[i])
112 jac[i] += self.Qlowerdiag[i] * (x[i + 1] - self.target[i + 1])
113
114 return jac
115
116 def evaluateDirectionalSD(self, x, dx, rowno, jacnum, thread):
117 """
118 @copydoc conopt.ModelData.evaluateDirectionalSD
119 @ingroup PYTHON1THREAD_QP4
120 """
121 dirsd = [0] * self.NN
122 for i in range(self.NN):
123 dirsd[i] += self.Qdiag[i] * dx[i]
124 if i < self.NN - 1:
125 dirsd[i + 1] += self.Qlowerdiag[i] * dx[i]
126 dirsd[i] += self.Qlowerdiag[i] * dx[i + 1]
127
128 return dirsd
129
130 def evaluateSDLagrangian(self, x, u, hessianrow, hessiancol):
131 """
132 @copydoc conopt.ModelData.evaluateSDLagrangian
133 @ingroup PYTHON1THREAD_QP4
134 """
135 hessian = [
136 x * u[0]
137 for i in range(self.NN - 1)
138 for x in [self.Qdiag[i], self.Qlowerdiag[i]]
139 ] + [self.Qdiag[-1] * u[0]]
140
141 return hessian
142
143
144if __name__ == '__main__':
145 name = os.path.basename(__file__)[:-3]
146
147 conopt = co.Conopt(name)
148 model = QPModelData()
149 msghdlr = std.TutMessageHandler(name)
150
151 model.buildModel()
152
153 conopt.loadModel(model)
154 conopt.setMessageHandler(msghdlr)
155
156 # getting the license variables
157 license_int_1 = os.environ.get('CONOPT_LICENSE_INT_1', None)
158 license_int_2 = os.environ.get('CONOPT_LICENSE_INT_2', None)
159 license_int_3 = os.environ.get('CONOPT_LICENSE_INT_3', None)
160 license_text = os.environ.get('CONOPT_LICENSE_TEXT', None)
161 if (
162 license_int_1 is not None
163 and license_int_2 is not None
164 and license_int_3 is not None
165 and license_text is not None
166 ):
167 conopt.setLicense(
168 int(license_int_1),
169 int(license_int_2),
170 int(license_int_3),
171 license_text,
172 )
173
174 coi_error = conopt.solve()
175
176 retcode = std.checkSolve(conopt, 59978.0, coi_error, 0.001)
177
178 sys.exit(retcode)
list Qdiag
Definition qp4.py:26
list Qlowerdiag
Definition qp4.py:27
__init__(self)
Definition qp4.py:18
list target
Definition qp4.py:25
static int checkSolve(String name, int model_status, int solution_status, double objective, double expected_objective, double tol)
Definition std.java:20
evaluateSDLagrangian(self, x, u, hessianrow, hessiancol)
Computes and returns the numerical values of the Lagrangian of the Hessian.
Definition qp4.py:130
setLagrangianStructure(self)
define the lagrangian structure and supplies it to CONOPT
Definition qp4.py:62
evaluateDirectionalSD(self, x, dx, rowno, jacnum, thread)
computes the directional second derivative for a single constraint
Definition qp4.py:116
buildModel(self)
adding the variables and constraints to the model
Definition qp4.py:31
evaluateNonlinearTerm(self, x, rowno, ignerr, thread)
callback method for evaluating the nonlinear terms in a given row
Definition qp4.py:77
evaluateNonlinearJacobian(self, x, rowno, jacnum, ignerr, thread)
callback method for evaluating the jacobian for the nonlinear terms in a given row
Definition qp4.py:101