我正在尝试使用分支定界方法和Little的算法来实现TSP求解器。该软件本身应用于演示离散数学的演示。
利用Little的算法,我找到了一个候选游览,然后应该与其他候选游览进行比较。但是,在进入分支和界限之前,我就遇到了Little的算法实现结果带来的问题。
我使用double.positiveinfinity删除我已经检查过的路由,以及反向路由和从点x到点x的路由。
算法本身如下:
我们将在每一行和每一列中至少获得1个零。
下面是我编写的函数。
//find minimum element in row i of matrix m excluding element with number exc
private double GetRowMin(double[,] m, int i, int exc = -1)
{
double[] SubRow = new double[m.GetLength(1)];
Buffer.BlockCopy(m, 8 * m.GetLength(1) * i, SubRow, 0, 8 * m.GetLength(1));
if (exc != -1)
SubRow[exc] = Double.PositiveInfinity;
return SubRow.Min();
}
//find minimum element in col j of matrix m excluding element with number exc
private double GetColMin(double[,] m, int j, int exc = -1)
{
double[] SubCol = new double[m.GetLength(0)];
SubCol = Enumerable.Range(0, m.GetLength(0)).Select(xr => m[xr, j]).ToArray();
if (exc != -1)
SubCol[exc] = Double.PositiveInfinity;
return SubCol.Min();
}
//reduce matrix m by subtracting minimum for every row and col
private double[,] MReduce(double[,] m)
{
double[,] resm = new double[m.GetLength(0), m.GetLength(1)];
for (int i = 0; i < m.GetLength(0); i++)
for (int j = 0; j < m.GetLength(1); j++)
if (m[i, j] < Double.PositiveInfinity)
resm[i, j] = m[i, j] - GetRowMin(m, i, i);
else
resm[i, j] = Double.PositiveInfinity;
for (int i = 0; i < m.GetLength(0); i++)
for (int j = 0; j < m.GetLength(1); j++)
if (m[i, j] < Double.PositiveInfinity)
resm[i, j] = m[i, j] - GetColMin(m, j, j);
else
resm[i, j] = Double.PositiveInfinity;
return resm;
}
//find zero element with maximum value
private Point FindMaxVElem(double[,] m)
{
double MaxV = Double.MinValue;
Point MaxP = new Point();
for (int i = 0; i < m.GetLength(0); i++)
for (int j = 0; j < m.GetLength(1); j++)
if (m[i, j] == 0)
{
double s = 0;
if (!Double.IsInfinity(GetRowMin(m, i, j)))
s += GetRowMin(m, i, j);
if (!Double.IsInfinity(GetColMin(m, j, i)))
s += GetColMin(m, j, i);
if (Double.IsInfinity(s))
s = 0;
if (s > MaxV)
{
MaxV = s;
MaxP.X = i;
MaxP.Y = j;
}
}
return MaxP;
}
//delete row/col and backroute from accounting
private double[,] RCSubtract(double[,] m, int l, int n)
{
double[,] resm = new double[m.GetLength(0), m.GetLength(1)];
for (int i = 0; i < m.GetLength(0); i++)
for (int j = 0; j < m.GetLength(1); j++)
{
if (i == l || j == n)
resm[i, j] = Double.PositiveInfinity;
else
resm[i, j] = m[i, j];
}
resm[n, l] = Double.PositiveInfinity;
return resm;
}
驱动程序代码如下:
public List<PointD> PList; //list for storing coordinates of all points
double[,] AdjM; //distance matrix
List<Point> path; //here will be unordered subroutes of the tour
...
for (int i = 0; i < PList.Count; i++)
{
AdjM = MReduce(AdjM);
path.Add(FindMaxVElem(AdjM));
AdjM = RCSubtract(AdjM, path.Last().X, path.Last().Y);
}
在大多数情况下(简单和复杂),一切都很好,并且可以找到游览。问题是,我的Little的算法算法不是在几个紧密定位的点的单独组上,而不是对所有点进行完全封闭的巡回显示,而是返回几个单独的封闭的游览,如下所示:
(猜测我没有足够的声誉来发布图片,对不起)https://pp.userapi.com/c849236/v849236895/174a46/ASAPt1F8zs4.jpg
逐步矩阵正像这样求解:
0 1 2 3 4 5 Min
--------------------------------------------
0: нет 25,4 31,5 146,3 159,6 140,2 25,4
1: 25,4 нет 24,8 160,3 176,3 159,3 24,8
2: 31,5 24,8 нет 138,3 155,9 141,2 24,8
3: 146,3 160,3 138,3 нет 26,3 40,8 26,3
4: 159,6 176,3 155,9 26,3 нет 27,9 26,3
5: 140,2 159,3 141,2 40,8 27,9 нет 27,9
Min 25,4 24,8 24,8 26,3 26,3 27,9 310,9
0 1 2 3 4 5 Min
--------------------------------------------
0: нет 0,5 6,7 120,1 нет 112,4 0,5
1: 0 нет 0 134,1 нет 131,5 0
2: 6,2 0 нет 112 нет 113,3 0
3: нет нет нет нет нет нет нет
4: 134,2 151,5 131 нет нет 0 0
5: 114,9 134,5 116,3 14,6 нет нет 14,6
Min 0 0 0 14,6 нет 0 29,7
0 1 2 3 4 5 Min
--------------------------------------------
0: нет 0,5 6,7 105,5 нет нет 0,5
1: 0 нет 0 119,5 нет нет 0
2: 6,2 0 нет 97,4 нет нет 0
3: нет нет нет нет нет нет нет
4: нет нет нет нет нет нет нет
5: 114,9 134,5 116,3 0 нет нет 0
Min 0 0 0 0 нет нет 0,5
0 1 2 3 4 5 Min
--------------------------------------------
0: нет 0,5 6,7 нет нет нет 0,5
1: 0 нет 0 нет нет нет 0
2: 6,2 0 нет нет нет нет 0
3: нет нет нет нет нет нет нет
4: нет нет нет нет нет нет нет
5: нет нет нет нет нет нет нет
Min 0 0 0 нет нет нет 0,5
0 1 2 3 4 5 Min
--------------------------------------------
0: нет 0,5 нет нет нет нет 0,5
1: нет нет нет нет нет нет нет
2: 6,2 нет нет нет нет нет 6,2
3: нет нет нет нет нет нет нет
4: нет нет нет нет нет нет нет
5: нет нет нет нет нет нет нет
Min 6,2 0,5 нет нет нет нет 13,4
0 1 2 3 4 5 Min
--------------------------------------------
0: нет нет нет нет нет нет нет
1: нет нет нет нет нет нет нет
2: 0 нет нет нет нет нет 0
3: нет нет нет нет нет нет нет
4: нет нет нет нет нет нет нет
5: нет нет нет нет нет нет нет
Min 0 нет нет нет нет нет 0
所以我知道我做错了(可能搞砸了无穷大),因为已经在单独定位的点组上进行第一次迭代返回了一些封闭的巡回路线,而不是一次。但我无法弄清楚到底出了什么问题。有人有什么想法吗?