旅行商问题的编译器优化
Compiler optimization on the traveling salesman problem
我正在解决旅行商问题,正在查看以下版本:
城镇是 2d space 中的点,从每个城镇到所有其他城镇都有路径,长度是点之间的距离。因此,在检查 n
点的所有排列并计算路径长度的情况下,实现简单的解决方案非常容易。
但是我发现对于 n >= 10
编译器做了一些魔术并打印了一个肯定不是实际最短路径的值。我用Microsoft visual studio compiler in release mode with the default settings
编译。对于值 (10,30)
,它考虑了 30 秒,然后 returns 一些数字似乎是正确的,但事实并非如此(我以不同的方式检查)。而对于 n > 40
它会立即计算出一个结果并且总是 2.14748e+09
.
我正在寻找编译器在不同情况下做什么的解释((10,30)
情况真的很有趣)。还有一个例子,其中这些优化比只是旋转到世界尽头的程序更有用。
vector<pair<int,int>> points;
void min_len()
{
// n is a global variable with the number of points(towns)
double min = INT_MAX;
// there are n! permutations of n elements
for (auto j = 0; j < factorial(n); ++j)
{
double sum = 0;
for (auto i = 0; i < n - 1; ++i)
{
sum += distance_points(points[i], points[i + 1]);
}
if (sum < min)
{
min = sum;
s_path = points;
}
next_permutation(points.begin(), points.end());
}
for (auto i = 0; i < n; ++i)
{
cout << s_path[i].first << " " << s_path[i].second << endl;
}
cout << min << endl;
}
unsigned int factorial(unsigned int n)
{
int res = 1, i;
for (i = 2; i <= n; i++)
res *= i;
return res;
}
您的阶乘函数溢出。尝试将其替换为一个返回 int64_t
并查看您的代码需要 3 年才能终止 n > 20.
constexpr uint64_t factorial(unsigned int n) {
return n ? n * factorial(n-1) : 1;
}
另外,你根本不需要计算这个。 std::next_permutation
函数 returns 0 当所有排列都发生时(从排序位置开始)。
我正在解决旅行商问题,正在查看以下版本:
城镇是 2d space 中的点,从每个城镇到所有其他城镇都有路径,长度是点之间的距离。因此,在检查 n
点的所有排列并计算路径长度的情况下,实现简单的解决方案非常容易。
但是我发现对于 n >= 10
编译器做了一些魔术并打印了一个肯定不是实际最短路径的值。我用Microsoft visual studio compiler in release mode with the default settings
编译。对于值 (10,30)
,它考虑了 30 秒,然后 returns 一些数字似乎是正确的,但事实并非如此(我以不同的方式检查)。而对于 n > 40
它会立即计算出一个结果并且总是 2.14748e+09
.
我正在寻找编译器在不同情况下做什么的解释((10,30)
情况真的很有趣)。还有一个例子,其中这些优化比只是旋转到世界尽头的程序更有用。
vector<pair<int,int>> points;
void min_len()
{
// n is a global variable with the number of points(towns)
double min = INT_MAX;
// there are n! permutations of n elements
for (auto j = 0; j < factorial(n); ++j)
{
double sum = 0;
for (auto i = 0; i < n - 1; ++i)
{
sum += distance_points(points[i], points[i + 1]);
}
if (sum < min)
{
min = sum;
s_path = points;
}
next_permutation(points.begin(), points.end());
}
for (auto i = 0; i < n; ++i)
{
cout << s_path[i].first << " " << s_path[i].second << endl;
}
cout << min << endl;
}
unsigned int factorial(unsigned int n)
{
int res = 1, i;
for (i = 2; i <= n; i++)
res *= i;
return res;
}
您的阶乘函数溢出。尝试将其替换为一个返回 int64_t
并查看您的代码需要 3 年才能终止 n > 20.
constexpr uint64_t factorial(unsigned int n) {
return n ? n * factorial(n-1) : 1;
}
另外,你根本不需要计算这个。 std::next_permutation
函数 returns 0 当所有排列都发生时(从排序位置开始)。