遗憾配比算法-石头剪刀布的猜拳游戏
根据博弈问题的遗憾配比算法写的石头剪刀布的猜拳游戏python程序
以下是对代码逐行的解释:
import numpy as np
import pandas as pd引入必要的库:numpy和pandas
class RPS:
actions = ['ROCK', 'PAPER', 'SCISSORS']
n_actions = 3
utilities = pd.DataFrame([
# 石头 布 剪刀
[ 0, -1, 1], # 石头
[ 1, 0, -1], # 布
[-1, 1, 0] # 剪刀
], columns=actions, index=actions)定义了一个包含石头剪刀布游戏相关信息的类RPS,其中包括可选动作列表(actions)、动作数量(n_actions)和效用矩阵(utilities)。效用矩阵记录了每个参与者采取不同动作所获得的收益。例如,如果第一个参与者选择了「石头」,而第二个参与者选择了「剪刀」,那么第一个参与者会获得1的收益,而第二个参与者会获得-1的收益。
class Player:
def __init__(self, name):
self.strategy, self.avg_strategy,\
self.strategy_sum, self.regret_sum = np.zeros((4, RPS.n_actions))
self.name = name
def __repr__(self):
return self.name定义了一个参与者类Player,其中包括策略向量(strategy)、平均策略向量(avg_strategy)、策略向量总和(strategy_sum)和遗憾值向量(regret_sum)。在初始化时,所有向量都设置为全0。
def update_strategy(self):
# 将选择行动的偏好(策略)设置为正遗憾值的比例
# 例如,更倾向于选择「布」(Paper)的策略是[0.2, 0.6, 0.2]
self.strategy = np.copy(self.regret_sum)
self.strategy[self.strategy < 0] = 0 # 将遗憾值中的负值归零
summation = sum(self.strategy)
if summation > 0:
# 进行规范化
self.strategy /= summation
else:
# 是使用均匀分布来减少被利用的可能性
self.strategy = np.repeat(1 / RPS.n_actions, RPS.n_actions)
self.strategy_sum += self.strategy定义了一个方法update_strategy(),用于更新参与者的策略向量。该方法将策略向量设置为正遗憾值的比例,并进行规范化。如果所有遗憾值都是非正数,则使用均匀分布来减少被利用的可能性。最后,更新策略向量总和。
def regret(self, my_action, opp_action):
# 我们定义没有选择某个行动的遗憾值为该行动效用值与实际选择行动的效用值之间的差异(相对于其他参与者选择固定的行动而言)。
# 在博弈论中,遗憾值是一种测量策略表现的指标,它可以被看作是选择当前最优策略所带来的错失收益。
# 因此,当我们执行一个行动后,可以计算出每个可能行动的遗憾值,并将其加到遗憾值的总和中,以便在下一次迭代中更新策略
result = RPS.utilities.loc[my_action, opp_action]
facts = RPS.utilities.loc[:, opp_action].values
regret = facts - result
self.regret_sum += regret定义了一个方法regret(),用于计算遗憾值。遗憾值是指没有选择某个行动的效用值与实际选择行动的效用值之间的差异。为了计算遗憾值,需要传入自己的行动(my_action)和对手的行动(opp_action)。根据效用矩阵可以计算出每个可能行动的效用值,并将其减去实际选择的行动的效用值,得到每个可能行动的遗憾值。然后将所有遗憾值加到遗憾值总和(regret_sum)中,以便在下一次迭代中更新策略。
def action(self, use_avg=False):
# 根据策略概率选择一个动作
strategy = self.avg_strategy if use_avg else self.strategy
return np.random.choice(RPS.actions, p=strategy)定义了一个方法action(),用于根据参与者的策略概率选择一个动作。如果use_avg参数为True,则使用平均策略向量。最后,使用numpy的random.choice()函数从可选动作列表中选择一个动作,根据策略概率进行加权。
def learn_avg_strategy(self):
# 平均策略会收敛到纳什均衡(Nash Equilibrium)
summation = sum(self.strategy_sum)
if summation > 0:
self.avg_strategy = self.strategy_sum / summation
else:
self.avg_strategy = np.repeat(1/RPS.n_actions, RPS.n_actions)定义了一个方法learn_avg_strategy(),用于学习平均策略向量。该方法将参与者的平均策略向量设置为所有策略向量的加权平均值,并进行规范化。如果所有策略向量总和为0,则使用均匀分布。
class Game:
def __init__(self, max_game=10000):
self.p1 = Player('Tom')
self.p2 = Player('Pater')
self.max_game = max_game
def winner(self, a1, a2):
result = RPS.utilities.loc[a1, a2]
if result == 1: return self.p1
elif result == -1: return self.p2
else: return 'Draw'定义了一个游戏类Game,其中包括两个参与者(p1和p2)和最大游戏次数(max_game)。还定义了一个方法winner(),用于根据两个参与者选择的行动计算胜利者。如果第一个参与者获胜,则返回p1;如果第二个参与者获胜,则返回p2;否则返回字符“Draw”。
def play(self, avg_regret_matching=False):
def play_regret_matching():
for i in range(0, self.max_game):
self.p1.update_strategy()
self.p2.update_strategy()
a1 = self.p1.action()
a2 = self.p2.action()
self.p1.regret(a1, a2)
self.p2.regret(a2, a1)
winner = self.winner(a1, a2)
num_wins[winner] += 1
def play_avg_regret_matching():
for i in range(0, self.max_game):
a1 = self.p1.action(use_avg=True)
a2 = self.p2.action(use_avg=True)
winner = self.winner(a1, a2)
num_wins[winner] += 1
num_wins = {
self.p1: 0,
self.p2: 0,
'Draw': 0
}
play_regret_matching() if not avg_regret_matching else play_avg_regret_matching()
print(num_wins)定义了一个方法play(),用于进行游戏。如果avg_regret_matching参数为False,则使用简单的遗憾匹配算法;否则使用平均后悔匹配算法。在每次游戏中,参与者会更新自己的策略向量,并根据所选动作计算遗憾值。然后,根据两个参与者选择的行动计算胜利者,并将胜利者的数量加到num_wins字典中。最后打印出胜利者的数量。
if __name__ == '__main__':
game = Game()
print('使用简单的遗憾匹配算法')
game.play()
print('使用平均后悔遗憾匹配算法')
game.conclude()
game.play(avg_regret_matching=True)调用函数,输出结果

评论已关闭 >_<