计算在多个彩票中达到目标金额的概率



如果我有不同奖金大小和不同中奖几率的不同彩票,如果我同时只玩一次彩票,我如何计算至少赢得给定金额的概率?

  • 彩票A: 50%的机会赢得5金。
  • 彩票B: 40%的机会赢得6金。
  • 彩票C: 30%的机会赢得7金。

如果我同时玩所有彩票,是否有一种方法可以计算我赢得至少给定值(如10金)的概率?理想情况下,我希望它能够为一组大约40张彩票工作。

输入将是一个包含概率和奖励大小的元组列表,如:

lottery_list = [(0.5, 5), (0.4, 6), (0.3, 7)]

然后是一个函数来计算赢得至少一个目标值的概率,比如在这个例子中是10金:

prob = win_at_least(lottery_list, target_val=10)

最后我自己创造了一个解决方案。这段代码忽略了不相关的组合,即如果一组给定的彩票已经产生了目标值,则所有"下游"彩票的组合。40张彩票大约需要10毫秒,并且似乎可以很好地扩展。

import numpy as np
import pandas as pd

def multi_lottery(lottery_list: list, target: float) -> float:
"""
This function calculates the odds of winning at least the target
value from a list of lotteries, where each lottery has a
different probability of winning and a different value.
Args:
lottery_list (list): A list of tuples with lottery
probabilities and values.
target (float): The target value.
Returns:
float: The odds of winning at least target value.
"""
# Create a pandas dataframe with the lottery list.
df = pd.DataFrame(lottery_list, columns=["probability", "value"])
# Sort the dataframe by descending value.
df_sorted = df.sort_values("value", ascending=False, ignore_index=True)
probs = df_sorted["probability"].values
values = df_sorted["value"].values
# Create a mask equal to the length of the lottery list.
# This will be used to determine which lotteries are included in
# each combination.
length = len(df_sorted)
mask = np.ones(length, dtype=int)
# Start with odds of losing at 1.
total_odds = 0
while True:
# Go through the lottery list using the mask to determine if
# each lottery is won, and add the values together until the target
# value is reached.
odds = 1
value = 0
for idx, prob in enumerate(probs):
# Include the winning chance if the binary number is 1.
if mask[idx] == 1:
odds *= prob
value += values[idx]
# Else include the losing chance.
else:
odds *= 1 - prob
# If the target value is reached, all subsequent lotteries
# are ignored and the odds are added to the total.
if value >= target:
# Update the anti-odds.
total_odds += odds
# Update the mask by setting the current lottery to zero.
mask[idx] = 0
break
# Else if the last lottery is reached, update the mask by
# setting the largest active lottery to zero and all smaller lotteries to one.
elif idx == length - 1:
largest_active_idx = 0
for i, v in enumerate(mask):
if v == 1:
largest_active_idx = i
mask[largest_active_idx] = 0
mask[largest_active_idx + 1 :] = 1
# Check if the mask is all zeros. If so, break the loop.
if np.sum(mask) == 0:
break
return total_odds

最新更新