关于提高仿真效率同时减少Python中差异的建议

时间:2019-02-25 17:53:12

标签: python performance optimization simulation

我使用538的Riddler练习代码。用Python编写了一个简单的模拟,但是必须添加另一个嵌套循环来获取均值,以减少输出方差。试图运行它,但是在45分钟后我停止了它,认为必须要有一种方法来提高代码的效率。

就上下文而言,问题是:您有一台收音机,每天播放100首歌曲。播放同一首歌曲的概率必须等于50%。

我的方法是将播放列表的大小(从7000开始)增加1,直到重播的平均概率的总平均值等于50%,并且样本数量和样本数量均使用1000。

代码是:

import random

playlist = 7000
chance_of_replay = []
sample = 1000
mean_chance_of_replay = 0
replays = 0
temp_sum = 0

while mean_chance_of_replay > 0.5 or mean_chance_of_replay == 0.0:

    playlist += 1

    for j in range(0, sample):

        for i in range(1, sample + 1):

            songs_to_play = 100
            songs_played = []

            while songs_to_play > 0:

                song_pick = random.randint(1, playlist + 1)

                if song_pick not in songs_played:
                    songs_played.append(song_pick)
                    songs_to_play -= 1
                else:
                    replays += 1
                    break

        chance_of_replay.insert(j, (replays / sample))
        replays = 0

    for element in chance_of_replay:
        temp_sum = temp_sum + element

    mean_chance_of_replay = temp_sum/sample

print(playlist)

2 个答案:

答案 0 :(得分:0)

在查看代码中的性能问题之前,首先要解决一个更大的问题:代码处于无限循环中。

永远不会清除列表 chance_of_replay ,并且永远不会将变量 temp_sum 设置为0。因此,变量 mean_chance_of_replay 始终会增加并且您的代码将永远运行。

修复了这两个逻辑错误之后,您应该开始担心性能优化。

答案 1 :(得分:0)

播放列表大小增加时,播放同一首歌曲中的两首歌曲的机会降低。 您是否考虑过以7000的播放列表播放同一首歌曲的几率实际上低于50%?如果是这样,那么检查任何较高的值只会导致较小的百分比,因此您将永远找不到答案。

如果要进行仿真(与纯数学方法相反),我可以找到的主要优化是,多次执行数组插入和追加操作是相当大的性能杀手。我要做的是创建一个布尔值数组,用于存储是否已播放任何给定歌曲的状态。检查给定的歌曲是否已播放,并且不需要任何插入即可在幕后制作新阵列的操作要容易得多。

代码如下:

from random import randint

playlist_size = 1
samples = 1000

songs_per_sample = 100

simulation_running = True
while simulation_running:
    replays = 0

    for _ in range(samples):
        songs_played = [False] * playlist_size

        for song_sample in range(songs_per_sample):
            song_to_play_index = randint(0, playlist_size - 1)

            if songs_played[song_to_play_index]:
                replays += 1

            songs_played[song_to_play_index] = True

    replay_chance = replays / (samples * songs_per_sample)

    if replay_chance <= 0.5:
        break

    playlist_size += 1

print(playlist_size)

运行此命令实际上给出了一个令人惊讶的答案,即低于7000!