当前位置:文档之家› 非线性方程组-最速下降法(梯度法)

非线性方程组-最速下降法(梯度法)

梯度法(又名,最速下降法)
(该法总可以收敛,但是,在接近真解时收敛的速度会放慢。

) 梯度法又称为最速下降法,用于求解实系数非线性方程组
12(,,,)0,
1,2,,i n f x x x i n
== (7-15)
的一组根。

梯度法首先是定义一个目标函数
2
12121
(,,,)(,,,)
n
n i n i x x x f x x x =Φ=

(7-16)
使目标函数2
1
n
i
i f =Φ=

达到最小的12,,,n x x x 是我们寻找的一组解,这是非
线性最小二乘法问题。

如果第(0,1,2,)k k = 步求得一组解1
2
,,,n
k k k x x x ,使得
12(,,,)n k k k
x x x ε
Φ< (7-17)
则认为1
2
,,,n
k k k x x x 是原方程组满足一定精度的()ε要求的一组解。

梯度法的计算过程是:
(1)先给定一组不全为零的初值1
2
000,,,n
x x x ,第k 步的一组根为1
2
,,,n
k k k
x x x ;
(2)计算目标函数1
2
(,,,)n
k k k x x x Φ 的值;(单独子程序:fn =TargetFunction)
(3)若1
2
(,,,)n
k k k x x x εΦ< ,则认为1
2
,,,n
k k k x x x 是满足一定精度()ε的一组
解,否则,作如下修正计算
1
α
+=∂Φ=-∂i
k
i i
k k k
i i
x x x x x (7-18)
其中
121212*********
1111222
(,,,)
(,,,)(,,,)(,,,)(,,,)(,,,)(,,,)*,1,2,,α
==⎫Φ=
⎪⎛⎫
⎪∂Φ ⎪ ⎪
∂⎝⎭Φ+-Φ∂Φ=∂⎬Φ+-Φ∂Φ=
∂Φ+-Φ∂Φ
=
∂==∑ n k
j j
n n n n n n k k k
k
n j j x x k k k k k k
k k k k k k k k k k k k
n n n
k
i i x x x x x h x x x x x x h x x h x x x x x h x x x h x x x x h h H x i n ⎪⎪⎪
⎪⎪⎪⎪
⎪⎪⎪

⎪⎪⎪⎪⎪⎭
(7-19)
H 为控制收敛的常数,通常选为(10-5~10-6),收敛精度ε
选为(10-6~10
-8
)。

(4)重复修正1
k i
x +,直到
12111
(,,,)n k k k ε
+++ΦΦΦ< ,计算终止。

图7-3 最速下降法计算框图
对应的计算程序代码为C语言编程,据称该程序经Turboc 2.0编译通过。

/* grad1.c 程序段名称
A system of non-linear equations is solved by using gradient method
梯度法解非线性方程组例题
3*X1-cos(X2*X3)-0.5=0
X1^2-81*(X2+0.1)^2+sin(X3)+1.06=0
exp(-X1*X2)+20+X3+(10*PI-3)/3=0
#include<math.h> ‘主程序头,包含数学头<math.h >
main()
{int i , j ,n = 3; ‘定义整型数据,并给定方程个数,n 值
double y[4], x[4]={0.0,0.5,0.5,0.5}; ‘公用数据的定义,初始化根和变量
double eps = 1.e-08; ‘精度要求,以上数据在newton函数中需要用
newton(n,x,y,eps); ‘调用牛顿子程序
printf(“The solutions of non-linear equations\n”);‘制表、划线
pri_line(45);
(for (i=1; i<=n; i++) ‘显示迭代结果
printf(“ x%1d=%12.6f\tf%1d=%12.6E\n”,i,x[i],i,y[i]);
pri_line(45);
} …主程序段结束
double fn(n,x,y)‟定义函数fn(),计算目标函数值平方加和值并返回
int n; double x[], y[]; ‘公用数据接口有2个矩阵和n
{ int i; double s2=0.0; ‘定义数据,s2为目标函数加和
y[1]=3.0*x[1]-cos(x[2]*x[3]-0.5; ‘构建方程组,并求值
y[2]=x[1]*x[1]-81.0*(x[2]+0.1)*(x[2]+0.1)+sin(x[3])+1.06;
y[3]=exp(-x[1]*x[2]+20.0*x[3]+(10*M_PI-3.0)/3.0;
for (i=1; i<=n ; i++)
s2+= y[i]*y[i]; ‘计算目标函数值平方的加和
return(s2); ‘返回计算结果}
newton ( n, x, y, eps ) ‘牛顿子程序
int n; double x[ ], y[ ], eps; …公用数据申明,这些数据为已知
{ int i;
double s[4], s0, s1, s2, t, alpha, h=1.e-05; …自用数据定义
… s[4] = [ 1212(,,,)(,,,)
Φ+-Φ∂Φ=
∂ n n k k k k k k
n n
n
x x x h x x x x h ] 序列
… s0 = 12(,,,)
Φ n k
k
k
x x x
目标函数值 … s1 = 2
1==
⎛⎫
∂Φ ⎪ ⎪∂⎝⎭
∑k
j j
n
j j x x x =
s1+=s[i]*s[i]; … s2 =
12(,,,)
Φ+ n k k k
n x x x h
… t = x[i] 值的临时存放单元 …
122
1(,,,)α
==Φ==
⎛⎫∂Φ ⎪ ⎪∂⎝⎭
∑ n k
j j
k k k
k
n
j j x x x x x alpha x
while (1) ‘while do 循环体
{ s2 = fn(n,x,y); … 调用目标函数计算 s0 = s2; ‘保留k 值时的
12(,,,)
Φ n k
k
k
x x x
‘给新的目标函数值让位
if (s0<eps) break; ‘判断是否已经求解出了根
s1=0.0; …当未求解出根的时候继续迭代
for ( i=1; i<=n; i++) ‘for ()
{t = x[i]; …保留x (k) x[i] = (1.0+h)*t; ‘计算 (x i +h i )和s2,
*= k
i i
h H x ,
s2 = fn(n, x, y); …针对(x i +h)计算目标函数值 s[i] = (s2-s0) / (h*t); …s[ ]序列的值在循环体外要使用,
…所以要有固定的数组变量来存放
‘1212(,,,)(,,,)
Φ+-Φ∂Φ
=
∂ n n k k k k k k
n n
n
x x x h x x x x h 求导数值
s1+=s[i]*s[i]; …导数平方值加和=2
1==⎛⎫
∂Φ ⎪ ⎪∂⎝⎭
∑k
j j
n
j j x x x
x[i]=t; } ‘将新的赋给x (k+1), alpha = s0/s1; ‘得到alpha 新值 for (i=1; i<=n; i++) … 循环求向量序列 x[i] = x[i] - alpha*s[i] ; ‘得到修正后的x i 序列;
… 为再一次的调用fn( )做准备.
} …while do 循环终点
} …Newton( )结束 pri_line(int n) …划线子程序 { int i;
for (i=0 ; i<n ; i++)
printf(“%c”,0xc4);printf(“\n”); }。

相关主题