大家好,又见面了,我是你们的朋友全栈君。
一、牛顿法概述
处的一阶导数(梯度)和二阶导数(Hessen矩阵)对目标函数进行二次函数近似,然后把二次模型的极小点作为新的迭代点,并不断重复这一过程,直至求得满足精度的近似极小值。牛顿法的速度相当快,而且能高度逼近最优值。牛顿法分为基本的牛顿法和全局牛顿法。
二、基本牛顿法
1、基本牛顿法的原理
,求函数的极值的问题可以转化为求导函数
。对函数
进行泰勒展开到二阶,得到
2、基本牛顿法的流程
- 给定终止误差值,初始点,令;
- 计算,若,则停止,输出;
- 计算,并求解线性方程组得解:;
- 令,,并转2。
三、全局牛顿法
1、全局牛顿法的流程
- 给定终止误差值,,,初始点,令;
- 计算,若,则停止,输出;
- 计算,并求解线性方程组得解:;
- 记是不满足下列不等式的最小非负整数:;
- 令,,,并转2。
2、Armijo搜索
,
,令步长因子
,其中
是满足下列不等式的最小非负整数:
四、算法实现
,最小值为
。
1、基本牛顿法Java实现
package org.algorithm.newtonmethod;
/**
* Newton法
*
* @author dell
*
*/
public class NewtonMethod {
private double originalX;// 初始点
private double e;// 误差阈值
private double maxCycle;// 最大循环次数
/**
* 构造方法
*
* @param originalX初始值
* @param e误差阈值
* @param maxCycle最大循环次数
*/
public NewtonMethod(double originalX, double e, double maxCycle) {
this.setOriginalX(originalX);
this.setE(e);
this.setMaxCycle(maxCycle);
}
// 一系列get和set方法
public double getOriginalX() {
return originalX;
}
public void setOriginalX(double originalX) {
this.originalX = originalX;
}
public double getE() {
return e;
}
public void setE(double e) {
this.e = e;
}
public double getMaxCycle() {
return maxCycle;
}
public void setMaxCycle(double maxCycle) {
this.maxCycle = maxCycle;
}
/**
* 原始函数
*
* @param x变量
* @return 原始函数的值
*/
public double getOriginal(double x) {
return x * x - 3 * x + 2;
}
/**
* 一次导函数
*
* @param x变量
* @return 一次导函数的值
*/
public double getOneDerivative(double x) {
return 2 * x - 3;
}
/**
* 二次导函数
*
* @param x变量
* @return 二次导函数的值
*/
public double getTwoDerivative(double x) {
return 2;
}
/**
* 利用牛顿法求解
*
* @return
*/
public double getNewtonMin() {
double x = this.getOriginalX();
double y = 0;
double k = 1;
// 更新公式
while (k <= this.getMaxCycle()) {
y = this.getOriginal(x);
double one = this.getOneDerivative(x);
if (Math.abs(one) <= e) {
break;
}
double two = this.getTwoDerivative(x);
x = x - one / two;
k++;
}
return y;
}
}
2、全局牛顿法Java实现
package org.algorithm.newtonmethod;
/**
* 全局牛顿法
*
* @author dell
*
*/
public class GlobalNewtonMethod {
private double originalX;
private double delta;
private double sigma;
private double e;
private double maxCycle;
public GlobalNewtonMethod(double originalX, double delta, double sigma,
double e, double maxCycle) {
this.setOriginalX(originalX);
this.setDelta(delta);
this.setSigma(sigma);
this.setE(e);
this.setMaxCycle(maxCycle);
}
public double getOriginalX() {
return originalX;
}
public void setOriginalX(double originalX) {
this.originalX = originalX;
}
public double getDelta() {
return delta;
}
public void setDelta(double delta) {
this.delta = delta;
}
public double getSigma() {
return sigma;
}
public void setSigma(double sigma) {
this.sigma = sigma;
}
public double getE() {
return e;
}
public void setE(double e) {
this.e = e;
}
public double getMaxCycle() {
return maxCycle;
}
public void setMaxCycle(double maxCycle) {
this.maxCycle = maxCycle;
}
/**
* 原始函数
*
* @param x变量
* @return 原始函数的值
*/
public double getOriginal(double x) {
return x * x - 3 * x + 2;
}
/**
* 一次导函数
*
* @param x变量
* @return 一次导函数的值
*/
public double getOneDerivative(double x) {
return 2 * x - 3;
}
/**
* 二次导函数
*
* @param x变量
* @return 二次导函数的值
*/
public double getTwoDerivative(double x) {
return 2;
}
/**
* 利用牛顿法求解
*
* @return
*/
public double getGlobalNewtonMin() {
double x = this.getOriginalX();
double y = 0;
double k = 1;
// 更新公式
while (k <= this.getMaxCycle()) {
y = this.getOriginal(x);
double one = this.getOneDerivative(x);
if (Math.abs(one) <= e) {
break;
}
double two = this.getTwoDerivative(x);
double dk = -one / two;// 搜索的方向
double m = 0;
double mk = 0;
while (m < 20) {
double left = this.getOriginal(x + Math.pow(this.getDelta(), m)
* dk);
double right = this.getOriginal(x) + this.getSigma()
* Math.pow(this.getDelta(), m)
* this.getOneDerivative(x) * dk;
if (left <= right) {
mk = m;
break;
}
m++;
}
x = x + Math.pow(this.getDelta(), mk)*dk;
k++;
}
return y;
}
}
3、主函数
package org.algorithm.newtonmethod;
/**
* 测试函数
* @author dell
*
*/
public class TestNewton {
public static void main(String args[]) {
NewtonMethod newton = new NewtonMethod(0, 0.00001, 100);
System.out.println("基本牛顿法求解:" + newton.getNewtonMin());
GlobalNewtonMethod gNewton = new GlobalNewtonMethod(0, 0.55, 0.4,
0.00001, 100);
System.out.println("全局牛顿法求解:" + gNewton.getGlobalNewtonMin());
}
}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/138693.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...