Home > Net >  I do not know why my simulation is so slow. I need to optimize my simulation and improve the way I u
I do not know why my simulation is so slow. I need to optimize my simulation and improve the way I u

Time:09-25

This is a python program that does some sort of simulation,, I am looking for any type of optimization while keeping the same p[i] form, I have tried Pypy and I got an around 3x performance gain over python. Any suggestions are welcomed

import random
from time import perf_counter
infected, non_infected = 1, 99999
infectation_chance, infection_days, death_chance = 1/100, 2/1000, 2/100
population, population_list = infected   non_infected, non_infected * [0]   infected * [1]
place = 10
p = {i: [] for i in range(1,place   1)}
day = 1
simulation_duration = 3
while 0 < simulation_duration:
    print(f"Working on day {day}..")
    time1 = perf_counter()
    for person in population_list:
        p[random.randint(1, place)].append(person)
    time2 = perf_counter()
    i = 0
    while i < place:
        tl = []
        i  = 1
        for crowd in p[i]:
            if crowd == 0:
                 if (random.random() < infectation_chance * str(p[i]).count("1")) - (infectation_chance/100 * str(p[i]).count("0")):
                     tl.append(1)
                 else:
                    tl.append(0)
            if crowd == 1:
                tl.append(1)
        p[i] = tl

    i = 0
    population_list = []
    while i < place:
        i  = 1
        population_list.append(p[i])
    simulation_duration -= 1
    day  = 1
    print(f"Total time: {perf_counter() - time1} \nInfection time: {perf_counter() - time2} \nPlacing time: {time2-time1}")
print(str(population_list).count("1"), str(population_list).count("0"))

CodePudding user response:

here is a corrected version in pure python, commented because there were some bugs. your major time loss was counting infected/non-infected inside the for loop, though the result is always the same. it could be optimized again with numpy if you wanna use a bigger population

import random
from time import perf_counter
infected, non_infected = 1, 99999
infectation_chance, infection_days, death_chance = 1/100, 2/1000, 2/100
population, population_list = infected   non_infected, non_infected * [0]   infected * [1]
place = 10
day = 1
simulation_duration = 3
while 0 < simulation_duration:
    # p must be reset here or it will grow indefinitely
    p = {i: [] for i in range(1,place   1)}
    print(f"Working on day {day}..")
    time1 = perf_counter()
    for person in population_list:
        p[random.randint(1, place)].append(person)
    time2 = perf_counter()
    i = 0
    while i < place:
        i  = 1
        # if you need to, count infected/non-infected here
        # not in your for loop where it has always the same value
        # and don't cast to str, what's the point?
        # pi_infected = p[i].count(1)
        # pi_sane = p[i].count(0)
        for j, crowd in enumerate(p[i]):
            if crowd == 0:
                # your formula was broken (a-b is always true)
                # i used a generic one
                if random.random()>(1-infectation_chance):
                    # change your list in place:
                    # no need for temp list, save lots of cycles
                    p[i][j] = 1

    i = 0
    population_list = []
    while i < place:
        i  = 1
        # it's extend, not append here or your population list
        # will have a length of #place
        population_list.extend(p[i])
    simulation_duration -= 1
    day  = 1
    print(f"Total time: {perf_counter() - time1} \nInfection time: {perf_counter() - time2} \nPlacing time: {time2-time1}")
print(population_list.count(1), population_list.count(0))
  • Related