一个模拟退火算法求TSP问题的C#实现

用的是随机点的测试数据。 一个模拟退火算法求TSP问题的C#实现_第1张图片
  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 >= 0break;
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

你可能感兴趣的:(一个模拟退火算法求TSP问题的C#实现)