CONOPT
Loading...
Searching...
No Matches
leastsq2.py
Go to the documentation of this file.
7
8import sys
9import os
10import math
11
12import conopt as co
13
14sys.path.append('../common/')
15import std
16
17
18class LeastSqModelData(co.ModelData):
19 def __init__(self, numobs: int, dimensionx: int):
20 self.seed = 12359 # seed for random number generator
21
22 self.nobs = numobs
23 self.dimx = dimensionx
24
25 self.A = [0] * (self.nobs * self.dimx)
26 self.B = [0] * (self.nobs * self.dimx)
27 self.Obs = [0] * self.nobs
28
29 self.varx = []
30 self.varres = []
31 self.consresidual = []
32
33 self.define_data()
34
35 super().__init__()
36
37 def rndx(self):
38 """
39 Defines a pseudo random number between 0 and 1
40
41 NOTE: it would be possible to use random module to generate the random
42 numbers. We have written our own random number generator to be consistent
43 with the original Fortran example.
44 """
45 self.seed = self.seed * 1027 + 25
46 times = int(self.seed / 1048576)
47 self.seed = self.seed - 1048576 * times
48 return self.seed / 1048576.0
49
50 def define_data(self):
51 """
52 Defines the data for the problem
53 """
54 Xtarg = -1.0
55 Noise = 1.0
56 k = 0
57
58 for i in range(self.nobs):
59 O = 0
60 for j in range(self.dimx):
61 self.A[k] = self.rndx()
62 self.B[k] = self.rndx()
63 O += self.A[k] * Xtarg + self.B[k] * math.pow(Xtarg, 2)
64 k = k + 1
65 self.Obs[i] = O + Noise * self.rndx()
66
67 def buildModel(self):
68 """
69 adding the variables and constraints to the model
70 @ingroup PYTHON1THREAD_LEASTSQ2
71 """
72 # adding the variables to the model
73 for i in range(self.dimx):
74 varidx = self.addVariable(
75 -co.Conopt.Infinity, co.Conopt.Infinity, -0.8
76 )
77 self.varx.append(varidx)
78
79 for i in range(self.nobs):
80 varidx = self.addVariable(-co.Conopt.Infinity, co.Conopt.Infinity, 0.0)
81 self.varres.append(varidx)
82
83 # adding the constraints to the model
84 for i in range(self.nobs):
85 varidx = self.varx.copy()
86 coeffs = [0.0] * self.dimx
87 nlf = [1] * self.dimx
88
89 # ADD THE OUTPUT RESIDUAL VARIABLE
90 varidx.append(self.varres[i]) # residual variable index
91 coeffs.append(-1.0) # linear coefficient
92 nlf.append(0) # linear
93
94 considx = self.addConstraint(
95 co.ConstraintType_Eq, self.Obs[i], varidx, coeffs, nlf
96 )
97 self.consresidual.append(considx)
98
99 # Constraint nobs (Objective)
100 objVarIdx = self.varres.copy()
101 objCoeffs = [1.0] * self.nobs
102 objNlf = [1] * self.nobs
103
104 self.consobj = self.addConstraint(
105 co.ConstraintType_Free, 0.0, objVarIdx, objCoeffs, objNlf
106 )
107
108 # setting the objective constraint
109 self.setObjectiveElement(co.ObjectiveElement_Constraint, self.consobj)
110
111 # setting the optimisation direction
112 self.setOptimizationSense(co.Sense_Minimize)
113
114 # We assume that this is a Large Residual model, where the most
115 # important 2nd derivatives are those that appear directly in the
116 # objective.
117 # We will therefore only define the 2nd derivatives corresponding to
118 # the objective constraint where the 2nd derivatives is 2*I.
119 # CONOPT will by default complain that some nonlinear variables do
120 # not appear in the Hessian. We will therefore define one dummy element
121 # on the diagonal of the Hessian for each of the nonlinear X-variables
122 # and give it the numerical value 0.
123
124 # setting the structure of the hessian
125 Qrow = [0] * (self.dimx + self.nobs)
126 Qcol = [0] * (self.dimx + self.nobs)
127
128 for i in range(self.dimx + self.nobs):
129 Qrow[i] = i
130 Qcol[i] = i
131
132 self.setSDLagrangianStructure(Qrow, Qcol)
133
134 def evaluateNonlinearTerm(self, x, rowno, ignerr, thread):
135 """
136 @copydoc conopt.ModelData.evaluateNonlinearTerm
137 @ingroup PYTHON1THREAD_LEASTSQ2
138 """
139 g = 0
140 if rowno == self.consobj:
141 sum = 0.0
142 for i in range(self.nobs):
143 sum += pow(x[self.varres[i]], 2)
144 g = sum
145
146 else:
147 k = rowno * self.dimx
148 sum = 0.0
149 for i in range(self.dimx):
150 sum += self.A[k] * x[self.varx[i]] + self.B[k] * pow(
151 x[self.varx[i]], 2
152 )
153 k += 1
154 g = sum
155
156 return g
157
158 def evaluateNonlinearJacobian(self, x, rowno, jacnum, ignerr, thread):
159 """
160 @copydoc conopt.ModelData.evaluateNonlinearJacobian
161 @ingroup PYTHON1THREAD_LEASTSQ2
162 """
163
164 jac = []
165 if rowno == self.consobj:
166 for i in range(self.nobs):
167 jac.append(2 * x[self.varres[i]])
168
169 else:
170 k = rowno * self.dimx
171 for i in range(self.dimx):
172 jac.append(self.A[k] + 2 * self.B[k] * x[self.varx[i]])
173 k += 1
174
175 return jac
176
177 def evaluateSDLagrangian(self, x, u, hessianrow, hessiancol):
178 """
179 @copydoc conopt.ModelData.evaluateSDLagrangian
180 @ingroup PYTHON1THREAD_LEASTSQ2
181 """
182 numhessian = len(hessianrow)
183 hessian = [0 for i in range(numhessian)]
184 for i in range(self.dimx):
185 hessian[self.varx[i]] = 0.0
186 for i in range(self.nobs):
187 hessian[self.varres[i]] = 2.0 * u[self.nobs]
188
189 return hessian
190
191
192if __name__ == '__main__':
193 name = os.path.basename(__file__)[:-3]
194
195 conopt = co.Conopt(name)
196 model = LeastSqModelData(700, 500)
197 msghdlr = std.TutMessageHandler(name)
198
199 model.buildModel()
200
201 conopt.loadModel(model)
202 conopt.setMessageHandler(msghdlr)
203
204 # getting the license variables
205 license_int_1 = os.environ.get('CONOPT_LICENSE_INT_1', None)
206 license_int_2 = os.environ.get('CONOPT_LICENSE_INT_2', None)
207 license_int_3 = os.environ.get('CONOPT_LICENSE_INT_3', None)
208 license_text = os.environ.get('CONOPT_LICENSE_TEXT', None)
209 if (
210 license_int_1 is not None
211 and license_int_2 is not None
212 and license_int_3 is not None
213 and license_text is not None
214 ):
215 conopt.setLicense(
216 int(license_int_1),
217 int(license_int_2),
218 int(license_int_3),
219 license_text,
220 )
221
222 coi_error = conopt.solve()
223
224 retcode = std.checkSolve(conopt, 19.4443, coi_error, 0.001)
225
226 sys.exit(retcode)
rndx(self)
Defines a pseudo random number between 0 and 1.
Definition leastsq2.py:37
define_data(self)
Defines the data for the problem.
Definition leastsq2.py:50
__init__(self, int numobs, int dimensionx)
Definition leastsq2.py:19
static int checkSolve(String name, int model_status, int solution_status, double objective, double expected_objective, double tol)
Definition std.java:20
evaluateNonlinearTerm(self, x, rowno, ignerr, thread)
callback method for evaluating the nonlinear terms in a given row
Definition leastsq2.py:134
evaluateNonlinearJacobian(self, x, rowno, jacnum, ignerr, thread)
callback method for evaluating the jacobian for the nonlinear terms in a given row
Definition leastsq2.py:158
evaluateSDLagrangian(self, x, u, hessianrow, hessiancol)
Computes and returns the numerical values of the Lagrangian of the Hessian.
Definition leastsq2.py:177
buildModel(self)
adding the variables and constraints to the model
Definition leastsq2.py:67
float rndx()
Defines a pseudo random number between 0 and 1.
Definition leastsq.c:22