diff --git a/_sources/games/arknights/index.rst.txt b/_sources/games/arknights/index.rst.txt index 9a2d28d..5002606 100644 --- a/_sources/games/arknights/index.rst.txt +++ b/_sources/games/arknights/index.rst.txt @@ -1,7 +1,228 @@ -明日方舟 +.. _arknights_gacha_model: + +明日方舟抽卡模型 ======================== -.. toctree:: - :maxdepth: 1 - :caption: 目录 - gacha_models \ No newline at end of file +GGanalysis 使用基本的抽卡模板模型结合 `明日方舟抽卡系统参数 `_ 定义了一系列可以直接取用的抽卡模型。需要注意的是明日方舟的抽卡系统模型的确定程度并没有很高,使用时需要注意。 + +此外,还针对性编写了如下模板模型: + + 适用于计算 `定向选调 `_ 时获得特定UP六星干员的模型 + :class:`~GGanalysis.games.arknights.AKDirectionalModel` + + 适用于计算通过 `统计数据 `_ 发现的类型硬保底的模型 + :class:`~GGanalysis.games.arknights.AKHardPityModel` + + 适用于计算集齐多种六星的模型(不考虑300井、定向选调及类型硬保底机制) + :class:`~GGanalysis.games.arknights.AK_Limit_Model` + +.. 本节部分内容自一个资深的烧饼编写文档修改而来,MilkWind 增写内容 + +参数意义 +------------------------ + + - ``item_num`` 需求道具个数,由于 sphinx autodoc 的 `bug `_ 在下面没有显示 + + - ``multi_dist`` 是否以列表返回获取 1-item_num 个道具的所有分布列,默认为False + + - ``item_pity`` 道具保底状态,通俗的叫法为水位、垫抽,默认为0 + + - ``type_pity`` 定向选调的类型保底状态,默认为0,即该机制尚未开始触发;若为其它数,如20,那么就意味着定向选调机制已经垫了20抽,还有130抽就位于该保底机制的触发范围了(算上偏移量,实际为131抽) + + - ``calc_pull`` 采用伯努利模型时最高计算的抽数,高于此不计算(仅五星采用伯努利模型) + +六星模型 +------------------------ + +**获取任意六星干员** + +.. automethod:: GGanalysis.games.arknights.gacha_model.common_6star + +.. code:: python + + import GGanalysis.games.arknights as AK + dist = AK.common_6star(item_num=1) + print('抽到六星的期望抽数为:{}'.format(dist.exp)) # 34.59455493520977 + +**无定向选调获取标准寻访-单UP六星干员** + +.. automethod:: GGanalysis.games.arknights.gacha_model.single_up_6star_old + +**有定向选调获取标准寻访-单UP六星干员** + +.. automethod:: GGanalysis.games.arknights.gacha_model.single_up_6star + +.. code:: python + + import GGanalysis.games.arknights as AK + dist = AK.single_up_6star(item_num=1, item_pity=0, type_pity=0) + print('4.6寻访机制更新后,无水位时抽到单up六星的期望抽数为:{}'.format(dist.exp)) + +.. container:: output stream stdout + + :: + + 4.6寻访机制更新后,无水位时抽到单up六星的期望抽数为:66.16056206529494 + +**无类型硬保底轮换池获取特定六星干员** + +.. automethod:: GGanalysis.games.arknights.gacha_model.dual_up_specific_6star_old + +**有类型硬保底时轮换池获取特定六星干员** + +.. automethod:: GGanalysis.games.arknights.gacha_model.dual_up_specific_6star + +.. code:: python + + import GGanalysis.games.arknights as AK + dist = AK.dual_up_specific_6star(item_num=1) + print('准备100抽,从轮换池捞出玛恩纳的概率只有:{}%'.format(sum(dist[:100+1]) * 100)) + +.. container:: output stream stdout + + :: + + 准备100抽,从轮换池捞出玛恩纳的概率只有:49.60442859476116% + +**双UP限定池获取特定六星干员** + +.. automethod:: GGanalysis.games.arknights.gacha_model.limited_up_6star + + + 需要注意的是,此模型返回的结果是不考虑井的分布。如需考虑井需要自行进行一定后处理。 + + +.. code:: python + + import GGanalysis.games.arknights as AK + dist = AK.limited_up_6star(item_num=5) + print('一井满潜限定的概率:{}%'.format(sum(dist_4[:300+1]) * 100)) + +.. container:: output stream stdout + + :: + + 一井满潜限定的概率:14.881994954229667% + +**双UP限定池集齐两种UP六星干员** + +.. automethod:: GGanalysis.games.arknights.gacha_model.limited_both_up_6star + +.. code:: python + + import GGanalysis.games.arknights as AK + dist = AK.limited_both_up_6star() + print('全六党吃井概率:{}%'.format((1-sum(dist[:300+1])) * 100)) + +.. container:: output stream stdout + + :: + + 全六党吃井概率:7.130522684168872% + +五星模型 +------------------------ + +.. attention:: + + 明日方舟五星干员实际上有概率递增的星级保底机制,但其保底进度会被六星重置。这里对五星模型采用了近似,认为其是一个概率为考虑了概率递增的伯努利模型。另外,此处提供的五星模型也没有考虑类型保底。 + + 此外明日方舟五星模型没有采用 :class:`~GGanalysis.BernoulliLayer` 构建模型,而是直接采用了 :class:`~GGanalysis.BernoulliGachaModel` ,当设置 ``calc_pull`` 太低时,返回的分布概率和可能距离 1 有相当大差距,需要适当设高。 + +**获取任意五星干员** + +.. automethod:: GGanalysis.games.arknights.gacha_model.common_5star + +**获取单UP五星干员** + +.. automethod:: GGanalysis.games.arknights.gacha_model.single_up_specific_5star + +**获取双UP中特定五星干员** + +.. automethod:: GGanalysis.games.arknights.gacha_model.dual_up_specific_5star + +**获取三UP中特定五星干员** + +.. automethod:: GGanalysis.games.arknights.gacha_model.triple_up_specific_5star + + +自定义抽卡模型例子 +------------------------ + +.. attention:: + + ``AKDirectionalModel`` 可以为某个 ``FiniteDist`` 类型的,无保底类型的分布载入定向选调机制。 + + ``AKHardPityModel`` 可以为某个 ``FiniteDist`` 类型的,无保底类型的分布载入类型硬保底机制。 + + ``AK_Limit_Model`` 未加入新增的定向选调机制,其使用的 `CouponCollectorLayer` 不考虑集齐多套的需求。这个模型接下来可能重写,如果想要在其他地方引用的话可以先临时复制代码出来本地使用,或是将 `AK_Limit_Model` 加入__all__公开列表进行调用。 + +**联合行动池集齐三种UP六星干员** + +.. code:: python + + import GGanalysis.games.arknights as AK + triple_up_specific_6star = AK.AK_Limit_Model(AK.PITY_6STAR, 1, total_item_types=3, collect_item=3) + dist = triple_up_specific_6star(item_pity=5) # (默认)期望集齐一轮,此前垫了5抽 + print('期望抽数为:{}'.format(dist.exp)) # 期望抽数为:188.63258247595024 + print('方差为:{}'.format(dist.var)) # 方差为:10416.175324956945 + print('100抽以内达成目标的概率为:{}%'.format(sum(dist[:100+1]) * 100)) # 100抽以内达成目标的概率为:16.390307170816875% + +**定向寻访池获取特定六星干员** + +.. code:: python + + import GGanalysis as gg + import GGanalysis.games.arknights as AK + # 六星100%概率,UP三个,故抽到目标UP六星的概率为1/3 + triple_up_specific_6star = gg.PityBernoulliModel(AK.PITY_6STAR, 1 / 3) # 尚未证实定向寻访是否存在类型硬保底机制,仅使用保底伯努利模型 + dist = triple_up_specific_6star(2) # 在定向寻访池期望抽到目标六星干员两次,此前没有垫抽 + print('期望抽数为:{}'.format(dist.exp)) # 期望抽数为:207.56732961125866 + +**双UP限定池获取特定权值提升的非UP六星干员** + + 非UP六星干员在六星中占比采用下式计算 + + .. math:: p = 0.3\frac{5}{5 * \text{secondary up number} + \text{others number}} + + 其中 ``secondary up number`` 为权值提升的非UP六星干员数量, ``others number`` 为除了主要UP干员和权值提升的非UP六星干员,其他准许获取的六星干员的数量。 + +.. code:: python + + import GGanalysis as gg + others = 71 # 假设除了主要UP干员和权值提升的非UP六星干员外,其他准许获取的六星干员的数量为71 + triple_second_up_specific_6star = gg.PityBernoulliModel(AK.PITY_6STAR, 0.3 / (5 * 3 + others) * 5) # 在当前卡池内,权值提升的非UP六星干员数量一般为3 + success_count = 3 # 期望抽到某个权值提升的非UP六星干员三次 + dist = triple_second_up_specific_6star(success_count, True) # `multi_dist` 为True表示以列表形式返回分布 + for i in range(1, success_count + 1): + print(f"抽到第{i}个目标干员~期望抽数:{round(dist[i].exp, 2)},方差:{round(dist[i].var, 2)}") # 结果保留两位小数 + + # 抽到第1个目标干员~期望抽数:1983.42,方差:3890458.19 + # 抽到第2个目标干员~期望抽数:3966.84,方差:7780916.38 + # 抽到第3个目标干员~期望抽数:5950.26,方差:11671374.57 + + # 不太建议计算非主要UP的干员的数据,分布会很长 + +**标准寻访-单UP池中集齐两种UP五星干员** + +.. code:: python + + import GGanalysis.games.arknights as AK + both_up_5star = AK.AK_Limit_Model(AK.PITY_5STAR, 0.5, total_item_types=2, collect_item=2) + dist = both_up_5star() # 期望在轮换单UP池中抽到两个UP的五星干员,此前没有垫抽 + print('期望抽数为:{}'.format(dist.exp)) # 期望抽数为:63.03402819816313 + +**自定义带有类型硬保底的模型** + +.. code:: python + + # 添加定向选调前已知存在类型硬保底的卡池为标准寻访中的单UP和双UP池,其它卡池暂无证据表明存在此机制,此处仅为演示如何定义此类模型,不能当做机制参考 + import GGanalysis as gg + import GGanalysis.games.arknights as AK + # 假设定向寻访池存在类型硬保底机制 + + # 六星100%概率,UP三个,故抽到目标UP六星的概率为1/3 + triple_up_specific_6star_without_hard_pity = gg.PityBernoulliModel(AK.PITY_6STAR, 1 / 3) # 没有硬保底 + triple_up_specific_6star_has_hard_pity = AK.AKHardPityModel(triple_up_specific_6star_without_hard_pity(1), AK.p2dist(AK.PITY_6STAR), type_pity_gap=200, item_types=3, up_rate=1, type_pull_shift=1) # 载入硬保底 + dist = triple_up_specific_6star_has_hard_pity(2) # 在定向寻访池期望抽到目标六星干员两次,此前没有垫抽 + print('期望抽数为:{}'.format(dist.exp)) # 期望抽数为:207.0218117279958 \ No newline at end of file diff --git a/_sources/games/azur_lane/index.rst.txt b/_sources/games/azur_lane/index.rst.txt index b226126..8adcee2 100644 --- a/_sources/games/azur_lane/index.rst.txt +++ b/_sources/games/azur_lane/index.rst.txt @@ -1,8 +1,57 @@ -碧蓝航线 +碧蓝航线抽卡模型 ======================== -.. toctree:: - :maxdepth: 1 - :caption: 目录 - gacha_models - \ No newline at end of file +.. attention:: + + GGanalysis 提供的预定义模型没有考虑 200 抽天井的情况,如需考虑此情况请参照此 :ref:`示例代码 ` 。 + 碧蓝航线的预定义抽卡模型按卡池 **彩 金 紫** 道具数量进行模型命名,例如1彩2金3紫模型命名为 ``model_1_2_3``,此例中预定义的彩、金、紫道具名称分别为 ``UR1`` ``SSR1`` ``SSR2`` ``SR1`` ``SR2`` ``SR3``。 + 使用时输入初始道具收集状态和目标道具收集状态,模型以 ``FiniteDist`` 类型返回所需抽数分布。 + +参数意义 +------------------------ + + - ``init_item`` 初始道具收集状态,一个包含了已经拥有哪些道具的字符串列表,由于 sphinx autodoc 的 `bug `_ 在下面没有显示 + + - ``target_item`` 目标道具收集状态,一个包含了目标要收集哪些道具的字符串列表 + +预定义模型 +------------------------ + +.. automethod:: GGanalysis.games.azur_lane.gacha_model.model_1_1_3 + +.. automethod:: GGanalysis.games.azur_lane.gacha_model.model_0_3_2 + +.. automethod:: GGanalysis.games.azur_lane.gacha_model.model_0_2_3 + +.. automethod:: GGanalysis.games.azur_lane.gacha_model.model_0_2_2 + +.. automethod:: GGanalysis.games.azur_lane.gacha_model.model_0_2_1 + +.. automethod:: GGanalysis.games.azur_lane.gacha_model.model_0_1_1 + +.. code:: python + + import GGanalysis.games.azur_lane as AL + # 碧蓝航线2金3紫卡池在已有1金0紫的情况下集齐剩余1金及特定2紫的情况 + dist = AL.model_0_2_3(init_item=['SSR1'], target_item=['SSR1', 'SSR2', 'SR1', 'SR2']) + print('期望为', dist.exp, '方差为', dist.var, '分布为', dist.dist) + +.. _azur_lane_hard_pity_example: + +处理天井示例代码 +------------------------ + +.. code:: python + + import GGanalysis as gg + import GGanalysis.games.azur_lane as AL + # 对于 1_1_3 带200天井的情况,需要单独处理 + dist_0 = AL.model_1_1_3(target_item=['UR1', 'SSR1']) # 未触发200天井时 + dist_1 = AL.model_1_1_3(target_item=['SSR1']) # 触发200天井时 + cdf_0 = gg.dist2cdf(dist_0) + cdf_1 = gg.dist2cdf(dist_1) + cdf_0 = cdf_0[:min(len(cdf_0), len(cdf_1))] + cdf_1 = cdf_1[:min(len(cdf_0), len(cdf_1))] + cdf_0[200:] = cdf_1[200:] + # 此时 cdf_0 就是含天井的累积概率密度函数 + diff --git a/_sources/introduction_to_gacha/basic_concepts.rst.txt b/_sources/introduction_to_gacha/basic_concepts.rst.txt new file mode 100644 index 0000000..43495c5 --- /dev/null +++ b/_sources/introduction_to_gacha/basic_concepts.rst.txt @@ -0,0 +1,3 @@ +基本概念约定 +======================== + diff --git a/_sources/introduction_to_gacha/foundations.rst.txt b/_sources/introduction_to_gacha/foundations.rst.txt new file mode 100644 index 0000000..1e64008 --- /dev/null +++ b/_sources/introduction_to_gacha/foundations.rst.txt @@ -0,0 +1,60 @@ +基本概念约定 +======================== + +简单抽卡模型 +------------------------ + +定义每次抽卡至多获得一个道具,每次获得道具所需抽数为独立同分布的随机变量 :math:`X` 抽卡模型为简单抽卡模型。 +如每次抽卡都是独立伯努利试验,固定概率为 :math:`P` 的抽卡模型是简单抽卡模型,其获得道具所需抽数分布为几何分布。 + +.. note:: + + 现实情况中很少出现一抽能同时获得多个道具的情况,将讨论局限于简单抽卡模型是有好处的。 + 如简单抽卡模型中,可以将所有当前条件概率的表述等价转化为当前获取道具所需抽数分布的形式,同理也可以反向转换。这样的性质可以为很多操作带来方便。 + +简单保底抽卡模型 +------------------------ + +如果一个简单抽卡模型获得道具所需抽数是具有 **有限支持** (finite support)的,即随机变量的概率分布在有限个值上的取值不为零,有限个值之外的所有其他值上,概率分布为零。将这种抽卡模型称为简单保底抽卡模型。 +常见带保底的抽卡模型大都可以归类为简单保底抽卡模型。例如原神获取五星物品的模型,每次获得五星物品所耗费抽数都是独立同分布的,并在有限抽内一定能获得五星物品。 + +简单保底抽卡模型的相关计算 +-------------------------- + +**符号约定** + +:math:`P_i` 表示在前 ``i-1`` 抽没有获得道具,第 ``i`` 抽获得道具的条件概率。 +:math:`P(X=i)` 表示获得一个道具时,恰好用了 ``i`` 抽的概率。或 :math:`X` 的分布律在 ``i`` 处的值。 + +**已知条件概率求抽数分布** + +易得 :math:`P(X=i)=P_i\prod_{n=1}^{i-1}{(1-P_n)}` + +**已知抽数分布求条件概率** + +易得 :math:`P_i=\frac{P(X=i)}{\sum_{n=i}^{n_{\text{max}}}{P(X=n)}}` + +.. note:: + + 易得,简单保底抽卡模型存在非零概率分布的最后一个位置对应条件概率为1,即保底位置一定能获得道具。 + +**获得多个道具时所需抽数分布** + +实际情况中也关心要获取多个道具时所需抽数的分布,即求获取第 ``1-n`` 个道具分布的叠加 :math:`X_{total}=X_1+X_2+...+X_n` 。 + +.. note:: + + 继续以原神五星的抽卡模型举例,已知抽一个五星道具所需的抽数分布,现在想知道如果连续抽。 + +说明一下问题,通俗举例,然后可以用随机变量相加解释。 +可以采用的方法有很多,模拟、转移矩阵、动态规划、卷积。 +先以获得两个道具的抽数分布举例 +:math:`P(X_{UP}=i)=0.5\cdot P(X_1=i)+0.5\cdot P(X_2=i)` + + +两类问题 +------------------------ + +一个是抽n个道具,需要花费抽数的分布 + +一个是投入k抽,能抽到道具个数的分布 \ No newline at end of file diff --git a/_sources/introduction_to_gacha/index.rst.txt b/_sources/introduction_to_gacha/index.rst.txt index 2bbab8c..af58b84 100644 --- a/_sources/introduction_to_gacha/index.rst.txt +++ b/_sources/introduction_to_gacha/index.rst.txt @@ -10,6 +10,7 @@ :maxdepth: 2 :caption: 目录 + foundations feedback_item_problem \ No newline at end of file diff --git a/_sources/start_using/custom_gacha_model.rst.txt b/_sources/start_using/custom_gacha_model.rst.txt index 2f9075e..2917f05 100644 --- a/_sources/start_using/custom_gacha_model.rst.txt +++ b/_sources/start_using/custom_gacha_model.rst.txt @@ -27,7 +27,7 @@ GGanalysis 中已经预定义好了结合保底抽卡模型和伯努利抽卡模 # 采用预定义的保底伯努利抽卡类 gacha_model = gg.PityBernoulliModel(pity_p, 1/5) # 根据定义的类计算从零开始获取一个道具的分布,由于可能永远获得不了道具,分布是截断的 - dist = gacha_model(item_num=1, pull_state=0) + dist = gacha_model(item_num=1, item_pity=0) 组合抽卡层自定义抽卡模型 ------------------------ @@ -54,5 +54,5 @@ GGanalysis 也支持更细粒度的定制抽卡模型。可以继承 :class:`~GG self.layers.append(gg.BernoulliLayer(p, e_error, max_dist_len)) # 根据自定义的类计算从零开始获取一个道具的分布,由于可能永远获得不了道具,分布是截断的 gacha_model = MyModel(pity_p, 1/5) - # 关于 pull_state 等条件输入,如有需要可以参考预置类中 __call__ 和 _build_parameter_list 的写法 + # 关于 item_pity 等条件输入,如有需要可以参考预置类中 __call__ 和 _build_parameter_list 的写法 dist = gacha_model(item_num=1) \ No newline at end of file diff --git a/_sources/start_using/use_predefined_model.rst.txt b/_sources/start_using/use_predefined_model.rst.txt index 5267b02..f80136c 100644 --- a/_sources/start_using/use_predefined_model.rst.txt +++ b/_sources/start_using/use_predefined_model.rst.txt @@ -11,7 +11,7 @@ # 导入预定义好的原神模块 import GGanalysis.games.genshin_impact as GI # 原神角色池的计算 - dist_c = GI.up_5star_character(item_num=3, pull_state=20, up_guarantee=1) + dist_c = GI.up_5star_character(item_num=3, item_pity=20, up_pity=1) print('期望为', dist_c.exp, '方差为', dist_c.var, '分布为', dist_c.dist) 以明日方舟为例说明如何使用预先定义好的抽卡模型。更多预定义模型可在 :ref:`明日方舟抽卡模型 ` 中查阅。 @@ -20,6 +20,6 @@ # 计算抽卡所需抽数分布律 以明日方舟为例 import GGanalysis.games.arknights as AK - # 普池双UP的计算 item_num是要抽多少个 pull_state是当前垫了多少抽,从零开始填0就行 - dist_c = AK.dual_up_specific_6star(item_num=3, pull_state=20) + # 普池双UP的计算 item_num是要抽多少个 item_pity是当前垫了多少抽,从零开始填0就行 + dist_c = AK.dual_up_specific_6star(item_num=3, item_pity=20) print('期望为', dist_c.exp, '方差为', dist_c.var, '分布为', dist_c.dist) diff --git a/games/arknights/index.html b/games/arknights/index.html index f6ec174..ca09e37 100644 --- a/games/arknights/index.html +++ b/games/arknights/index.html @@ -3,10 +3,10 @@ - + - 明日方舟 - GGanalysis + 明日方舟抽卡模型 - GGanalysis @@ -136,7 +136,7 @@ -