C#,动态规划(DP)模拟退火(Simulated Annealing)算法与源代码

news2024/12/23 11:09:24

1 模拟退火

*问题:**给定一个成本函数f:r^n–>r*,找到一个 n 元组,该元组最小化 f 的值。请注意,最小化函数值在算法上等同于最大化(因为我们可以将成本函数重新定义为 1-f)。 很多有微积分/分析背景的人可能都熟悉单变量函数的简单优化。例如,函数 f(x) = x^2 + 2x 可以通过将一阶导数设置为零来优化,从而获得产生最小值 f(-1) = -1 的解 x = -1 。这种技术适用于变量很少的简单函数。然而,通常情况下,研究人员对优化几个变量的函数感兴趣,在这种情况下,只能通过计算获得解。

一个困难的优化任务的极好例子是芯片平面规划问题。假设你在英特尔工作,你的任务是设计集成电路的布局。您有一组不同形状/大小的模块,以及可以放置模块的固定区域。你想要达到的目标有很多:最大化导线连接元件的能力,最小化净面积,最小化芯片成本,等等。考虑到这些,您创建了一个成本函数,取所有,比如说, 1000 个变量配置,并返回一个代表输入配置“成本”的实数值。我们称之为目标函数,因为目标是最小化它的值。 一个简单的算法是完全的空间搜索——我们搜索所有可能的配置,直到找到最小值。这对于变量很少的函数来说可能就足够了,但是我们想到的问题需要这样一个强力算法来玩 *O(n!)*。

由于这类问题和其他 NP 难问题的计算困难,许多优化试探法已经被开发出来,试图产生一个好的,尽管可能是次优的值。在我们的例子中,我们不一定需要找到一个严格的最优值——找到一个接近最优的值将满足我们的目标。一种广泛使用的技术是模拟退火,通过它我们引入了一定程度的随机性,有可能从一个更好的解转移到一个更差的解,试图逃离局部极小值并收敛到一个更接近全局最优的值。

模拟退火是基于冶金实践,通过这种实践,材料被加热到高温并冷却。在高温下,原子可能会不可预测地移动,通常会随着材料冷却成纯晶体而消除杂质。这是通过模拟退火优化算法复制的,能量状态对应于当前解。 在这个算法中,我们定义了一个初始温度和一个最低温度,初始温度通常设置为 1,最低温度的数量级为 10^-4.当前温度乘以某个分数α,然后降低,直到达到最低温度。对于每个不同的温度值,我们运行核心优化例程的次数是固定的。优化程序包括找到一个相邻解并以概率e^(f(c–f(n)】接受它,其中 c 是当前解而 n 是相邻解。通过对当前解施加微小的扰动来找到相邻解。这种随机性有助于避开优化启发式算法的常见陷阱——陷入局部极小值。通过潜在地接受一个比我们目前拥有的更差的最优解,并以与成本增加相反的概率接受它,算法更有可能收敛到全局最优。设计一个邻居函数是相当棘手的,必须在个案的基础上完成,但以下是在位置优化问题中寻找邻居的一些想法。

  • 在随机方向上将所有点移动 0 或 1 个单位
  • 随机移动输入元素
  • 交换输入序列中的随机元素
  • 置换输入序列
  • 将输入序列分成随机数量的段和置换段

一个警告是,我们需要提供一个初始解决方案,以便算法知道从哪里开始。这可以通过两种方式来实现:(1)使用关于问题的先验知识来输入良好的起点,以及(2)生成随机解。尽管生成随机解更糟糕,有时会抑制算法的成功,但对于我们对环境一无所知的问题,这是唯一的选择。

还有许多其他优化技术,尽管模拟退火是一种有用的随机优化启发式方法,适用于大型离散搜索空间,在这些空间中,随着时间的推移,最优性是优先的。下面,我包含了一个基于位置的模拟退火的基本框架(可能是模拟退火最适用的优化风格)。当然,成本函数、候选生成函数和邻居函数必须根据手头的具体问题来定义,尽管核心优化例程已经实现。

2 源程序(文本格式)

using System;
using System.Text;

namespace Legalsoft.Truffer.Algorithm
{
    /// <summary>
    /// 算法核心数据类
    /// 含:方差系数均方根误差,配置参数(数组)
    /// </summary>
    public class Anneal_Solution
    {
        /// <summary>
        /// 方差系数均方根误差
        /// Coefficient of Variance Root Mean Squared Error
        /// 默认初值0.0;不超过1.0;
        /// </summary>
        public double CVRMSE { get; set; } = 0.0;
        /// <summary>
        /// 配置参数(数组)
        /// 整型数组;无初值(null);
        /// </summary>
        public int[] Config { get; set; } = null;
        /// <summary>
        /// (无参)默认构造函数
        /// </summary>
        public Anneal_Solution()
        {
        }
        /// <summary>
        /// (有参)构造函数
        /// </summary>
        /// <param name="CVRMSE">方差系数均方根误差</param>
        /// <param name="configuration">配置参数(数组)</param>
        public Anneal_Solution(double CVRMSE, int[] configuration)
        {
            this.CVRMSE = CVRMSE;
            Config = configuration;
        }
    }

    /// <summary>
    /// 模拟退火算法
    /// </summary>
    public class Simulated_Annealing
    {
        private static Random rand { get; set; } = new Random((int)DateTime.Now.Ticks);

        public static string Solve(int M = 15, int N = 15, double T_Minium = 0.0001, double Alpha = 0.9, int Maxium_Iterations = 100)
        {
            string[,] sourceArray = new string[M, N];
            Anneal_Solution min = new Anneal_Solution(double.MaxValue, null);
            Anneal_Solution currentSol = Rand_Solution(M);

            double temperature = 1.0;
            while (temperature > T_Minium)
            {
                for (int i = 0; i < Maxium_Iterations; i++)
                {
                    if (currentSol.CVRMSE < min.CVRMSE)
                    {
                        min = currentSol;
                    }

                    Anneal_Solution newSol = Neighbor(currentSol);
                    double ap = Math.Pow(Math.E, (currentSol.CVRMSE - newSol.CVRMSE) / temperature);
                    if (ap > rand.NextDouble())
                    {
                        currentSol = newSol;
                    }
                }
                temperature *= Alpha;
            }
            #endregion

            for (int i = 0; i < sourceArray.GetLength(0); i++)
            {
                for (int j = 0; j < sourceArray.GetLength(1); j++)
                {
                    sourceArray[i, j] = "X";
                }
            }

            foreach (int k in min.Config)
            {
                int[] coord = Index_To_Points(M, N, k);
                sourceArray[coord[0], coord[1]] = "-";
            }

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < sourceArray.GetLength(0); i++)
            {
                for (int j = 0; j < sourceArray.GetLength(1); j++)
                {
                    sb.Append(sourceArray[i, j] + ", ");
                }
                sb.AppendLine("<br>");
            }
            return sb.ToString();
        }

        public static Anneal_Solution Neighbor(Anneal_Solution currentSol)
        {
            return currentSol;
        }

        public static Anneal_Solution Rand_Solution(int n)
        {
            int[] a = new int[n];
            for (int i = 0; i < n; i++)
            {
                a[i] = i + 1;
            }
            return new Anneal_Solution(-1, a);
        }

        public static double Cost(int[] inputConfiguration)
        {
            return -1;
        }

        public static int[] Index_To_Points(int M, int N, int index)
        {
            int[] points = { index % M, index / M };
            return points;
        }
    }
}
 

3 代码格式

using System;
using System.Text;

namespace Legalsoft.Truffer.Algorithm
{
    /// <summary>
    /// 算法核心数据类
    /// 含:方差系数均方根误差,配置参数(数组)
    /// </summary>
    public class Anneal_Solution
    {
        /// <summary>
        /// 方差系数均方根误差
        /// Coefficient of Variance Root Mean Squared Error
        /// 默认初值0.0;不超过1.0;
        /// </summary>
        public double CVRMSE { get; set; } = 0.0;
        /// <summary>
        /// 配置参数(数组)
        /// 整型数组;无初值(null);
        /// </summary>
        public int[] Config { get; set; } = null;
        /// <summary>
        /// (无参)默认构造函数
        /// </summary>
        public Anneal_Solution()
        {
        }
        /// <summary>
        /// (有参)构造函数
        /// </summary>
        /// <param name="CVRMSE">方差系数均方根误差</param>
        /// <param name="configuration">配置参数(数组)</param>
        public Anneal_Solution(double CVRMSE, int[] configuration)
        {
            this.CVRMSE = CVRMSE;
            Config = configuration;
        }
    }

    /// <summary>
    /// 模拟退火算法
    /// </summary>
    public class Simulated_Annealing
    {
        private static Random rand { get; set; } = new Random((int)DateTime.Now.Ticks);

        public static string Solve(int M = 15, int N = 15, double T_Minium = 0.0001, double Alpha = 0.9, int Maxium_Iterations = 100)
        {
            string[,] sourceArray = new string[M, N];
            Anneal_Solution min = new Anneal_Solution(double.MaxValue, null);
            Anneal_Solution currentSol = Rand_Solution(M);

            double temperature = 1.0;
            while (temperature > T_Minium)
            {
                for (int i = 0; i < Maxium_Iterations; i++)
                {
                    if (currentSol.CVRMSE < min.CVRMSE)
                    {
                        min = currentSol;
                    }

                    Anneal_Solution newSol = Neighbor(currentSol);
                    double ap = Math.Pow(Math.E, (currentSol.CVRMSE - newSol.CVRMSE) / temperature);
                    if (ap > rand.NextDouble())
                    {
                        currentSol = newSol;
                    }
                }
                temperature *= Alpha;
            }
            #endregion

            for (int i = 0; i < sourceArray.GetLength(0); i++)
            {
                for (int j = 0; j < sourceArray.GetLength(1); j++)
                {
                    sourceArray[i, j] = "X";
                }
            }

            foreach (int k in min.Config)
            {
                int[] coord = Index_To_Points(M, N, k);
                sourceArray[coord[0], coord[1]] = "-";
            }

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < sourceArray.GetLength(0); i++)
            {
                for (int j = 0; j < sourceArray.GetLength(1); j++)
                {
                    sb.Append(sourceArray[i, j] + ", ");
                }
                sb.AppendLine("<br>");
            }
            return sb.ToString();
        }

        public static Anneal_Solution Neighbor(Anneal_Solution currentSol)
        {
            return currentSol;
        }

        public static Anneal_Solution Rand_Solution(int n)
        {
            int[] a = new int[n];
            for (int i = 0; i < n; i++)
            {
                a[i] = i + 1;
            }
            return new Anneal_Solution(-1, a);
        }

        public static double Cost(int[] inputConfiguration)
        {
            return -1;
        }

        public static int[] Index_To_Points(int M, int N, int index)
        {
            int[] points = { index % M, index / M };
            return points;
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1468863.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux---进程间通信(下)

1、System V 共享内存 原理如下图 系统调用接口介绍 int shmget(key_t key, size_t size, int shmflg) 功能&#xff1a;用来创建共享内存 参数 key&#xff1a;这个共享内存段名字&#xff0c;内核用key来标识共享内存size&#xff1a;共享内存大小shmflg&#xff1a;由九个权…

留子厨房开发日志

以下记录了使用go语言框架Beego&#xff0c;Mysql数据库&#xff0c;Redis数据库实现一个点菜/菜谱应用API的全过程。 技术方案 github地址 数据库设计 新建数据库&#xff1a; CREATE DATABASE menu;新建数据表&#xff1a; CREATE TABLE menu ( id int(10) unsigned NOT …

Docker 第十九章 : 阿里云个人镜像仓使用

Docker 第十九章 : 阿里云个人镜像仓使用 本章知识点: 如何创建镜像库,如何设置密码,如何登录与退出个人镜像仓,如何本地打镜像,如何将本地镜像推送到个人镜像库。 背景 在项目YapiDocker部署中,因读取mongo:latest 版本不一致,导致后续执行步骤的异常。遇到此场景…

OpenCV Mat实例详解 六

本文将接着OpenCV Mat实例详解继续介绍OpenCV Mat类的操作符及公有成员函数。 Mat & operator Mat & operator (const Mat &m) 将一个Mat对象赋值个另一个Mat对象。 Mat & operator (const MatExpr &expr) 将一个Mat表达式值赋值给Mat对象 Mat & op…

【高德地图】Android高德地图绘制标记点Marker

&#x1f4d6;第4章 Android高德地图绘制标记点Marker ✅绘制默认 Marker✅绘制多个Marker✅绘制自定义 Marker✅Marker点击事件✅Marker动画效果✅Marker拖拽事件✅绘制默认 Infowindow&#x1f6a9;隐藏InfoWindow 弹框 ✅绘制自定义 InfoWindow&#x1f6a9;实现 InfoWindow…

Covalent Network(CQT)与 Movement Labs 达成合作,重新定义 M2 系统区块链数据可用性与性能

Covalent Network&#xff08;CQT&#xff09;是行业领先的多链索引器&#xff0c;正在与 Movement Labs 的 M2 展开具有突破性意义的合作。M2 是以太坊上的首个 Move-EVM&#xff08;MEVM&#xff09;ZK rollup 。这一战略合作标志着先进的实时数据索引和部署工具&#xff0c;…

Sora - 探索AI视频模型的无限可能

Sora - 探索AI视频模型的无限可能 随着人工智能技术的飞速发展,AI视频模型已成为科技领域的新热点。而在这个浪潮中,OpenAI推出的首个AI视频模型Sora,以其卓越的性能和前瞻性的技术,引领着AI视频领域的创新发展。让我们将一起探讨Sora的技术特点、应用场景以及对未来创作方…

高级RAG:使用RAGAs + LlamaIndex进行RAG评估,包括原理、图和代码

原文地址&#xff1a;Using RAGAs LlamaIndex for RAG evaluation 2024 年 2 月 5 日 如果您已经为实际的业务系统开发了检索增强生成&#xff08;Retrieval Augmented Generation, RAG&#xff09;应用程序&#xff0c;那么您可能会关心它的有效性。换句话说&#xff0c;您…

【大数据】Flink 内存管理(三):TaskManager 内存分配(理论篇)

Flink 内存管理&#xff08;三&#xff09;&#xff1a;TaskManager 内存分配 1.配置 Total Memory2.配置 Heap and Managed Memory2.1 Task (Operator) Heap Memory2.2 Managed Memory 3.配置 Off-Heap Memory&#xff08;Direct or Native&#xff09;4.详细内存模型5.Framew…

现在学Oracle是49年入国军么?

今天周末&#xff0c;不聊技术&#xff0c;聊聊大家说的最多的一个话题 先说明一下&#xff0c;防止挨喷&#x1f606; 本人并不是职业dba&#xff0c;对数据库就是爱好&#xff0c;偶尔兼职&#xff0c;以下仅个人观点分析&#xff0c;如有不同观点请轻喷&#xff0c;哈哈&…

分享一个我爱工具网源码优化版

应用介绍 本文来自&#xff1a;分享一个我爱工具网源码优化版 - 源码1688 前几天在网上看到了一个不错的工具网源码&#xff0c;但是源码存在一些问题&#xff0c;遂进行了修改优化。 主要修改内容有&#xff1a; 1、后台改为账号密码登录&#xff0c;上传即用&#xff0c;不…

算法分析-面试1-字符串

文章目录 前言一、分类&#xff1a;看看就行了二、字符串API&#xff1a;创建和初始化&#xff1a;查询操作&#xff1a;比较操作&#xff1a;修改操作&#xff1a;截取操作&#xff1a;分割操作&#xff1a;格式化操作&#xff1a;连接操作&#xff08;Java 8 及以后&#xff…

pclpy KD-Tree半径最近邻搜索

pclpy 半径最近邻搜索 一、算法原理1.KD-Tree 介绍2.原理 二、代码三、结果1.原点云2.半径最近邻搜索的点云 四、相关数据 一、算法原理 1.KD-Tree 介绍 kd 树或 k 维树是计算机科学中使用的一种数据结构&#xff0c;用于在具有 k 维的空间中组织一定数量的点。它是一个二叉搜…

Windows下VTK 源码编译(For Qt PCL)

虽然我们在windows下安装PCL的时候就已经安装了VTK&#xff0c;由于跟着PCL安装的VTK是没有和QT联合编译的&#xff0c;所以在使用PCL和QT做点云可视化界面的时候是无法使用QT的插件QVTKWidget。 VTK 源码下载 Tags VTK / VTK GitLab 我这里的环境是Win10 Visual Studio&…

Qt 设置隐式加载dll路径

在c++中DLL的加载方式有两种,显式加载和隐式加载。 隐式加载 在程序从开始运行时,就会按照系统中一定的搜索路径,寻找动态库,找到就自动加载它,才能成功运行程序,这些步骤,是系统自动完成的。 显示加载 我们对动态库的调用,是在代码中直接使用LoadLibrary,或其他加载函…

ContainerHelpers之二分查找算法详解

目录 前言一、JAVA移位运算符1.1 >> 带符号右移位运算符1.2 >>> 无符号右移位运算符1.3 << 左移位运算符1.4 Java 中没有 <<<1.5 ~取反操作 二、ContainerHelpers二分查找算法总结 前言 安卓SparseArray中多次用到了ContainerHelpers的binarySe…

Android java中包的使用

一.包的使用 为了更好的实现项目中类的管理&#xff0c;提供包的概念。 package语句作为Java源文件的第一条语句&#xff0c;指明该文件中定义的类所在的包。(若缺省该语句&#xff0c;则指定为无名包)。 它的格式为&#xff1a;package 顶层包名.子包名 ; 二.java中主要的包…

Leetcode3039. 进行操作使字符串为空

Every day a Leetcode 题目来源&#xff1a;3039. 进行操作使字符串为空 解法1&#xff1a;哈希 排序 操作的定义&#xff1a;每次操作依次遍历 ‘a’ 到 ‘z’&#xff0c;如果当前字符出现在 s 中&#xff0c;那么删除出现位置最早的该字符&#xff08;如果存在的话&…

【ArcGIS】利用DEM进行水文分析:流向/流量等

利用DEM进行水文分析 ArcGIS实例参考 水文分析通过建立地表水文模型&#xff0c;研究与地表水流相关的各种自然现象&#xff0c;在城市和区域规划、农业及森林、交通道路等许多领域具有广泛的应用。 ArcGIS实例 某流域30m分辨率DEM如下&#xff1a; &#xff08;1&#xff09…

机器学习模型的过拟合与欠拟合

机器学习模型的训练过程中&#xff0c;可能会出现3种情况&#xff1a;模型欠拟合、模型正常拟合与模型过拟合。其中模型欠拟合与模型过拟合都是不好的情况。下面将会从不同的角度介绍如何判断模型属于哪种拟合情况。 &#xff08;1&#xff09;欠拟合与过拟合表现方式 欠拟合…