非线性方程组求解算法的C++实现

头文件:

/*
 * 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.

你可能感兴趣的:(非线性方程组求解算法的C++实现)