用模拟退火法挑战建立信号基站的问题
来源:互联网 发布:php调用webservice 编辑:程序博客网 时间:2024/05/10 12:43
挑战建立信号基站问题成功,下面说说具体的想法。
模拟退火法其实很简单,分如下几步:
1、首先确定评价函数。
2、选取初始点,并用评价函数计算初始值,把初始值作为当前值。
3、按步进规则获取新点
4、计算新点的值(也可能是附近的多个值)。
5、比较新值和当前值差距,如果小于预期,执行步骤6,否则按一定概率执行步骤6。
6、那么取把新值作为当前值,新点作为当前点,执行步骤3。
7、更新步进值,执行步骤3。
首先说评价函数,在这个问题中,即为选取点到所有基站的距离和。在这里说一下,网上不少人用欧式空间距离,即sqrt((x1-x0)*(x1-x0),(y1-y0)*(y1-y0)),增加了计算时间。其实没必要,完全可以用max(|x1-x0|,|y1-y0|)。因为作为空间长度的度量只要满足如下几个条件就可以了:
1、||A,A||=0;
2、||A,B||=||B,A||
3、||A,B||+||B,C||>=||A,C||
大家可以证明下,max(|x1-x0|,|y1-y0|)是可以作为空间距离度量的。
初始点选取,我就选择了第一点,没什么道理,随便选的一个,反正最后都会收敛的。
唯一修改的地方就是步进值得选择上,稍稍改进了一下,判断新值和原值的差距,如果相差大,就大幅调整步进,否则小幅调整步进。
贴上代码
package pango.bestdistance;public class Main {public static double getDistance(double[] pointA, double[] pointB) {return Math.max(Math.abs(pointA[0] - pointB[0]),Math.abs(pointA[1] - pointB[1]));}public static double getSumDistance(double[][] points, double[] point0) {double result = 0;for (int i = 0; i < points.length; i++) {result += getDistance(points[i], point0);}return result;}public static double bestDistance(int[] x, int[] y) {if (x == null || y == null || x.length != y.length)throw new UnknownError();double[] nextPoint = new double[2];double[] curPoint = new double[2];double[][] direct = new double[][] { { 0, 1 }, { 0, -1 }, { 1, 0 },{ -1, 0 }, { 0.7071, 0.7071 }, { 0.7071, -0.7071 },{ -0.7071, 0.7071 }, { -0.7071, -0.7071 }, };double step = 100000000;double r = 0.99;double chance = 0.99;double precision = 0.0001;double[][] points = new double[x.length][2];for (int i = 0; i < x.length; i++) {points[i][0] = x[i];points[i][1] = y[i];}curPoint[0] = points[0][0];curPoint[1] = points[0][1];double result = getSumDistance(points, curPoint);while (Double.compare(step, precision) > 0) {boolean ok = true;double good = 0.0;while (ok) {ok = false;for (int i = 0; i < direct.length; i++) {nextPoint[0] = direct[i][0] * step + curPoint[0];nextPoint[1] = direct[i][1] * step + curPoint[1];if (Double.compare(nextPoint[0], -1000000000.0) < 0|| Double.compare(nextPoint[1], -1000000000.0) < 0) {continue;}double t = getSumDistance(points, nextPoint);if(Double.compare(result, 0.0) != 0 ) {good=Math.abs(1.0 - Math.abs(t - result / result));}else {good=Math.abs(1 - Math.abs(t));}if (Double.compare(t, result) < 0) {result = t;curPoint[0] = nextPoint[0];curPoint[1] = nextPoint[1];ok = true;} else if (Math.random() > chance) {result = t;curPoint[0] = nextPoint[0];curPoint[1] = nextPoint[1];ok = true;}}}step = Double.compare(good, 1) > 0 ? step * r : step * good * 0.9;}return result;}public static void main(String[] args) {/*** * (1,4) (2,3) (0,1) (1,1) */int[] x = new int[] { 1, 2, 0, 1 };int[] y = new int[] { 4, 3, 1, 1 };System.out.println(bestDistance(x, y));}}
解释一下69行那个步长更新,原来解释不是很清楚,实际上是越接近最优点,步长减的更慢,我称之为让子弹多飞一会儿。道理嘛,是根据我的本专业《金属材料》知识,凭直觉加的那么一句。步长的更新速度实际上等同于温度降低的快慢,让温度降的慢一点,就更有利于原子的向更低的能级组成方式排列。
- 用模拟退火法挑战建立信号基站的问题
- 模拟退火法---飞机巡航问题
- 模拟退火法 --- matlab
- 模拟退火法
- 模拟退火法模板
- 模拟退火法
- 模拟退火法
- 模拟退火法【matlab】
- 模拟退火法与调度VM pair问题
- POJ 2420 模拟退火法
- POJ 1379 模拟退火法
- poj 1379 模拟退火法
- 优化方法-模拟退火法
- poj 2420 模拟退火法基础
- HDU - 5017 Ellipsoid(模拟退火法)
- 模拟退火法(吊打XXX)Bzoj3680
- 模拟退火法、神经网络、遗传算法
- 建立信号基站
- vs2008进行mobil开发 编译慢的解决方法
- GCC 命令详解 http://www.cnblogs.com/ggjucheng/archive/2011/12/14/2287738.html
- 今天开始自学j2ee+android
- 8种方法突破iGuard网页防篡改软件保护
- 在线QQ悬浮插件
- 用模拟退火法挑战建立信号基站的问题
- delete[] 出错
- ext4.1 grid group field is a object。
- Oracle修改表空间大小
- VMware vSphere5.0 HA高可用性原理
- 数据库
- 开源命令行系统监视工具:glances
- ipse中Debug 为什么显示source not found
- C# datagridview 输入时间格式