-
Notifications
You must be signed in to change notification settings - Fork 0
/
world.py
114 lines (95 loc) · 4.21 KB
/
world.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
import matplotlib.pyplot as plt
import networkx as nx
import osmnx as ox
import numpy as np
import pathlib
class World:
"""
A general class representing a world.
Attributes
----------
graph: nx.Graph
the graph of the whole world
"""
def __init__(self, number_of_warehouses=1, number_of_hospitals=15, seed=3, max_demand=3):
"""
Initializer of the function. There are three types of nodes. (0) is a hospital, (1) a warehouse and (2) anything
else, like cross roads.
Parameters
----------
number_of_warehouses: int
the number of warehouses to be considered for a given world. Needs to be smaller than number_of_nodes
seed: int
the random seed used to generate the world
"""
# Get graph and positions
filepath = pathlib.Path(__file__).parent.absolute() / "Cambridge_Graph.xml"
self.graph = ox.load_graphml(filepath)
# self.graph = ox.project_graph(ox.io.load_graphml(filepath), to_crs="EPSG:3395")
self.graph = ox.add_edge_speeds(self.graph)
self.graph_type1 = ox.add_edge_travel_times(self.graph)
self.graph_type2 = ox.add_edge_travel_times(self.graph)
# Generate random warehouses and hospitals
np.random.seed(seed)
random_locations = np.random.choice(self.graph.nodes, number_of_warehouses + number_of_hospitals, replace=False)
random_warehouse_locations = random_locations[:number_of_warehouses]
random_hospital_locations = random_locations[number_of_warehouses:]
# Set them to be readable by the object
self.warehouses = list(random_warehouse_locations)
self.hospitals = list(random_hospital_locations)
# Label all the nodes
for node in self.graph.nodes:
pointer = self.graph.nodes[node]
if node in random_hospital_locations:
# Hospitals
pointer['type'] = 0
pointer['demand1'] = np.random.randint(max_demand) # Going to change this to between 0 and 1 for now
pointer['demand2'] = np.random.randint(max_demand)
pointer['priority'] = np.random.randint(1, 3)
pointer['init_demand1'] = pointer['demand1']
pointer['init_demand2'] = pointer['demand2']
elif node in random_warehouse_locations:
# Warehouses
pointer['type'] = 1
else:
# Corners
pointer['type'] = 2
# Label all the edges with traffic - to get higher values change the multiplier
for edge in self.graph.edges:
pointer = self.graph.edges[edge]
pointer['travel_time'] *= 1.0
def plot(self, ax, show=True, annotate=True):
"""
Plots a simple representation of the world. The hospitals are marked in blue, the warehouses in green.
"""
# Obtain the edge labels
# edge_labels = {}
# for edge in self.graph.edges:
# edge_labels[edge] = self.graph.edges[edge[0], edge[1]]['length']
# Obtain the node colors
node_colors = []
for node in self.graph.nodes:
if self.graph.nodes[node]['type'] == 0:
node_colors.append("#ff0000ff")
elif self.graph.nodes[node]['type'] == 1:
node_colors.append("#00ff00ff")
else:
node_colors.append("#00000000")
# Plot the graph
ox.plot_graph(self.graph, ax=ax, node_color=node_colors, node_size=80, show=False)
# Plot the text for the hospitals
for node in self.hospitals:
pointer = self.graph.nodes[node]
print(pointer['x'], pointer['y'])
if annotate==True:
ax.annotate(f"{pointer['init_demand1']}/{pointer['init_demand2']}"f"/{pointer['priority']}",
xy=(pointer['x'] + 100, pointer['y'] - 20), color='black',
bbox=dict(facecolor='white', alpha=0.75, edgecolor='white'))
# Show the plot if required
if show:
plt.show()
if __name__ == "__main__":
# Run a test
world = World()
print(world.warehouses, world.hospitals)
world.plot()