forked from anivenk25/Blood_reaper
-
Notifications
You must be signed in to change notification settings - Fork 0
/
crpa4.py
212 lines (185 loc) · 9.42 KB
/
crpa4.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
import networkx as nx
import requests
from copy import deepcopy
import os
class BloodSupplyChainOptimizer:
def __init__(self, traffic_api_key, weather_api_key, google_places_api_key):
self.graph = nx.Graph()
self.traffic_api_key = traffic_api_key
self.weather_api_key = weather_api_key
self.google_places_api_key = google_places_api_key
def fetch_and_add_locations(self, latitude, longitude, radius=5000, location_type='hospital'):
"""
Fetch locations of a specific type (e.g., hospitals) and add them to the graph.
"""
locations = self.search_nearby_locations(latitude, longitude, radius, location_type)
for loc in locations:
self.add_location(loc['name'], loc['latitude'], loc['longitude'], is_hospital=(location_type == 'hospital'))
def search_nearby_locations(self, latitude, longitude, radius=5000, location_type='hospital'):
"""
Search for nearby locations of a specific type using the Google Places API.
"""
try:
url = f"https://maps.googleapis.com/maps/api/place/nearbysearch/json?location={latitude},{longitude}&radius={radius}&type={location_type}&key={self.google_places_api_key}"
response = requests.get(url)
response.raise_for_status()
results = response.json().get('results', [])
locations = []
for place in results:
name = place['name']
lat = place['geometry']['location']['lat']
lng = place['geometry']['location']['lng']
locations.append({'name': name, 'latitude': lat, 'longitude': lng})
return locations
except requests.RequestException as e:
print(f"Error fetching locations: {e}")
return []
def add_location(self, name, latitude, longitude, is_hospital=False, blood_inventory=None):
"""
Add a location to the graph.
"""
self.graph.add_node(name, latitude=latitude, longitude=longitude, is_hospital=is_hospital,
blood_inventory=blood_inventory or {})
def add_route(self, loc1, loc2, base_travel_time):
"""
Add a route between two locations with a base travel time.
"""
if loc1 in self.graph.nodes and loc2 in self.graph.nodes:
self.graph.add_edge(loc1, loc2, base_travel_time=base_travel_time)
else:
raise ValueError(f"One or both locations {loc1} and {loc2} are not in the graph.")
def update_edge_weights(self):
"""
Update edge weights dynamically based on real-time traffic and weather data.
"""
for u, v, data in self.graph.edges(data=True):
if 'latitude' in self.graph.nodes[u] and 'latitude' in self.graph.nodes[v]:
base_time = data['base_travel_time']
traffic_factor = self.get_real_time_traffic(u, v)
weather_factor = self.get_real_time_weather(u, v)
data['weight'] = base_time * (1 + traffic_factor + weather_factor)
else:
print(f"Skipping edge ({u}, {v}) due to missing latitude/longitude data.")
def get_real_time_traffic(self, loc1, loc2):
"""
Fetch real-time traffic data between two locations.
"""
try:
origin = f"{self.graph.nodes[loc1]['latitude']},{self.graph.nodes[loc1]['longitude']}"
destination = f"{self.graph.nodes[loc2]['latitude']},{self.graph.nodes[loc2]['longitude']}"
traffic_data = requests.get(
f"https://maps.googleapis.com/maps/api/distancematrix/json?origins={origin}&destinations={destination}&key={self.traffic_api_key}"
).json()
duration = traffic_data['rows'][0]['elements'][0]['duration']['value']
return duration / 60.0 # Convert to minutes
except (IndexError, KeyError, requests.RequestException) as e:
print(f"Error fetching traffic data between {loc1} and {loc2}: {e}")
return 0
def get_real_time_weather(self, loc1, loc2):
"""
Fetch real-time weather data for a location.
"""
try:
latitude = self.graph.nodes[loc1]['latitude']
longitude = self.graph.nodes[loc1]['longitude']
weather_data = requests.get(
f"https://api.weather.com/weather?lat={latitude}&lon={longitude}&key={self.weather_api_key}"
).json()
return weather_data.get('weather_factor', 0) # Default to 0 if no data available
except (KeyError, IndexError, requests.RequestException) as e:
print(f"Error fetching weather data for {loc1}: {e}")
return 0
def find_optimal_route(self, hospital_name, blood_type, required_units, urgency='regular'):
"""
Find the optimal route to fulfill a hospital's blood request.
"""
self.update_edge_weights()
best_time = float('inf')
best_path = None
backup_paths = []
for blood_bank in self.graph.nodes():
if not self.graph.nodes[blood_bank]['is_hospital']:
inventory = self.graph.nodes[blood_bank]['blood_inventory']
if inventory.get(blood_type, 0) >= required_units:
try:
path_length = nx.dijkstra_path_length(self.graph, hospital_name, blood_bank, weight='weight')
if urgency == 'immediate':
path_length *= 1.0 # Higher priority
else:
path_length *= 1.2 # Normal priority
if path_length < best_time:
if best_path:
backup_paths.append((best_path, best_time)) # Save the previous best path as a backup
best_time = path_length
best_path = nx.dijkstra_path(self.graph, hospital_name, blood_bank, weight='weight')
else:
backup_paths.append(
(nx.dijkstra_path(self.graph, hospital_name, blood_bank, weight='weight'), path_length))
except nx.NetworkXNoPath:
continue
return best_path, best_time, backup_paths
def process_immediate_request(self, hospital_name, blood_type, required_units):
"""
Handle an immediate request from a hospital.
"""
best_path, best_time, backup_paths = self.find_optimal_route(hospital_name, blood_type, required_units,
urgency='immediate')
if best_path:
# Deduct the required units from the blood bank's inventory
blood_bank = best_path[-1]
if self.graph.nodes[blood_bank]['blood_inventory'][blood_type] >= required_units:
self.graph.nodes[blood_bank]['blood_inventory'][blood_type] -= required_units
return best_path, best_time
else:
# If inventory is insufficient, try backup paths
for backup_path, _ in backup_paths:
blood_bank_backup = backup_path[-1]
if self.graph.nodes[blood_bank_backup]['blood_inventory'][blood_type] >= required_units:
self.graph.nodes[blood_bank_backup]['blood_inventory'][blood_type] -= required_units
return backup_path, _
return None, None # No suitable blood bank found
def restock_blood_bank(self, blood_bank_name, blood_type, units):
"""
Restock a blood bank with specific units of a blood type.
"""
if not self.graph.nodes[blood_bank_name]['is_hospital']:
if blood_type in self.graph.nodes[blood_bank_name]['blood_inventory']:
self.graph.nodes[blood_bank_name]['blood_inventory'][blood_type] += units
else:
self.graph.nodes[blood_bank_name]['blood_inventory'][blood_type] = units
def scalable_add_locations(self, locations):
"""
Add multiple locations (hospitals or blood banks) at once.
"""
for loc in locations:
self.add_location(**loc)
def scalable_add_routes(self, routes):
"""
Add multiple routes between locations at once.
"""
for route in routes:
self.add_route(**route)
def print_graph(self):
"""
Print the nodes and edges of the graph with their attributes.
"""
print("Nodes:")
for node, data in self.graph.nodes(data=True):
print(f"Node: {node}, Data: {data}")
print("\nEdges:")
for u, v, data in self.graph.edges(data=True):
print(f"Edge: ({u}, {v}), Data: {data}")
# Example usage
traffic_api_key = 'YOUR_TRAFFIC_API_KEY'
weather_api_key = 'YOUR_WEATHER_API_KEY'
google_places_api_key = 'YOUR_GOOGLE_PLACES_API_KEY'
optimizer = BloodSupplyChainOptimizer(traffic_api_key, weather_api_key, google_places_api_key)
# Fetch and add hospitals and blood banks
latitude = 13.082680
longitude = 77.2090
optimizer.fetch_and_add_locations(latitude, longitude, location_type='hospital')
optimizer.fetch_and_add_locations(latitude, longitude, location_type='blood_bank')
# Add routes between locations (this should be adjusted based on your specific needs)
# Example: optimizer.add_route('Hospital A', 'Blood Bank 1', base_travel_time=30)
# Print the graph details
optimizer.print_graph()