Exercises and Proofs#
There are two extensions for jupyterbook that enable us to add exercises and proofs in our lecture series.
These extensions provide a beautiful and clear separation from the text and offer a better reading experience.
Guiding Principles
Use gated syntax whenever your exercise uses:
executable code cells
any nested directives (such as
math
,note
etc.)
Use
:class: dropdown
for solutions by default[pdf] For compatibility with
pdf
builds, use theimage
directive (rather thanfigure
directive) when inside another directive such asexercise
andsolution
directives
Nested Directives#
When you need to include one directive inside another (such as including math
, code-cell
, figure
, or note
directives inside exercise
, solution
, or prf:proof
directives), you have two main options:
Option 1: Tick Count Management#
Ensure the outer directive uses more ticks than any nested directive inside it. The MyST parser needs to clearly identify where each directive begins and ends.
Standard pattern:
Nested directive: 3 ticks (```)
Enclosing directive: 4 ticks (````)
````{prf:theorem}
:label: my-theorem
This theorem contains a nested math directive.
```{math}
x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}
```
The math directive uses 3 ticks, so the theorem uses 4 ticks.
````
Note
Multiple levels of nesting are discouraged. While technically possible with tick count management, we recommend using the gated syntax approach (Option 2) for better clarity and readability when you need complex nested structures.
Option 2: Gated Syntax (sphinx-exercise only)#
For exercise
and solution
directives, you can use gated syntax with start
/end
pairs:
```{exercise-start}
:label: my-exercise
```
Recall that $n!$ is read as "$n$ factorial" and defined as
$n! = n \times (n - 1) \times \cdots \times 2 \times 1$.
```{code-cell} python
def factorial(n):
return 1 if n <= 1 else n * factorial(n-1)
factorial(5)
```
```{exercise-end}
```
Important
Directive Support Summary:
sphinx-exercise directives (
exercise
,solution
): Support both tick count management AND gated syntax (usingexercise-start
/exercise-end
andsolution-start
/solution-end
)sphinx-proof directives (
prf:proof
,prf:theorem
, etc.): Only support tick count management (no gated syntax)Standard MyST directives (
note
,warning
, etc.): Only support tick count management
When to Use Each Option#
Use gated syntax when:
Working with
exercise
orsolution
directivesIncluding executable code cells (
code-cell
)Including multiple nested directives
You want cleaner, more readable source code
Use tick count management when:
Working with
prf:
directives (proofs, theorems, etc.)Working with any other standard directives
You have simple, single-level nesting
Gated syntax is not supported for your directive type
Exercises#
See also
To learn more about sphinx-exercise please read the documentation.
Here we provide a brief tutorial on using exercise
admonitions in the quantecon
lectures
To make an exercise you can use the exercise
admonition
```{exercise}
:label: my-exercise
Recall that $n!$ is read as "$n$ factorial" and defined as
$n! = n \times (n - 1) \times \cdots \times 2 \times 1$.
There are functions to compute this in various modules, but let's
write our own version as an exercise.
In particular, write a function `factorial` such that `factorial(n)` returns $n!$
for any positive integer $n$.
```
where the label
enables you to reference the exercise using ref
or numref
roles.
This will be rendered as
Exercise 1
Recall that \(n!\) is read as “\(n\) factorial” and defined as \(n! = n \times (n - 1) \times \cdots \times 2 \times 1\).
There are functions to compute this in various modules, but let’s write our own version as an exercise.
In particular, write a function factorial
such that factorial(n)
returns \(n!\)
for any positive integer \(n\).
and then you can easily reference the exercise using the {ref}
role (Exercise 1) or using the {numref}
role (Exercise 1).
See also
There are additional configuration options available
but are not frequently used in QuantEcon
lectures
Each exercise admonition should be paired with a solution
admonition.
The exercise extension also provides us with a useful property that enables us to convert our solutions into a dropdown paragraph.
This helps the reader to have more time to think about the questions without being tempted by the solution.
You can add this feature in class
.
```{solution-start} my-exercise
:class: dropdown
:label: my-solution
```
Here's one solution.
```{code-cell} python
def factorial(n):
k = 1
for i in range(n):
k = k * (i + 1)
return k
factorial(4)
```
```{solution-end}
```
which is rendered as
Solution to Exercise 1
Here’s one solution.
def factorial(n):
k = 1
for i in range(n):
k = k * (i + 1)
return k
factorial(4)
24
The solution
can be referenced
using the label
property using ref
and numref
.
The solution
directive requires the label of the exercise.
Given many solutions across QuantEcon projects typically require code execution we frequently make use of the gated syntax
.
Note: If a solution does not require code execution it is possible to use the primary solution
admonition.
Warning
The code in this example is not executed but is syntax highlighted
````{solution} my-exercise
:label: my-solution
Here's one solution.
```{code-block} python
def factorial(n):
k = 1
for i in range(n):
k = k * (i + 1)
return k
factorial(4)
```
````
which is rendered as
Solution to Exercise 1
Here’s one solution.
def factorial(n):
k = 1
for i in range(n):
k = k * (i + 1)
return k
factorial(4)
Proofs#
There is a range of directives provided by sphinx-proof:
Note
The prf:
included in each directive name is required in both the directive
and when
referencing the admonition such as {prf:ref}
. These belong to the Sphinx prf
domain that supports
references and linking.
An example proof:
Tip
This package does not support the gated syntax
provided by sphinx-exercise
, therefore
you must use the tick count management
option for nested directives. See the
Nested Directives section for detailed guidance and examples.
````{prf:proof}
We'll omit the full proof.
But we will prove sufficiency of the asserted conditions.
To this end, let $y \in \mathbb R^n$ and let $S$ be a linear subspace of $\mathbb R^n$.
Let $\hat y$ be a vector in $\mathbb R^n$ such that $\hat y \in S$ and $y - \hat y \perp S$.
Let $z$ be any other point in $S$ and use the fact that $S$ is a linear subspace to deduce
```{math}
\| y - z \|^2
= \| (y - \hat y) + (\hat y - z) \|^2
= \| y - \hat y \|^2 + \| \hat y - z \|^2
```
Hence $\| y - z \| \geq \| y - \hat y \|$, which completes the proof.
```
````
will render as
Proof. We’ll omit the full proof.
But we will prove sufficiency of the asserted conditions.
To this end, let \(y \in \mathbb R^n\) and let \(S\) be a linear subspace of \(\mathbb R^n\).
Let \(\hat y\) be a vector in \(\mathbb R^n\) such that \(\hat y \in S\) and \(y - \hat y \perp S\).
Let \(z\) be any other point in \(S\) and use the fact that \(S\) is a linear subspace to deduce
Hence \(\| y - z \| \geq \| y - \hat y \|\), which completes the proof.