Pre: Demo of creating a random number generator =============================================== Corresponding lab sheet: ------------------------ - `Data Structures and Functions `_ Objectives ---------- - Motivate the use of lists and functions by creating a random number generator. - Describe list manipulation; - Describe functions and start discussing writing good code; - Give insight about random numbers. Notes ----- Explain to students that we are going to use programming to generate random numbers. **Ask students to discuss in groups how they would generate a random number?** Bring this discussion together, perhaps some students will talk about using dice, flipping a coin, etc... **Ask how would we be able to check that a number is being generated randomly?** Lead the conversation to the notion of being able to predict a number no better than by "chance". Discuss how this could be done by a computer, there are actually only very few **true** random number generators: - Atmospheric noise. - Thermal noise. - Cosmic background radiation measured over a short amount of time. We are going to look at something called *pseudo*-random number generators. There are a number we could choose: - `Middle Square Method `_ - `Blum Blum Shub `_ - `Linear Congruence Generator `_ We will consider the last one (LCG) which was considered for a little while to be state of the art (before being proved to be cyrptographically unsafe: ie predictable). This generator takes the form: .. math:: X_{n + 1} = aX_n + c \text{mod} m X_0 = \text{s} Where :math:`a, c, m, s` are some parameters. **In groups choose some parameters and ask students to generate some random numbers.** Here is an example using :math:`a=2`, :math:`c=1`, :math:`s=0` and :math:`m=4`: +------------+------------+ | n | X_n | +============+============+ | 0 | 0 | +------------+------------+ | 1 | 1 | +------------+------------+ | 2 | 3 | +------------+------------+ | 3 | 3 | +------------+------------+ | 4 | 3 | +------------+------------+ | 5 | 3 | +------------+------------+ **Is this random? Did any other group come up with more randomness?** Now let us code this, to do so we will make use of two new programming concepts: - Lists - Functions First let us write a function that represents the definition of the random number generator:: >>> def random_number_generator(previous_term, ... modulus=4, ... multiplier_a=2, ... multiplier_c=1): ... """ ... Generate a random number using ... the linear congruential generator ... """ ... return (previous_term * multiplier_a + multiplier_c) % modulus Let us confirm the table above:: >>> random_number_generator(previous_term=0) 1 >>> random_number_generator(previous_term=1) 3 >>> random_number_generator(previous_term=3) 3 >>> random_number_generator(previous_term=3) 3 This becomes quickly tedious: it would be much easier to be able to "hold" the calculated numbers in a container of some sort. In python these are called lists:: >>> seed = 0 >>> random_numbers = [seed] >>> number_of_numbers = 10 >>> for _ in range(number_of_numbers): ... random_numbers.append(random_number_generator(random_numbers[-1])) >>> random_numbers [0, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3] If the numbers we were generating were truly random what would the mean of our list be?:: >>> sum(random_numbers) / len(random_numbers) 2.545... >>> sum(range(4)) / 4 1.5 Our choice of parameters is clearly poor, here is a more common choice:: >>> modulus = 2 ** 32 >>> multiplier_a = 1664525 >>> multiplier_c = 1013904223 I am going to use the code I wrote previously so I will wrap it in a function:: >>> def generate_random_numbers(number_of_numbers, seed, modulus, multiplier_a, multiplier_c): ... """Generate N random numbers""" ... random_numbers = [seed] ... for repetition in range(number_of_numbers): ... random_numbers.append(random_number_generator(random_numbers[-1], ... modulus=modulus, ... multiplier_a=multiplier_a, ... multiplier_c=multiplier_c,)) ... return random_numbers Let us generate a thousand random numbers:: >>> random_numbers = generate_random_numbers(number_of_numbers=10 ** 3, ... seed=0, ... modulus=modulus, ... multiplier_a=multiplier_a, ... multiplier_c=multiplier_c) >>> sum(random_numbers) / len(random_numbers) 2114463563.02497... We will see in a few weeks time how to plot with python but here's a quick example:: >>> import matplotlib.pyplot as plt >>> plt.plot(random_numbers) [