CONOPT
Loading...
Searching...
No Matches
leastsq10.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 self.consobj = 0
25
26 self.A = [0] * (self.nobs * self.dimx)
27 self.B = [0] * (self.nobs * self.dimx)
28 self.C = [0] * (self.nobs * self.dimx)
29 self.Obs = [0] * self.nobs
30
31 self.varx = []
32 self.varres = []
33 self.consresidual = []
34
35 self.define_data()
36
37 super().__init__()
38
39 def rndx(self):
40 """
41 Defines a pseudo random number between 0 and 1
42
43 NOTE: it would be possible to use random module to generate the random
44 numbers. We have written our own random number generator to be consistent
45 with the original Fortran example.
46 """
47 self.seed = self.seed * 1027 + 25
48 times = int(self.seed / 1048576)
49 self.seed = self.seed - 1048576 * times
50 return self.seed / 1048576.0
51
52 def define_data(self):
53 """
54 Defines the data for the problem
55 """
56 Xtarg = -1.0
57 Noise = 1.0
58 k = 0
59
60 for i in range(self.nobs):
61 O = 0
62 for j in range(self.dimx):
63 self.A[k] = self.rndx()
64 self.B[k] = self.rndx()
65 O += self.A[k] * Xtarg + self.B[k] * math.pow(Xtarg, 2)
66 k += 1
67 self.Obs[i] = O + Noise * self.rndx()
68
69 def buildModel(self):
70 """
71 adding the variables and constraints to the model
72 @ingroup PYTHON1THREAD_LEASTSQ10
73 """
74 # adding the variables to the model
75 for i in range(self.dimx):
76 varidx = self.addVariable(
77 -co.Conopt.Infinity, co.Conopt.Infinity, -0.8
78 )
79 self.varx.append(varidx)
80
81 for i in range(self.nobs):
82 varidx = self.addVariable(-co.Conopt.Infinity, co.Conopt.Infinity, 0.0)
83 self.varres.append(varidx)
84
85 # adding the constraints to the model
86 for i in range(self.nobs):
87 varidx = self.varx.copy()
88 coeffs = [0.0] * self.dimx
89 nlf = [1] * self.dimx
90
91 # ADD THE OUTPUT RESIDUAL VARIABLE
92 varidx.append(self.varres[i]) # residual variable index
93 coeffs.append(-1.0) # linear coefficient
94 nlf.append(0) # linear
95
96 considx = self.addConstraint(
97 co.ConstraintType_Eq, self.Obs[i], varidx, coeffs, nlf
98 )
99 self.consresidual.append(considx)
100
101 # Constraint nobs (Objective)
102 objVarIdx = self.varres.copy()
103 objCoeffs = [1.0] * self.nobs
104 objNlf = [1] * self.nobs
105
106 self.consobj = self.addConstraint(
107 co.ConstraintType_Free, 0.0, objVarIdx, objCoeffs, objNlf
108 )
109
110 # setting the objective constraint
111 self.setObjectiveElement(co.ObjectiveElement_Constraint, self.consobj)
112
113 # setting the optimisation direction
114 self.setOptimizationSense(co.Sense_Minimize)
115
116 # setting the second derivative evaluation type
117 self.setSDEvaluationType(co.SDEvaluationType_Constraint)
118
119 def evaluateNonlinearTerm(self, x, rowno, ignerr, thread):
120 """
121 @copydoc conopt.ModelData.evaluateNonlinearTerm
122 @ingroup PYTHON1THREAD_LEASTSQ10
123 """
124 g = 0
125 if rowno == self.consobj:
126 sum = 0.0
127 for i in range(self.nobs):
128 sum += pow(x[self.varres[i]], 2)
129 g = sum
130
131 else:
132 k = rowno * self.dimx
133 sum = 0.0
134 for i in range(self.dimx):
135 sum += self.A[k] * x[self.varx[i]] + self.B[k] * pow(
136 x[self.varx[i]], 2
137 )
138 k += 1
139 g = sum
140
141 return g
142
143 def evaluateNonlinearJacobian(self, x, rowno, jacnum, ignerr, thread):
144 """
145 @copydoc conopt.ModelData.evaluateNonlinearJacobian
146 @ingroup PYTHON1THREAD_LEASTSQ10
147 """
148
149 jac = []
150 if rowno == self.consobj:
151 for i in range(self.nobs):
152 jac.append(2 * x[self.varres[i]])
153
154 else:
155 k = rowno * self.dimx
156 for i in range(self.dimx):
157 jac.append(self.A[k] + 2 * self.B[k] * x[self.varx[i]])
158 k += 1
159
160 return jac
161
162 def initDirectionalSDEval(self, x, dx, rowlist, numthread, newpoint):
163 """
164 @copydoc conopt.ModelData.initDirectionalSDEval
165 @ingroup PYTHON1THREAD_LEASTSQ10
166 """
167
168 # Constraint row with b(i,j)*x(j)**2 as only nonlinear term.
169 # Compute the directional term 2*b(i,j)*dx(j) and keep for later
170
171 k = 0
172 for i in range(self.nobs):
173 for j in range(self.dimx):
174 self.C[k] = 2.0 * self.B[k] * dx[self.varx[j]]
175 k += 1
176
177 def evaluateDirectionalSD(self, x, dx, rowno, jacnum, thread):
178 """
179 @copydoc conopt.ModelData.evaluateDirectionalSD
180 @ingroup PYTHON1THREAD_LEASTSQ10
181 """
182
183 if rowno == self.nobs:
184 # Objective row: sum(i, res(i)**2 )
185 dirsd = [0.0] * (self.dimx + self.nobs)
186 for i in range(self.dimx):
187 dirsd[self.varx[i]] = 0
188
189 for i in range(self.nobs):
190 dirsd[self.varres[i]] = 2.0 * dx[self.varres[i]]
191
192 else:
193 # Constraint row with b(i,j)*x(j)**2 as only nonlinear term
194 k = rowno * self.dimx
195 for i in range(self.dimx):
196 dirsd[self.varx[i]] = self.C[k]
197 k += 1
198
199 for i in range(self.nobs):
200 dirsd[self.varres[i]] = 0
201
202 return dirsd
203
204
205if __name__ == '__main__':
206 name = os.path.basename(__file__)[:-3]
207
208 conopt = co.Conopt(name)
209 model = LeastSqModelData(700, 500)
210 msghdlr = std.TutMessageHandler(name)
211
212 conopt.setMessageHandler(msghdlr)
213
214 model.buildModel()
215 conopt.loadModel(model)
216
217 # getting the license variables
218 license_int_1 = os.environ.get('CONOPT_LICENSE_INT_1', None)
219 license_int_2 = os.environ.get('CONOPT_LICENSE_INT_2', None)
220 license_int_3 = os.environ.get('CONOPT_LICENSE_INT_3', None)
221 license_text = os.environ.get('CONOPT_LICENSE_TEXT', None)
222 if (
223 license_int_1 is not None
224 and license_int_2 is not None
225 and license_int_3 is not None
226 and license_text is not None
227 ):
228 conopt.setLicense(
229 int(license_int_1),
230 int(license_int_2),
231 int(license_int_3),
232 license_text,
233 )
234
235 coi_error = conopt.solve()
236
237 retcode = std.checkSolve(conopt, 19.4443, coi_error, 0.001)
238
239 sys.exit(retcode)
__init__(self, int numobs, int dimensionx)
Definition leastsq10.py:19
define_data(self)
Defines the data for the problem.
Definition leastsq10.py:52
rndx(self)
Defines a pseudo random number between 0 and 1.
Definition leastsq10.py:39
static int checkSolve(String name, int model_status, int solution_status, double objective, double expected_objective, double tol)
Definition std.java:20
initDirectionalSDEval(self, x, dx, rowlist, numthread, newpoint)
a callback for the initialisation of the second derivative evaluation.
Definition leastsq10.py:162
evaluateNonlinearTerm(self, x, rowno, ignerr, thread)
callback method for evaluating the nonlinear terms in a given row
Definition leastsq10.py:119
evaluateDirectionalSD(self, x, dx, rowno, jacnum, thread)
computes the directional second derivative for a single constraint
Definition leastsq10.py:177
evaluateNonlinearJacobian(self, x, rowno, jacnum, ignerr, thread)
callback method for evaluating the jacobian for the nonlinear terms in a given row
Definition leastsq10.py:143
buildModel(self)
adding the variables and constraints to the model
Definition leastsq10.py:69
float rndx()
Defines a pseudo random number between 0 and 1.
Definition leastsq.c:22