C#,数值计算——基于模拟退火的极小化问题单纯形(下山)算法的计算方法与C#源程序

1 模拟退火

模拟退火算法其实是一个类似于仿生学的算法,模仿的就是物理退火的过程。

我们炼钢的时候,如果我们急速冷凝,这时候的状态是不稳定的,原子间杂乱无章的排序,能量很高。而如果我们让钢水慢慢冷凝,很缓慢的降温,那么这个时候的状态就是很稳定的,各个分子都趋向于自己能量最低的位置。而模拟退火算法,恰恰就是利用了物理退火这一过程的原理,求解一个优化目标(目标函数)的最小值。

模拟退火算法来源于固体退火原理,是一种基于概率的算法,将固体加温至充分高,再让其徐徐冷却,加温时,固体内部粒子随温升变为无序状,内能增大,而徐徐冷却时粒子渐趋有序,在每个温度都达到平衡态,最后在常温时达到基态,内能减为最小。

2 模拟退火算法

模拟退火算法(Simulated Annealing,SA)最早由Metropolis等人于 1953 年提出。1983 年Kirkpatrick等人第一次使用模拟退火算法求解组合优化问题后,它就发表在了 Science 上。直到今天,它依然被广泛使用,这篇文章将详细介绍C#的代码实现。

3 单纯形法

单纯形法是针对求解线性规划问题的一个算法,这个名称里的'单纯形'是代数拓扑里的一个概念

实际问题当中变量x是多维的,约束条件也会比示例多的多,这就需要一个一劳永逸的算法能通过计算机来获得正解,单纯形法就是这样的一个算法。单纯形法最早由 George Dantzig于1947年提出,单纯形法对于求解线性规划问题是具有跨时代意义的,其实不仅仅是针对线性规划,对于非线性规划问题在求解的过程中也大量依赖单纯形法,George Dantzig本人也被称为'线性规划之父',他是好莱坞电影《心灵捕手》的原型。

4 C#源程序

using System;

namespace Legalsoft.Truffer

{

/// <summary>

/// 模拟退火下山单纯形极小化

/// Downhill simplex minimization with simulated annealing

/// </summary>

public class Amebsa

{

public RealValueFun funk;

public Ranq1 ran;

private int mpts { get; set; }

private int ndim { get; set; }

private double[] pb { get; set; }

private double[] y { get; set; }

private double[,] p { get; set; }

private double ftol { get; }

private double yb { get; set; }

private double tt { get; set; }

public Amebsa(double[] point, double del, RealValueFun funkk, double ftoll)

{

this.funk = funkk;

this.ran = new Ranq1(1234);

this.ftol = ftoll;

this.yb = double.MaxValue;

this.ndim = point.Length;

this.pb = new double[ndim];

this.mpts = ndim + 1;

this.y = new double[mpts];

this.p = new double[mpts, ndim];

for (int i = 0; i < mpts; i++)

{

for (int j = 0; j < ndim; j++)

{

p[i, j] = point[j];

}

if (i != 0)

{

p[i, i - 1] += del;

}

}

inity();

}

public Amebsa(double[] point, double[] dels, RealValueFun funkk, double ftoll)

{

this.funk = funkk;

this.ran = new Ranq1(1234);

this.ftol = ftoll;

this.yb = double.MaxValue;

this.ndim = point.Length;

this.pb = new double[ndim];

this.mpts = ndim + 1;

this.y = new double[mpts];

this.p = new double[mpts, ndim];

for (int i = 0; i < mpts; i++)

{

for (int j = 0; j < ndim; j++)

{

p[i, j] = point[j];

}

if (i != 0)

{

p[i, i - 1] += dels[i - 1];

}

}

inity();

}

public Amebsa(double[,] pp, RealValueFun funkk, double ftoll)

{

this.funk = funkk;

this.ran = new Ranq1(1234);

this.ftol = ftoll;

this.yb = double.MaxValue;

this.ndim = pp.GetLength(1);

this.pb = new double[ndim];

this.mpts = pp.GetLength(0);

this.y = new double[mpts];

this.p = pp;

inity();

}

public void inity()

{

double[] x = new double[ndim];

for (int i = 0; i < mpts; i++)

{

for (int j = 0; j < ndim; j++)

{

x[j] = p[i, j];

}

y[i] = funk.funk(x);

}

}

public bool anneal(ref int iter, double temperature)

{

double[] psum = new double[ndim];

tt = -temperature;

get_psum(p, psum);

for (; ; )

{

int ilo = 0;

int ihi = 1;

double ylo = y[0] + tt * Math.Log(ran.doub());

double ynhi = ylo;

double yhi = y[1] + tt * Math.Log(ran.doub());

if (ylo > yhi)

{

ihi = 0;

ilo = 1;

ynhi = yhi;

yhi = ylo;

ylo = ynhi;

}

for (int i = 3; i <= mpts; i++)

{

double yt = y[i - 1] + tt * Math.Log(ran.doub());

if (yt <= ylo)

{

ilo = i - 1;

ylo = yt;

}

if (yt > yhi)

{

ynhi = yhi;

ihi = i - 1;

yhi = yt;

}

else if (yt > ynhi)

{

ynhi = yt;

}

}

double rtol = 2.0 * Math.Abs(yhi - ylo) / (Math.Abs(yhi) + Math.Abs(ylo));

if (rtol < ftol || iter < 0)

{

Globals.SWAP(ref y[0], ref y[ilo]);

for (int n = 0; n < ndim; n++)

{

Globals.SWAP(ref p[0, n], ref p[ilo, n]);

}

if (rtol < ftol)

{

return true;

}

else

{

return false;

}

}

iter -= 2;

double ytry = amotsa(p, y, psum, ihi, ref yhi, -1.0);

if (ytry <= ylo)

{

ytry = amotsa(p, y, psum, ihi, ref yhi, 2.0);

}

else if (ytry >= ynhi)

{

double ysave = yhi;

ytry = amotsa(p, y, psum, ihi, ref yhi, 0.5);

if (ytry >= ysave)

{

for (int i = 0; i < mpts; i++)

{

if (i != ilo)

{

for (int j = 0; j < ndim; j++)

{

psum[j] = 0.5 * (p[i, j] + p[ilo, j]);

p[i, j] = psum[j];

}

y[i] = funk.funk(psum);

}

}

iter -= ndim;

get_psum(p, psum);

}

}

else

{

++iter;

}

}

}

public void get_psum(double[,] p, double[] psum)

{

for (int n = 0; n < ndim; n++)

{

double sum = 0.0;

for (int m = 0; m < mpts; m++)

{

sum += p[m, n];

}

psum[n] = sum;

}

}

public double amotsa(double[,] p, double[] y, double[] psum, int ihi, ref double yhi, double fac)

{

double[] ptry = new double[ndim];

double fac1 = (1.0 - fac) / ndim;

double fac2 = fac1 - fac;

for (int j = 0; j < ndim; j++)

{

ptry[j] = psum[j] * fac1 - p[ihi, j] * fac2;

}

double ytry = funk.funk(ptry);

if (ytry <= yb)

{

for (int j = 0; j < ndim; j++)

{

pb[j] = ptry[j];

}

yb = ytry;

}

double yflu = ytry - tt * Math.Log(ran.doub());

if (yflu < yhi)

{

y[ihi] = ytry;

yhi = yflu;

for (int j = 0; j < ndim; j++)

{

psum[j] += ptry[j] - p[ihi, j];

p[ihi, j] = ptry[j];

}

}

return yflu;

}

}

}

相关推荐
MogulNemenis32 分钟前
力扣150题——多维动态规划
算法·leetcode·动态规划
白茶等风1213834 分钟前
C#_封装详解
开发语言·c#
繁依Fanyi1 小时前
使用 Spring Boot + Redis + Vue 实现动态路由加载页面
开发语言·vue.js·pytorch·spring boot·redis·python·算法
aloha_7891 小时前
B站宋红康JAVA基础视频教程(chapter14数据结构与集合源码)
java·数据结构·spring boot·算法·spring cloud·mybatis
临沂堇2 小时前
CCF刷题计划——训练计划(反向拓扑排序)
数据结构·c++·算法·拓扑·ccf
铁匠匠匠2 小时前
【C总集篇】第八章 数组和指针
c语言·开发语言·数据结构·经验分享·笔记·学习·算法
Unicorn建模2 小时前
2024“华为杯”中国研究生数学建模竞赛(E题)深度剖析|数学建模完整过程+详细思路+代码全解析
python·算法·数学建模
咕咕吖2 小时前
二叉树的层序遍历(c)
数据结构·算法
“JB...One”3 小时前
openssl-AES-128-CTR加解密结构体
linux·数据结构·算法·ssl
爱数模的小云3 小时前
【华为杯】2024华为杯数模研赛D题 解题思路
算法·华为