cost-matrix 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ from .euclidean_matrix import euclidean # noqa F401
2
+ from .manhattan_matrix import manhattan # noqa F401
3
+ from .osrm_matrix import osrm # noqa F401
4
+ from .spherical_matrix import spherical # noqa F401
@@ -0,0 +1,5 @@
1
+ import numpy as np
2
+
3
+
4
+ def euclidean(sources: np.ndarray, destinations: np.ndarray) -> np.ndarray:
5
+ return np.linalg.norm(sources - destinations, axis=1)
@@ -0,0 +1,5 @@
1
+ import numpy as np
2
+
3
+
4
+ def manhattan(sources: np.ndarray, destinations: np.ndarray) -> np.ndarray:
5
+ return np.sum(np.abs(sources - destinations), axis=1)
@@ -0,0 +1,136 @@
1
+ from math import ceil
2
+
3
+ import numpy as np
4
+ import requests
5
+
6
+
7
+ def osrm(
8
+ sources: np.ndarray,
9
+ destinations: np.ndarray,
10
+ server_address: str = "http://router.project-osrm.org",
11
+ batch_size: int = 150,
12
+ cost_type: str = "distances",
13
+ ) -> np.ndarray:
14
+ """Compute the OSRM cost matrix between sources and destinations"""
15
+
16
+ num_sources = sources.shape[0]
17
+ num_destinations = destinations.shape[0]
18
+ cost_matrix = np.zeros((num_sources, num_destinations))
19
+
20
+ num_batches_i = ceil(num_sources / batch_size)
21
+ num_batches_j = ceil(num_destinations / batch_size)
22
+
23
+ for i in range(num_batches_i):
24
+ start_i = i * batch_size
25
+ end_i = min((i + 1) * batch_size, num_sources)
26
+
27
+ for j in range(num_batches_j):
28
+ start_j = j * batch_size
29
+ end_j = min((j + 1) * batch_size, num_destinations)
30
+ sources_batch = sources[start_i:end_i]
31
+ destinations_batch = destinations[start_j:end_j]
32
+
33
+ cost_matrix[start_i:end_i, start_j:end_j] = (
34
+ _get_batch_osrm_distance(
35
+ sources_batch,
36
+ destinations_batch,
37
+ server_address,
38
+ cost_type=cost_type,
39
+ )
40
+ )
41
+
42
+ return cost_matrix
43
+
44
+
45
+ def _get_batch_osrm_distance(
46
+ sources_batch: np.ndarray,
47
+ destinations_batch: np.ndarray,
48
+ server_address: str,
49
+ cost_type: str,
50
+ ):
51
+ """Request the OSRM cost matrix for a given batch"""
52
+
53
+ url = _format_osrm_url(
54
+ sources_batch, destinations_batch, server_address, cost_type
55
+ )
56
+ resp = requests.get(url)
57
+ resp.raise_for_status()
58
+
59
+ return np.array(resp.json()[cost_type])
60
+
61
+
62
+ def _format_osrm_url(
63
+ sources_batch: np.ndarray,
64
+ destinations_batch: np.ndarray,
65
+ server_address: str,
66
+ cost_type: str,
67
+ ) -> str:
68
+ """Format OSRM url string with sources and destinations
69
+
70
+ Notes
71
+ -----
72
+ Consider the N sources in the form
73
+ (lat_src1, lgn_src1), (lat_src2, lgn_src2), ...
74
+
75
+ and the M destinations in the form
76
+ (lat_dest1, lgn_dest1), (lat_dest2, lgn_dest2), ...
77
+
78
+ This function converts these properties in a URL of the form
79
+ {OSRM_SERVER_ADDRESS}/table/v1/driving/
80
+ lng_src1,lat_src1;lng_src2,lat_src2;...;lng_srcN,lat_srcN;
81
+ lng_dest1,lat_dest1;lng_dest2,lat_dest2;...;lng_destM,lng_destM
82
+ ?sources=0;1;...;N-1
83
+ &destinations=N;N+1;...;N+M-1
84
+ &annotations=distance
85
+
86
+ In the simpler case when sources == destinations, the URL is simplified to
87
+ {OSRM_SERVER_ADDRESS}/table/v1/driving/
88
+ lng_src1,lat_src1;lng_src2,lat_src2;...;lng_srcN,lat_srcN
89
+ ?annotations=distance
90
+
91
+ Obs: Replace "distance" with "duration" if a time matrix is required
92
+ Obs2: The matrix type follows the singular form in the URL (e.g.,
93
+ "distance"), but the returned JSON follows the plural form (e.g.,
94
+ "distances"). Thus, we ignore the last letter of the input type
95
+ """
96
+
97
+ url_cost_type = cost_type[:-1]
98
+ sources_coord = ";".join(
99
+ f"{source[1]},{source[0]}" for source in sources_batch
100
+ )
101
+
102
+ # If sources == destinations, return a simpler URL early. Notice it needs
103
+ # at least two points, otherwise OSRM complains
104
+ if (
105
+ np.array_equal(sources_batch, destinations_batch)
106
+ and sources_batch.shape[0] > 1
107
+ ):
108
+ return (
109
+ f"{server_address}/table/v1/driving/"
110
+ f"{sources_coord}"
111
+ f"?annotations={url_cost_type}"
112
+ )
113
+
114
+ destinations_coord = ";".join(
115
+ f"{destination[1]},{destination[0]}"
116
+ for destination in destinations_batch
117
+ )
118
+ locations_coord = sources_coord + ";" + destinations_coord
119
+
120
+ # Get indices of sources and destinations in the form
121
+ # sources = 0,1,...,N' and destinations = N'+1,N'+2...N'+M'
122
+ num_sources = sources_batch.shape[0]
123
+ num_destinations = destinations_batch.shape[0]
124
+
125
+ sources_indices = ";".join(str(index) for index in range(num_sources))
126
+ destinations_indices = ";".join(
127
+ str(index)
128
+ for index in range(num_sources, num_sources + num_destinations)
129
+ )
130
+
131
+ return (
132
+ f"{server_address}/table/v1/driving/"
133
+ f"{locations_coord}"
134
+ f"?sources={sources_indices}&destinations={destinations_indices}"
135
+ f"&annotations={url_cost_type}"
136
+ )
@@ -0,0 +1,31 @@
1
+ import numpy as np
2
+
3
+ EARTH_RADIUS_METERS = 6371000
4
+
5
+
6
+ def spherical(sources: np.ndarray, destinations: np.ndarray) -> np.ndarray:
7
+ """Distance matrix using the Spherical distance"""
8
+
9
+ sources_rad = np.radians(sources)
10
+ destinations_rad = np.radians(destinations)
11
+
12
+ delta_lambda = sources_rad[:, [1]] - destinations_rad[:, 1] # (N x M) lng
13
+ phi1 = sources_rad[:, [0]] # (N x 1) array of source latitudes
14
+ phi2 = destinations_rad[:, 0] # (1 x M) array of destination latitudes
15
+
16
+ delta_sigma = np.arctan2(
17
+ np.sqrt(
18
+ (np.cos(phi2) * np.sin(delta_lambda)) ** 2
19
+ + (
20
+ np.cos(phi1) * np.sin(phi2)
21
+ - np.sin(phi1) * np.cos(phi2) * np.cos(delta_lambda)
22
+ )
23
+ ** 2
24
+ ),
25
+ (
26
+ np.sin(phi1) * np.sin(phi2)
27
+ + np.cos(phi1) * np.cos(phi2) * np.cos(delta_lambda)
28
+ ),
29
+ )
30
+
31
+ return EARTH_RADIUS_METERS * delta_sigma
@@ -0,0 +1,72 @@
1
+ Metadata-Version: 2.1
2
+ Name: cost-matrix
3
+ Version: 0.1.0
4
+ Summary: Designed to simplify the creation of cost matrices for optimization problems.
5
+ Author: Luan
6
+ Author-email: llvdmoraes@gmail.com
7
+ Requires-Python: >=3.9,<3.13
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.9
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Requires-Dist: numpy (>=1.26.4,<2.0.0)
14
+ Requires-Dist: requests (>=2.32.3,<3.0.0)
15
+ Description-Content-Type: text/markdown
16
+
17
+ # cost-matrix
18
+
19
+ `cost-matrix` is a Python package designed to simplify the creation of cost matrices for optimization problems. Whether you're dealing with distance calculations or travel durations, `cost-matrix` provides a robust set of tools to meet your needs.
20
+
21
+ This package is invaluable for anyone working on optimization problems, data analysis, or transportation planning. With its diverse range of distance calculation methods and integration with OSRM, it provides a comprehensive solution for generating cost matrices efficiently.
22
+
23
+ ## Key Features:
24
+ - **Manhattan**: Compute distances based on orthogonal paths.
25
+ - **Euclidean**: Calculate straight-line distances in a Cartesian plane.
26
+ - **Spherical**: Calculate distances between geographical points considering the Earth's curvature.
27
+ - **OSRM**: Integrate with the Open Source Routing Machine (OSRM) to obtain travel duration or distance matrices.
28
+
29
+ ## Installation
30
+
31
+ To install the `cost-matrix` package, you can use pip:
32
+
33
+ ```sh
34
+ pip install cost-matrix
35
+ ```
36
+
37
+
38
+ ## Example Usage:
39
+ ```python
40
+ import numpy as np
41
+ import cost_matrix
42
+
43
+ # Define source and destination coordinates (latitude, longitude)
44
+ sources = np.array([[37.7749, -122.4194], [34.0522, -118.2437]]) # San Francisco, Los Angeles
45
+ destinations = np.array([[40.7128, -74.0060], [51.5074, -0.1278]]) # New York, London
46
+
47
+ # Calculate Manhattan distance matrix
48
+ manhattan_matrix = cost_matrix.manhattan(sources, destinations)
49
+ print(manhattan_matrix)
50
+
51
+ # Calculate Euclidean distance matrix
52
+ euclidean_matrix = cost_matrix.euclidean(sources, destinations)
53
+ print(euclidean_matrix)
54
+
55
+ # Calculate Spherical distance matrix
56
+ spherical_matrix = cost_matrix.spherical(sources, destinations)
57
+ print(spherical_matrix)
58
+
59
+ # Calculate OSRM travel distances matrix
60
+ osrm_distance_matrix = cost_matrix.osrm(sources, destinations)
61
+ print(osrm_distance_matrix)
62
+
63
+ # Calculate OSRM travel durations matrix
64
+ osrm_duration_matrix = cost_matrix.osrm(
65
+ sources,
66
+ destinations,
67
+ cost_type="durations",
68
+ server_address="http://localhost:5000",
69
+ batch_size=250
70
+ )
71
+ print(osrm_duration_matrix)
72
+
@@ -0,0 +1,8 @@
1
+ cost_matrix/__init__.py,sha256=9EaPsXe0SIuym34-CPmzUPSGJuBd2AkQZHqjcwlUywE,202
2
+ cost_matrix/euclidean_matrix.py,sha256=a8uLh0COVb5duaKV6DMfG9HklkJX2dOARKfnnWxLxsc,155
3
+ cost_matrix/manhattan_matrix.py,sha256=bWTTiIgvb0PDWSdfCXuffHEIgb9nNMb4w7Qwhe3EbaQ,155
4
+ cost_matrix/osrm_matrix.py,sha256=VuuoQVRGxMjoN_eUfs9yur9lwINg8JZxB3SX-6cvBFk,4327
5
+ cost_matrix/spherical_matrix.py,sha256=SxaihjkKyrp0den5w-VsimGcjjQEi-q-_cvxeTM3xyY,946
6
+ cost_matrix-0.1.0.dist-info/METADATA,sha256=4TVrFT0TlklV7jcvRAJarKqi-TE2_TPMtSJJtVZTmIQ,2676
7
+ cost_matrix-0.1.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
8
+ cost_matrix-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 1.9.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any