File indexing completed on 2026-09-28 09:20:53
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef _MathSys_Newton_HeaderFile
0015 #define _MathSys_Newton_HeaderFile
0016
0017 #include <MathUtils_Types.hxx>
0018 #include <MathUtils_Config.hxx>
0019 #include <MathLin_Gauss.hxx>
0020 #include <math_FunctionSetWithDerivatives.hxx>
0021
0022 #include <cmath>
0023
0024 namespace MathSys
0025 {
0026 using namespace MathUtils;
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040 template <typename FuncSetType>
0041 VectorResult Newton(FuncSetType& theFunc,
0042 const math_Vector& theStart,
0043 const math_Vector& theTolX,
0044 double theTolF,
0045 size_t theMaxIter = 100)
0046 {
0047 VectorResult aResult;
0048
0049 const int aN = theFunc.NbVariables();
0050 const int aM = theFunc.NbEquations();
0051
0052
0053 if (aN != aM || theStart.Length() != aN || theTolX.Length() != aN)
0054 {
0055 aResult.Status = Status::InvalidInput;
0056 return aResult;
0057 }
0058
0059 const int aLower = theStart.Lower();
0060 const int aUpper = theStart.Upper();
0061
0062
0063 math_Vector aSol = theStart;
0064 math_Vector aF(aLower, aUpper);
0065 math_Vector aDeltaX(aLower, aUpper);
0066 math_Matrix aJacobian(aLower, aUpper, aLower, aUpper);
0067
0068
0069 for (size_t anIter = 0; anIter < theMaxIter; ++anIter)
0070 {
0071
0072 if (!theFunc.Values(aSol, aF, aJacobian))
0073 {
0074 aResult.Status = Status::NumericalError;
0075 aResult.NbIterations = anIter;
0076 return aResult;
0077 }
0078
0079
0080
0081 math_Vector aNegF(aLower, aUpper);
0082 for (int i = aLower; i <= aUpper; ++i)
0083 {
0084 aNegF(i) = -aF(i);
0085 }
0086
0087 auto aLinResult = MathLin::Solve(aJacobian, aNegF);
0088 if (!aLinResult.IsDone())
0089 {
0090 aResult.Status = Status::Singular;
0091 aResult.NbIterations = anIter;
0092 return aResult;
0093 }
0094
0095 aDeltaX = *aLinResult.Solution;
0096
0097
0098 bool aXConverged = true;
0099 for (int i = aLower; i <= aUpper; ++i)
0100 {
0101 if (std::abs(aDeltaX(i)) > theTolX(i))
0102 {
0103 aXConverged = false;
0104 break;
0105 }
0106 }
0107
0108
0109 for (int i = aLower; i <= aUpper; ++i)
0110 {
0111 aSol(i) += aDeltaX(i);
0112 }
0113
0114
0115 if (!theFunc.Value(aSol, aF))
0116 {
0117 aResult.Status = Status::NumericalError;
0118 aResult.NbIterations = anIter + 1;
0119 return aResult;
0120 }
0121
0122
0123 bool aFConverged = true;
0124 for (int i = aLower; i <= aUpper; ++i)
0125 {
0126 if (std::abs(aF(i)) > theTolF)
0127 {
0128 aFConverged = false;
0129 break;
0130 }
0131 }
0132
0133 if (aXConverged && aFConverged)
0134 {
0135 aResult.Status = Status::OK;
0136 aResult.NbIterations = anIter + 1;
0137 aResult.Solution = aSol;
0138 aResult.Jacobian = aJacobian;
0139 return aResult;
0140 }
0141
0142 aResult.NbIterations = anIter + 1;
0143 }
0144
0145
0146 aResult.Status = Status::MaxIterations;
0147 aResult.Solution = aSol;
0148 aResult.Jacobian = aJacobian;
0149 return aResult;
0150 }
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166 template <typename FuncSetType>
0167 VectorResult NewtonBounded(FuncSetType& theFunc,
0168 const math_Vector& theStart,
0169 const math_Vector& theInfBound,
0170 const math_Vector& theSupBound,
0171 const math_Vector& theTolX,
0172 double theTolF,
0173 size_t theMaxIter = 100)
0174 {
0175 VectorResult aResult;
0176
0177 const int aN = theFunc.NbVariables();
0178 const int aM = theFunc.NbEquations();
0179
0180
0181 if (aN != aM || theStart.Length() != aN || theTolX.Length() != aN || theInfBound.Length() != aN
0182 || theSupBound.Length() != aN)
0183 {
0184 aResult.Status = Status::InvalidInput;
0185 return aResult;
0186 }
0187
0188 const int aLower = theStart.Lower();
0189 const int aUpper = theStart.Upper();
0190
0191
0192 math_Vector aSol = theStart;
0193 math_Vector aF(aLower, aUpper);
0194 math_Vector aDeltaX(aLower, aUpper);
0195 math_Matrix aJacobian(aLower, aUpper, aLower, aUpper);
0196
0197
0198 for (int i = aLower; i <= aUpper; ++i)
0199 {
0200 if (aSol(i) < theInfBound(i))
0201 {
0202 aSol(i) = theInfBound(i);
0203 }
0204 if (aSol(i) > theSupBound(i))
0205 {
0206 aSol(i) = theSupBound(i);
0207 }
0208 }
0209
0210
0211 for (size_t anIter = 0; anIter < theMaxIter; ++anIter)
0212 {
0213
0214 if (!theFunc.Values(aSol, aF, aJacobian))
0215 {
0216 aResult.Status = Status::NumericalError;
0217 aResult.NbIterations = anIter;
0218 return aResult;
0219 }
0220
0221
0222 math_Vector aNegF(aLower, aUpper);
0223 for (int i = aLower; i <= aUpper; ++i)
0224 {
0225 aNegF(i) = -aF(i);
0226 }
0227
0228 auto aLinResult = MathLin::Solve(aJacobian, aNegF);
0229 if (!aLinResult.IsDone())
0230 {
0231 aResult.Status = Status::Singular;
0232 aResult.NbIterations = anIter;
0233 return aResult;
0234 }
0235
0236 aDeltaX = *aLinResult.Solution;
0237
0238
0239 bool aXConverged = true;
0240 for (int i = aLower; i <= aUpper; ++i)
0241 {
0242 if (std::abs(aDeltaX(i)) > theTolX(i))
0243 {
0244 aXConverged = false;
0245 break;
0246 }
0247 }
0248
0249
0250 for (int i = aLower; i <= aUpper; ++i)
0251 {
0252 aSol(i) += aDeltaX(i);
0253 if (aSol(i) < theInfBound(i))
0254 {
0255 aSol(i) = theInfBound(i);
0256 }
0257 if (aSol(i) > theSupBound(i))
0258 {
0259 aSol(i) = theSupBound(i);
0260 }
0261 }
0262
0263
0264 if (!theFunc.Value(aSol, aF))
0265 {
0266 aResult.Status = Status::NumericalError;
0267 aResult.NbIterations = anIter + 1;
0268 return aResult;
0269 }
0270
0271
0272 bool aFConverged = true;
0273 for (int i = aLower; i <= aUpper; ++i)
0274 {
0275 if (std::abs(aF(i)) > theTolF)
0276 {
0277 aFConverged = false;
0278 break;
0279 }
0280 }
0281
0282 if (aXConverged && aFConverged)
0283 {
0284 aResult.Status = Status::OK;
0285 aResult.NbIterations = anIter + 1;
0286 aResult.Solution = aSol;
0287 aResult.Jacobian = aJacobian;
0288 return aResult;
0289 }
0290
0291 aResult.NbIterations = anIter + 1;
0292 }
0293
0294
0295 aResult.Status = Status::MaxIterations;
0296 aResult.Solution = aSol;
0297 aResult.Jacobian = aJacobian;
0298 return aResult;
0299 }
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309 template <typename FuncSetType>
0310 VectorResult Newton(FuncSetType& theFunc,
0311 const math_Vector& theStart,
0312 double theTolX,
0313 double theTolF,
0314 size_t theMaxIter = 100)
0315 {
0316 math_Vector aTolXVec(theStart.Lower(), theStart.Upper(), theTolX);
0317 return Newton(theFunc, theStart, aTolXVec, theTolF, theMaxIter);
0318 }
0319
0320 }
0321
0322 #endif