put all routers into one dict
This commit is contained in:
parent
6536a204db
commit
160629f356
3 changed files with 46 additions and 35 deletions
|
@ -174,8 +174,7 @@ class Graph:
|
||||||
|
|
||||||
# Router
|
# Router
|
||||||
def build_routers(self):
|
def build_routers(self):
|
||||||
level_routers = {}
|
routers = {}
|
||||||
room_routers = {}
|
|
||||||
|
|
||||||
empty_distances = np.empty(shape=(len(self.level_transfer_points),) * 2, dtype=np.float16)
|
empty_distances = np.empty(shape=(len(self.level_transfer_points),) * 2, dtype=np.float16)
|
||||||
empty_distances[:] = np.inf
|
empty_distances[:] = np.inf
|
||||||
|
@ -186,9 +185,8 @@ class Graph:
|
||||||
sparse_levels[:] = -1
|
sparse_levels[:] = -1
|
||||||
|
|
||||||
for i, level in enumerate(self.levels.values()):
|
for i, level in enumerate(self.levels.values()):
|
||||||
router, add_room_routers = level.build_routers()
|
routers.update(level.build_routers())
|
||||||
level_routers[level] = router
|
router = routers[level]
|
||||||
room_routers.update(add_room_routers)
|
|
||||||
|
|
||||||
level_distances = empty_distances.copy()
|
level_distances = empty_distances.copy()
|
||||||
in_level_i = np.array(tuple(level.room_transfer_points.index(point)
|
in_level_i = np.array(tuple(level.room_transfer_points.index(point)
|
||||||
|
@ -203,7 +201,9 @@ class Graph:
|
||||||
|
|
||||||
g_sparse = csgraph_from_dense(sparse_distances, null_value=np.inf)
|
g_sparse = csgraph_from_dense(sparse_distances, null_value=np.inf)
|
||||||
shortest_paths, predecessors = shortest_path(g_sparse, return_predecessors=True)
|
shortest_paths, predecessors = shortest_path(g_sparse, return_predecessors=True)
|
||||||
return GraphRouter(shortest_paths, predecessors), level_routers, room_routers
|
|
||||||
|
routers[self] = GraphRouter(shortest_paths, predecessors)
|
||||||
|
return routers
|
||||||
|
|
||||||
def get_location_points(self, location: Location):
|
def get_location_points(self, location: Location):
|
||||||
if isinstance(location, PointLocation):
|
if isinstance(location, PointLocation):
|
||||||
|
@ -229,7 +229,7 @@ class Graph:
|
||||||
best_route = NoRoute
|
best_route = NoRoute
|
||||||
|
|
||||||
# get routers
|
# get routers
|
||||||
graph_router, level_routers, room_routers = self.build_routers()
|
routers = self.build_routers()
|
||||||
|
|
||||||
# route within room
|
# route within room
|
||||||
orig_rooms = set(point.room for point in orig_points)
|
orig_rooms = set(point.room for point in orig_points)
|
||||||
|
@ -243,8 +243,8 @@ class Graph:
|
||||||
# if the points have common rooms, search for routes within those rooms
|
# if the points have common rooms, search for routes within those rooms
|
||||||
if common_rooms:
|
if common_rooms:
|
||||||
for room in common_rooms:
|
for room in common_rooms:
|
||||||
shortest_paths = room_routers[room].shortest_paths[orig_room_points[room][:, None],
|
shortest_paths = routers[room].shortest_paths[orig_room_points[room][:, None],
|
||||||
dest_room_points[room]]
|
dest_room_points[room]]
|
||||||
distance = shortest_paths.min()
|
distance = shortest_paths.min()
|
||||||
|
|
||||||
# Is this route better than the previous ones?
|
# Is this route better than the previous ones?
|
||||||
|
@ -255,12 +255,12 @@ class Graph:
|
||||||
from_point, to_point = np.argwhere(shortest_paths == distance)[0]
|
from_point, to_point = np.argwhere(shortest_paths == distance)[0]
|
||||||
from_point = orig_room_points[from_point]
|
from_point = orig_room_points[from_point]
|
||||||
to_point = dest_room_points[to_point]
|
to_point = dest_room_points[to_point]
|
||||||
best_route = RoomRouteSegment(room, room_routers[room], from_point, to_point).as_route()
|
best_route = RoomRouteSegment(room, routers, from_point, to_point).as_route()
|
||||||
|
|
||||||
# get reachable room transfer points and their distance
|
# get reachable room transfer points and their distance
|
||||||
# as a dictionary: global transfer point index => RoomRouteSegment
|
# as a dictionary: global transfer point index => RoomRouteSegment
|
||||||
orig_room_transfers = self._room_transfers(orig_rooms, orig_room_points, room_routers, mode='orig')
|
orig_room_transfers = self._room_transfers(orig_rooms, orig_room_points, routers, mode='orig')
|
||||||
dest_room_transfers = self._room_transfers(dest_rooms, dest_room_points, room_routers, mode='dest')
|
dest_room_transfers = self._room_transfers(dest_rooms, dest_room_points, routers, mode='dest')
|
||||||
|
|
||||||
# route within level
|
# route within level
|
||||||
orig_levels = set(room.level for room in orig_rooms)
|
orig_levels = set(room.level for room in orig_rooms)
|
||||||
|
@ -278,7 +278,7 @@ class Graph:
|
||||||
for level in common_levels:
|
for level in common_levels:
|
||||||
o_points = orig_room_transfer_points[level]
|
o_points = orig_room_transfer_points[level]
|
||||||
d_points = dest_room_transfer_points[level]
|
d_points = dest_room_transfer_points[level]
|
||||||
shortest_paths = level_routers[level].shortest_paths[o_points[:, None], d_points]
|
shortest_paths = routers[level].shortest_paths[o_points[:, None], d_points]
|
||||||
|
|
||||||
# add distances to the the room transfer points to the rows and columns
|
# add distances to the the room transfer points to the rows and columns
|
||||||
shortest_paths += np.array(tuple(orig_room_transfers[level.room_transfer_points[in_level_i]].distance
|
shortest_paths += np.array(tuple(orig_room_transfers[level.room_transfer_points[in_level_i]].distance
|
||||||
|
@ -296,13 +296,13 @@ class Graph:
|
||||||
from_point = o_points[from_point]
|
from_point = o_points[from_point]
|
||||||
to_point = d_points[to_point]
|
to_point = d_points[to_point]
|
||||||
best_route = Route((orig_room_transfers[level.room_transfer_points[from_point]],
|
best_route = Route((orig_room_transfers[level.room_transfer_points[from_point]],
|
||||||
LevelRouteSegment(level, level_routers[level], from_point, to_point),
|
LevelRouteSegment(level, routers, from_point, to_point),
|
||||||
dest_room_transfers[level.room_transfer_points[to_point]]), distance=distance)
|
dest_room_transfers[level.room_transfer_points[to_point]]), distance=distance)
|
||||||
|
|
||||||
# get reachable level transfer points and their distance
|
# get reachable level transfer points and their distance
|
||||||
# as a dictionary: global transfer point index => Route
|
# as a dictionary: global transfer point index => Route
|
||||||
orig_level_transfers = self._level_transfers(orig_levels, orig_room_transfers, level_routers, mode='orig')
|
orig_level_transfers = self._level_transfers(orig_levels, orig_room_transfers, routers, mode='orig')
|
||||||
dest_level_transfers = self._level_transfers(orig_levels, dest_room_transfers, level_routers, mode='dest')
|
dest_level_transfers = self._level_transfers(orig_levels, dest_room_transfers, routers, mode='dest')
|
||||||
|
|
||||||
# get reachable roomtransfer points for each level (points as room transfer point index within level)
|
# get reachable roomtransfer points for each level (points as room transfer point index within level)
|
||||||
orig_level_transfer_points = self._allowed_points_index(self.level_transfer_points, orig_level_transfers)
|
orig_level_transfer_points = self._allowed_points_index(self.level_transfer_points, orig_level_transfers)
|
||||||
|
@ -312,7 +312,7 @@ class Graph:
|
||||||
if True:
|
if True:
|
||||||
o_points = orig_level_transfer_points
|
o_points = orig_level_transfer_points
|
||||||
d_points = dest_level_transfer_points
|
d_points = dest_level_transfer_points
|
||||||
shortest_paths = graph_router.shortest_paths[o_points[:, None], d_points]
|
shortest_paths = routers[self].shortest_paths[o_points[:, None], d_points]
|
||||||
|
|
||||||
# add distances to the the room transfer points to the rows and columns
|
# add distances to the the room transfer points to the rows and columns
|
||||||
shortest_paths += np.array(tuple(orig_level_transfers[self.level_transfer_points[in_graph_i]].distance
|
shortest_paths += np.array(tuple(orig_level_transfers[self.level_transfer_points[in_graph_i]].distance
|
||||||
|
@ -328,12 +328,12 @@ class Graph:
|
||||||
from_point = o_points[from_point]
|
from_point = o_points[from_point]
|
||||||
to_point = d_points[to_point]
|
to_point = d_points[to_point]
|
||||||
best_route = Route((orig_level_transfers[self.level_transfer_points[from_point]],
|
best_route = Route((orig_level_transfers[self.level_transfer_points[from_point]],
|
||||||
GraphRouteSegment(self, graph_router, from_point, to_point),
|
GraphRouteSegment(self, routers, from_point, to_point),
|
||||||
dest_level_transfers[self.level_transfer_points[to_point]]), distance=distance)
|
dest_level_transfers[self.level_transfer_points[to_point]]), distance=distance)
|
||||||
|
|
||||||
return best_route
|
return best_route
|
||||||
|
|
||||||
def _room_transfers(self, rooms, room_points, room_routers, mode):
|
def _room_transfers(self, rooms, room_points, routers, mode):
|
||||||
if mode not in ('orig', 'dest'):
|
if mode not in ('orig', 'dest'):
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
|
||||||
|
@ -343,9 +343,9 @@ class Graph:
|
||||||
|
|
||||||
points = room_points[room]
|
points = room_points[room]
|
||||||
if mode == 'orig':
|
if mode == 'orig':
|
||||||
shortest_paths = room_routers[room].shortest_paths[points[:, None], room_transfer_points]
|
shortest_paths = routers[room].shortest_paths[points[:, None], room_transfer_points]
|
||||||
else:
|
else:
|
||||||
shortest_paths = room_routers[room].shortest_paths[room_transfer_points[:, None], points]
|
shortest_paths = routers[room].shortest_paths[room_transfer_points[:, None], points]
|
||||||
|
|
||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
for from_i, to_i in np.argwhere(shortest_paths != np.inf):
|
for from_i, to_i in np.argwhere(shortest_paths != np.inf):
|
||||||
|
@ -355,11 +355,11 @@ class Graph:
|
||||||
|
|
||||||
transfer_i = room.points[to_i if mode == 'orig' else from_i]
|
transfer_i = room.points[to_i if mode == 'orig' else from_i]
|
||||||
if transfer_i not in room_transfers or room_transfers[transfer_i].distance < distance:
|
if transfer_i not in room_transfers or room_transfers[transfer_i].distance < distance:
|
||||||
room_transfers[transfer_i] = RoomRouteSegment(room, room_routers[room], from_i, to_i)
|
room_transfers[transfer_i] = RoomRouteSegment(room, routers, from_i, to_i)
|
||||||
|
|
||||||
return room_transfers
|
return room_transfers
|
||||||
|
|
||||||
def _level_transfers(self, levels, all_room_transfers, level_routers, mode):
|
def _level_transfers(self, levels, all_room_transfers, routers, mode):
|
||||||
if mode not in ('orig', 'dest'):
|
if mode not in ('orig', 'dest'):
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
|
||||||
|
@ -375,10 +375,10 @@ class Graph:
|
||||||
distances = np.array(distances)
|
distances = np.array(distances)
|
||||||
|
|
||||||
if mode == 'orig':
|
if mode == 'orig':
|
||||||
shortest_paths = level_routers[level].shortest_paths[points[:, None], level_transfer_points]
|
shortest_paths = routers[level].shortest_paths[points[:, None], level_transfer_points]
|
||||||
shortest_paths += distances[:, None]
|
shortest_paths += distances[:, None]
|
||||||
else:
|
else:
|
||||||
shortest_paths = level_routers[level].shortest_paths[level_transfer_points[:, None], points]
|
shortest_paths = routers[level].shortest_paths[level_transfer_points[:, None], points]
|
||||||
shortest_paths += distances
|
shortest_paths += distances
|
||||||
|
|
||||||
# noinspection PyTypeChecker
|
# noinspection PyTypeChecker
|
||||||
|
@ -390,7 +390,7 @@ class Graph:
|
||||||
transfer_i = level.room_transfer_points[to_i if mode == 'orig' else from_i]
|
transfer_i = level.room_transfer_points[to_i if mode == 'orig' else from_i]
|
||||||
room_transfer_i = level.room_transfer_points[from_i if mode == 'orig' else to_i]
|
room_transfer_i = level.room_transfer_points[from_i if mode == 'orig' else to_i]
|
||||||
if transfer_i not in level_transfers or level_transfers[transfer_i].distance < distance:
|
if transfer_i not in level_transfers or level_transfers[transfer_i].distance < distance:
|
||||||
segments = [LevelRouteSegment(level, level_routers[level], from_i, to_i)]
|
segments = [LevelRouteSegment(level, routers, from_i, to_i)]
|
||||||
if mode == 'orig':
|
if mode == 'orig':
|
||||||
segments.insert(0, all_room_transfers[room_transfer_i])
|
segments.insert(0, all_room_transfers[room_transfer_i])
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -195,7 +195,7 @@ class GraphLevel():
|
||||||
|
|
||||||
# Routing
|
# Routing
|
||||||
def build_routers(self):
|
def build_routers(self):
|
||||||
room_routers = {}
|
routers = {}
|
||||||
|
|
||||||
empty_distances = np.empty(shape=(len(self.room_transfer_points),) * 2, dtype=np.float16)
|
empty_distances = np.empty(shape=(len(self.room_transfer_points),) * 2, dtype=np.float16)
|
||||||
empty_distances[:] = np.inf
|
empty_distances[:] = np.inf
|
||||||
|
@ -207,7 +207,7 @@ class GraphLevel():
|
||||||
|
|
||||||
for i, room in enumerate(self.rooms):
|
for i, room in enumerate(self.rooms):
|
||||||
router = room.build_router()
|
router = room.build_router()
|
||||||
room_routers[room] = router
|
routers[room] = router
|
||||||
|
|
||||||
room_distances = empty_distances.copy()
|
room_distances = empty_distances.copy()
|
||||||
in_room_i = np.array(tuple(room.points.index(point) for point in room.room_transfer_points))
|
in_room_i = np.array(tuple(room.points.index(point) for point in room.room_transfer_points))
|
||||||
|
@ -222,7 +222,9 @@ class GraphLevel():
|
||||||
|
|
||||||
g_sparse = csgraph_from_dense(sparse_distances, null_value=np.inf)
|
g_sparse = csgraph_from_dense(sparse_distances, null_value=np.inf)
|
||||||
shortest_paths, predecessors = shortest_path(g_sparse, return_predecessors=True)
|
shortest_paths, predecessors = shortest_path(g_sparse, return_predecessors=True)
|
||||||
return LevelRouter(shortest_paths, predecessors, room_transfers), room_routers
|
|
||||||
|
routers[self] = LevelRouter(shortest_paths, predecessors, room_transfers)
|
||||||
|
return routers
|
||||||
|
|
||||||
|
|
||||||
LevelRouter = namedtuple('LevelRouter', ('shortest_paths', 'predecessors', 'rooms_transfers', ))
|
LevelRouter = namedtuple('LevelRouter', ('shortest_paths', 'predecessors', 'rooms_transfers', ))
|
||||||
|
|
|
@ -18,13 +18,22 @@ class RouteSegment(ABC):
|
||||||
def as_route(self):
|
def as_route(self):
|
||||||
return Route([self])
|
return Route([self])
|
||||||
|
|
||||||
|
def _get_points(self):
|
||||||
|
points = [self.to_point]
|
||||||
|
first = self.from_point
|
||||||
|
current = self.to_point
|
||||||
|
while current != first:
|
||||||
|
current = self.router.predecessors[first, current]
|
||||||
|
points.append(current)
|
||||||
|
return tuple(reversed(points))
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def distance(self):
|
def distance(self):
|
||||||
return self.router.shortest_paths[self.from_point, self.to_point]
|
return self.router.shortest_paths[self.from_point, self.to_point]
|
||||||
|
|
||||||
|
|
||||||
class RoomRouteSegment(RouteSegment):
|
class RoomRouteSegment(RouteSegment):
|
||||||
def __init__(self, room, router, from_point, to_point):
|
def __init__(self, room, routers, from_point, to_point):
|
||||||
"""
|
"""
|
||||||
Route segment within a Room
|
Route segment within a Room
|
||||||
:param room: GraphRoom
|
:param room: GraphRoom
|
||||||
|
@ -32,7 +41,7 @@ class RoomRouteSegment(RouteSegment):
|
||||||
:param from_point: in-room index of first point
|
:param from_point: in-room index of first point
|
||||||
:param to_point: in-room index of last point
|
:param to_point: in-room index of last point
|
||||||
"""
|
"""
|
||||||
super().__init__(router, from_point, to_point)
|
super().__init__(routers[room], from_point, to_point)
|
||||||
self.room = room
|
self.room = room
|
||||||
self.global_from_point = room.points[from_point]
|
self.global_from_point = room.points[from_point]
|
||||||
self.global_to_point = room.points[to_point]
|
self.global_to_point = room.points[to_point]
|
||||||
|
@ -43,12 +52,12 @@ class RoomRouteSegment(RouteSegment):
|
||||||
|
|
||||||
|
|
||||||
class LevelRouteSegment(RouteSegment):
|
class LevelRouteSegment(RouteSegment):
|
||||||
def __init__(self, level, router, from_point, to_point):
|
def __init__(self, level, routers, from_point, to_point):
|
||||||
"""
|
"""
|
||||||
Route segment within a Level (from room transfer point to room transfer point)
|
Route segment within a Level (from room transfer point to room transfer point)
|
||||||
:param level: GraphLevel
|
:param level: GraphLevel
|
||||||
"""
|
"""
|
||||||
super().__init__(router, from_point, to_point)
|
super().__init__(routers[level], from_point, to_point)
|
||||||
self.level = level
|
self.level = level
|
||||||
self.global_from_point = level.room_transfer_points[from_point]
|
self.global_from_point = level.room_transfer_points[from_point]
|
||||||
self.global_to_point = level.room_transfer_points[to_point]
|
self.global_to_point = level.room_transfer_points[to_point]
|
||||||
|
@ -59,12 +68,12 @@ class LevelRouteSegment(RouteSegment):
|
||||||
|
|
||||||
|
|
||||||
class GraphRouteSegment(RouteSegment):
|
class GraphRouteSegment(RouteSegment):
|
||||||
def __init__(self, graph, router, from_point, to_point):
|
def __init__(self, graph, routers, from_point, to_point):
|
||||||
"""
|
"""
|
||||||
Route segment within a Graph (from level transfer point to level transfer point)
|
Route segment within a Graph (from level transfer point to level transfer point)
|
||||||
:param graph: Graph
|
:param graph: Graph
|
||||||
"""
|
"""
|
||||||
super().__init__(router, from_point, to_point)
|
super().__init__(routers[graph], from_point, to_point)
|
||||||
self.graph = graph
|
self.graph = graph
|
||||||
self.global_from_point = graph.level_transfer_points[from_point]
|
self.global_from_point = graph.level_transfer_points[from_point]
|
||||||
self.global_to_point = graph.level_transfer_points[to_point]
|
self.global_to_point = graph.level_transfer_points[to_point]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue