Skip to content

Commit e2994ac

Browse files
authored
Merge pull request #193 from QuantEcon/lec-review-3
Chapter 3 Review: Add Explanations and Address Exercise Issue
2 parents cbc6699 + e8c672e commit e2994ac

File tree

1 file changed

+131
-102
lines changed

1 file changed

+131
-102
lines changed

lectures/python_by_example.md

Lines changed: 131 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -139,15 +139,14 @@ In fact, a package is just a directory containing
139139
1. possibly some compiled code that can be accessed by Python (e.g., functions compiled from C or FORTRAN code)
140140
1. a file called `__init__.py` that specifies what will be executed when we type `import package_name`
141141

142-
In fact, you can find and explore the directory for NumPy on your computer
143-
easily enough if you look around.
144-
145-
On this machine, it's located in
142+
You can check the location of your `__init__.py` for NumPy in python by running the code:
146143

147144
```{code-block} ipython
148145
:class: no-execute
149146
150-
anaconda3/lib/python3.7/site-packages/numpy
147+
import numpy as np
148+
149+
print(np.__file__)
151150
```
152151

153152
#### Subpackages
@@ -159,7 +158,9 @@ Consider the line `ϵ_values = np.random.randn(100)`.
159158

160159
Here `np` refers to the package NumPy, while `random` is a **subpackage** of NumPy.
161160

162-
Subpackages are just packages that are subdirectories of another package.
161+
Subpackages are just packages that are subdirectories of another package.
162+
163+
For instance, you can find folder `random` under the directory of NumPy.
163164

164165
### Importing Names Directly
165166

@@ -208,7 +209,7 @@ We can and will look at various ways to configure and improve this plot below.
208209

209210
## Alternative Implementations
210211

211-
Let's try writing some alternative versions of {ref}`our first program <ourfirstprog>`, which plotted IID draws from the normal distribution.
212+
Let's try writing some alternative versions of {ref}`our first program <ourfirstprog>`, which plotted IID draws from the standard normal distribution.
212213

213214
The programs below are less efficient than the original one, and hence
214215
somewhat artificial.
@@ -250,7 +251,9 @@ Let's study some parts of this program in more detail.
250251

251252
Consider the statement `ϵ_values = []`, which creates an empty list.
252253

253-
Lists are a *native Python data structure* used to group a collection of objects.
254+
Lists are a *native Python data structure* used to group a collection of objects.
255+
256+
Items in lists are ordered, and duplicates are allowed in lists.
254257

255258
For example, try
256259

@@ -259,7 +262,7 @@ x = [10, 'foo', False]
259262
type(x)
260263
```
261264

262-
The first element of `x` is an [integer](https://en.wikipedia.org/wiki/Integer_%28computer_science%29), the next is a [string](https://en.wikipedia.org/wiki/String_%28computer_science%29), and the third is a [Boolean value](https://en.wikipedia.org/wiki/Boolean_data_type).
265+
The first element of `x` is an [integer](https://en.wikipedia.org/wiki/Integer_(computer_science)), the next is a [string](https://en.wikipedia.org/wiki/String_(computer_science)), and the third is a [Boolean value](https://en.wikipedia.org/wiki/Boolean_data_type).
263266

264267
When adding a value to a list, we can use the syntax `list_name.append(some_value)`
265268

@@ -274,7 +277,7 @@ x
274277

275278
Here `append()` is what's called a *method*, which is a function "attached to" an object---in this case, the list `x`.
276279

277-
We'll learn all about methods later on, but just to give you some idea,
280+
We'll learn all about methods {doc}`later on <oop_intro>`, but just to give you some idea,
278281

279282
* Python objects such as lists, strings, etc. all have methods that are used to manipulate the data contained in the object.
280283
* String objects have [string methods](https://docs.python.org/3/library/stdtypes.html#string-methods), list objects have [list methods](https://docs.python.org/3/tutorial/datastructures.html#more-on-lists), etc.
@@ -332,7 +335,7 @@ for animal in animals:
332335
print("The plural of " + animal + " is " + animal + "s")
333336
```
334337

335-
This example helps to clarify how the `for` loop works: When we execute a
338+
This example helps to clarify how the `for` loop works: When we execute a
336339
loop of the form
337340

338341
```{code-block} python3
@@ -397,10 +400,18 @@ plt.plot(ϵ_values)
397400
plt.show()
398401
```
399402

403+
A while loop will keep executing the code block delimited by indentation until the condition (```i < ts_length```) is satisfied.
404+
405+
In this case, the program will keep adding values to the list ```ϵ_values``` until ```i``` equals ```ts_length```:
406+
407+
```{code-cell} python3
408+
i == ts_length #the ending condition for the while loop
409+
```
410+
400411
Note that
401412

402-
* the code block for the `while` loop is again delimited only by indentation
403-
* the statement `i = i + 1` can be replaced by `i += 1`
413+
* the code block for the `while` loop is again delimited only by indentation.
414+
* the statement `i = i + 1` can be replaced by `i += 1`.
404415

405416
## Another Application
406417

@@ -478,8 +489,30 @@ Set $T=200$ and $\alpha = 0.9$.
478489
```{exercise-end}
479490
```
480491

492+
```{solution-start} pbe_ex1
493+
:class: dropdown
494+
```
481495

482-
```{exercise}
496+
Here's one solution.
497+
498+
```{code-cell} python3
499+
α = 0.9
500+
T = 200
501+
x = np.empty(T+1)
502+
x[0] = 0
503+
504+
for t in range(T):
505+
x[t+1] = α * x[t] + np.random.randn()
506+
507+
plt.plot(x)
508+
plt.show()
509+
```
510+
511+
```{solution-end}
512+
```
513+
514+
515+
```{exercise-start}
483516
:label: pbe_ex2
484517
485518
Starting with your solution to exercise 1, plot three simulated time series,
@@ -495,87 +528,63 @@ Hints:
495528
* For the legend, noted that the expression `'foo' + str(42)` evaluates to `'foo42'`.
496529
```
497530

498-
```{exercise}
499-
:label: pbe_ex3
500-
501-
Similar to the previous exercises, plot the time series
502-
503-
$$
504-
x_{t+1} = \alpha \, |x_t| + \epsilon_{t+1}
505-
\quad \text{where} \quad
506-
x_0 = 0
507-
\quad \text{and} \quad t = 0,\ldots,T
508-
$$
509-
510-
Use $T=200$, $\alpha = 0.9$ and $\{\epsilon_t\}$ as before.
511-
512-
Search online for a function that can be used to compute the absolute value $|x_t|$.
531+
```{exercise-end}
513532
```
514533

515534

516-
```{exercise-start}
517-
:label: pbe_ex4
535+
```{solution-start} pbe_ex2
536+
:class: dropdown
518537
```
519538

520-
One important aspect of essentially all programming languages is branching and
521-
conditions.
522-
523-
In Python, conditions are usually implemented with if--else syntax.
539+
```{code-cell} python3
540+
α_values = [0.0, 0.8, 0.98]
541+
T = 200
542+
x = np.empty(T+1)
524543
525-
Here's an example, that prints -1 for each negative number in an array and 1
526-
for each nonnegative number
544+
for α in α_values:
545+
x[0] = 0
546+
for t in range(T):
547+
x[t+1] = α * x[t] + np.random.randn()
548+
plt.plot(x, label=f'$\\alpha = {α}$')
527549
528-
```{code-cell} python3
529-
numbers = [-9, 2.3, -11, 0]
550+
plt.legend()
551+
plt.show()
530552
```
531553

532-
```{code-cell} python3
533-
for x in numbers:
534-
if x < 0:
535-
print(-1)
536-
else:
537-
print(1)
538-
```
554+
Note: `f'$\\alpha = {α}$'` in the solution is an application of [f-String](https://docs.python.org/3/tutorial/inputoutput.html#tut-f-strings), which allows you to use `{}` to contain an expression.
539555

540-
Now, write a new solution to Exercise 3 that does not use an existing function
541-
to compute the absolute value.
556+
The contained expression will be evaluated, and the result will be placed into the string.
542557

543-
Replace this existing function with an if--else condition.
544558

545-
```{exercise-end}
559+
```{solution-end}
546560
```
547561

548-
549562
```{exercise-start}
550-
:label: pbe_ex5
551-
```
563+
:label: pbe_ex3
552564
553-
Here's a harder exercise, that takes some thought and planning.
565+
Similar to the previous exercises, plot the time series
554566
555-
The task is to compute an approximation to $\pi$ using [Monte Carlo](https://en.wikipedia.org/wiki/Monte_Carlo_method).
567+
$$
568+
x_{t+1} = \alpha \, |x_t| + \epsilon_{t+1}
569+
\quad \text{where} \quad
570+
x_0 = 0
571+
\quad \text{and} \quad t = 0,\ldots,T
572+
$$
556573
557-
Use no imports besides
574+
Use $T=200$, $\alpha = 0.9$ and $\{\epsilon_t\}$ as before.
558575
559-
```{code-cell} python3
560-
import numpy as np
576+
Search online for a function that can be used to compute the absolute value $|x_t|$.
561577
```
562578

563-
Your hints are as follows:
564-
565-
* If $U$ is a bivariate uniform random variable on the unit square $(0, 1)^2$, then the probability that $U$ lies in a subset $B$ of $(0,1)^2$ is equal to the area of $B$.
566-
* If $U_1,\ldots,U_n$ are IID copies of $U$, then, as $n$ gets large, the fraction that falls in $B$, converges to the probability of landing in $B$.
567-
* For a circle, $area = \pi * radius^2$.
568-
569579
```{exercise-end}
570580
```
571581

572-
## Solutions
573582

574-
```{solution-start} pbe_ex1
583+
```{solution-start} pbe_ex3
575584
:class: dropdown
576585
```
577586

578-
Here's one solution.
587+
Here's one solution:
579588

580589
```{code-cell} python3
581590
α = 0.9
@@ -584,7 +593,7 @@ x = np.empty(T+1)
584593
x[0] = 0
585594
586595
for t in range(T):
587-
x[t+1] = α * x[t] + np.random.randn()
596+
x[t+1] = α * np.abs(x[t]) + np.random.randn()
588597
589598
plt.plot(x)
590599
plt.show()
@@ -594,52 +603,38 @@ plt.show()
594603
```
595604

596605

597-
```{solution-start} pbe_ex2
598-
:class: dropdown
606+
```{exercise-start}
607+
:label: pbe_ex4
599608
```
600609

601-
```{code-cell} python3
602-
α_values = [0.0, 0.8, 0.98]
603-
T = 200
604-
x = np.empty(T+1)
605-
606-
for α in α_values:
607-
x[0] = 0
608-
for t in range(T):
609-
x[t+1] = α * x[t] + np.random.randn()
610-
plt.plot(x, label=f'$\\alpha = {α}$')
611-
612-
plt.legend()
613-
plt.show()
614-
```
610+
One important aspect of essentially all programming languages is branching and
611+
conditions.
615612

616-
```{solution-end}
617-
```
613+
In Python, conditions are usually implemented with if--else syntax.
618614

615+
Here's an example, that prints -1 for each negative number in an array and 1
616+
for each nonnegative number
619617

620-
```{solution-start} pbe_ex3
621-
:class: dropdown
618+
```{code-cell} python3
619+
numbers = [-9, 2.3, -11, 0]
622620
```
623621

624-
Here's one solution:
625-
626622
```{code-cell} python3
627-
α = 0.9
628-
T = 200
629-
x = np.empty(T+1)
630-
x[0] = 0
623+
for x in numbers:
624+
if x < 0:
625+
print(-1)
626+
else:
627+
print(1)
628+
```
631629

632-
for t in range(T):
633-
x[t+1] = α * np.abs(x[t]) + np.random.randn()
630+
Now, write a new solution to Exercise 3 that does not use an existing function
631+
to compute the absolute value.
634632

635-
plt.plot(x)
636-
plt.show()
637-
```
633+
Replace this existing function with an if--else condition.
638634

639-
```{solution-end}
635+
```{exercise-end}
640636
```
641637

642-
643638
```{solution-start} pbe_ex4
644639
:class: dropdown
645640
```
@@ -683,6 +678,31 @@ plt.show()
683678
```
684679

685680

681+
682+
```{exercise-start}
683+
:label: pbe_ex5
684+
```
685+
686+
Here's a harder exercise, that takes some thought and planning.
687+
688+
The task is to compute an approximation to $\pi$ using [Monte Carlo](https://en.wikipedia.org/wiki/Monte_Carlo_method).
689+
690+
Use no imports besides
691+
692+
```{code-cell} python3
693+
import numpy as np
694+
```
695+
696+
Your hints are as follows:
697+
698+
* If $U$ is a bivariate uniform random variable on the unit square $(0, 1)^2$, then the probability that $U$ lies in a subset $B$ of $(0,1)^2$ is equal to the area of $B$.
699+
* If $U_1,\ldots,U_n$ are IID copies of $U$, then, as $n$ gets large, the fraction that falls in $B$, converges to the probability of landing in $B$.
700+
* For a circle, $area = \pi * radius^2$.
701+
702+
```{exercise-end}
703+
```
704+
705+
686706
```{solution-start} pbe_ex5
687707
:class: dropdown
688708
```
@@ -704,12 +724,20 @@ We estimate the area by sampling bivariate uniforms and looking at the
704724
fraction that falls into the circle.
705725

706726
```{code-cell} python3
707-
n = 100000
727+
n = 1000000 # sample size for Monte Carlo simulation
708728
709729
count = 0
710730
for i in range(n):
731+
732+
# drawing random positions on the square
711733
u, v = np.random.uniform(), np.random.uniform()
734+
735+
# check whether the point falls within the boundary
736+
# of the unit circle centred at (0.5,0.5)
712737
d = np.sqrt((u - 0.5)**2 + (v - 0.5)**2)
738+
739+
# if it falls within the inscribed circle,
740+
# add it to the count
713741
if d < 0.5:
714742
count += 1
715743
@@ -720,3 +748,4 @@ print(area_estimate * 4) # dividing by radius**2
720748

721749
```{solution-end}
722750
```
751+

0 commit comments

Comments
 (0)