Objectives

  1. Understand how computers can be used to represent real-world phenomena or outcomes
  2. Compare simulations with real-world contexts.
  3. Implement code to mimic real world situations, problems, or phenomena.

What are simulations by College Board definition?

  • Simulations are abstractions that mimic more complex objects or phenomena from the real world
    • Purposes include drawing inferences without the constraints of the real world
  • Simulations use varying sets of values to reflect the the changing state of a real phenomenon
  • Often, when developing a simulation, it is necessary to remove specific details or simplify aspects
    • Simulations can often contain bias based on which details or real-world elements were included/excluded
  • Simulations allow the formulation of hypothesis under consideration
  • Variability and randomness of the world is considered using random number generators
  • Examples: rolling dice, spinners, molecular models, analyze chemicals/reactions...

Analyzing an Example: Air-Traffic Simulator

  • Say we want to find out what the optimal number of aircrafts that can be in the air in one area is.
  • A simulation allows us to explore this question without real world contraints of money, time, safety
    • Unfortunately we can't just fly 67 planes all at once and see what happens
  • Since the simulation won't be able to take all variables into control, it may have a bias towards one answer
  • Will not always have the same result

Functions we often need (python)

import random # a module that defines a series of functions for generating or manipulating random integers
random.choice() #returns a randomly selected element from the specified sequence
random.choice(mylist) # returns random value from list
random.randint(0,10) #randomly selects an integer from given range; range in this case is from 0 to 10
random.random() #will generate a random float between 0.0 to 1.

Functions we often need (js)

// Math.random(); returns a random number
// Math.floor(Math.random() * 10); // Returns a random integer from 0 to 9:

College Board Question 1

Question: The following code simulates the feeding of 4 fish in an aquarium while the owner is on a 5-day trip:

numFish ← 4

foodPerDay ← 20

foodLeft ← 160

daysStarving ← 0

    REPEAT 5 TIMES {

    foodConsumed ← numFish * foodPerDay

    foodLeft ← foodLeft - foodConsumed

    IF (foodLeft < 0) {

    daysStarving ← daysStarving + 1

    }

}

  • This simulation simplifies a real-world scenario into something that can be modeled in code and executed on a computer.
  • Summarize how the code works: The code sets a variable for the amount of fish the amount of food they eat and the amount that is left to see in a span of 5 days how much food will be left or if they will starve and for how long.

Examples

Card Flip

import random

cards = ["Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"] 
suits = ["Diamonds", "Hearts", "Spades", "Clubs"]

print(random.choice(cards) + " of " + random.choice(suits))

Coin Flip

import random

def coinflip():         #def function 
    randomflip = random.randint(0, 1) #picks either 0 or 1 randomly 
    if randomflip == 0: #assigning 0 to be heads--> if 0 is chosen then it will print, "Heads"
        print("Heads")
    else:
        if randomflip == 1: #assigning 1 to be tails--> if 1 is chosen then it will print, "Tails"
            print("Tails")

#Tossing the coin 5 times:
t1 = coinflip()
t2 = coinflip()
t3 = coinflip()
t4 = coinflip()
t5 = coinflip()

Your turn: Change the code to make it simulate the flipping of a weighted coin.

import random

def coinflip():         #def function 
    randomflip = random.randint(0, 35) #picks either 0 or 1 randomly 
    if randomflip in range(34): #assigning 0 to be heads--> if 0 is chosen then it will print, "Heads"
        print("Heads")
    else:
        if randomflip == 35: #assigning 1 to be tails--> if 1 is chosen then it will print, "Tails"
            print("Tails")

#Tossing the coin 5 times:
t1 = coinflip()
t2 = coinflip()
t3 = coinflip()
t4 = coinflip()
t5 = coinflip()
Heads
Heads
Heads
Heads
Heads

Adding images (in Python)

  • Add a heads and tails images into your images directory with the correct names and run the code below
import random

# importing Image class from PIL package
from PIL import Image
 
# creating a object
im = Image.open(r"images/HeadsOn2.png")
image = Image.open(r"images/TailsOn2.png")

i=random.randint(0,1)

if i == 1:
    print("heads")
    display(im)

else:
    print("tails")
    display(image)
tails

In order to display an image in python, we can use the PIL package we previously learned about.

Spin the Wheel

import random

print("Spin the wheel!")
print("----------------------------------")

n = 300
blue = 0
red = 0
 
for i in range(n):
    spin = random.randint(1,2)
    if spin == 1: # head
        blue = blue + 1
    else:         # tail
        red = red + 1
 
print('Number of blue:', blue)
print('Number of red:', red)
Spin the wheel!
----------------------------------
Number of blue: 154
Number of red: 146
import random
import matplotlib.pyplot as plt

print("Spin the wheel!")
print("----------------------------------")

n = 300
blue = 0
red = 0
 
for i in range(n):
    spin = random.randint(1,2)
    if spin == 1: # head
        blue = blue + 1
    else:         # tail
        red = red + 1
 
print('Number of blue:', blue)
print('Number of red:', red)

# Plot the results in a bar graph
colors = ['Blue', 'Red']
counts = [blue, red]
plt.bar(colors, counts, color=['blue', 'red'])
plt.title('Spin the wheel!')
plt.xlabel('Color')
plt.ylabel('Count')
plt.show()
Spin the wheel!
----------------------------------
Number of blue: 155
Number of red: 145

Your turn: Add a visual to the simulation!

Population Growth and Plots

import random

totalPopulation = 50 
growthFactor = 1.00005
dayCount = 0 #Every 2 months the population is reported

while totalPopulation < 1000000:
    totalPopulation *= growthFactor
    #Every 56th day, population is reported
    dayCount += 1
    if dayCount == 56: 
        dayCount = 0
        print(totalPopulation)

Here we initialize the total population to be 50, then set the growth factor as 1.00005 (.005 percent change). It will print the population every 56th day until it reaches one million. It multiplies the current population by the growth factor in each iteration, and increments the day count. When the day count reaches 56, it prints the current population and resets the day count to 0.

Note! This simulation assumes that the growth factor remains constant as time progresses, which may not be a realistic assumption in real-world scenarios.

import matplotlib.pyplot as plt

# Define the initial population and growth rate
population = 100
growth_rate = 0.05

# Define the number of years to simulate
num_years = 50

# Create lists to store the population and year values
populations = [population]
years = [0]

# Simulate population growth for the specified number of years
for year in range(1, num_years+1):
    # Calculate the new population size
    new_population = population + (growth_rate * population)
    # Update the population and year lists
    populations.append(new_population)
    years.append(year)
    # Set the new population as the current population for the next iteration
    population = new_population
    
# Plot the population growth over time
plt.plot(years, populations)
plt.xlabel('Year')
plt.ylabel('Population')
plt.title('Population Growth Simulation')
plt.show()

If we create quantative data, we can plot it using the Matplotlib library.

Example on how simplification can cause bias

import random

beak =  ["small-beak", "long-beak", "medium-beak"],
wing = ["small-wings", "large-wings", "medium-wings"],
height = ["short", "tall","medium"]


naturaldisaster = ["flood", "drought", "fire", "hurricane", "dustbowl"]


print("When a" , random.choice(naturaldisaster) , "hit",  random.choice(height), "birds died") 

How does this simulation have bias?

  • There is no reason for why a trait occurs and is purely random so there is no way to be able to properly simulate the category along with only taking into account the height of a bird.

JS examples

Hacks

  • Answer all questions and prompts in the notes (0.2)
  • Create a simulation
    1. Create a simulation that uses iteration and some form of data collection (list, dictionary...) (0.4)
      • try creating quantative data and using the Matplotlib library to display said data
      • Comment and describe function of each parts
      • How does your simulation help solve/mimic a real world problem?
    2. Create a simulation that uses randomization (0.4)
      • Is there any bias in your simulation? Meaning, are there any discrepancies between your program and the real event?
  • Answer these simulation questions (0.3)
  • Bonus: take a real world event and make a pseudocode representation or pseudocode on a flowchart of how you would make a simulation for it (up to +0.1 bonus)

Simulation

A Clothing Store Simulation where users buy clothes which match their preferences

Real World Scenario

  • This mimics a real world scenario where a store owner can see if their inventory will sell to a random assortment of customers for their large amount of preferences that the user has for the things they want to buy that may be in their store. This could allow the store to make better purchase decisions or see if their inventory will sell.

Bias in Simulation

  • The issues in the simulation are that the users' preferences will not always have their choices determined from the inventory in the store so they may have a brand they like that isn't in the store or a price etc. Also the user can make compromises on their preferences so they may not always buy the things they want but are ok with buying which will make the amount of purchases artificially low. So in real life there will be more purchases than in the simulation also the customer may see something that they didn't know they wanted and buy it which is not accounted for in the simulation or they might buy more things than just one of their preferred product.

Questions

  • A theme park wants to create a simulation to determine how long it should expect the wait time at its most popular ride. Which of the following characteristics for the virtual patrons would be most useful? Select two answers

    • A & B as a user's ride and the distance they are willing to walk indicates the ride they want to ride and the more user's want to ride a ride the longer the wait time will be.
  • A programmer has created a program that models the growth of foxes and rabbits. Which of the following potential aspects of the simulation does NOT need to be implemented?

    • A as the other options indicate how many rabbits they are how much grass they eat per day is not a valuable piece of information to know for the simulation.
  • The heavy use of chemicals called chlorofluorocarbons (CFCs) has caused damage to the Earth’s ozone layer, creating a noticeable hole over Antarctica. A scientist created a simulation of the hole in the layer using a computer, which models the growth of the hole over many years. Which of the following could be useful information that the simulation could produce?

    • B as the simulation models the growth of the hole over many years and so it would allow for one to be able to solve for the size at any given point in time
  • A program is being created to simulate the growth of a brain-based on randomly determined environmental factors. The developer plans to add a feature that lets the user quickly run several hundred simulations with any number of factors kept constant. Why would this be useful? Select two answers.

    • (B & D) B is a correct answer as it allows for variables to isolated and thus be able to see their effects on the rest of the program & D is also correct as it would make it so that the user can generate a simulation that is specific to testing a certain variable and make it more detailed and make better conclusions.
  • Which of the following statements describes a limitation of using a computer simulation to model a real-world object or system?

    • C as every single attribute cannot possibly be represented in a computer program as there are just too many factors in the real world for a simulation to be 100% accurate it can only allow for a general idea of what the real world scenario would be like.
import random
import matplotlib.pyplot as plt

# Defines the classes and their attributes
class ClothingShopper:
    def __init__(self, preferred_brand, preferred_size, preferred_color, preferred_price, preferred_style):
        self.preferred_brand = preferred_brand
        self.preferred_size = preferred_size
        self.preferred_color = preferred_color
        self.preferred_price = preferred_price
        self.preferred_style = preferred_style

class ClothingItem:
    def __init__(self, brand, size, color, price, style):
        self.brand = brand
        self.size = size
        self.color = color
        self.price = price
        self.style = style
    
    # Match function to see if the shopper's preferences match the item if it does sim will say they bought it
    def is_match(self, shopper):
        return (self.style == shopper.preferred_style and
                self.brand == shopper.preferred_brand and
                self.size == shopper.preferred_size and
                self.color == shopper.preferred_color and
                self.price <= shopper.preferred_price)

def simulate_shopping(products, num_users):
    purchases_by_brand = {}
    revenue_by_brand = {}
    no_purchases = 0
    
    for i in range(num_users):
        # randomly generate shopper preferences
        preferred_brand = random.choice(list(set([p.brand for p in products])))
        preferred_size = random.choice(["S", "M", "L"])
        preferred_color = random.choice(["red", "blue", "green", "yellow", "black", "white"])
        preferred_price = random.randint(10, 100)
        preferred_style = random.choice(["casual", "formal", "sporty"])
        
        shopper = ClothingShopper(preferred_brand, preferred_size, preferred_color, preferred_price, preferred_style)
        
        # check if any products match shopper preferences
        matches = []
        for p in products:
            if p.is_match(shopper):
                matches.append(p)
                
        # make a purchase if a match is found
        if matches:
            purchase = random.choice(matches)
            brand = purchase.brand
            if brand in purchases_by_brand:
                purchases_by_brand[brand] += 1
                revenue_by_brand[brand] += purchase.price
            else:
                purchases_by_brand[brand] = 1
                revenue_by_brand[brand] = purchase.price
        else:
            no_purchases += 1
            
    
    # print out results
    print("Purchases by brand:")
    for brand, total_purchases in purchases_by_brand.items():
        print(f"{brand}: {total_purchases} purchases")
    print(f"No purchases made for {no_purchases} shoppers out of {num_users} total shoppers.")
    
    # create bar chart for purchases by brand
    brands = list(purchases_by_brand.keys())
    values = list(purchases_by_brand.values())
    no_purchase_value = no_purchases
    brands.append("No purchase")
    values.append(no_purchase_value)
    fig = plt.figure(facecolor='white')
    plt.bar(brands, values)
    plt.title("Purchases by brand")
    plt.xlabel("Brand")
    plt.ylabel("Purchases")
    plt.xticks(rotation=45, ha='right')
    plt.show()
    
    # create bar chart for revenue by brand
    brands = list(revenue_by_brand.keys())
    values = list(revenue_by_brand.values())
    total_revenue = sum(values)
    brands.append("Total revenue")
    values.append(total_revenue)
    fig = plt.figure(facecolor='white')
    plt.bar(brands, values)
    plt.title("Revenue by brand")
    plt.xlabel("Brand")
    plt.ylabel("Revenue")
    plt.xticks(rotation=45, ha='right')
    plt.show()



products = [
    ClothingItem("Nike", "M", "red", 50, "sporty"),
    ClothingItem("Adidas", "L", "blue", 30, "sporty"),
    ClothingItem("Levi's", "S", "black", 70, "casual"),
    ClothingItem("Gap", "M", "green", 40, "casual"),
    ClothingItem("Calvin Klein", "L", "white", 90, "formal"),
    ClothingItem("H&M", "S", "yellow", 20, "casual"),
    ClothingItem("Zara", "M", "red", 60, "formal"),
    ClothingItem("Tommy Hilfiger", "L", "blue", 80, "sporty"),
    ClothingItem("Ralph Lauren", "M", "green", 70, "casual"),
    ClothingItem("Puma", "S", "black", 50, "sporty")
]
num_users = 100000
simulate_shopping(products, num_users)
Purchases by brand:
Zara: 77 purchases
Gap: 124 purchases
Levi's: 66 purchases
H&M: 161 purchases
Nike: 112 purchases
Adidas: 144 purchases
Puma: 113 purchases
Ralph Lauren: 63 purchases
Tommy Hilfiger: 50 purchases
Calvin Klein: 17 purchases
No purchases made for 99073 shoppers out of 100000 total shoppers.