聚类的实现参考这篇论文。
Potential-Aware Imperfect-Recall Abstraction with Earth Mover’s Distance in
Imperfect-Information Games
首先我们思考一下如何判断一手牌的强弱,如果我们将一套牌和随机对手1326套牌进行对抗,存下他的胜率,平率,输率 ,最后进行kmean聚类就可以获得牌的强弱。但是这样存在几个问题,比如我在转牌公牌 Ac Td 9c 5s 手牌是2c 3c 只要河牌发出c花色我就可以变成超强牌,如果发不出我啥都没有,根据德州扑克4/2法则,河牌大概还有9*2=18%的概率能发出c。
,如果只按胜率计算,这类牌的胜率为18%,而德州扑克中这种牌是最适合诈唬的牌。
论文中阐述的算法是先用胜率对河牌的牌进行聚类,然后计算转牌的每一套牌到河牌的不同类的概率分布,这种概率分布不能使用欧氏距离,需要使用emd距离。左边是potential-aware的算法原理,右边是一个计算emd距离的近似加速的原理。
Wasserstein距离也被描述为推土距离(EMD)。如果我们将分布想象为两个有一定存土量的土堆,那么EMD就是将一个土堆 转换 为另一个土堆所需的最小总工作量。工作量的定义是 单位泥土 的总量乘以它移动的距离。下图是转换第一个概率到第二个概率的方式,注意颜色变化。
河牌的聚类最简单,计算对手1326套牌多少套大于你就行。
转牌的聚类和翻牌圈的聚类存在一些区别,先介绍转牌河牌聚类我们直接使用的胜率,河牌聚类类和类之间的距离是计算好的,比如0类比1326类多强了1326套。
下图是标准的kmeans算法 关注calc_nearest_cluster_idx这个函数,他传入了每套牌的到河牌的概率分布,和每个聚类的中心,返回最近的聚类中心的id
关注calc_thist_mhist_dist_opt这个函数,这个函数是用贪心法计算emd的近似加速函数。
Total_dist保存距离。我们是将聚类中心的概率分布向当前这套牌的概率分布挪动,
const std::vector<int32_t> &turn_histogram,
const std::vector<std::pair<int32_t, double>> &mean_histogram,
这两个代码格式不同,第一个是转牌发到河牌发出47种不同河牌聚类的id,第二个是聚类中心累计的概率。
算法首先判断remaining_t是否大于聚类中心剩下的距离,如果大于则把remaining_m剩下的都挪到t中,如果remaining_t比remaining_m小,则当前这个target完成,将k ++开始挪动下一个id。
abs(turn_histogram[k] - itr->first)是挪动需要的距离。