用的是随机点的测试数据。

1
// ******************************************************************************************
2
// 物体降温退火过程中,其能量转移服从Boltzmann distribution规律 P(E) ∝ exp(-E/kT);
3
// P(E)是系统处于低能E的概率(probability),k为Boltzmann常数,T为系统温度。
4
// 模拟退火算法原理
5
// (1)初始温度T(0) = T0。迭代次数t=0,任意初始状态做当前解V(0)∈V
6
// (2)按某一规则有当前状态产生当前状态的下一次侯选状态。
7
// 计算目标代价变化△C,若△C<0则接受解,(△ delta)
8
// 否则考虑当前温度下状态活动概率 P(△C) = exp(-△C/T);P(△C)≥λ则接受解,否则不接受
9
// λ(lambda)为预先指定或随机产生的正数。 (0<λ<1)
10
// (3)按某种策略对T更新(降温)。
11
// (4)按某种标准检查退火过程是否应该结束,若不满足则转(2)
12
// (5)输出状态V(t)做问题解
13
// ******************************************************************************************
14
15
using System;
16
using System.Drawing;
17
18
namespace Algorithm.SimulatedAnnealing
19
{
20
public class TravellingSalesmanProblem
21
{
22
private Point[] _points;
23
private double[,] _distanceMatrix;
24
private double _initialTemperature = 0d;
25
private double _currentTemperature = 0d;
26
27
private int _routerCount;
28
29
private int[] _currentRouter;
30
private int[] _resultRouter;
31
32
private Random _rdm;
33
private bool _IsCalculated = false;
34
private DateTime calculate_begin;
35
private DateTime calculate_end;
36
37
public TravellingSalesmanProblem(Point[] pts)
38
{
39
_points = (Point[])pts.Clone();
40
41
_routerCount = _points.Length;
42
_currentRouter = new int[_routerCount];
43
_resultRouter = new int[_routerCount];
44
_distanceMatrix = new double[_routerCount, _routerCount];
45
46
_rdm = new Random((int)DateTime.Now.Ticks);
47
48
double minDistance = 10000d;
49
double maxDistance = 0d;
50
51
for(int i = 0; i < _points.Length; i++)
52
{
53
_currentRouter[i] = i; // init point router 1 > 2 > 3
> n
54
_resultRouter[i] = i;
55
for(int j = i + 1; j < _points.Length; j++)
56
{
57
double offsetX = (double)(_points[i].X - _points[j].X);
58
double offsetY = (double)(_points[i].Y - _points[j].Y);
59
double distance = Math.Sqrt(offsetX * offsetX + offsetY * offsetY); //计算两点间的距离
60
_distanceMatrix[i, j] = distance;
61
_distanceMatrix[j, i] = distance;
62
if(distance > maxDistance) maxDistance = distance;
63
if(distance < minDistance) minDistance = distance;
64
}
65
}
66
_initialTemperature = 20 * (_routerCount * maxDistance - _routerCount * minDistance);// 计算起始温度
67
_currentTemperature = _initialTemperature;
68
}
69
70
// 得出最优距离
71
public double GetTotalDistancOptimization()
72
{
73
if(!_IsCalculated)
74
Calculation();
75
return CalculateTotalDistance(_resultRouter);
76
}
77
78
// 得到最优路由
79
public int[] GetRouterOptimization()
80
{
81
if(!_IsCalculated)
82
Calculation();
83
return _resultRouter;
84
}
85
86
public double GetCalculationalTime()
87
{
88
if(_IsCalculated)
89
{
90
TimeSpan span = calculate_end - calculate_begin;
91
return span.TotalMilliseconds;
92
}
93
else
94
return 0d;
95
}
96
97
// 求出最优解
98
private void Calculation()
99
{
100
//Random rdm = new Random((int)DateTime.Now.Ticks);
101
calculate_begin = DateTime.Now;
102
while(true)
103
{
104
int IterCount = 0;
105
while(true)
106
{
107
double totalDistance1 = CalculateTotalDistance(_resultRouter);
108
BuildRandomRouter(); // change router
109
double totalDistance2 = CalculateTotalDistance(_currentRouter);
110
111
double deltaTotalDistance = totalDistance2 - totalDistance1;//delta
112
//原理见顶部注释
113
if(deltaTotalDistance <= 0d)
114
{
115
for(int i = 0; i < _resultRouter.Length; i++)
116
_resultRouter[i] = _currentRouter[i];//赋值到结果路由
117
}
118
else
119
{
120
//原理见顶部注释
121
double probability = Math.Exp( -(deltaTotalDistance/_currentTemperature));
122
double lambda = ((double)(_rdm.Next() % 10000)) / 10000d;//随机指定的正数lambda
123
if(probability > lambda)
124
{
125
for(int i = 0; i < _resultRouter.Length; i++)
126
_resultRouter[i] = _currentRouter[i];
127
}
128
}
129
if(IterCount >= _routerCount * _routerCount * _routerCount) //某一温度下的循环次数是点个数的三次方
130
{
131
break;
132
}
133
else
134
{
135
IterCount++;
136
}
137
}
138
if(_currentTemperature <= 0.01) //温度小于等于0.01时跳出外循环
139
{
140
break;
141
}
142
else
143
{
144
_currentTemperature = 0.96 * _currentTemperature;// 温度下降方式 T(k+1) = K*T(k),K=0.95
145
}
146
}
147
_IsCalculated = true;
148
calculate_end = DateTime.Now;
149
}
150
151
private double CalculateTotalDistance(int[] router)
152
{
153
double totalDistance = 0d;
154
for(int i = 0; i < router.Length - 1; i++)
155
{
156
totalDistance += _distanceMatrix[router[i], router[i + 1]];
157
}
158
totalDistance += _distanceMatrix[_currentRouter[router.Length - 1], router[0]];
159
return totalDistance;
160
}
161
162
// 按某种概率过程产生新的搜索状态
163
// 随机产生一个新的路由
164
private void BuildRandomRouter()
165
{
166
int rdm1, rdm2;
167
while(true)
168
{
169
rdm1 = _rdm.Next() % _currentRouter.Length - 1;
170
if(rdm1 >= 0) break;
171
}
172
while(true)
173
{
174
rdm2 = _rdm.Next() % _currentRouter.Length - 1;
175
if(rdm1 != rdm2 && rdm2 >= 0)
176
{
177
int temp = _currentRouter[rdm1];
178
_currentRouter[rdm1] = _currentRouter[rdm2];
179
_currentRouter[rdm2] = temp;
180
break;
181
}
182
}
183
}
184
185
}
186
}
187
// ******************************************************************************************2
// 物体降温退火过程中,其能量转移服从Boltzmann distribution规律 P(E) ∝ exp(-E/kT);3
// P(E)是系统处于低能E的概率(probability),k为Boltzmann常数,T为系统温度。4
// 模拟退火算法原理5
// (1)初始温度T(0) = T0。迭代次数t=0,任意初始状态做当前解V(0)∈V6
// (2)按某一规则有当前状态产生当前状态的下一次侯选状态。7
// 计算目标代价变化△C,若△C<0则接受解,(△ delta)8
// 否则考虑当前温度下状态活动概率 P(△C) = exp(-△C/T);P(△C)≥λ则接受解,否则不接受9
// λ(lambda)为预先指定或随机产生的正数。 (0<λ<1)10
// (3)按某种策略对T更新(降温)。11
// (4)按某种标准检查退火过程是否应该结束,若不满足则转(2)12
// (5)输出状态V(t)做问题解13
// ******************************************************************************************14

15
using System;16
using System.Drawing;17

18
namespace Algorithm.SimulatedAnnealing19
{20
public class TravellingSalesmanProblem21
{22
private Point[] _points;23
private double[,] _distanceMatrix;24
private double _initialTemperature = 0d;25
private double _currentTemperature = 0d;26

27
private int _routerCount;28

29
private int[] _currentRouter;30
private int[] _resultRouter;31

32
private Random _rdm;33
private bool _IsCalculated = false;34
private DateTime calculate_begin;35
private DateTime calculate_end;36

37
public TravellingSalesmanProblem(Point[] pts)38
{39
_points = (Point[])pts.Clone();40

41
_routerCount = _points.Length;42
_currentRouter = new int[_routerCount];43
_resultRouter = new int[_routerCount];44
_distanceMatrix = new double[_routerCount, _routerCount];45

46
_rdm = new Random((int)DateTime.Now.Ticks);47

48
double minDistance = 10000d;49
double maxDistance = 0d;50

51
for(int i = 0; i < _points.Length; i++)52
{53
_currentRouter[i] = i; // init point router 1 > 2 > 3
> n54
_resultRouter[i] = i; 55
for(int j = i + 1; j < _points.Length; j++)56
{57
double offsetX = (double)(_points[i].X - _points[j].X);58
double offsetY = (double)(_points[i].Y - _points[j].Y);59
double distance = Math.Sqrt(offsetX * offsetX + offsetY * offsetY); //计算两点间的距离60
_distanceMatrix[i, j] = distance;61
_distanceMatrix[j, i] = distance;62
if(distance > maxDistance) maxDistance = distance;63
if(distance < minDistance) minDistance = distance;64
}65
}66
_initialTemperature = 20 * (_routerCount * maxDistance - _routerCount * minDistance);// 计算起始温度67
_currentTemperature = _initialTemperature;68
}69

70
// 得出最优距离71
public double GetTotalDistancOptimization()72
{73
if(!_IsCalculated)74
Calculation();75
return CalculateTotalDistance(_resultRouter);76
}77

78
// 得到最优路由79
public int[] GetRouterOptimization()80
{81
if(!_IsCalculated)82
Calculation();83
return _resultRouter;84
}85

86
public double GetCalculationalTime()87
{88
if(_IsCalculated)89
{90
TimeSpan span = calculate_end - calculate_begin;91
return span.TotalMilliseconds;92
}93
else94
return 0d;95
}96

97
// 求出最优解98
private void Calculation()99
{100
//Random rdm = new Random((int)DateTime.Now.Ticks);101
calculate_begin = DateTime.Now;102
while(true)103
{104
int IterCount = 0;105
while(true)106
{107
double totalDistance1 = CalculateTotalDistance(_resultRouter);108
BuildRandomRouter(); // change router109
double totalDistance2 = CalculateTotalDistance(_currentRouter);110

111
double deltaTotalDistance = totalDistance2 - totalDistance1;//delta112
//原理见顶部注释113
if(deltaTotalDistance <= 0d)114
{115
for(int i = 0; i < _resultRouter.Length; i++)116
_resultRouter[i] = _currentRouter[i];//赋值到结果路由117
}118
else119
{120
//原理见顶部注释121
double probability = Math.Exp( -(deltaTotalDistance/_currentTemperature));122
double lambda = ((double)(_rdm.Next() % 10000)) / 10000d;//随机指定的正数lambda123
if(probability > lambda)124
{125
for(int i = 0; i < _resultRouter.Length; i++)126
_resultRouter[i] = _currentRouter[i];127
}128
}129
if(IterCount >= _routerCount * _routerCount * _routerCount) //某一温度下的循环次数是点个数的三次方130
{131
break;132
}133
else134
{135
IterCount++;136
}137
}138
if(_currentTemperature <= 0.01) //温度小于等于0.01时跳出外循环139
{140
break;141
}142
else143
{144
_currentTemperature = 0.96 * _currentTemperature;// 温度下降方式 T(k+1) = K*T(k),K=0.95145
}146
}147
_IsCalculated = true;148
calculate_end = DateTime.Now;149
}150

151
private double CalculateTotalDistance(int[] router)152
{153
double totalDistance = 0d;154
for(int i = 0; i < router.Length - 1; i++)155
{156
totalDistance += _distanceMatrix[router[i], router[i + 1]];157
}158
totalDistance += _distanceMatrix[_currentRouter[router.Length - 1], router[0]];159
return totalDistance;160
}161

162
// 按某种概率过程产生新的搜索状态163
// 随机产生一个新的路由164
private void BuildRandomRouter()165
{166
int rdm1, rdm2;167
while(true)168
{169
rdm1 = _rdm.Next() % _currentRouter.Length - 1;170
if(rdm1 >= 0) break;171
}172
while(true)173
{174
rdm2 = _rdm.Next() % _currentRouter.Length - 1;175
if(rdm1 != rdm2 && rdm2 >= 0)176
{177
int temp = _currentRouter[rdm1];178
_currentRouter[rdm1] = _currentRouter[rdm2];179
_currentRouter[rdm2] = temp;180
break;181
}182
}183
}184

185
}186
}187


浙公网安备 33010602011771号