基本上我使用的是TSPLIB的数据,我有这个规格。
这就是我计算欧氏距离的方法(根据上面的规范):
public static double calculateDistance(double x1, double y1, double x2, double y2){
double xDistance = Math.abs(x1 - x2);
double yDistance = Math.abs(y1 - y2);
double distance = Math.sqrt( (xDistance*xDistance) + (yDistance*yDistance) );
return distance;
}
这是我计算地理距离的方式(根据上面的规范):
public static double calculateGeoDistance(double lat1, double lon1, double lat2, double lon2) {
double lat1Rad = coordinates2Radians(lat1);
double lat2Rad = coordinates2Radians(lat2);
double lon1Rad = coordinates2Radians(lon1);
double lon2Rad = coordinates2Radians(lon2);
double R = 6378.388;
double q1 = Math.cos(lon1Rad - lon2Rad);
double q2 = Math.cos(lat1Rad - lat2Rad);
double q3 = Math.cos(lat1Rad + lat2Rad);
double distance = (R * Math.acos(0.5 * ((1.0 + q1) * q2 - (1.0 - q1) * q3)) + 1.0);
return distance;
}
private static double coordinates2Radians(double coordinate) {
double deg = Math.round(coordinate);
double min = coordinate - deg;
double rad = Math.PI * (deg + 5.0 * min / 3.0) / 180.0;
return rad;
}
但是这个问题是我得到的结果低于TSPLIB最优(不可能!)。我的计算有问题吗?我已经尝试使用预定义的数据和距离来计算最优,我确实得到了最优,我不知道为什么这不起作用..
非常感谢。
答案 0 :(得分:0)
你转换为弧度看起来很可疑。我会尝试:
private static double coordinates2Radians(double coordinate) {
return Math.PI * coordinate / 180.0;
}
另外,我会在上面评论中提到的Movable Type网站上使用公式。
答案 1 :(得分:0)
这可能对您阅读TSPLIB的常见问题
有所帮助http://comopt.ifi.uni-heidelberg.de/software/TSPLIB95/TSPFAQ.html
检查问:GEO类型的问题我得错了。
我遵循了该实现,而不是TSPLIB 95规范中列出的内容。我的实现(在Groovy中):
static int[][] distancesInGEO(List nodes) {
int dim = nodes.size();
double[] latitude = new double[dim];
double[] longitude = new double[dim];
final double PI = 3.141592;
for (int i = 0; i < dim; i++) {
int deg = (int) (nodes[i].x);
double min = nodes[i].x - deg;
latitude[i] = PI * (deg + 5 * min / 3) / 180;
deg = (int) nodes[i].y;
min = nodes[i].y - deg;
longitude[i] = PI * (deg + 5 * min / 3) / 180;
}
int[][] d = new int[dim][dim];
final double RRR = 6378.388;
for (int i = 0; i < dim; i++)
for (int j = i + 1; j < dim; j++) {
double q1 = cos(longitude[i] - longitude[j]);
double q2 = cos(latitude[i] - latitude[j]);
double q3 = cos(latitude[i] + latitude[j]);
d[i][j] = (int) (RRR * acos(0.5 * ((1.0 + q1) * q2 - (1.0 - q1) * q3)) + 1.0);
d[j][i] = d[i][j];
}
return d;
}
我猜测您的问题是由于遵循规范并使用nint
计算学位而产生的。但那确实是错的。例如,输入10.53表示10度和53分钟。但是如果你使用nint
来围绕10.53,那么你将获得11度,并且随后的分钟计算也将是错误的。
答案 2 :(得分:0)
我遇到了类似的问题,并且有点恼火,因为两个地理点之间的距离计算偏差超过两倍,如果仔细选择四舍五入程序就不会发生这种情况。
在这里找到:
分析下面的距离时,您会发现明显的差异,例如在第14点和第13点之间,范围从52 km(FAQ)到122 km(docu),真相约73 km。这可能会导致不同的最佳解决方案。
问题发生在将度四舍五入为整数(最小或数学)。
弧度中的第14点:
常见问题解答:0.660607,0.266744-> 37.85,15.28
纪录片:0.648971、0.266744-> 37.18、15.28
实数:0.654673、0.264766-> 37.51、15.17
在四舍五入的FAQ位置和Docu位置之间,大约有50公里!
Ulysses16 calculated according to the FAQ (should be used to compare results with TSPLIB optimal solutions):
TSP-Tour Optimal:
Location ID: 1 (38,24|20,42), in Radians: Latitude: 0,670206, Longitude: 0,361283
Location ID: 14 (37,51|15,17), in Radians: Latitude: 0,660607, Longitude: 0,266744
Location ID: 13 (38,15|15,35), in Radians: Latitude: 0,667588, Longitude: 0,271980
Location ID: 12 (38,47|15,13), in Radians: Latitude: 0,676897, Longitude: 0,265581
Location ID: 7 (38,42|13,11), in Radians: Latitude: 0,675442, Longitude: 0,230093
Location ID: 6 (37,56|12,19), in Radians: Latitude: 0,662061, Longitude: 0,214966
Location ID: 15 (35,49|14,32), in Radians: Latitude: 0,625119, Longitude: 0,253654
Location ID: 5 (33,48|10,54), in Radians: Latitude: 0,589921, Longitude: 0,190241 TP Hull
Location ID: 11 (36,08|-5,21), in Radians: Latitude: 0,630646, Longitude: -0,093375 TP Hull
Location ID: 9 (41,23|9,10), in Radians: Latitude: 0,722275, Longitude: 0,159988 TP Hull
Location ID: 10 (41,17|13,05), in Radians: Latitude: 0,720530, Longitude: 0,228347 TP Hull
Location ID: 16 (39,36|19,56), in Radians: Latitude: 0,691150, Longitude: 0,347902
Location ID: 3 (40,56|25,32), in Radians: Latitude: 0,714421, Longitude: 0,445641 TP Hull
Location ID: 2 (39,57|26,15), in Radians: Latitude: 0,697259, Longitude: 0,458149 TP Hull
Location ID: 4 (36,26|23,12), in Radians: Latitude: 0,635881, Longitude: 0,404916 TP Hull
Location ID: 8 (37,52|20,44), in Radians: Latitude: 0,660898, Longitude: 0,361865
Distances:
From 1 to 14: 479,0
From 14 to 13: 52,0
From 13 to 12: 68,0
From 12 to 7: 177,0
From 7 to 6: 115,0
From 6 to 15: 308,0
From 15 to 5: 401,0
From 5 to 11: 1.504,0
From 11 to 9: 1.387,0
From 9 to 10: 328,0
From 10 to 16: 610,0
From 16 to 3: 499,0
From 3 to 2: 126,0
From 2 to 4: 474,0
From 4 to 8: 271,0
From 8 to 1: 60,0
Total: 6.859,0
Ulysses16 calculated according to the manual tsp95.pdf.
Because of the different distance calculation now a better optimum can be found.
TSP-Tour (not) Optimal (given optimal tour by TSPLIB):
Location ID: 1 (38,24|20,42), in Radians: Latitude: 0,670206, Longitude: 0,361283
Location ID: 14 (37,51|15,17), in Radians: Latitude: 0,648971, Longitude: 0,266744
Location ID: 13 (38,15|15,35), in Radians: Latitude: 0,667588, Longitude: 0,271980
Location ID: 12 (38,47|15,13), in Radians: Latitude: 0,676897, Longitude: 0,265581
Location ID: 7 (38,42|13,11), in Radians: Latitude: 0,675442, Longitude: 0,230093
Location ID: 6 (37,56|12,19), in Radians: Latitude: 0,650426, Longitude: 0,214966
Location ID: 15 (35,49|14,32), in Radians: Latitude: 0,625119, Longitude: 0,253654
Location ID: 5 (33,48|10,54), in Radians: Latitude: 0,589921, Longitude: 0,178605 TP Hull
Location ID: 11 (36,08|-5,21), in Radians: Latitude: 0,630646, Longitude: -0,093375 TP Hull
Location ID: 9 (41,23|9,10), in Radians: Latitude: 0,722275, Longitude: 0,159988 TP Hull
Location ID: 10 (41,17|13,05), in Radians: Latitude: 0,720530, Longitude: 0,228347 TP Hull
Location ID: 16 (39,36|19,56), in Radians: Latitude: 0,691150, Longitude: 0,336267
Location ID: 3 (40,56|25,32), in Radians: Latitude: 0,702786, Longitude: 0,445641 TP Hull
Location ID: 2 (39,57|26,15), in Radians: Latitude: 0,685623, Longitude: 0,458149 TP Hull
Location ID: 4 (36,26|23,12), in Radians: Latitude: 0,635881, Longitude: 0,404916 TP Hull
Location ID: 8 (37,52|20,44), in Radians: Latitude: 0,649262, Longitude: 0,361865
Distances:
From 1 to 14: 496,0
From 14 to 13: 122,0
From 13 to 12: 68,0
From 12 to 7: 177,0
From 7 to 6: 177,0
From 6 to 15: 256,0
From 15 to 5: 453,0
From 5 to 11: 1.444,0
From 11 to 9: 1.387,0
From 9 to 10: 328,0
From 10 to 16: 557,0
From 16 to 3: 540,0
From 3 to 2: 126,0
From 2 to 4: 416,0
From 4 to 8: 236,0
From 8 to 1: 134,0
Total: 6.917,0
TSP-Tour (real) Optimal (brute force calculated):
Distances:
From 1 to 3: 466,0
From 3 to 2: 126,0
From 2 to 4: 416,0
From 4 to 8: 236,0
From 8 to 14: 484,0
From 14 to 15: 167,0
From 15 to 6: 256,0
From 6 to 5: 430,0
From 5 to 11: 1.444,0
From 11 to 9: 1.387,0
From 9 to 10: 328,0
From 10 to 7: 288,0
From 7 to 12: 177,0
From 12 to 13: 68,0
From 13 to 16: 353,0
From 16 to 1: 183,0
Total: 6.809,0
-
TSP-Tour Optimal (real distances, but optimum like FAQ optimum):
Location ID: 1 (38,24|20,42), in Radians: Latitude: 0,667414, Longitude: 0,356396
Location ID: 14 (37,51|15,17), in Radians: Latitude: 0,654673, Longitude: 0,264766
Location ID: 13 (38,15|15,35), in Radians: Latitude: 0,665843, Longitude: 0,267908
Location ID: 12 (38,47|15,13), in Radians: Latitude: 0,671428, Longitude: 0,264068
Location ID: 7 (38,42|13,11), in Radians: Latitude: 0,670555, Longitude: 0,228813
Location ID: 6 (37,56|12,19), in Radians: Latitude: 0,655546, Longitude: 0,212756
Location ID: 15 (35,49|14,32), in Radians: Latitude: 0,619417, Longitude: 0,249931
Location ID: 5 (33,48|10,54), in Radians: Latitude: 0,584336, Longitude: 0,183958 TP Hull
Location ID: 11 (36,08|-5,21), in Radians: Latitude: 0,629715, Longitude: -0,090932 TP Hull
Location ID: 9 (41,23|9,10), in Radians: Latitude: 0,719599, Longitude: 0,158825 TP Hull
Location ID: 10 (41,17|13,05), in Radians: Latitude: 0,718552, Longitude: 0,227765 TP Hull
Location ID: 16 (39,36|19,56), in Radians: Latitude: 0,686962, Longitude: 0,341386
Location ID: 3 (40,56|25,32), in Radians: Latitude: 0,707906, Longitude: 0,441917 TP Hull
Location ID: 2 (39,57|26,15), in Radians: Latitude: 0,690627, Longitude: 0,456404 TP Hull
Location ID: 4 (36,26|23,12), in Radians: Latitude: 0,632856, Longitude: 0,403520 TP Hull
Location ID: 8 (37,52|20,44), in Radians: Latitude: 0,654848, Longitude: 0,356745
Distances:
From 1 to 14: 468,4
From 14 to 13: 73,0
From 13 to 12: 40,5
From 12 to 7: 176,2
From 7 to 6: 125,2
From 6 to 15: 299,0
From 15 to 5: 412,7
From 5 to 11: 1.467,2
From 11 to 9: 1.367,5
From 9 to 10: 330,9
From 10 to 16: 588,4
From 16 to 3: 509,2
From 3 to 2: 130,9
From 2 to 4: 454,5
From 4 to 8: 276,8
From 8 to 1: 80,2
Total: 6.800,5
-
// y and x are flipped, because latitude is given first, which graphically is y
// rounding degree to int is problematic
// part of constructor, you figure it out
this.x = y; // y = longitude in degrees from file
this.y = x; // x = latitude in degrees from file
// calcRadians();
if (USE_TSPLIB_CALC) {
// https://www.iwr.uni-heidelberg.de/groups/comopt/software/TSPLIB95/tsp95.pdf
final double PI = 3.141592;
int degree;
if (USE_TSPLIB_CALC_FAQ)
degree = (int) this.y; // FAQ int to floor
else
degree = (int) Math.round(this.y);
double min = this.y - degree;
this.latitudeRadians = PI * (degree + 5 * min / 3d) / 180d;
if (USE_TSPLIB_CALC_FAQ)
degree = (int) this.x; // FAQ int to floor
else
degree = (int) Math.round(this.x); // tsp95.doc nearest int
min = this.x - degree;
this.longitudeRadians = PI * (degree + 5 * min / 3d) / 180d;
} else {
this.latitudeRadians = Math.toRadians(this.y);
this.longitudeRadians = Math.toRadians(this.x);
}
/**
* Calculates the distance between two points.
*
* @param location other Location
* @return distance
*/
static double EARTH_RADIUS_KM = 6378.388;
private double distance_GEO(Location location) {
if (USE_TSPLIB_CALC) {
// https://www.iwr.uni-heidelberg.de/groups/comopt/software/TSPLIB95/tsp95.pdf
double q1 = cos(longitudeRadians - location.longitudeRadians);
double q2 = cos(latitudeRadians - location.latitudeRadians);
double q3 = cos(latitudeRadians + location.latitudeRadians);
double distance = (int) (EARTH_RADIUS_KM * acos(0.5 * ((1.0 + q1) * q2 - (1.0 - q1) * q3)) + 1.0);
return distance;
} else {
// https://www.movable-type.co.uk/scripts/latlong.html
// https://stackoverflow.com/questions/365826/calculate-distance-between-2-gps-coordinates
double dLat = Math.toRadians(y - location.y);
double dLon = Math.toRadians(x - location.x);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(latitudeRadians) * Math.cos(location.latitudeRadians);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return EARTH_RADIUS_KM * c;
}
}