CONOPT
Loading...
Searching...
No Matches
leastsq.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.0] * (self.nobs * self.dimx)
27 self.B = [0.0] * (self.nobs * self.dimx)
28 self.Obs = [0.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.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_LEASTSQ
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 def evaluateNonlinearTerm(self, x, rowno, ignerr, thread):
116 """
117 @copydoc conopt.ModelData.evaluateNonlinearTerm
118 @ingroup PYTHON1THREAD_LEASTSQ
119 """
120 g = 0
121 if rowno == self.consobj:
122 sum = 0.0
123 for i in range(self.nobs):
124 sum += pow(x[self.varres[i]], 2)
125 g = sum
126
127 else:
128 k = rowno * self.dimx
129 sum = 0.0
130 for i in range(self.dimx):
131 sum += self.A[k] * x[self.varx[i]] + self.B[k] * pow(
132 x[self.varx[i]], 2
133 )
134 k += 1
135 g = sum
136
137 return g
138
139 def evaluateNonlinearJacobian(self, x, rowno, jacnum, ignerr, thread):
140 """
141 @copydoc conopt.ModelData.evaluateNonlinearJacobian
142 @ingroup PYTHON1THREAD_LEASTSQ
143 """
144 jac = []
145 if rowno == self.consobj:
146 for i in range(self.nobs):
147 jac.append(2 * x[self.varres[i]])
148
149 else:
150 k = rowno * self.dimx
151 for i in range(self.dimx):
152 jac.append(self.A[k] + 2 * self.B[k] * x[self.varx[i]])
153 k += 1
154
155 return jac
156
157
158if __name__ == '__main__':
159 name = os.path.basename(__file__)[:-3]
160
161 conopt = co.Conopt(name)
162 model = LeastSqModelData(700, 500)
163 msghdlr = std.TutMessageHandler(name)
164
165 conopt.setMessageHandler(msghdlr)
166
167 model.buildModel()
168 conopt.loadModel(model)
169
170 # getting the license variables
171 license_int_1 = os.environ.get('CONOPT_LICENSE_INT_1', None)
172 license_int_2 = os.environ.get('CONOPT_LICENSE_INT_2', None)
173 license_int_3 = os.environ.get('CONOPT_LICENSE_INT_3', None)
174 license_text = os.environ.get('CONOPT_LICENSE_TEXT', None)
175 if (
176 license_int_1 is not None
177 and license_int_2 is not None
178 and license_int_3 is not None
179 and license_text is not None
180 ):
181 conopt.setLicense(
182 int(license_int_1),
183 int(license_int_2),
184 int(license_int_3),
185 license_text,
186 )
187
188 coi_error = conopt.solve()
189
190 retcode = std.checkSolve(conopt, 19.4443, coi_error, 0.001)
191
192 sys.exit(retcode)
rndx(self)
Defines a pseudo random number between 0 and 1.
Definition leastsq.py:38
__init__(self, int numobs, int dimensionx)
Definition leastsq.py:19
define_data(self)
Defines the data for the problem.
Definition leastsq.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 leastsq.py:139
evaluateNonlinearTerm(self, x, rowno, ignerr, thread)
callback method for evaluating the nonlinear terms in a given row
Definition leastsq.py:115
buildModel(self)
adding the variables and constraints to the model
Definition leastsq.py:68
float rndx()
Defines a pseudo random number between 0 and 1.
Definition leastsq.c:22