Java实现黄金分割法的示例代码

目录
  • 1、概述
  • 2、黄金分割法
  • 3、修改后的黄金分割算法
  • 4、编程实现修改后的黄金分割算法

1、概述

黄金分割法是一种区间收缩方法。

所谓区间收缩方法,指的是将含有最优解的区间逐步缩小,直至区间长度为零的方法。比如,为求函数f(x)在区间[a,b]上的最小值点,可在该区间中任取两点x1、x2,通过比较函数f(x)在这两点的函数值或者导数值等,来决定去掉一部分区间[a,x1​]或者[x2​,b],从而使搜索区间长度变小,如此迭代,直至区间收缩为一点为止,或区间长度小于某给定的精度为止。

对于区间[a,b]上的单峰函数f(x),可以在其中任意选取两点x1​、x2​,通过比较这两点的函数值,就可以将搜索区间缩小。比如说,如果f(x1​)<f(x2​),则选取[a1​,b1​]=[a,x2​],如果f(x1​)> f(x2​),则选取[a1​,b1​]=[x1​,b],如果f(x1​)=f(x2),则选取[a1​,b1​]=[x1​,x2​],这样就得到f(x)的更小的搜索区间[a1​,b1​],然后根据这一方法再进行划分,得到一系列搜索区间满足

于是对事先给定的某个精度ε,当

时,可以将f(x)的最小值点近似地取为

单峰函数与搜索区间的定义如下:

如何选取x1和x2才能使得算法的效率更高?

这里推导过程不在详细讨论,直接给出满足对称取点、等比收缩和单点计算三个原则的分点。

或者

2、黄金分割法

算法描述如下:

这个算法非常理想,整个迭代过程中。除最初计算分点时使用过一次乘法外,后边的分点全部都由加减法完成,并且每次迭代只需计算一个分点的函数值。但是,在实际应用中,该方法存在一定的缺陷。这种缺陷主要来源于无理数(-1+√5)/2的取值。这里我们只取了小数点后三位数。因而有一定误差,所以在迭代过程中,经过多次累计,误差就会很大,从而导致最终选取的两点并不一定是我们所期望的那两点,事实上,常常发生x2小于x1的情形。

为避免这种情况的出现,我们也可以通过将无理数(-1+√5)/2小数点后面的位数提高来避免算法的这一缺陷。不过这样做的效果未必很好。因为我们不知道在算法中到底要经过多少次迭代,当迭代次数很大时,这种做法依然是不能奏效的。因此,我们在程序中每次计算分点时不得不根据算法原理,使用一次乘法,即第二个分点不用加减法产生,而直接用乘法计算得出。由此即可避免累计误差所带来的缺陷。我们仍假设f(x)是区间[a,b]上的单峰函数。修改后的黄金分割法的计算框图如下图所示。

3、修改后的黄金分割算法

修改后的黄金分割算法如下:

4、编程实现修改后的黄金分割算法

用黄金分割法求函数 f(x)=x³-12x-11在区间[0,10]上的最小值点,取ε=0.01。

import java.math.BigDecimal;

/**
 * 黄金分割法测试
 */
public class GoldenCut {
    public static final BigDecimal C=new BigDecimal("0.01");

    public static  BigDecimal end=null;

    /**
     *x^3-12x-11
     * @param x 输入参数x
     * @return x^3-12x-11
     */
    public static BigDecimal ComputeFx(BigDecimal x){
        return x.pow(3).subtract(new BigDecimal("12").multiply(x)).subtract(new BigDecimal("11"))
                .setScale(10,BigDecimal.ROUND_HALF_EVEN);
    }

    /**
     * a+0.382*(b-a)
     * @param a
     * @param b
     * @return a+0.382*(b-a)
     */
    public static BigDecimal Compute382(BigDecimal a,BigDecimal b){
        return a.add(new BigDecimal("0.382").multiply(b.subtract(a)))
                .setScale(10,BigDecimal.ROUND_HALF_EVEN);
    }

    /**
     * a+0.618(b-a)
     * @param a
     * @param b
     * @return
     */
    public static BigDecimal Compute618(BigDecimal a,BigDecimal b){
        return a.add(new BigDecimal("0.618").multiply(b.subtract(a)))
                    .setScale(10,BigDecimal.ROUND_HALF_EVEN);
    }
    /**
     * a+b-x1
     * @param a
     * @param b
     * @param x1
     * @return
     */
    public static BigDecimal Subtractabx1(BigDecimal a,BigDecimal b,BigDecimal x1){
        return a.add(b).subtract(x1)
                .setScale(10,BigDecimal.ROUND_HALF_EVEN);
    }
    //判断是否满足精度 b-a<C?
    public static boolean OK(BigDecimal a,BigDecimal b){
        return b.subtract(a).compareTo(C) < 0;
    }
    //输出最优解
    public static BigDecimal Success(BigDecimal a, BigDecimal b){
        return (a.add(b)).divide(new BigDecimal("2"))
                .setScale(10,BigDecimal.ROUND_HALF_EVEN);
    }
    //修改后的黄金分割法
    public static void goldenTest1(BigDecimal a,BigDecimal b){
        System.out.println("初始化");
        BigDecimal x1=Compute382(a,b);
        BigDecimal x2=Subtractabx1(a,b,x1);
        BigDecimal f1=ComputeFx(x1);
        BigDecimal f2=ComputeFx(x2);
        System.out.println("x1="+x1);
        System.out.println("x2="+x2);
        System.out.println("f1="+f1);
        System.out.println("f2="+f2);
        System.out.println("迭代区间如下:");
        int count=0;    //迭代次数
        while(!OK(a,b)){//只要不满足精度就一直迭代
            System.out.println("["+a+"\t,\t"+b+"]");
            count++;    //迭代次数+1
            if(f1.compareTo(f2)==1){//f1>f2
                a=x1;
                if(OK(a,b)){     //精度判断
                    end = Success(a, b);
                    break;
                }else{
                    f1=f2;
                    x1=x2;
                    x2=Compute618(a,b);
                    f2=ComputeFx(x2);
                }
            }else{
                b=x2;
                if(OK(a,b)){
                    end = Success(a, b);
                    break;
                }else{
                    f2=f1;
                    x2=x1;
                    x1=Compute382(a,b);
                    f1=ComputeFx(x1);
                }
            }
        }
        System.out.println("迭代结束,迭代次数"+count);
    }
    public static void main(String[] args) {
        BigDecimal a=new BigDecimal("0");
        BigDecimal b=new BigDecimal("10");

        goldenTest1(a,b);
        System.out.println("最优解为x*="+end);
        System.out.println("f(x*)="+ComputeFx(end));
    }
}

由运行结果可以看到,迭代次数15次,最优解为x*=2.0009942948,f(x*)=-26.9999940673。迭代区间如下:

可以证明,黄金分割法是线性收敛的。

到此这篇关于Java实现黄金分割法的示例代码的文章就介绍到这了,更多相关Java黄金分割法内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 计算黄金分割的javascript代码

    value: 黄金分割 [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]

  • java 实现黄金分割数的示例详解

    黄金分割数 0.618 与美学有重要的关系.舞台上报幕员所站的位置大约就是舞台宽度的 0.618 处, 墙上的画像一般也挂在房间高度的 0.618 处,甚至股票的波动据说也能找到 0.618 的影子- 黄金分割数是个无理数,也就是无法表示为两个整数的比值. 0.618 只是它的近似值,其真值可以通过对 5 开方减去 1 再除以 2 来获得, 我们取它的一个较精确的近似值:0.618034 有趣的是,一些简单的数列中也会包含这个无理数,这很令数学家震惊! 1 3 4 7 11 18 29 47 -

  • python实现黄金分割法的示例代码

    一.问题 使用黄金分割法来计算 二.代码 #黄金分割法python求解PPT上第一个例题 #因为函数要求解最大值而这个方法一般求解最小值所以把函数取负 import numpy as np import matplotlib.pyplot as plt rate = 0.618034 def f(x): #求解体积函数公式,乘1.0将结果变为浮点数 return -1.0*x*(350-2*x)*(260-2*x) def tarceback(f,a0,b0,accuracy): a = a0

  • python中黄金分割法实现方法

    本文实例讲述了python中黄金分割法实现方法.分享给大家供大家参考.具体实现方法如下: ''' a,b = bracket(f,xStart,h) Finds the brackets (a,b) of a minimum point of the user-supplied scalar function f(x). The search starts downhill from xStart with a step length h. x,fMin = search(f,a,b,tol=1

  • Java实现黄金分割法的示例代码

    目录 1.概述 2.黄金分割法 3.修改后的黄金分割算法 4.编程实现修改后的黄金分割算法 1.概述 黄金分割法是一种区间收缩方法. 所谓区间收缩方法,指的是将含有最优解的区间逐步缩小,直至区间长度为零的方法.比如,为求函数f(x)在区间[a,b]上的最小值点,可在该区间中任取两点x1.x2,通过比较函数f(x)在这两点的函数值或者导数值等,来决定去掉一部分区间[a,x1​]或者[x2​,b],从而使搜索区间长度变小,如此迭代,直至区间收缩为一点为止,或区间长度小于某给定的精度为止. 对于区间[

  • Java模拟UDP通信示例代码

    Java基础:模拟UDP通信 1.一次发送,一次接收 1.1.发送方 // 发送端,不需要连接服务器 public class UdpClientDemo {     public static void main(String[] args) throws Exception {         // 1. 发送数据包需要一个Socket         DatagramSocket socket = new DatagramSocket();         // 1.2 建立一个包    

  • java实现发送邮件的示例代码

    代码 import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeUtility; import javax.mail.Session; import javax.mail.MessagingException; import javax.mail.Transport; /** * @author BuNuo */ public

  • java生成图片验证码的示例代码

    给大家分享一款java生成验证码的源码,可设置随机字符串,去掉了几个容易混淆的字符,还可以设置验证码位数,比如4位,6位.当然也可以根据前台验证码的位置大小,设置验证码图片的大小.下边是源码分享,直接看吧,很简单! 创建servlet类 import java.io.IOException; import javax.servlet.Servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServ

  • java 格式化时间的示例代码

    package jkcs; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; public class jdcs { public static void main(String[] args) th

  • Java实现二叉树的示例代码(递归&迭代)

    目录 1.二叉树基本概念见上节:详解Java中二叉树的基础概念(递归&迭代) 2.本次展示链式存储 以此图为例,完整代码如下: //基础二叉树实现 //使用左右孩子表示法 import java.util.*; import java.util.Deque; public class myBinTree { private static class TreeNode{ char val; TreeNode left; TreeNode right; public TreeNode(char va

  • Java实现归并排序的示例代码

    目录 1.算法理解 2.实现代码 3.实现效果 1.算法理解 参考:图解Java中归并排序算法的原理与实现 2.实现代码 import java.lang.reflect.Array; import java.util.*; public class MergeSort{ // 我们的算法类不允许产生任何实例 private MergeSort(){} // 将arr[l...mid]和arr[mid+1...r]两部分进行归并 private static void merge(Compara

  • Java实现warcraft java版游戏的示例代码

    目录 前言 主要需求 功能截图 代码实现 启动入口 ModelAttacker类 ModelUnit类 总结 前言 致敬经典的warcraft,<warcraft java版>是一款即时战略题材单机游戏,采用魔兽原味风格和机制.收集资源,建造防御工事,消灭所有敌军. 人类:洛丹伦人类联盟自兽人首次穿过黑暗之门时便告成立.他们坚韧不拔,勇敢无畏,身穿坚甲,手握利刃,英勇迎敌. 兽人:兽人是一个粗犷而坚韧的种族,他们身穿简单的皮毛和带有尖刺的皮甲,以肆意凶狠的战斗风格而闻名. 用java语言实现,

  • Java实现定时任务的示例代码

    目录 xxl-job官网 引入依赖 配置信息(application.properties) 配置类(XxlJobConfiguration) 调用xxl-job-admin模块的接口 添加调度任务 调度任务 xxl-job官网 https://www.xuxueli.com/xxl-job/ 调用xxl-job中的xxl-job-admin模块启用 引入依赖 <!-- 调度任务 --> <dependency> <groupId>com.xuxueli</gro

随机推荐