Generates a simulation. There are 3 ads to choose from of different lenghts (10s, 15s, 20s). Start by importing simpy and random. Simpy is used to set up the simulation and random is mainly for picking a random ad to watch.
import simpy
import random
This will run our simulation. Each new audience person will have to wait (technically) until the room for each advertisement is vacant. I actually set the arrival time far enough apart so that they shouldn't have to wait, but don't quote me. Each advertisement can only be watched by 1 person at a time. As each person watches an ad, we'll keep track of when they started watching and keep track of how many people watched each ad.
def ad_simulation(env, ad_picked):
global num_audience_ad1
global num_audience_ad2
global num_audience_ad3
global times_watched_ad1
global times_watched_ad2
global times_watched_ad3
if ad_picked == ad1:
with ad1.request() as req:
yield req
times_watched_ad1.append(env.now)
num_audience_ad1 += 1
yield env.timeout(10)
elif ad_picked == ad2:
with ad2.request() as req:
yield req
times_watched_ad2.append(env.now)
num_audience_ad2 += 1
yield env.timeout(15)
elif ad_picked == ad3:
with ad3.request() as req:
yield req
times_watched_ad3.append(env.now)
num_audience_ad3 += 1
yield env.timeout(20)
It was easier just to make randomly picking as ad its own function.
def pick_ad(env, ad):
ad_picked = random.choice(ad)
return ad_picked
Generates a new person coming in at a lambda of (1/5) or one person every 5 seconds averagely. After the person arrives, they pick an ad to watch and go to that line.
def audience_arrival(env):
while True:
yield env.timeout(random.expovariate(1/5))
env.process(ad_simulation(env, pick_ad(env, ad)))
Set up environment, specify that each ad is a resource and only has a capacity of 1 person at a time, prepare the metrics you want the simulation to update and then run it. I opted to use global variables here as there was nothing that needed to be local and also saved me a lot of code to type.
env = simpy.Environment()
ad1 = simpy.Resource(env, 1)
ad2 = simpy.Resource(env, 1)
ad3 = simpy.Resource(env, 1)
ad = [ad1, ad2, ad3]
num_audience_ad1 = 0
num_audience_ad2 = 0
num_audience_ad3 = 0
times_watched_ad1 =[]
times_watched_ad2 =[]
times_watched_ad3 =[]
#<Process(car) object at 0x...>
env.process(audience_arrival(env))
env.run(until=120)
I wanted to testhow "likable" my scenario was. AKA what's the average time from the previous audience of the ad to the next. In an ideal world, you'd want after one person leaves the next goes right in so if the ad time was 10s and the average distance should be 10s as well. If it's longer, the event just wasn't popular or you have too many resources or there was that one ad that people were like "nah" (although in this case I made each ad equally likely to get picked).
avg_ad1=0
total_distance_ad1 = 0
for i in range(len(times_watched_ad1)):
if(i+1 < len(times_watched_ad1)):
total_distance_ad1 += (times_watched_ad1[i+1]-times_watched_ad1[i])
#avg=sum(avg_ad1)/len(avg(ad1))
avg_ad1 = total_distance_ad1/(len(times_watched_ad1)-1)
avg_ad2=0
total_distance_ad2 = 0
for i in range(len(times_watched_ad2)):
if(i+1 < len(times_watched_ad2)):
total_distance_ad2 += (times_watched_ad2[i+1]-times_watched_ad2[i])
#avg=sum(avg_ad1)/len(avg(ad1))
avg_ad2 = total_distance_ad2/(len(times_watched_ad2)-1)
avg_ad3=0
total_distance_ad3 = 0
for i in range(len(times_watched_ad3)):
if(i+1 < len(times_watched_ad3)):
total_distance_ad3 += (times_watched_ad3[i+1]-times_watched_ad3[i])
#avg=sum(avg_ad1)/len(avg(ad1))
avg_ad3 = total_distance_ad3/(len(times_watched_ad3)-1)
Finally, print out the results. The below is the only information I cared about: average time between audience per ad, total audiences for each ad and the raw data(time each person starts watching an ad).
print('ad1 has length 10s and average time interval between each audience member is:', avg_ad1)
print('ad2 has length 15s and average time interval between each audience member is:', avg_ad2)
print('ad3 has length 20s and average time interval between each audience member is:', avg_ad3)
print('Total audience for ad 1:', num_audience_ad1)
print('Times watched for ad 1:', times_watched_ad1)
print('Total audience for ad 2:', num_audience_ad2)
print('Times watched for ad 2:', times_watched_ad2)
print('Total audience for ad 3:', num_audience_ad3)
print('Times watched for ad 3:', times_watched_ad3)
Be forwarned that because this simulation was randomized, each time the code is run it won't provide the same outputs (I chose not to set a seed to control the randomization). If this was applied to real life, I'd iterate the simulation to find point of convergence. Something like combining this code and my Lottery code will probably give you a good indication as to whether or not you have enough resources/simulation will succeed...or some better math techniques. This code used very simply math...by simple I mean just one: Poisson distribution.
Also, this code made me cry.