1 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 // + This file is part of enGrid. +
5 // + Copyright 2008-2014 enGits GmbH +
7 // + enGrid is free software: you can redistribute it and/or modify +
8 // + it under the terms of the GNU General Public License as published by +
9 // + the Free Software Foundation, either version 3 of the License, or +
10 // + (at your option) any later version. +
12 // + enGrid is distributed in the hope that it will be useful, +
13 // + but WITHOUT ANY WARRANTY; without even the implied warranty of +
14 // + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +
15 // + GNU General Public License for more details. +
17 // + You should have received a copy of the GNU General Public License +
18 // + along with enGrid. If not, see <http://www.gnu.org/licenses/>. +
20 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
21 #include "optimisation.h"
22 #include "guimainwindow.h"
24 ErrorFunction::ErrorFunction()
35 void ErrorFunction::set(QString settings_txt
)
37 QStringList items
= settings_txt
.split(';');
38 if (items
.size() != 2) {
39 EG_ERR_RETURN("syntax error for error weighting");
41 m_Err0
= items
[0].trimmed().toDouble();
43 m_XS
= items
[1].trimmed().toDouble();
46 m_Exp
= log(m_ErrS
/m_Err0
)/log(1.0 - m_XS
);
50 double ErrorFunction::operator()(double x
)
54 double x0
= fabs(1-x
);
55 e
= m_Err0
*pow(x0
, m_Exp
);
56 m_MaxErr
= max(m_MaxErr
, x0
);
65 double ErrorFunction::averageError()
67 if (m_NumTotalCalls
== 0) {
70 return m_AverageError
/m_NumTotalCalls
;
73 double ErrorFunction::totalError()
75 if (m_NumCalls
== 0) {
78 return m_TotalError
/m_NumCalls
;
81 void ErrorFunction::reset(bool reset_average
)
92 Optimisation::Optimisation()
96 for (int i
= 0; i
< 3; ++i
) {
97 F
[i
] = new double*[3];
98 for (int j
= 0; j
< 3; ++j
) {
99 F
[i
][j
] = new double[3];
102 m_ErrorFunctions
.clear();
105 void Optimisation::getErrSet(QString group
, QString key
, double err0
, double xs
, ErrorFunction
* err_func
)
107 QString err0_txt
, xs_txt
;
108 err0_txt
.setNum(err0
);
110 QString value
= err0_txt
+ "; " + xs_txt
;
112 QSettings
*qset
= GuiMainWindow::settings();
113 QString typed_key
= "string/" + key
;
114 if (group
!= QObject::tr("General")) {
115 qset
->beginGroup(group
);
117 if (!qset
->contains(typed_key
)) {
118 qset
->setValue(typed_key
, value
);
120 variable
= (qset
->value(typed_key
,variable
)).toString();
121 if (group
!= QObject::tr("General")) {
124 err_func
->set(variable
);
125 err_func
->setName(key
.replace(" ", "_"));
126 m_ErrorFunctions
.append(err_func
);
129 double Optimisation::angleX(const vec3_t
&v1
, const vec3_t
&v2
)
131 double va1
= v1
.abs();
132 double va2
= v2
.abs();
133 double scal
= max(0.0, v1
*v2
);
134 double alpha
= acos(scal
/(va1
*va2
));
135 return fabs(1 - 2*alpha
/M_PI
);
138 void Optimisation::computeDerivatives(vec3_t x
)
140 F
[0][0][0] = func(x
[0]-Dx
, x
[1]-Dy
, x
[2]-Dz
);
141 F
[1][0][0] = func(x
[0], x
[1]-Dy
, x
[2]-Dz
);
142 F
[2][0][0] = func(x
[0]+Dx
, x
[1]-Dy
, x
[2]-Dz
);
143 F
[0][1][0] = func(x
[0]-Dx
, x
[1], x
[2]-Dz
);
144 F
[1][1][0] = func(x
[0], x
[1], x
[2]-Dz
);
145 F
[2][1][0] = func(x
[0]+Dx
, x
[1], x
[2]-Dz
);
146 F
[0][2][0] = func(x
[0]-Dx
, x
[1]+Dy
, x
[2]-Dz
);
147 F
[1][2][0] = func(x
[0], x
[1]+Dy
, x
[2]-Dz
);
148 F
[2][2][0] = func(x
[0]+Dx
, x
[1]+Dy
, x
[2]-Dz
);
149 F
[0][0][1] = func(x
[0]-Dx
, x
[1]-Dy
, x
[2]);
150 F
[1][0][1] = func(x
[0], x
[1]-Dy
, x
[2]);
151 F
[2][0][1] = func(x
[0]+Dx
, x
[1]-Dy
, x
[2]);
152 F
[0][1][1] = func(x
[0]-Dx
, x
[1], x
[2]);
153 F
[1][1][1] = func(x
[0], x
[1], x
[2]);
154 F
[2][1][1] = func(x
[0]+Dx
, x
[1], x
[2]);
155 F
[0][2][1] = func(x
[0]-Dx
, x
[1]+Dy
, x
[2]);
156 F
[1][2][1] = func(x
[0], x
[1]+Dy
, x
[2]);
157 F
[2][2][1] = func(x
[0]+Dx
, x
[1]+Dy
, x
[2]);
158 F
[0][0][2] = func(x
[0]-Dx
, x
[1]-Dy
, x
[2]+Dz
);
159 F
[1][0][2] = func(x
[0], x
[1]-Dy
, x
[2]+Dz
);
160 F
[2][0][2] = func(x
[0]+Dx
, x
[1]-Dy
, x
[2]+Dz
);
161 F
[0][1][2] = func(x
[0]-Dx
, x
[1], x
[2]+Dz
);
162 F
[1][1][2] = func(x
[0], x
[1], x
[2]+Dz
);
163 F
[2][1][2] = func(x
[0]+Dx
, x
[1], x
[2]+Dz
);
164 F
[0][2][2] = func(x
[0]-Dx
, x
[1]+Dy
, x
[2]+Dz
);
165 F
[1][2][2] = func(x
[0], x
[1]+Dy
, x
[2]+Dz
);
166 F
[2][2][2] = func(x
[0]+Dx
, x
[1]+Dy
, x
[2]+Dz
);
168 grad_f
[0] = (F
[2][1][1]-F
[0][1][1])/(2*Dx
);
169 grad_f
[1] = (F
[1][2][1]-F
[1][0][1])/(2*Dy
);
170 grad_f
[2] = (F
[1][1][2]-F
[1][1][0])/(2*Dz
);
172 J
[0][0] = (F
[0][1][1]-2*F
[1][1][1]+F
[2][1][1])/(Dx
*Dx
);
173 J
[1][1] = (F
[1][0][1]-2*F
[1][1][1]+F
[1][2][1])/(Dy
*Dy
);
174 J
[2][2] = (F
[1][1][0]-2*F
[1][1][1]+F
[1][1][2])/(Dz
*Dz
);
176 J
[0][1] = ((F
[2][2][1]-F
[0][2][1]) - (F
[2][0][1]-F
[0][0][1]))/(4*Dx
*Dy
);
177 J
[0][2] = ((F
[2][1][2]-F
[0][1][2]) - (F
[2][1][0]-F
[0][1][0]))/(4*Dx
*Dz
);
178 J
[1][2] = ((F
[1][2][2]-F
[1][2][2]) - (F
[1][0][0]-F
[1][0][0]))/(4*Dy
*Dz
);
184 vec3_t
Optimisation::optimise(vec3_t x
)
186 computeDerivatives(x
);
187 mat3_t M
= J
.inverse();
188 vec3_t x_new
= (-1)*(M
*grad_f
);
189 if (!checkVector(x_new
)) {
196 void Optimisation::resetErrorFunctions(bool reset_average
)
198 foreach (ErrorFunction
*err_func
, m_ErrorFunctions
) {
199 err_func
->reset(reset_average
);
203 double Optimisation::totalError()
206 foreach (ErrorFunction
*err_func
, m_ErrorFunctions
) {
207 e
+= err_func
->totalError();
212 void Optimisation::printErrors()
214 foreach (ErrorFunction
*err_func
, m_ErrorFunctions
) {
215 if (err_func
->active()) {
216 cout
<< qPrintable(err_func
->name()) << ":\n average=" << err_func
->averageError() << "\n maximum=" << err_func
->maxError() << endl
;