题目:
已知 f(x) = (x1-1)2+5(x2-5)2+(x3-1)2+5(x4-5)2 ,用快速下降法、牛顿法或共轭梯度法求 minf(x) 。
共轭梯度法代码:
//共轭梯度法
//请根据具体题目,修改本程序“//@”所在行的下一行代码。
#include<math.h>
#include<stdio.h>
#include<stdlib.h>
//@ 题目中方程是几元的,此处将LEN设为几
#define LEN 4
#define TYPE float
TYPE fAnswer(TYPE *x) { //求f(x)的值,并返回
TYPE f;
//@ 题目中的方程写与此
f = (x[0] - 1) * (x[0] - 1) + 5 * (x[1] - 5) * (x[1] - 5) + (x[2] - 1) * (x[2] - 1) + 5 * (x[3] - 5) * (x[3] - 5);
return f;
}
void vectorMultiply(TYPE *x, TYPE e) { //常数e乘x向量,赋值给x向量 【若求负梯度,可用梯度乘-1】
int i;
for(i = 0; i < LEN; i++) {
x[i] = e * x[i];
}
}
void vectorAdd(TYPE *x, TYPE *y, TYPE *z) { //向量加法操作
int i;
for(i = 0; i < LEN; i++) {
z[i] = x[i] + y[i];
}
}
void vectorSub(TYPE *x, TYPE *y, TYPE *z) { //向量减法操作
int i;
for(i = 0; i < LEN; i++) {
z[i] = x[i] - y[i];
}
}
void vectoreEqual(TYPE *x, TYPE *y) { //向量赋值操作
int i;
for(i = 0; i < LEN; i++) {
y[i] = x[i];
}
}
TYPE norm2_graded(TYPE *x) { //负梯度模的平方
int i;
TYPE norm2 = 0.0;
for(i = 0; i < LEN; i++) {
norm2 += x[i] * x[i];
}
return norm2;
}
//@ 对题目的xi分别求偏倒,赋值给stepLength[i]
void setStepLength(TYPE *stepLength, TYPE *x0) {
stepLength[0] = 2 * (1 - x0[0]);
stepLength[1] = 10 * (5 - x0[1]);
stepLength[2] = 2 * (1 - x0[2]);
stepLength[3] = 10 * (5 - x0[3]);
}
void DSC(TYPE *x0, TYPE *stepLength) { //用D.S.C.法求下一个x落点
TYPE x1[LEN];
TYPE x2[LEN];
TYPE x3[LEN];
TYPE x4[LEN];
TYPE x5[LEN];
TYPE xa[LEN];
TYPE xb[LEN];
TYPE xc[LEN];
vectorAdd(x0, stepLength, x1);
if(fAnswer(x1) > fAnswer(x0))
vectorMultiply(stepLength, -1);
vectorAdd(x0, stepLength, x1);
while(fAnswer(x1) <= fAnswer(x0)) {
vectoreEqual(x1, x0);
vectorAdd(stepLength, stepLength, stepLength);
vectorAdd(x1, stepLength, x1);
}
vectorMultiply(stepLength, 0.5);
vectorSub(x0, stepLength, x2);
vectoreEqual(x1, x4);
vectoreEqual(x0, x3);
vectorSub(x1, stepLength, x5);
if(fAnswer(x5) > fAnswer(x3))
vectoreEqual(x3, xb);
else
vectoreEqual(x5, xb);
vectorSub(xb, stepLength, xa);
vectorAdd(xb, stepLength, xc);
vectorMultiply(stepLength, (fAnswer(xa) - fAnswer(xc)) / (2 * (fAnswer(xa) - 2 * fAnswer(xb) + fAnswer(xc))));
vectorAdd(xb, stepLength, x0);
setStepLength(stepLength, xb);
}
void main() { //方法主体
TYPE x0[LEN]; //初始点
TYPE stepLength[LEN]; //步长
TYPE stepLength2[LEN];
TYPE e = 0.001; //误差
TYPE a = 0.00;
int i; //用于循环计数
int n = LEN;
int count = 0;
printf("请输入x的初始值:\n");
for(i = 0; i < LEN; i++) { //初始化x0数组
printf("x%d = ", i+1);
scanf("%f", &x0[i]);
}
setStepLength(stepLength, x0);
for(i = 1; norm2_graded(stepLength) > e * e; i++) { //共轭梯度法的实现主体
DSC(x0, stepLength);
if(i != n) {
if(norm2_graded(stepLength) <= e * e) break;
setStepLength(stepLength2, x0);
a = norm2_graded(stepLength2) / norm2_graded(stepLength);
vectorMultiply(stepLength, a);
vectorAdd(stepLength2, stepLength, stepLength);
i = i + 1;
} else {
i = 1;
}
count = count + 1;
}
printf("共轭梯度法循环结束,共循环%d次\n", count);
printf("使用共轭梯度法获得的最优点为:\n");
for(i = 0; i < LEN; i++) {
printf("x%d = %f\n", i+1, x0[i]);
}
printf("minf(x) = %f\n", fAnswer(x0));
printf("共轭梯度法程序结束!!!\n");
}
总结
本解法所使用的一维搜索算法仍是改进的D.S.C.法,将步长 的初始值改为负梯度向量,D.S.C.算法中的其它一维参量也采用向量形式替换,使此D.S.C.法可适用于多维搜索。
本解法仅通过将我发表的最速下降法中的main()函数中最速下降法的实现主体替换为共轭梯度法的实现主体而得到。
经测试验证,此方法无误。
分享到:
相关推荐
下面我们将深入探讨PRP共轭梯度法以及如何用C++来实现这一算法。 PRP共轭梯度法全称为Polak-Ribiére-Polyak共轭梯度法,它是共轭梯度法的一个变种,由法国数学家Wolfgang Polak和罗马尼亚数学家Gheorghe Ribiére...
它通过在多维空间中的单纯形(一个多面体)边缘移动来寻找最优解。这种方法可以处理有多个变量和约束条件的优化问题,是运筹学中的基础工具,广泛应用于生产计划、资源分配等领域。 3. **数值积分(Numerical ...
3. 结果分析:得到的解xk+1可能是局部最优解,但并不保证是全局最优解。优化结果的质量依赖于初始点的选择、步长策略以及方向更新公式。 MATLAB中的实现通常包括编写迭代函数,输入目标函数、初始点、最大迭代次数...
### 共轭梯度法原理 #### 一、共轭梯度法简介 共轭梯度法是一种高效的数值优化算法,...通过合理构建H-共轭方向,该方法能够在有限的迭代次数内收敛到最优解,这使其成为许多科学计算和工程应用中的首选算法之一。
### 最优化方法中的梯度法和共轭梯度法 #### 一、无约束最优化问题 无约束最优化问题是求解一个多元函数在没有额外限制条件下的最小值问题。通常表示为寻找一个向量\( \mathbf{x} \in \mathbb{R}^n \),使得目标...
通过这些共轭方向,我们可以逐步接近最优解,每次迭代都沿着最陡峭的下降方向前进。 算法流程如下: 1. 初始化:选择一个初始向量 x0 和一个初始搜索方向 p0,通常 p0 可设置为 b - Ax0。 2. 计算残差 r0 = b - Ax...
共轭梯度法是另一種常用的优化方法,该方法的主要思想是通过不断地更新搜索方向来逼近最优解。 共轭梯度法的算法步骤如下: 1. 给定控制误差 ε,初始点 x1,k=1。 2. 计算 gk=g (xk)。 3. 若 ‖gk‖≤ε,则 x*=...
共轭梯度法的基本思想是通过迭代过程逐步逼近最优解,每次迭代都沿着当前方向的梯度方向前进,并确保这些方向是共轭的,以减少不必要的计算。算法主要包括以下步骤: 1. 初始化:选择一个初始向量x0,通常选择为零...
在数值分析和优化领域,"进退法"、"共轭梯度法"以及"黄金分割法"都是非常重要的算法。这些方法广泛应用于解决线性和非线性方程组,尤其是在科学计算和工程问题中。 首先,让我们来了解一下"进退法"。这是一种迭代法...
通过反复迭代,算法会逐渐接近最优解。这些算法的性能和适用性取决于问题的特性,例如函数的平滑性、目标函数的形状以及初始猜测值的选择。 理解并熟练运用这些优化算法对于解决实际问题至关重要,因为它们广泛应用...
共轭梯度法的核心思想是通过构造一组相互正交的搜索方向来逼近最优解,每个方向都是前一个方向的共轭,即它们在 A 矩阵下的内积为零。这种方法使得每次迭代都能最大程度地减少残差,从而快速收敛。 实现共轭梯度法...
非线性共轭梯度法(Nonlinear Conjugate Gradient Method)是一种在数值优化领域广泛应用的迭代算法,尤其适用于求解大型、稀疏的非线性优化问题。它结合了线性共轭梯度法的优点,即快速收敛速度和不需要存储大量的...
2. **终止条件检查**:如果\( \|g_k\| ),则停止迭代并返回\( x_k \)作为最优解。 3. **步长选择**:通过新的线搜索条件(见后文)找到合适的步长因子\( \alpha_k \)。 4. **更新迭代点**:计算下一个迭代点\( x...
在本例中,我们使用共轭梯度法来计算22121212()52410f Xxxx xxx的最优解。我们首先定义了目标函数fun1和梯度计算函数fun2,然后使用main函数来实现共轭梯度法的迭代过程。最终,我们输出了迭代次数、极值点和极小值...
总的来说,PRP共轭梯度法结合非单调策略是一种强大的优化工具,它在处理大型稀疏线性系统时表现优秀,且能够有效地寻找全局最优解。通过MATLAB这样的编程环境,我们可以方便地实现和应用这种算法,解决各种实际问题...
共轭梯度法是一种有效的无约束优化算法,通过构建 \(\mathbf{H}\)-共轭方向组来逐步逼近最优解。本文详细介绍了共轭梯度法的基础概念和理论依据,并通过具体的数学证明阐述了其有效性和正确性。对于实际应用而言,...
共轭梯度法通过迭代的方式逐步逼近最优解。其基本步骤包括: 1. **初始化**:选择初始点\( x_0 \)和初始搜索方向\( d_0 \)。 2. **搜索步长**:确定沿搜索方向的步长\( \alpha_k \)。 3. **更新迭代点**:计算下一...
接下来,算法通过迭代的方式,沿着一系列互相共轭的方向搜索最优解,直到满足收敛条件为止。 #### 三、算法细节与实施步骤 1. **初始化**:首先设定初始表面模型,并确定一个初始方向。这通常可以通过简单的平面或...