Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 极小极大逻辑工作缓慢_Python_Cs50 - Fatal编程技术网

Python 极小极大逻辑工作缓慢

Python 极小极大逻辑工作缓慢,python,cs50,Python,Cs50,在参加哈佛大学的CS-50课程后,我正在使用带有alpha-beta修剪的minimax算法编程Tic-Tac-Toe。 我的逻辑是完美的,除了minimax的返回时间(特别是在第一次呼叫时,只有一个玩家在玩)。我正在考虑将minimax的额外递归调用替换为max/min值。我想强调的是,对于我来说,minimax的速度相对较慢(大约0.5秒) 导入数学 导入副本 导入时间 X=“X” O=“O” 空=无 def初始_状态(): """ 返回板的开始状态。 """ return[[EMPTY,E

在参加哈佛大学的CS-50课程后,我正在使用带有alpha-beta修剪的minimax算法编程Tic-Tac-Toe。 我的逻辑是完美的,除了minimax的返回时间(特别是在第一次呼叫时,只有一个玩家在玩)。我正在考虑将minimax的额外递归调用替换为max/min值。我想强调的是,对于我来说,minimax的速度相对较慢(大约0.5秒)

导入数学
导入副本
导入时间
X=“X”
O=“O”
空=无
def初始_状态():
"""
返回板的开始状态。
"""
return[[EMPTY,EMPTY,EMPTY],
[空,空,空],
[空,空,空]]
def播放器(板):
"""
返回棋盘上下一回合的玩家。
"""
如果电路板==初始状态():
返回X
X_计数器=0
O_计数器=0
对于板中的行:
对于行中的单元格:
如果单元格==X:
X_计数器+=1
elif单元==O:
O_计数器+=1
如果X_计数器>O_计数器,则返回O,否则返回X
def行动(委员会):
"""
返回板上可用的所有可能操作(i,j)的集合。
"""
可能的移动=设置()
对于范围(3)中的i:
对于范围(3)内的j:
如果董事会[i][j]为无:
可能的移动。添加((i,j))
返回可能的移动
def结果(董事会、行动):
"""
返回在板上移动(i,j)所产生的板。
"""
新板=复制。深度复制(板)
新手板[动作[0]][动作[1]]=玩家(棋盘)
返回新船
def优胜者(董事会):
"""
返回游戏的赢家(如果有)。
"""
如果板[0][0]==板[0][1]==板[0][2]!=无:#1、2、3
返回板[0][0]
如果板[1][0]==板[1][1]==板[1][2]!=无:#4、5、6
返回板[1][0]
如果板[2][0]==板[2][1]==板[2][2]!=无:#7、8、9
返回板[2][0]
如果板[0][0]==板[1][0]==板[2][0]!=无:#1、4、7
返回板[0][0]
如果板[0][1]==板[1][1]==板[2][1]!=无:#2、5、8
返回板[0][1]
如果板[0][2]==板[1][2]==板[2][2]!=无:#3、6、9
返回板[0][2]
如果板[0][0]==板[1][1]==板[2][2]!=无:#1、4、7
返回板[0][0]
如果板[0][2]==板[1][1]==板[2][0]!=无:#3、5、7
返回板[0][2]
一无所获
def终端(板):
"""
如果游戏结束,则返回True,否则返回False。
"""
def检查图(电路板):
对于板中的行:
对于行中的单元格:
如果单元格为无:
返回错误
返回真值
如果获胜者(棋盘)不是无或勾选抽签(棋盘):#或有人赢了,或有抽签
返回真值
返回错误
def实用程序(板):
"""
如果X赢了游戏,则返回1;如果O赢了,则返回1;否则返回0。
"""
临时=优胜者(董事会)
如果温度==X:
返回1
elif温度==O:
返回-1
返回0
def minimax(电路板):
"""
返回棋盘上当前玩家的最佳动作。
"""
选项=操作(板)
如果玩家(棋盘)=X:
vT=-math.inf
move=set()
关于选项中的操作:
v、 count=minvalue(结果(电路板,动作),-math.inf,math.inf,0)
如果v>vT:
vT=v
移动=动作
其他:
vT=math.inf
move=set()
关于选项中的操作:
v、 count=maxvalue(结果(板,动作),-math.inf,math.inf,0)
如果vβ:
打破
返回v,计数+1
def最小值(电路板、alpha、beta、计数):
"""
递归计算给定电路板的最小值和最大值
"""
如果终端(板):返回实用程序(板),计数+1
v=math.inf
posactions=操作(板)
对于posactions中的操作:
vret,count=maxvalue(结果(板、动作)、alpha、beta、count)
v=最小值(v,vret)
β=最小值(v,β)
如果α>β:
打破
返回v,计数+1
而不是:

def player(board):
    """
    Returns player who has the next turn on a board.
    """
    if board == initial_state():
        return X
    X_counter = 0
    O_counter = 0
    for row in board:
        for cell in row:
            if cell == X:
                X_counter += 1
            elif cell == O:
                O_counter += 1
    return O if X_counter > O_counter else X
您可以通过以下方式获得什么样的性能:

def player(board):
    """
    Returns player who has the next turn on a board.
    """
    counts = collections.Counter(cell for row in board for cell in row if cell)
    return O if counts.get(X, 0) > counts.get(O, 0) else X
一个问题可能会出现,为什么提高球员的表现可能会有很大的不同

为了计算第一步,我计算了每个方法被调用的次数:

[('winner', 53673), ('player', 30442), ('result', 30441), ('terminal', 30441), ('utility', 23232), ('maxvalue', 16248), ('actions', 14419), ('minvalue', 14193), ('minimax', 1)]
我们可以看到,
player()
经常被调用。下一个候选对象显然是
winner()
,因为它比
player()
调用得更频繁。我们可以观察到,
winner()
仅由
terminal()
utility()
调用。此外,我们可以观察到,
terminal()
utility()
只能一起调用,如下所示:

if terminal(board): return utility(board), count+1
那么,让我们看看我们是否可以做些什么来组合它们

那么:

def terminal(board):
    """
    Returns True if game is over, False otherwise.
    """
    is_winner = winner(board)

    if is_winner == X:
        return 1

    if is_winner == O:
        return -1

    if not actions(board):
        return 0

    return None
我们可以像这样使用它:

who_wins = terminal(board)
if who_wins is not None: return who_wins, count+1
这可以减轻
winner()的压力。

这比已经缩短的时间减少了25%


在我的系统上,原始代码(平均)第一步需要2.5秒。通过这些简单的更新,相同的推荐移动平均在0.001秒内生成。

与其执行
EMPTY=None
,不如只执行
None
?哦,这样就有了样板代码了?你能指出哪些零件是给你的,哪些零件是你手上的吗?有几点效率低下
who_wins = terminal(board)
if who_wins is not None: return who_wins, count+1
[('player', 30442), ('result', 30441), ('terminal', 30441), ('winner', 30441), ('maxvalue', 16248), ('actions', 14419), ('minvalue', 14193), ('minimax', 1)]