DuquesnoyPaul
commited on
Commit
·
dad800b
1
Parent(s):
12031b6
PDL : heuristic functions implementation and test
Browse files
app/travel_resolver/libs/pathfinder/heuristic.py
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import math
|
| 2 |
+
|
| 3 |
+
def euclidean_distance(lat1 : float, lon1 : float, lat2 : float, lon2 : float):
|
| 4 |
+
"""
|
| 5 |
+
Calculate the Euclidean distance between two points given by their latitudes and longitudes.
|
| 6 |
+
The coordinates are in degrees.
|
| 7 |
+
Args:
|
| 8 |
+
lat1 (float): Latitude of the first point.
|
| 9 |
+
lon1 (float): Longitude of the first point.
|
| 10 |
+
lat2 (float): Latitude of the second point.
|
| 11 |
+
lon2 (float): Longitude of the first point.
|
| 12 |
+
|
| 13 |
+
Returns:
|
| 14 |
+
(float): The Euclidean distance (radians) between the two points.
|
| 15 |
+
"""
|
| 16 |
+
# Conversion des degrés en radians
|
| 17 |
+
lat1, lon1 = math.radians(lat1), math.radians(lon1)
|
| 18 |
+
lat2, lon2 = math.radians(lat2), math.radians(lon2)
|
| 19 |
+
|
| 20 |
+
# Différence des coordonnées
|
| 21 |
+
delta_lat = lat2 - lat1
|
| 22 |
+
delta_lon = lon2 - lon1
|
| 23 |
+
|
| 24 |
+
# Distance euclidienne (approximation plane)
|
| 25 |
+
distance = math.sqrt(delta_lat**2 + delta_lon**2)
|
| 26 |
+
|
| 27 |
+
return distance
|
| 28 |
+
|
| 29 |
+
def haversine_distance(lat1 : float, lon1 : float, lat2 : float, lon2 : float):
|
| 30 |
+
"""
|
| 31 |
+
Calculates the distance as the crow flies between two points on the Earth
|
| 32 |
+
(coordinates specified in degrees) using the Haversine formula.
|
| 33 |
+
Args:
|
| 34 |
+
lat1 (float): Latitude of the first point.
|
| 35 |
+
lon1 (float): Longitude of the first point.
|
| 36 |
+
lat2 (float): Latitude of the second point.
|
| 37 |
+
lon2 (float): Longitude of the first point.
|
| 38 |
+
|
| 39 |
+
Returns:
|
| 40 |
+
(float): The distance as the crow flies (kilometers) between the two points.
|
| 41 |
+
"""
|
| 42 |
+
# Rayon de la Terre en kilomètres
|
| 43 |
+
R = 6371.0
|
| 44 |
+
|
| 45 |
+
# Conversion des degrés en radians
|
| 46 |
+
lat1, lon1 = math.radians(lat1), math.radians(lon1)
|
| 47 |
+
lat2, lon2 = math.radians(lat2), math.radians(lon2)
|
| 48 |
+
|
| 49 |
+
# Différences des coordonnées
|
| 50 |
+
delta_lat = lat2 - lat1
|
| 51 |
+
delta_lon = lon2 - lon1
|
| 52 |
+
|
| 53 |
+
# Formule de haversine
|
| 54 |
+
a = math.sin(delta_lat / 2)**2 + math.cos(lat1) * math.cos(lat2) * math.sin(delta_lon / 2)**2
|
| 55 |
+
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
|
| 56 |
+
|
| 57 |
+
# Distance à vol d'oiseau
|
| 58 |
+
distance = R * c
|
| 59 |
+
|
| 60 |
+
return distance
|
app/travel_resolver/tests/heuristic_test.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import unittest
|
| 2 |
+
from travel_resolver.libs.pathfinder.heuristic import euclidean_distance,haversine_distance
|
| 3 |
+
|
| 4 |
+
class TestHeuristic(unittest.TestCase):
|
| 5 |
+
|
| 6 |
+
def setUp(self):
|
| 7 |
+
self.latParis, self.lonParis = 48.8566, 2.3522
|
| 8 |
+
self.latLyon, self.lonLyon = 45.7640, 4.8357
|
| 9 |
+
|
| 10 |
+
def test_euclidian_distance(self):
|
| 11 |
+
expected_distance = 0.06922589910147367
|
| 12 |
+
distance = euclidean_distance(self.latParis, self.lonParis, self.latLyon, self.lonLyon)
|
| 13 |
+
self.assertEqual(distance, expected_distance)
|
| 14 |
+
|
| 15 |
+
def test_haversin_distance(self):
|
| 16 |
+
expected_distance = 391.4989316742569
|
| 17 |
+
distance = haversine_distance(self.latParis, self.lonParis, self.latLyon, self.lonLyon)
|
| 18 |
+
self.assertEqual(distance, expected_distance)
|
| 19 |
+
|
| 20 |
+
if __name__ == '__main__':
|
| 21 |
+
unittest.main()
|