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"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings" defaultProject="true" />
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||||
|
</component>
|
||||||
</project>
|
</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