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