done: homework3
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="com.codeverse.userSettings.MarscodeWorkspaceAppSettingsState">
|
||||
<option name="ckgOperationStatus" value="SUCCESS" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="jdk" jdkName="ai-homework" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Black">
|
||||
<option name="sdkName" value="ai-homework" />
|
||||
</component>
|
||||
</project>
|
||||
Generated
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/homework3.iml" filepath="$PROJECT_DIR$/.idea/homework3.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+3
-1
@@ -1,4 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings" defaultProject="true" />
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,183 @@
|
||||
import numpy as np
|
||||
|
||||
class State:
|
||||
def __init__(self, state, directionFlag=None, parent=None, f=0):
|
||||
"""八数码问题状态类
|
||||
Args:
|
||||
state: 3x3 numpy数组,表示当前状态
|
||||
directionFlag: 禁止的移动方向(用于防止走回头路)
|
||||
parent: 父状态节点
|
||||
f: 评估函数值(f = g + h)
|
||||
"""
|
||||
self.state = state # 当前状态矩阵
|
||||
self.direction = ['up', 'down', 'right', 'left'] # 可移动方向
|
||||
if directionFlag: # 移除来源方向防止回退
|
||||
self.direction.remove(directionFlag)
|
||||
self.parent = parent # 父节点指针
|
||||
self.f = f # 评估函数值
|
||||
|
||||
def getDirection(self):
|
||||
"""获取当前允许的移动方向列表"""
|
||||
return self.direction
|
||||
|
||||
def setF(self, f):
|
||||
"""设置评估函数值"""
|
||||
self.f = f
|
||||
return
|
||||
|
||||
# 打印结果
|
||||
def showInfo(self):
|
||||
"""打印当前状态矩阵"""
|
||||
for i in range(len(self.state)):
|
||||
for j in range(len(self.state)):
|
||||
print(self.state[i, j], end=' ')
|
||||
print("\n")
|
||||
print('->')
|
||||
return
|
||||
|
||||
# 获取0点
|
||||
def getZeroPos(self):
|
||||
"""获取空白格(0)的位置坐标
|
||||
Returns:
|
||||
tuple: 包含空白格的行列坐标(x, y)
|
||||
"""
|
||||
postion = np.where(self.state == 0)
|
||||
return postion
|
||||
|
||||
# 曼哈顿距离 f = g + h,g=1,如果用宽度优先的评估函数可以不调用该函数
|
||||
def getFunctionValue(self):
|
||||
"""计算曼哈顿距离评估值
|
||||
Returns:
|
||||
int: 当前状态到目标状态的评估值(f = 移动步数 + 启发函数值)
|
||||
"""
|
||||
cur_node = self.state.copy()
|
||||
fin_node = self.answer.copy()
|
||||
dist = 0 # 曼哈顿距离总和
|
||||
N = len(cur_node) # 矩阵维度(3)
|
||||
|
||||
# 遍历每个格子计算距离
|
||||
for i in range(N):
|
||||
for j in range(N):
|
||||
if cur_node[i][j] != fin_node[i][j]:
|
||||
index = np.argwhere(fin_node == cur_node[i][j]) # 找到对应数字在目标状态的位置
|
||||
x = index[0][0] # 目标x坐标
|
||||
y = index[0][1] # 目标y坐标
|
||||
dist += (abs(x - i) + abs(y - j)) # 累加曼哈顿距离
|
||||
return dist + 1 # 总距离+当前步数(g值固定为1)
|
||||
|
||||
def nextStep(self):
|
||||
"""生成所有可能的下一个合法状态
|
||||
Returns:
|
||||
State: 评估函数值最小的下一个状态
|
||||
"""
|
||||
if not self.direction: # 无可用移动方向
|
||||
return []
|
||||
subStates = [] # 子状态列表
|
||||
boarder = len(self.state) - 1 # 矩阵边界索引
|
||||
|
||||
# 获取0点位置
|
||||
x, y = self.getZeroPos()
|
||||
x, y = x[0], y[0] # 转换为标量值
|
||||
|
||||
# 向左移动
|
||||
if 'left' in self.direction and y > 0:
|
||||
s = self.state.copy()
|
||||
tmp = s[x, y - 1]
|
||||
s[x, y - 1] = s[x, y]
|
||||
s[x, y] = tmp
|
||||
news = State(s, directionFlag='right', parent=self)
|
||||
news.setF(news.getFunctionValue())
|
||||
subStates.append(news)
|
||||
|
||||
# 向上移动
|
||||
if 'up' in self.direction and x > 0:
|
||||
s = self.state.copy()
|
||||
tmp = s[x - 1, y]
|
||||
s[x - 1, y] = s[x, y]
|
||||
s[x, y] = tmp
|
||||
news = State(s, directionFlag='down', parent=self)
|
||||
news.setF(news.getFunctionValue())
|
||||
subStates.append(news)
|
||||
|
||||
# 向下移动
|
||||
if 'down' in self.direction and x < boarder:
|
||||
s = self.state.copy()
|
||||
tmp = s[x + 1, y]
|
||||
s[x + 1, y] = s[x, y]
|
||||
s[x, y] = tmp
|
||||
news = State(s, directionFlag='up', parent=self)
|
||||
news.setF(news.getFunctionValue())
|
||||
subStates.append(news)
|
||||
|
||||
# 向右移动
|
||||
if 'right' in self.direction and y < boarder:
|
||||
s = self.state.copy()
|
||||
tmp = s[x, y + 1]
|
||||
s[x, y + 1] = s[x, y]
|
||||
s[x, y] = tmp
|
||||
news = State(s, directionFlag='left', parent=self)
|
||||
news.setF(news.getFunctionValue())
|
||||
subStates.append(news)
|
||||
|
||||
# 返回F值最小的下一个点
|
||||
subStates.sort(key=compareNum)
|
||||
return subStates[0]
|
||||
|
||||
# A* 迭代
|
||||
def solve(self):
|
||||
"""执行A*算法求解路径
|
||||
Returns:
|
||||
list: 从初始状态到目标状态的路径节点列表
|
||||
"""
|
||||
# openList(待访问节点列表)
|
||||
openTable = []
|
||||
# closeList(已访问节点列表)
|
||||
closeTable = []
|
||||
openTable.append(self) # 初始节点加入open表
|
||||
|
||||
while len(openTable) > 0: # 当存在待访问节点时
|
||||
# 取出评估值最小的节点
|
||||
n = openTable.pop(0)
|
||||
# 加入已访问列表
|
||||
closeTable.append(n)
|
||||
# 生成子节点
|
||||
subStates = n.nextStep()
|
||||
path = []
|
||||
|
||||
# 判断是否到达目标状态
|
||||
if (subStates.state == subStates.answer).all():
|
||||
# 回溯路径
|
||||
while subStates.parent and subStates.parent != originState:
|
||||
path.append(subStates.parent)
|
||||
subStates = subStates.parent
|
||||
path.reverse() # 反转得到正序路径
|
||||
return path
|
||||
|
||||
# 将子节点加入open表
|
||||
openTable.append(subStates)
|
||||
else:
|
||||
return None, None
|
||||
|
||||
def compareNum(state):
|
||||
"""状态比较函数(用于排序)"""
|
||||
return state.f
|
||||
|
||||
if __name__ == '__main__':
|
||||
# 初始化起始状态(0代表空格)
|
||||
originState = State(np.array([[1, 5, 3], [2, 4, 6], [7, 0, 8]]))
|
||||
# 设置类属性:目标状态
|
||||
State.answer = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 0]])
|
||||
|
||||
# 创建初始状态对象
|
||||
s1 = State(state=originState.state)
|
||||
# 求解路径
|
||||
path = s1.solve()
|
||||
|
||||
# 输出结果
|
||||
if path:
|
||||
print("解决方案路径:")
|
||||
for node in path:
|
||||
node.showInfo()
|
||||
print("目标状态:")
|
||||
print(State.answer)
|
||||
print("总步数:%d" % len(path))
|
||||
|
||||
Reference in New Issue
Block a user