头文件:
/* * Copyright (c) 2008-2011 Zhang Ming (M. Zhang), [email protected] * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 2 or any later version. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. A copy of the GNU General Public License is available at: * http://www.fsf.org/licensing/licenses */ /***************************************************************************** * nlfuncs.h * * Nonlinear equations and functions. * * Zhang Ming, 2010-10, Xi'an Jiaotong University. *****************************************************************************/ #ifndef NLFUNCS_H #define NLFUNCS_H #include <vector.h> #include <matrix.h> namespace splab { template <typename Type> class NLEqus { public: /** * Compute the values of equations at point X. */ Vector<Type> operator()( const Vector<Type> &X ) { Vector<Type> XNew( X.dim() ); XNew(1) = ( X(1)*X(1) - X(2) + Type(0.5) ) / 2; XNew(2) = ( -X(1)*X(1) - 4*X(2)*X(2) + 8*X(2) + 4 ) / 8; return XNew; } }; // class NLEqus template <typename Type> class NLFuncs { public: /** * Compute the values of functions at point X. */ Vector<Type> operator()( Vector<Type> &X ) { Vector<Type> FX( X.dim() ); FX(1) = X(1)*X(1) - 2*X(1) - X(2) + Type(0.5); FX(2) = X(1)*X(1) + 4*X(2)*X(2) - 4; return FX; } /** * Compute the Jacobian-Matrix at point X. */ Matrix<Type> jacobi( Vector<Type> &X ) { Matrix<Type> JX( X.dim(), X.dim() ); JX(1,1) = 2*X(1) - 2; JX(1,2) = Type(-1); JX(2,1) = 2*X(1); JX(2,2) = 8*X(2); return JX; } }; // class NLFuncs } // namespace splab #endif // NLFUNCS_H
/* * Copyright (c) 2008-2011 Zhang Ming (M. Zhang), [email protected] * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 2 or any later version. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. A copy of the GNU General Public License is available at: * http://www.fsf.org/licensing/licenses */ /***************************************************************************** * nleroots.h * * Solution for nonlinear equations. * * This file includes two routines for finding roots of nonlinear equations. * The Seidel method is and improvement of Fixed-Point iteration mithod, * which don't need compute the Jacobi matrix, but with a slow convergence * rate. The other is Newton method, which can provide a faster rate of * convergence, but at the const of computing Jacobi matrix and its inverse * to get the iterative increment. * * Zhang Ming, 2010-10, Xi'an Jiaotong University. *****************************************************************************/ #ifndef NLEROOTS_H #define NLEROOTS_H #include <nlfuncs.h> #include <linequs1.h> namespace splab { template<typename Type> Vector<Type> seidel( NLEqus<Type> &G, const Vector<Type> &X0, const Type tol=Type(1.0e-6), int maxItr=MAXTERM ); template<typename Type> Vector<Type> newton( NLFuncs<Type> &F, const Vector<Type> &X0, const Type tol=Type(1.0e-6), const Type eps=Type(1.0e-9), int maxItr=MAXTERM ); #include <nleroots-impl.h> } // namespace splab #endif // NLEROOTS_H
实现文件:
/* * Copyright (c) 2008-2011 Zhang Ming (M. Zhang), [email protected] * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 2 or any later version. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. A copy of the GNU General Public License is available at: * http://www.fsf.org/licensing/licenses */ /***************************************************************************** * nleroots-impl.h * * Implementation for nonlinear equations rooting. * * Zhang Ming, 2010-10, Xi'an Jiaotong University. *****************************************************************************/ /** * Bisection method for finding function root. */ template <typename Type> Vector<Type> seidel( NLEqus<Type> &G, const Vector<Type> &X0, const Type tol, int maxItr ) { int N = X0.dim(); Vector<Type> X(X0), XNew(X0), tmp(N); for( int k=0; k<maxItr; ++k ) { // update X by the Seidel iteration method for( int i=1; i<=N; ++i ) { tmp = G(XNew); XNew(i) = tmp(i); } // conditional judgement for stopping iteration Type err = norm( XNew-X ), relErr = err / ( norm(XNew) + EPS ); if( (err < tol) || (relErr < tol) ) return XNew; X = XNew; } cout << "No solution for the specified tolerance!" << endl; return XNew; } /** * Newton method for finding function root. */ template <typename Type> Vector<Type> newton( NLFuncs<Type> &F, const Vector<Type> &X0, const Type tol, const Type eps, int maxItr ) { Vector<Type> X(X0), XNew( X0.dim() ); for( int k=0; k<maxItr; ++k ) { // update X by the Newton iteration method XNew = X - luSolver( F.jacobi(X), F(X) ); // conditional judgement for stopping iteration Type err = norm( XNew-X ), relErr = err / ( norm(XNew) + EPS ); if( (err < tol) || (relErr < tol) || (norm(F(XNew)) < eps) ) return XNew; X = XNew; } cout << "No solution for the specified tolerance!" << endl; return XNew; }
测试代码:
/***************************************************************************** * nle_test.cpp * * Rooting of nonlinear equations testing. * * Zhang Ming, 2010-10, Xi'an Jiaotong University. *****************************************************************************/ #include <iostream> #include <iomanip> #include <nleroots.h> using namespace std; using namespace splab; typedef double Type; const int N = 2; int main() { Vector<Type> X0(N); cout << setiosflags(ios::fixed) << setprecision(8); NLEqus<Type> G; X0(1) = 0; X0(2) = 1; cout << "Seidel iteration method : " << seidel( G, X0 ) << endl; NLFuncs<Type> F; X0(1) = 2; X0(2) = 0; cout << "Newton iteration method : " << newton( F, X0 ) << endl; return 0; }
运行结果:
Seidel iteration method : size: 2 by 1 -0.22221445 0.99380842 Newton iteration method : size: 2 by 1 1.90067673 0.31121857 Process returned 0 (0x0) execution time : 0.078 s Press any key to continue.