import heapq import copy # 定义状态类 class State: def __init__(self, board, moves=0, parent=None, last_move=None): self.board = board self.moves = moves self.parent = parent self.last_move = last_move def __lt__(self, other): return self.moves < other.moves def __eq__(self, other): return self.board == other.board # 定义转移函数 def move(state, direction): new_board = copy.deepcopy(state.board) for i in range(len(new_board)): if 0 in new_board[i]: j = new_board[i].index(0) break if direction == "up": if i == 0: return None else: new_board[i][j], new_board[i-1][j] = new_board[i-1][j], new_board[i][j] elif direction == "down": if i == len(new_board)-1: return None else: new_board[i][j], new_board[i+1][j] = new_board[i+1][j], new_board[i][j] elif direction == "left": if j == 0: return None else: new_board[i][j], new_board[i][j-1] = new_board[i][j-1], new_board[i][j] elif direction == "right": if j == len(new_board)-1: return None else: new_board[i][j], new_board[i][j+1] = new_board[i][j+1], new_board[i][j] return State(new_board, state.moves+1, state, direction) # 定义A*算法 def astar(start, goal): heap = [] closed = set() heapq.heappush(heap, start) while heap: state = heapq.heappop(heap) if state.board == goal: path = [] while state.parent: path.append(state) state = state.parent path.append(state) return path[::-1] closed.add(state) for direction in ["up", "down", "left", "right"]: child = move(state, direction) if child is None: continue if child in closed: continue if child not in heap: heapq.heappush(heap, child) else: for i, (p, c) in enumerate(heap): if c == child and p.moves > child.moves: heap[i] = (child, child) heapq.heapify(heap) # 测试 start_board = [[1, 2, 3], [4, 5, 6], [7, 8, 0]] goal_board = [[2, 3, 6], [1, 5, 8], [4, 7, 0]] start_state = State(start_board) goal_state = State(goal_board) path = astar(start_state, goal_board) for state in path: print(state.board) 这段代码运行后报错,因为State是不可hash的,那么如何修改才能使得功能一样且能够运行
时间: 2023-06-01 08:01:38 浏览: 42
import heapq 和 import copy 是 Python 中的两个模块。
import heapq 用于实现堆数据结构。堆是一种特殊的树形数据结构,它满足堆的性质:对于每个节点,其父节点的值都比其子节点的值要小(或大,具体取决于堆的类型)。堆可以用来实现优先队列,即每次弹出的元素都是优先级最高的。
import copy 用于实现复制操作。在 Python 中,变量之间的赋值实际上是将一个对象的引用赋给另一个变量,而不是将对象本身复制一份。因此,如果要复制一个对象并在原对象的基础上进行修改,就需要使用 copy 模块中的函数进行复制操作。copy 模块中提供了浅复制和深复制两种方式,具体的区别可以参见官方文档。
相关问题
class FixedSizeHeap: def __init__(self, max_size): self.max_size = max_size self.heap = [] def push(self, item): if len(self.heap) < self.max_size: heapq.heappush(self.heap, item) else: min_item = heapq.heappop(self.heap) if item > min_item: heapq.heappush(self.heap, item) else: heapq.heappush(self.heap, min_item) def pop(self): return heapq.heappop(self.heap) def __len__(self): return len(self.heap)对于这样的类怎么打印类中的元素
要打印类中的元素,可以通过实现`__str__`方法来实现。`__str__`方法应该返回一个字符串,该字符串包含对象的信息。例如,以下代码演示了如何在类中实现`__str__`方法以打印堆的元素:
```
import heapq
class FixedSizeHeap:
def __init__(self, max_size):
self.max_size = max_size
self.heap = []
def push(self, item):
if len(self.heap) < self.max_size:
heapq.heappush(self.heap, item)
else:
min_item = heapq.heappop(self.heap)
if item > min_item:
heapq.heappush(self.heap, item)
else:
heapq.heappush(self.heap, min_item)
def pop(self):
return heapq.heappop(self.heap)
def __len__(self):
return len(self.heap)
def __str__(self):
return str(self.heap)
new_heap = FixedSizeHeap(5)
new_heap.push(1)
new_heap.push(2)
new_heap.push(3)
new_heap.push(4)
new_heap.push(5)
print(new_heap) # 输出 [1, 2, 3, 4, 5]
```
在这个例子中,我们定义了`__str__`方法来返回堆的元素。我们将`self.heap`转换为字符串并返回。现在,当我们打印`new_heap`时,它将打印堆中的元素。
class Path(object): def __init__(self,path,distancecost,timecost): self.__path = path self.__distancecost = distancecost self.__timecost = timecost #路径上最后一个节点 def getLastNode(self): return self.__path[-1] #获取路径路径 @property def path(self): return self.__path #判断node是否为路径上最后一个节点 def isLastNode(self, node): return node == self.getLastNode() #增加加点和成本产生一个新的path对象 def addNode(self, node, dprice, tprice): return Path(self.__path+[node],self.__distancecost + dprice,self.__timecost + tprice) #输出当前路径 def printPath(self): for n in self.__path: if self.isLastNode(node=n): print(n) else: print(n, end="->") print(f"最短路径距离(self.__distancecost:.0f)m") print(f"红绿路灯个数(self.__timecost:.0f)个") #获取路径总成本的只读属性 @property def dCost(self): return self.__distancecost @property def tCost(self): return self.__timecost class DirectedGraph(object): def __init__(self, d): if isinstance(d, dict): self.__graph = d else: self.__graph = dict() print('Sth error') #通过递归生成所有可能的路径 def __generatePath(self, graph, path, end, results, distancecostIndex, timecostIndex): current = path.getLastNode() if current == end: results.append(path) else: for n in graph[current]: if n not in path.path: self.__generatePath(graph, path.addNode(n,self.__graph[path.getLastNode()][n][distancecostIndex][timecostIndex]), end, results, distancecostIndex, timecostIndex) #搜索start到end之间时间或空间最短的路径,并输出 def __searchPath(self, start, end, distancecostIndex, timecostIndex): results = [] self.__generatePath(self.__graph, Path([start],0,0), end, results,distancecostIndex,timecostIndex) results.sort(key=lambda p: p.distanceCost) results.sort(key=lambda p: p.timeCost) print('The {} shortest path from '.format("spatially" if distancecostIndex==0 else "temporally"), start, ' to ', end, ' is:', end="") print('The {} shortest path from '.format("spatially" if timecostIndex==0 else "temporally"), start, ' to ', end, ' is:', end="") results[0].printPath() #调用__searchPath搜索start到end之间的空间最短的路径,并输出 def searchSpatialMinPath(self,start, end): self.__searchPath(start,end,0,0) #调用__searc 优化这个代码
这段代码中可以进行如下优化:
1. 将类属性的命名改为下划线开头的私有属性,避免外部直接修改属性值,可以使用@property装饰器来获取属性的值。
2. 可以将类的构造函数中的参数改为可选参数,避免在初始化时需要传入参数,可以在需要时再传入参数。
3. 在递归函数的参数中加入默认值,避免在调用递归函数时需要传入所有参数。
4. 可以使用f-string格式化输出语句,代码更加简洁易读。
5. 可以使用列表推导式对列表进行过滤。
6. 在搜索最短路径时可以使用heapq模块的堆排序来优化效率。
优化后的代码如下:
```python
import heapq
class Path(object):
def __init__(self, path = [], distance_cost = 0, time_cost = 0):
self._path = path
self._distance_cost = distance_cost
self._time_cost = time_cost
def get_last_node(self):
return self._path[-1]
def is_last_node(self, node):
return node == self.get_last_node()
def add_node(self, node, d_price, t_price):
return Path(self._path + [node], self._distance_cost + d_price, self._time_cost + t_price)
def print_path(self):
for n in self._path:
print(n, end="->" if not self.is_last_node(n) else "\n")
print(f"最短路径距离({self._distance_cost:.0f}m)")
print(f"红绿路灯个数({self._time_cost:.0f})个")
@property
def d_cost(self):
return self._distance_cost
@property
def t_cost(self):
return self._time_cost
class DirectedGraph(object):
def __init__(self, d = {}):
if isinstance(d, dict):
self._graph = d
else:
self._graph = dict()
print('Something went wrong!')
def __generate_path(self, graph, path, end, results, distance_cost_index=0, time_cost_index=0):
current = path.get_last_node()
if current == end:
results.append(path)
else:
for n in graph[current]:
if n not in path._path:
self.__generate_path(graph, path.add_node(n, self._graph[path.get_last_node()][n][distance_cost_index][time_cost_index]), end, results, distance_cost_index, time_cost_index)
def __search_path(self, start, end, distance_cost_index=0, time_cost_index=0):
results = []
self.__generate_path(self._graph, Path([start], 0, 0), end, results, distance_cost_index, time_cost_index)
results = heapq.nsmallest(1, results, key=lambda p: (p.d_cost, p.t_cost))
print(f"The {'spatially' if distance_cost_index==0 else 'temporally'} shortest path from {start} to {end} is:")
results[0].print_path()
def search_spatial_min_path(self, start, end):
self.__search_path(start, end, 0, 0)
def search_temporal_min_path(self, start, end):
self.__search_path(start, end, 1, 1)
```