Chapter 6: Stochastic Discounting#

plot_interest_rates.py#

Hide code cell source
# Nominal interest rate from https://fred.stlouisfed.org/series/GS1
# Real interest rate from https://fred.stlouisfed.org/series/WFII10
#
# Download as CSV files
#

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.pyplot as plt

plt.rcParams.update({"text.usetex": True, "font.size": 14})

df_nominal = pd.read_csv("./data/GS1.csv")
df_real = pd.read_csv("./data/WFII10.csv")

def plot_rates(df, fontsize=16, savefig=True):
    r_type = 'nominal' if df.equals(df_nominal) else 'real'
    fig, ax = plt.subplots(figsize=(9, 5))
    ax.plot(df.iloc[:, 0], df.iloc[:, 1], label=f'{r_type} interest rate')
    ax.plot(df.iloc[:, 0], np.zeros(df.iloc[:, 1].size), c='k', ls='--')
    ax.set_xlim(df.iloc[0, 0], df.iloc[-1, 0])
    ax.legend(fontsize=fontsize, frameon=False)
    if savefig:
        fig.savefig(f'./figures/plot_interest_rates_{r_type}.pdf')
plot_rates(df_nominal)
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
Cell In[2], line 1
----> 1 plot_rates(df_nominal)

Cell In[1], line 25, in plot_rates(df, fontsize, savefig)
     23 ax.legend(fontsize=fontsize, frameon=False)
     24 if savefig:
---> 25     fig.savefig(f'./figures/plot_interest_rates_{r_type}.pdf')

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/figure.py:3343, in Figure.savefig(self, fname, transparent, **kwargs)
   3339     for ax in self.axes:
   3340         stack.enter_context(
   3341             ax.patch._cm_set(facecolor='none', edgecolor='none'))
-> 3343 self.canvas.print_figure(fname, **kwargs)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:2366, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
   2362 try:
   2363     # _get_renderer may change the figure dpi (as vector formats
   2364     # force the figure dpi to 72), so we need to set it again here.
   2365     with cbook._setattr_cm(self.figure, dpi=dpi):
-> 2366         result = print_method(
   2367             filename,
   2368             facecolor=facecolor,
   2369             edgecolor=edgecolor,
   2370             orientation=orientation,
   2371             bbox_inches_restore=_bbox_inches_restore,
   2372             **kwargs)
   2373 finally:
   2374     if bbox_inches and restore_bbox:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:2232, in FigureCanvasBase._switch_canvas_and_return_print_method.<locals>.<lambda>(*args, **kwargs)
   2228     optional_kws = {  # Passed by print_figure for other renderers.
   2229         "dpi", "facecolor", "edgecolor", "orientation",
   2230         "bbox_inches_restore"}
   2231     skip = optional_kws - {*inspect.signature(meth).parameters}
-> 2232     print_method = functools.wraps(meth)(lambda *args, **kwargs: meth(
   2233         *args, **{k: v for k, v in kwargs.items() if k not in skip}))
   2234 else:  # Let third-parties do as they see fit.
   2235     print_method = meth

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_pdf.py:2808, in FigureCanvasPdf.print_pdf(self, filename, bbox_inches_restore, metadata)
   2806     file = filename._file
   2807 else:
-> 2808     file = PdfFile(filename, metadata=metadata)
   2809 try:
   2810     file.newPage(width, height)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_pdf.py:713, in PdfFile.__init__(self, filename, metadata)
    711 self.original_file_like = None
    712 self.tell_base = 0
--> 713 fh, opened = cbook.to_filehandle(filename, "wb", return_opened=True)
    714 if not opened:
    715     try:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/cbook/__init__.py:489, in to_filehandle(fname, flag, return_opened, encoding)
    487         fh = bz2.BZ2File(fname, flag)
    488     else:
--> 489         fh = open(fname, flag, encoding=encoding)
    490     opened = True
    491 elif hasattr(fname, 'seek'):

FileNotFoundError: [Errno 2] No such file or directory: './figures/plot_interest_rates_nominal.pdf'
Error in callback <function _draw_all_if_interactive at 0x7fd4ee9a9360> (for post_execute):
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:255, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    254 try:
--> 255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:421, in check_output(timeout, *popenargs, **kwargs)
    419     kwargs['input'] = empty
--> 421 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
    422            **kwargs).stdout

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:503, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
    501     kwargs['stderr'] = PIPE
--> 503 with Popen(*popenargs, **kwargs) as process:
    504     try:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:971, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize)
    968             self.stderr = io.TextIOWrapper(self.stderr,
    969                     encoding=encoding, errors=errors)
--> 971     self._execute_child(args, executable, preexec_fn, close_fds,
    972                         pass_fds, cwd, env,
    973                         startupinfo, creationflags, shell,
    974                         p2cread, p2cwrite,
    975                         c2pread, c2pwrite,
    976                         errread, errwrite,
    977                         restore_signals,
    978                         gid, gids, uid, umask,
    979                         start_new_session)
    980 except:
    981     # Cleanup if the child failed starting.

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:1863, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session)
   1862         err_msg = os.strerror(errno_num)
-> 1863     raise child_exception_type(errno_num, err_msg, err_filename)
   1864 raise child_exception_type(err_msg)

FileNotFoundError: [Errno 2] No such file or directory: 'latex'

The above exception was the direct cause of the following exception:

RuntimeError                              Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/pyplot.py:120, in _draw_all_if_interactive()
    118 def _draw_all_if_interactive():
    119     if matplotlib.is_interactive():
--> 120         draw_all()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/_pylab_helpers.py:132, in Gcf.draw_all(cls, force)
    130 for manager in cls.get_all_fig_managers():
    131     if force or manager.canvas.figure.stale:
--> 132         manager.canvas.draw_idle()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:2082, in FigureCanvasBase.draw_idle(self, *args, **kwargs)
   2080 if not self._is_idle_drawing:
   2081     with self._idle_draw_cntx():
-> 2082         self.draw(*args, **kwargs)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:400, in FigureCanvasAgg.draw(self)
    396 # Acquire a lock on the shared font cache.
    397 with RendererAgg.lock, \
    398      (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar
    399       else nullcontext()):
--> 400     self.figure.draw(self.renderer)
    401     # A GUI class may be need to update a window using this draw, so
    402     # don't forget to call the superclass.
    403     super().draw()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:95, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
     93 @wraps(draw)
     94 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 95     result = draw(artist, renderer, *args, **kwargs)
     96     if renderer._rasterizing:
     97         renderer.stop_rasterizing()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/figure.py:3140, in Figure.draw(self, renderer)
   3137         # ValueError can occur when resizing a window.
   3139 self.patch.draw(renderer)
-> 3140 mimage._draw_list_compositing_images(
   3141     renderer, self, artists, self.suppressComposite)
   3143 for sfig in self.subfigs:
   3144     sfig.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axes/_base.py:3064, in _AxesBase.draw(self, renderer)
   3061 if artists_rasterized:
   3062     _draw_rasterized(self.figure, artists_rasterized, renderer)
-> 3064 mimage._draw_list_compositing_images(
   3065     renderer, self, artists, self.figure.suppressComposite)
   3067 renderer.close_group('axes')
   3068 self.stale = False

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1377, in Axis.draw(self, renderer, *args, **kwargs)
   1374 renderer.open_group(__name__, gid=self.get_gid())
   1376 ticks_to_draw = self._update_ticks()
-> 1377 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
   1379 for tick in ticks_to_draw:
   1380     tick.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in <listcomp>(.0)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:959, in Text.get_window_extent(self, renderer, dpi)
    954     raise RuntimeError(
    955         "Cannot get window extent of text w/o renderer. You likely "
    956         "want to call 'figure.draw_without_rendering()' first.")
    958 with cbook._setattr_cm(self.figure, dpi=dpi):
--> 959     bbox, info, descent = self._get_layout(self._renderer)
    960     x, y = self.get_unitless_position()
    961     x, y = self.get_transform().transform((x, y))

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:378, in Text._get_layout(self, renderer)
    375 ys = []
    377 # Full vertical extent of font, including ascenders and descenders:
--> 378 _, lp_h, lp_d = _get_text_metrics_with_cache(
    379     renderer, "lp", self._fontproperties,
    380     ismath="TeX" if self.get_usetex() else False, dpi=self.figure.dpi)
    381 min_dy = (lp_h - lp_d) * self._linespacing
    383 for i, line in enumerate(lines):

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:97, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
     94 """Call ``renderer.get_text_width_height_descent``, caching the results."""
     95 # Cached based on a copy of fontprop so that later in-place mutations of
     96 # the passed-in argument do not mess up the cache.
---> 97 return _get_text_metrics_with_cache_impl(
     98     weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:105, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
    101 @functools.lru_cache(4096)
    102 def _get_text_metrics_with_cache_impl(
    103         renderer_ref, text, fontprop, ismath, dpi):
    104     # dpi is unused, but participates in cache invalidation (via the renderer).
--> 105     return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:226, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
    224 _api.check_in_list(["TeX", True, False], ismath=ismath)
    225 if ismath == "TeX":
--> 226     return super().get_text_width_height_descent(s, prop, ismath)
    228 if ismath:
    229     ox, oy, width, height, descent, font_image = \
    230         self.mathtext_parser.parse(s, self.dpi, prop)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:645, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
    641 fontsize = prop.get_size_in_points()
    643 if ismath == 'TeX':
    644     # todo: handle properties
--> 645     return self.get_texmanager().get_text_width_height_descent(
    646         s, fontsize, renderer=self)
    648 dpi = self.points_to_pixels(72)
    649 if ismath:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:368, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
    366 if tex.strip() == '':
    367     return 0, 0, 0
--> 368 dvifile = cls.make_dvi(tex, fontsize)
    369 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
    370 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:300, in TexManager.make_dvi(cls, tex, fontsize)
    298     with TemporaryDirectory(dir=cwd) as tmpdir:
    299         tmppath = Path(tmpdir)
--> 300         cls._run_checked_subprocess(
    301             ["latex", "-interaction=nonstopmode", "--halt-on-error",
    302              f"--output-directory={tmppath.name}",
    303              f"{texfile.name}"], tex, cwd=cwd)
    304         (tmppath / Path(dvifile).name).replace(dvifile)
    305 return dvifile

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:259, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:
--> 259     raise RuntimeError(
    260         'Failed to process string with tex because {} could not be '
    261         'found'.format(command[0])) from exc
    262 except subprocess.CalledProcessError as exc:
    263     raise RuntimeError(
    264         '{prog} was not able to process the following string:\n'
    265         '{tex!r}\n\n'
   (...)
    272             exc=exc.output.decode('utf-8', 'backslashreplace'))
    273         ) from None

RuntimeError: Failed to process string with tex because latex could not be found
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:255, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    254 try:
--> 255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:421, in check_output(timeout, *popenargs, **kwargs)
    419     kwargs['input'] = empty
--> 421 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
    422            **kwargs).stdout

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:503, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
    501     kwargs['stderr'] = PIPE
--> 503 with Popen(*popenargs, **kwargs) as process:
    504     try:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:971, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize)
    968             self.stderr = io.TextIOWrapper(self.stderr,
    969                     encoding=encoding, errors=errors)
--> 971     self._execute_child(args, executable, preexec_fn, close_fds,
    972                         pass_fds, cwd, env,
    973                         startupinfo, creationflags, shell,
    974                         p2cread, p2cwrite,
    975                         c2pread, c2pwrite,
    976                         errread, errwrite,
    977                         restore_signals,
    978                         gid, gids, uid, umask,
    979                         start_new_session)
    980 except:
    981     # Cleanup if the child failed starting.

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:1863, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session)
   1862         err_msg = os.strerror(errno_num)
-> 1863     raise child_exception_type(errno_num, err_msg, err_filename)
   1864 raise child_exception_type(err_msg)

FileNotFoundError: [Errno 2] No such file or directory: 'latex'

The above exception was the direct cause of the following exception:

RuntimeError                              Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/IPython/core/formatters.py:340, in BaseFormatter.__call__(self, obj)
    338     pass
    339 else:
--> 340     return printer(obj)
    341 # Finally look for special method names
    342 method = get_real_method(obj, self.print_method)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/IPython/core/pylabtools.py:152, in print_figure(fig, fmt, bbox_inches, base64, **kwargs)
    149     from matplotlib.backend_bases import FigureCanvasBase
    150     FigureCanvasBase(fig)
--> 152 fig.canvas.print_figure(bytes_io, **kw)
    153 data = bytes_io.getvalue()
    154 if fmt == 'svg':

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:2342, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
   2336     renderer = _get_renderer(
   2337         self.figure,
   2338         functools.partial(
   2339             print_method, orientation=orientation)
   2340     )
   2341     with getattr(renderer, "_draw_disabled", nullcontext)():
-> 2342         self.figure.draw(renderer)
   2344 if bbox_inches:
   2345     if bbox_inches == "tight":

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:95, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
     93 @wraps(draw)
     94 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 95     result = draw(artist, renderer, *args, **kwargs)
     96     if renderer._rasterizing:
     97         renderer.stop_rasterizing()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/figure.py:3140, in Figure.draw(self, renderer)
   3137         # ValueError can occur when resizing a window.
   3139 self.patch.draw(renderer)
-> 3140 mimage._draw_list_compositing_images(
   3141     renderer, self, artists, self.suppressComposite)
   3143 for sfig in self.subfigs:
   3144     sfig.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axes/_base.py:3064, in _AxesBase.draw(self, renderer)
   3061 if artists_rasterized:
   3062     _draw_rasterized(self.figure, artists_rasterized, renderer)
-> 3064 mimage._draw_list_compositing_images(
   3065     renderer, self, artists, self.figure.suppressComposite)
   3067 renderer.close_group('axes')
   3068 self.stale = False

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1377, in Axis.draw(self, renderer, *args, **kwargs)
   1374 renderer.open_group(__name__, gid=self.get_gid())
   1376 ticks_to_draw = self._update_ticks()
-> 1377 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
   1379 for tick in ticks_to_draw:
   1380     tick.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in <listcomp>(.0)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:959, in Text.get_window_extent(self, renderer, dpi)
    954     raise RuntimeError(
    955         "Cannot get window extent of text w/o renderer. You likely "
    956         "want to call 'figure.draw_without_rendering()' first.")
    958 with cbook._setattr_cm(self.figure, dpi=dpi):
--> 959     bbox, info, descent = self._get_layout(self._renderer)
    960     x, y = self.get_unitless_position()
    961     x, y = self.get_transform().transform((x, y))

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:378, in Text._get_layout(self, renderer)
    375 ys = []
    377 # Full vertical extent of font, including ascenders and descenders:
--> 378 _, lp_h, lp_d = _get_text_metrics_with_cache(
    379     renderer, "lp", self._fontproperties,
    380     ismath="TeX" if self.get_usetex() else False, dpi=self.figure.dpi)
    381 min_dy = (lp_h - lp_d) * self._linespacing
    383 for i, line in enumerate(lines):

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:97, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
     94 """Call ``renderer.get_text_width_height_descent``, caching the results."""
     95 # Cached based on a copy of fontprop so that later in-place mutations of
     96 # the passed-in argument do not mess up the cache.
---> 97 return _get_text_metrics_with_cache_impl(
     98     weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:105, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
    101 @functools.lru_cache(4096)
    102 def _get_text_metrics_with_cache_impl(
    103         renderer_ref, text, fontprop, ismath, dpi):
    104     # dpi is unused, but participates in cache invalidation (via the renderer).
--> 105     return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:226, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
    224 _api.check_in_list(["TeX", True, False], ismath=ismath)
    225 if ismath == "TeX":
--> 226     return super().get_text_width_height_descent(s, prop, ismath)
    228 if ismath:
    229     ox, oy, width, height, descent, font_image = \
    230         self.mathtext_parser.parse(s, self.dpi, prop)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:645, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
    641 fontsize = prop.get_size_in_points()
    643 if ismath == 'TeX':
    644     # todo: handle properties
--> 645     return self.get_texmanager().get_text_width_height_descent(
    646         s, fontsize, renderer=self)
    648 dpi = self.points_to_pixels(72)
    649 if ismath:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:368, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
    366 if tex.strip() == '':
    367     return 0, 0, 0
--> 368 dvifile = cls.make_dvi(tex, fontsize)
    369 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
    370 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:300, in TexManager.make_dvi(cls, tex, fontsize)
    298     with TemporaryDirectory(dir=cwd) as tmpdir:
    299         tmppath = Path(tmpdir)
--> 300         cls._run_checked_subprocess(
    301             ["latex", "-interaction=nonstopmode", "--halt-on-error",
    302              f"--output-directory={tmppath.name}",
    303              f"{texfile.name}"], tex, cwd=cwd)
    304         (tmppath / Path(dvifile).name).replace(dvifile)
    305 return dvifile

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:259, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:
--> 259     raise RuntimeError(
    260         'Failed to process string with tex because {} could not be '
    261         'found'.format(command[0])) from exc
    262 except subprocess.CalledProcessError as exc:
    263     raise RuntimeError(
    264         '{prog} was not able to process the following string:\n'
    265         '{tex!r}\n\n'
   (...)
    272             exc=exc.output.decode('utf-8', 'backslashreplace'))
    273         ) from None

RuntimeError: Failed to process string with tex because latex could not be found
<Figure size 900x500 with 1 Axes>
plot_rates(df_real)
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
Cell In[3], line 1
----> 1 plot_rates(df_real)

Cell In[1], line 25, in plot_rates(df, fontsize, savefig)
     23 ax.legend(fontsize=fontsize, frameon=False)
     24 if savefig:
---> 25     fig.savefig(f'./figures/plot_interest_rates_{r_type}.pdf')

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/figure.py:3343, in Figure.savefig(self, fname, transparent, **kwargs)
   3339     for ax in self.axes:
   3340         stack.enter_context(
   3341             ax.patch._cm_set(facecolor='none', edgecolor='none'))
-> 3343 self.canvas.print_figure(fname, **kwargs)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:2366, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
   2362 try:
   2363     # _get_renderer may change the figure dpi (as vector formats
   2364     # force the figure dpi to 72), so we need to set it again here.
   2365     with cbook._setattr_cm(self.figure, dpi=dpi):
-> 2366         result = print_method(
   2367             filename,
   2368             facecolor=facecolor,
   2369             edgecolor=edgecolor,
   2370             orientation=orientation,
   2371             bbox_inches_restore=_bbox_inches_restore,
   2372             **kwargs)
   2373 finally:
   2374     if bbox_inches and restore_bbox:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:2232, in FigureCanvasBase._switch_canvas_and_return_print_method.<locals>.<lambda>(*args, **kwargs)
   2228     optional_kws = {  # Passed by print_figure for other renderers.
   2229         "dpi", "facecolor", "edgecolor", "orientation",
   2230         "bbox_inches_restore"}
   2231     skip = optional_kws - {*inspect.signature(meth).parameters}
-> 2232     print_method = functools.wraps(meth)(lambda *args, **kwargs: meth(
   2233         *args, **{k: v for k, v in kwargs.items() if k not in skip}))
   2234 else:  # Let third-parties do as they see fit.
   2235     print_method = meth

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_pdf.py:2808, in FigureCanvasPdf.print_pdf(self, filename, bbox_inches_restore, metadata)
   2806     file = filename._file
   2807 else:
-> 2808     file = PdfFile(filename, metadata=metadata)
   2809 try:
   2810     file.newPage(width, height)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_pdf.py:713, in PdfFile.__init__(self, filename, metadata)
    711 self.original_file_like = None
    712 self.tell_base = 0
--> 713 fh, opened = cbook.to_filehandle(filename, "wb", return_opened=True)
    714 if not opened:
    715     try:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/cbook/__init__.py:489, in to_filehandle(fname, flag, return_opened, encoding)
    487         fh = bz2.BZ2File(fname, flag)
    488     else:
--> 489         fh = open(fname, flag, encoding=encoding)
    490     opened = True
    491 elif hasattr(fname, 'seek'):

FileNotFoundError: [Errno 2] No such file or directory: './figures/plot_interest_rates_real.pdf'
Error in callback <function _draw_all_if_interactive at 0x7fd4ee9a9360> (for post_execute):
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:255, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    254 try:
--> 255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:421, in check_output(timeout, *popenargs, **kwargs)
    419     kwargs['input'] = empty
--> 421 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
    422            **kwargs).stdout

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:503, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
    501     kwargs['stderr'] = PIPE
--> 503 with Popen(*popenargs, **kwargs) as process:
    504     try:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:971, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize)
    968             self.stderr = io.TextIOWrapper(self.stderr,
    969                     encoding=encoding, errors=errors)
--> 971     self._execute_child(args, executable, preexec_fn, close_fds,
    972                         pass_fds, cwd, env,
    973                         startupinfo, creationflags, shell,
    974                         p2cread, p2cwrite,
    975                         c2pread, c2pwrite,
    976                         errread, errwrite,
    977                         restore_signals,
    978                         gid, gids, uid, umask,
    979                         start_new_session)
    980 except:
    981     # Cleanup if the child failed starting.

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:1863, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session)
   1862         err_msg = os.strerror(errno_num)
-> 1863     raise child_exception_type(errno_num, err_msg, err_filename)
   1864 raise child_exception_type(err_msg)

FileNotFoundError: [Errno 2] No such file or directory: 'latex'

The above exception was the direct cause of the following exception:

RuntimeError                              Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/pyplot.py:120, in _draw_all_if_interactive()
    118 def _draw_all_if_interactive():
    119     if matplotlib.is_interactive():
--> 120         draw_all()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/_pylab_helpers.py:132, in Gcf.draw_all(cls, force)
    130 for manager in cls.get_all_fig_managers():
    131     if force or manager.canvas.figure.stale:
--> 132         manager.canvas.draw_idle()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:2082, in FigureCanvasBase.draw_idle(self, *args, **kwargs)
   2080 if not self._is_idle_drawing:
   2081     with self._idle_draw_cntx():
-> 2082         self.draw(*args, **kwargs)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:400, in FigureCanvasAgg.draw(self)
    396 # Acquire a lock on the shared font cache.
    397 with RendererAgg.lock, \
    398      (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar
    399       else nullcontext()):
--> 400     self.figure.draw(self.renderer)
    401     # A GUI class may be need to update a window using this draw, so
    402     # don't forget to call the superclass.
    403     super().draw()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:95, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
     93 @wraps(draw)
     94 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 95     result = draw(artist, renderer, *args, **kwargs)
     96     if renderer._rasterizing:
     97         renderer.stop_rasterizing()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/figure.py:3140, in Figure.draw(self, renderer)
   3137         # ValueError can occur when resizing a window.
   3139 self.patch.draw(renderer)
-> 3140 mimage._draw_list_compositing_images(
   3141     renderer, self, artists, self.suppressComposite)
   3143 for sfig in self.subfigs:
   3144     sfig.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axes/_base.py:3064, in _AxesBase.draw(self, renderer)
   3061 if artists_rasterized:
   3062     _draw_rasterized(self.figure, artists_rasterized, renderer)
-> 3064 mimage._draw_list_compositing_images(
   3065     renderer, self, artists, self.figure.suppressComposite)
   3067 renderer.close_group('axes')
   3068 self.stale = False

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1377, in Axis.draw(self, renderer, *args, **kwargs)
   1374 renderer.open_group(__name__, gid=self.get_gid())
   1376 ticks_to_draw = self._update_ticks()
-> 1377 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
   1379 for tick in ticks_to_draw:
   1380     tick.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in <listcomp>(.0)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:959, in Text.get_window_extent(self, renderer, dpi)
    954     raise RuntimeError(
    955         "Cannot get window extent of text w/o renderer. You likely "
    956         "want to call 'figure.draw_without_rendering()' first.")
    958 with cbook._setattr_cm(self.figure, dpi=dpi):
--> 959     bbox, info, descent = self._get_layout(self._renderer)
    960     x, y = self.get_unitless_position()
    961     x, y = self.get_transform().transform((x, y))

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:378, in Text._get_layout(self, renderer)
    375 ys = []
    377 # Full vertical extent of font, including ascenders and descenders:
--> 378 _, lp_h, lp_d = _get_text_metrics_with_cache(
    379     renderer, "lp", self._fontproperties,
    380     ismath="TeX" if self.get_usetex() else False, dpi=self.figure.dpi)
    381 min_dy = (lp_h - lp_d) * self._linespacing
    383 for i, line in enumerate(lines):

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:97, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
     94 """Call ``renderer.get_text_width_height_descent``, caching the results."""
     95 # Cached based on a copy of fontprop so that later in-place mutations of
     96 # the passed-in argument do not mess up the cache.
---> 97 return _get_text_metrics_with_cache_impl(
     98     weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:105, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
    101 @functools.lru_cache(4096)
    102 def _get_text_metrics_with_cache_impl(
    103         renderer_ref, text, fontprop, ismath, dpi):
    104     # dpi is unused, but participates in cache invalidation (via the renderer).
--> 105     return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:226, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
    224 _api.check_in_list(["TeX", True, False], ismath=ismath)
    225 if ismath == "TeX":
--> 226     return super().get_text_width_height_descent(s, prop, ismath)
    228 if ismath:
    229     ox, oy, width, height, descent, font_image = \
    230         self.mathtext_parser.parse(s, self.dpi, prop)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:645, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
    641 fontsize = prop.get_size_in_points()
    643 if ismath == 'TeX':
    644     # todo: handle properties
--> 645     return self.get_texmanager().get_text_width_height_descent(
    646         s, fontsize, renderer=self)
    648 dpi = self.points_to_pixels(72)
    649 if ismath:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:368, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
    366 if tex.strip() == '':
    367     return 0, 0, 0
--> 368 dvifile = cls.make_dvi(tex, fontsize)
    369 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
    370 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:300, in TexManager.make_dvi(cls, tex, fontsize)
    298     with TemporaryDirectory(dir=cwd) as tmpdir:
    299         tmppath = Path(tmpdir)
--> 300         cls._run_checked_subprocess(
    301             ["latex", "-interaction=nonstopmode", "--halt-on-error",
    302              f"--output-directory={tmppath.name}",
    303              f"{texfile.name}"], tex, cwd=cwd)
    304         (tmppath / Path(dvifile).name).replace(dvifile)
    305 return dvifile

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:259, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:
--> 259     raise RuntimeError(
    260         'Failed to process string with tex because {} could not be '
    261         'found'.format(command[0])) from exc
    262 except subprocess.CalledProcessError as exc:
    263     raise RuntimeError(
    264         '{prog} was not able to process the following string:\n'
    265         '{tex!r}\n\n'
   (...)
    272             exc=exc.output.decode('utf-8', 'backslashreplace'))
    273         ) from None

RuntimeError: Failed to process string with tex because latex could not be found
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:255, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    254 try:
--> 255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:421, in check_output(timeout, *popenargs, **kwargs)
    419     kwargs['input'] = empty
--> 421 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
    422            **kwargs).stdout

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:503, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
    501     kwargs['stderr'] = PIPE
--> 503 with Popen(*popenargs, **kwargs) as process:
    504     try:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:971, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize)
    968             self.stderr = io.TextIOWrapper(self.stderr,
    969                     encoding=encoding, errors=errors)
--> 971     self._execute_child(args, executable, preexec_fn, close_fds,
    972                         pass_fds, cwd, env,
    973                         startupinfo, creationflags, shell,
    974                         p2cread, p2cwrite,
    975                         c2pread, c2pwrite,
    976                         errread, errwrite,
    977                         restore_signals,
    978                         gid, gids, uid, umask,
    979                         start_new_session)
    980 except:
    981     # Cleanup if the child failed starting.

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:1863, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session)
   1862         err_msg = os.strerror(errno_num)
-> 1863     raise child_exception_type(errno_num, err_msg, err_filename)
   1864 raise child_exception_type(err_msg)

FileNotFoundError: [Errno 2] No such file or directory: 'latex'

The above exception was the direct cause of the following exception:

RuntimeError                              Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/IPython/core/formatters.py:340, in BaseFormatter.__call__(self, obj)
    338     pass
    339 else:
--> 340     return printer(obj)
    341 # Finally look for special method names
    342 method = get_real_method(obj, self.print_method)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/IPython/core/pylabtools.py:152, in print_figure(fig, fmt, bbox_inches, base64, **kwargs)
    149     from matplotlib.backend_bases import FigureCanvasBase
    150     FigureCanvasBase(fig)
--> 152 fig.canvas.print_figure(bytes_io, **kw)
    153 data = bytes_io.getvalue()
    154 if fmt == 'svg':

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:2342, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
   2336     renderer = _get_renderer(
   2337         self.figure,
   2338         functools.partial(
   2339             print_method, orientation=orientation)
   2340     )
   2341     with getattr(renderer, "_draw_disabled", nullcontext)():
-> 2342         self.figure.draw(renderer)
   2344 if bbox_inches:
   2345     if bbox_inches == "tight":

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:95, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
     93 @wraps(draw)
     94 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 95     result = draw(artist, renderer, *args, **kwargs)
     96     if renderer._rasterizing:
     97         renderer.stop_rasterizing()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/figure.py:3140, in Figure.draw(self, renderer)
   3137         # ValueError can occur when resizing a window.
   3139 self.patch.draw(renderer)
-> 3140 mimage._draw_list_compositing_images(
   3141     renderer, self, artists, self.suppressComposite)
   3143 for sfig in self.subfigs:
   3144     sfig.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axes/_base.py:3064, in _AxesBase.draw(self, renderer)
   3061 if artists_rasterized:
   3062     _draw_rasterized(self.figure, artists_rasterized, renderer)
-> 3064 mimage._draw_list_compositing_images(
   3065     renderer, self, artists, self.figure.suppressComposite)
   3067 renderer.close_group('axes')
   3068 self.stale = False

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1377, in Axis.draw(self, renderer, *args, **kwargs)
   1374 renderer.open_group(__name__, gid=self.get_gid())
   1376 ticks_to_draw = self._update_ticks()
-> 1377 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
   1379 for tick in ticks_to_draw:
   1380     tick.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in <listcomp>(.0)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:959, in Text.get_window_extent(self, renderer, dpi)
    954     raise RuntimeError(
    955         "Cannot get window extent of text w/o renderer. You likely "
    956         "want to call 'figure.draw_without_rendering()' first.")
    958 with cbook._setattr_cm(self.figure, dpi=dpi):
--> 959     bbox, info, descent = self._get_layout(self._renderer)
    960     x, y = self.get_unitless_position()
    961     x, y = self.get_transform().transform((x, y))

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:378, in Text._get_layout(self, renderer)
    375 ys = []
    377 # Full vertical extent of font, including ascenders and descenders:
--> 378 _, lp_h, lp_d = _get_text_metrics_with_cache(
    379     renderer, "lp", self._fontproperties,
    380     ismath="TeX" if self.get_usetex() else False, dpi=self.figure.dpi)
    381 min_dy = (lp_h - lp_d) * self._linespacing
    383 for i, line in enumerate(lines):

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:97, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
     94 """Call ``renderer.get_text_width_height_descent``, caching the results."""
     95 # Cached based on a copy of fontprop so that later in-place mutations of
     96 # the passed-in argument do not mess up the cache.
---> 97 return _get_text_metrics_with_cache_impl(
     98     weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:105, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
    101 @functools.lru_cache(4096)
    102 def _get_text_metrics_with_cache_impl(
    103         renderer_ref, text, fontprop, ismath, dpi):
    104     # dpi is unused, but participates in cache invalidation (via the renderer).
--> 105     return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:226, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
    224 _api.check_in_list(["TeX", True, False], ismath=ismath)
    225 if ismath == "TeX":
--> 226     return super().get_text_width_height_descent(s, prop, ismath)
    228 if ismath:
    229     ox, oy, width, height, descent, font_image = \
    230         self.mathtext_parser.parse(s, self.dpi, prop)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:645, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
    641 fontsize = prop.get_size_in_points()
    643 if ismath == 'TeX':
    644     # todo: handle properties
--> 645     return self.get_texmanager().get_text_width_height_descent(
    646         s, fontsize, renderer=self)
    648 dpi = self.points_to_pixels(72)
    649 if ismath:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:368, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
    366 if tex.strip() == '':
    367     return 0, 0, 0
--> 368 dvifile = cls.make_dvi(tex, fontsize)
    369 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
    370 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:300, in TexManager.make_dvi(cls, tex, fontsize)
    298     with TemporaryDirectory(dir=cwd) as tmpdir:
    299         tmppath = Path(tmpdir)
--> 300         cls._run_checked_subprocess(
    301             ["latex", "-interaction=nonstopmode", "--halt-on-error",
    302              f"--output-directory={tmppath.name}",
    303              f"{texfile.name}"], tex, cwd=cwd)
    304         (tmppath / Path(dvifile).name).replace(dvifile)
    305 return dvifile

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:259, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:
--> 259     raise RuntimeError(
    260         'Failed to process string with tex because {} could not be '
    261         'found'.format(command[0])) from exc
    262 except subprocess.CalledProcessError as exc:
    263     raise RuntimeError(
    264         '{prog} was not able to process the following string:\n'
    265         '{tex!r}\n\n'
   (...)
    272             exc=exc.output.decode('utf-8', 'backslashreplace'))
    273         ) from None

RuntimeError: Failed to process string with tex because latex could not be found
<Figure size 900x500 with 1 Axes>

pd_ratio.py#

Hide code cell source
"""
Price-dividend ratio in a model with dividend and consumption growth.

"""

from quantecon.markov import tauchen
import numpy as np
from collections import namedtuple


# NamedTuple Model
Model = namedtuple("Model", ("x_vals", "P", "β", "γ",
                            "μ_c", "σ_c", "μ_d", "σ_d"))


def create_asset_pricing_model(
        n=200,               # state grid size
        ρ=0.9, ν=0.2,        # state persistence and volatility
        β=0.99, γ=2.5,       # discount and preference parameter
        μ_c=0.01, σ_c=0.02,  # consumption growth mean and volatility
        μ_d=0.02, σ_d=0.1):  # dividend growth mean and volatility
    """
    Creates an instance of the asset pricing model with Markov state.
    """
    mc = tauchen(n, ρ, ν)
    x_vals, P = np.exp(mc.state_values), mc.P
    return Model(x_vals=x_vals, P=P, β=β, γ=γ,
                 μ_c=μ_c, σ_c=σ_c, μ_d=μ_d, σ_d=σ_d)


def build_discount_matrix(model):
    """Build the discount matrix A."""
    x_vals, P, β, γ, μ_c, σ_c, μ_d, σ_d = model
    e = np.exp(μ_d - γ*μ_c + (γ**2 * σ_c**2 + σ_d**2)/2 + (1-γ)*x_vals)
    return β * (e * P.T).T



def pd_ratio(model):
    """
    Compute the price-dividend ratio associated with the model.
    """
    x_vals, P, β, γ, μ_c, σ_c, μ_d, σ_d = model
    A = build_discount_matrix(model)
    assert np.max(np.abs(np.linalg.eigvals(A))) < 1, "Requires r(A) < 1."
    n = len(x_vals)
    I = np.identity(n)
    return np.linalg.solve((I - A), np.dot(A, np.ones(n)))


# == Plots == #


import matplotlib.pyplot as plt
import matplotlib.pyplot as plt

plt.rcParams.update({"text.usetex": True, "font.size": 14})


default_model = create_asset_pricing_model()


def plot_main(μ_d_vals=(0.02, 0.08),
              savefig=False,
              figname="figures/pd_ratio_1.pdf"):
    fig, ax = plt.subplots(figsize=(9, 5.2))

    for μ_d in μ_d_vals:
        model = create_asset_pricing_model(μ_d=μ_d)
        x_vals, P, β, γ, μ_c, σ_c, μ_d, σ_d = model
        v_star = pd_ratio(model)
        ax.plot(x_vals, v_star, linewidth=2, alpha=0.6,
                label=r"$\mu_d$=" + f"{μ_d}")

    ax.legend(frameon=False)
    ax.set_xlabel(r"$x$")
    if savefig:
        fig.savefig(figname)
plot_main()
Error in callback <function _draw_all_if_interactive at 0x7fd4ee9a9360> (for post_execute):
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:255, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    254 try:
--> 255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:421, in check_output(timeout, *popenargs, **kwargs)
    419     kwargs['input'] = empty
--> 421 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
    422            **kwargs).stdout

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:503, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
    501     kwargs['stderr'] = PIPE
--> 503 with Popen(*popenargs, **kwargs) as process:
    504     try:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:971, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize)
    968             self.stderr = io.TextIOWrapper(self.stderr,
    969                     encoding=encoding, errors=errors)
--> 971     self._execute_child(args, executable, preexec_fn, close_fds,
    972                         pass_fds, cwd, env,
    973                         startupinfo, creationflags, shell,
    974                         p2cread, p2cwrite,
    975                         c2pread, c2pwrite,
    976                         errread, errwrite,
    977                         restore_signals,
    978                         gid, gids, uid, umask,
    979                         start_new_session)
    980 except:
    981     # Cleanup if the child failed starting.

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:1863, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session)
   1862         err_msg = os.strerror(errno_num)
-> 1863     raise child_exception_type(errno_num, err_msg, err_filename)
   1864 raise child_exception_type(err_msg)

FileNotFoundError: [Errno 2] No such file or directory: 'latex'

The above exception was the direct cause of the following exception:

RuntimeError                              Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/pyplot.py:120, in _draw_all_if_interactive()
    118 def _draw_all_if_interactive():
    119     if matplotlib.is_interactive():
--> 120         draw_all()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/_pylab_helpers.py:132, in Gcf.draw_all(cls, force)
    130 for manager in cls.get_all_fig_managers():
    131     if force or manager.canvas.figure.stale:
--> 132         manager.canvas.draw_idle()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:2082, in FigureCanvasBase.draw_idle(self, *args, **kwargs)
   2080 if not self._is_idle_drawing:
   2081     with self._idle_draw_cntx():
-> 2082         self.draw(*args, **kwargs)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:400, in FigureCanvasAgg.draw(self)
    396 # Acquire a lock on the shared font cache.
    397 with RendererAgg.lock, \
    398      (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar
    399       else nullcontext()):
--> 400     self.figure.draw(self.renderer)
    401     # A GUI class may be need to update a window using this draw, so
    402     # don't forget to call the superclass.
    403     super().draw()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:95, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
     93 @wraps(draw)
     94 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 95     result = draw(artist, renderer, *args, **kwargs)
     96     if renderer._rasterizing:
     97         renderer.stop_rasterizing()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/figure.py:3140, in Figure.draw(self, renderer)
   3137         # ValueError can occur when resizing a window.
   3139 self.patch.draw(renderer)
-> 3140 mimage._draw_list_compositing_images(
   3141     renderer, self, artists, self.suppressComposite)
   3143 for sfig in self.subfigs:
   3144     sfig.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axes/_base.py:3064, in _AxesBase.draw(self, renderer)
   3061 if artists_rasterized:
   3062     _draw_rasterized(self.figure, artists_rasterized, renderer)
-> 3064 mimage._draw_list_compositing_images(
   3065     renderer, self, artists, self.figure.suppressComposite)
   3067 renderer.close_group('axes')
   3068 self.stale = False

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1377, in Axis.draw(self, renderer, *args, **kwargs)
   1374 renderer.open_group(__name__, gid=self.get_gid())
   1376 ticks_to_draw = self._update_ticks()
-> 1377 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
   1379 for tick in ticks_to_draw:
   1380     tick.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in <listcomp>(.0)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:959, in Text.get_window_extent(self, renderer, dpi)
    954     raise RuntimeError(
    955         "Cannot get window extent of text w/o renderer. You likely "
    956         "want to call 'figure.draw_without_rendering()' first.")
    958 with cbook._setattr_cm(self.figure, dpi=dpi):
--> 959     bbox, info, descent = self._get_layout(self._renderer)
    960     x, y = self.get_unitless_position()
    961     x, y = self.get_transform().transform((x, y))

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:378, in Text._get_layout(self, renderer)
    375 ys = []
    377 # Full vertical extent of font, including ascenders and descenders:
--> 378 _, lp_h, lp_d = _get_text_metrics_with_cache(
    379     renderer, "lp", self._fontproperties,
    380     ismath="TeX" if self.get_usetex() else False, dpi=self.figure.dpi)
    381 min_dy = (lp_h - lp_d) * self._linespacing
    383 for i, line in enumerate(lines):

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:97, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
     94 """Call ``renderer.get_text_width_height_descent``, caching the results."""
     95 # Cached based on a copy of fontprop so that later in-place mutations of
     96 # the passed-in argument do not mess up the cache.
---> 97 return _get_text_metrics_with_cache_impl(
     98     weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:105, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
    101 @functools.lru_cache(4096)
    102 def _get_text_metrics_with_cache_impl(
    103         renderer_ref, text, fontprop, ismath, dpi):
    104     # dpi is unused, but participates in cache invalidation (via the renderer).
--> 105     return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:226, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
    224 _api.check_in_list(["TeX", True, False], ismath=ismath)
    225 if ismath == "TeX":
--> 226     return super().get_text_width_height_descent(s, prop, ismath)
    228 if ismath:
    229     ox, oy, width, height, descent, font_image = \
    230         self.mathtext_parser.parse(s, self.dpi, prop)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:645, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
    641 fontsize = prop.get_size_in_points()
    643 if ismath == 'TeX':
    644     # todo: handle properties
--> 645     return self.get_texmanager().get_text_width_height_descent(
    646         s, fontsize, renderer=self)
    648 dpi = self.points_to_pixels(72)
    649 if ismath:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:368, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
    366 if tex.strip() == '':
    367     return 0, 0, 0
--> 368 dvifile = cls.make_dvi(tex, fontsize)
    369 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
    370 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:300, in TexManager.make_dvi(cls, tex, fontsize)
    298     with TemporaryDirectory(dir=cwd) as tmpdir:
    299         tmppath = Path(tmpdir)
--> 300         cls._run_checked_subprocess(
    301             ["latex", "-interaction=nonstopmode", "--halt-on-error",
    302              f"--output-directory={tmppath.name}",
    303              f"{texfile.name}"], tex, cwd=cwd)
    304         (tmppath / Path(dvifile).name).replace(dvifile)
    305 return dvifile

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:259, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:
--> 259     raise RuntimeError(
    260         'Failed to process string with tex because {} could not be '
    261         'found'.format(command[0])) from exc
    262 except subprocess.CalledProcessError as exc:
    263     raise RuntimeError(
    264         '{prog} was not able to process the following string:\n'
    265         '{tex!r}\n\n'
   (...)
    272             exc=exc.output.decode('utf-8', 'backslashreplace'))
    273         ) from None

RuntimeError: Failed to process string with tex because latex could not be found
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:255, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    254 try:
--> 255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:421, in check_output(timeout, *popenargs, **kwargs)
    419     kwargs['input'] = empty
--> 421 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
    422            **kwargs).stdout

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:503, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
    501     kwargs['stderr'] = PIPE
--> 503 with Popen(*popenargs, **kwargs) as process:
    504     try:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:971, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize)
    968             self.stderr = io.TextIOWrapper(self.stderr,
    969                     encoding=encoding, errors=errors)
--> 971     self._execute_child(args, executable, preexec_fn, close_fds,
    972                         pass_fds, cwd, env,
    973                         startupinfo, creationflags, shell,
    974                         p2cread, p2cwrite,
    975                         c2pread, c2pwrite,
    976                         errread, errwrite,
    977                         restore_signals,
    978                         gid, gids, uid, umask,
    979                         start_new_session)
    980 except:
    981     # Cleanup if the child failed starting.

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:1863, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session)
   1862         err_msg = os.strerror(errno_num)
-> 1863     raise child_exception_type(errno_num, err_msg, err_filename)
   1864 raise child_exception_type(err_msg)

FileNotFoundError: [Errno 2] No such file or directory: 'latex'

The above exception was the direct cause of the following exception:

RuntimeError                              Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/IPython/core/formatters.py:340, in BaseFormatter.__call__(self, obj)
    338     pass
    339 else:
--> 340     return printer(obj)
    341 # Finally look for special method names
    342 method = get_real_method(obj, self.print_method)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/IPython/core/pylabtools.py:152, in print_figure(fig, fmt, bbox_inches, base64, **kwargs)
    149     from matplotlib.backend_bases import FigureCanvasBase
    150     FigureCanvasBase(fig)
--> 152 fig.canvas.print_figure(bytes_io, **kw)
    153 data = bytes_io.getvalue()
    154 if fmt == 'svg':

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:2342, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
   2336     renderer = _get_renderer(
   2337         self.figure,
   2338         functools.partial(
   2339             print_method, orientation=orientation)
   2340     )
   2341     with getattr(renderer, "_draw_disabled", nullcontext)():
-> 2342         self.figure.draw(renderer)
   2344 if bbox_inches:
   2345     if bbox_inches == "tight":

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:95, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
     93 @wraps(draw)
     94 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 95     result = draw(artist, renderer, *args, **kwargs)
     96     if renderer._rasterizing:
     97         renderer.stop_rasterizing()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/figure.py:3140, in Figure.draw(self, renderer)
   3137         # ValueError can occur when resizing a window.
   3139 self.patch.draw(renderer)
-> 3140 mimage._draw_list_compositing_images(
   3141     renderer, self, artists, self.suppressComposite)
   3143 for sfig in self.subfigs:
   3144     sfig.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axes/_base.py:3064, in _AxesBase.draw(self, renderer)
   3061 if artists_rasterized:
   3062     _draw_rasterized(self.figure, artists_rasterized, renderer)
-> 3064 mimage._draw_list_compositing_images(
   3065     renderer, self, artists, self.figure.suppressComposite)
   3067 renderer.close_group('axes')
   3068 self.stale = False

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1377, in Axis.draw(self, renderer, *args, **kwargs)
   1374 renderer.open_group(__name__, gid=self.get_gid())
   1376 ticks_to_draw = self._update_ticks()
-> 1377 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
   1379 for tick in ticks_to_draw:
   1380     tick.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in <listcomp>(.0)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:959, in Text.get_window_extent(self, renderer, dpi)
    954     raise RuntimeError(
    955         "Cannot get window extent of text w/o renderer. You likely "
    956         "want to call 'figure.draw_without_rendering()' first.")
    958 with cbook._setattr_cm(self.figure, dpi=dpi):
--> 959     bbox, info, descent = self._get_layout(self._renderer)
    960     x, y = self.get_unitless_position()
    961     x, y = self.get_transform().transform((x, y))

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:378, in Text._get_layout(self, renderer)
    375 ys = []
    377 # Full vertical extent of font, including ascenders and descenders:
--> 378 _, lp_h, lp_d = _get_text_metrics_with_cache(
    379     renderer, "lp", self._fontproperties,
    380     ismath="TeX" if self.get_usetex() else False, dpi=self.figure.dpi)
    381 min_dy = (lp_h - lp_d) * self._linespacing
    383 for i, line in enumerate(lines):

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:97, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
     94 """Call ``renderer.get_text_width_height_descent``, caching the results."""
     95 # Cached based on a copy of fontprop so that later in-place mutations of
     96 # the passed-in argument do not mess up the cache.
---> 97 return _get_text_metrics_with_cache_impl(
     98     weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:105, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
    101 @functools.lru_cache(4096)
    102 def _get_text_metrics_with_cache_impl(
    103         renderer_ref, text, fontprop, ismath, dpi):
    104     # dpi is unused, but participates in cache invalidation (via the renderer).
--> 105     return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:226, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
    224 _api.check_in_list(["TeX", True, False], ismath=ismath)
    225 if ismath == "TeX":
--> 226     return super().get_text_width_height_descent(s, prop, ismath)
    228 if ismath:
    229     ox, oy, width, height, descent, font_image = \
    230         self.mathtext_parser.parse(s, self.dpi, prop)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:645, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
    641 fontsize = prop.get_size_in_points()
    643 if ismath == 'TeX':
    644     # todo: handle properties
--> 645     return self.get_texmanager().get_text_width_height_descent(
    646         s, fontsize, renderer=self)
    648 dpi = self.points_to_pixels(72)
    649 if ismath:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:368, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
    366 if tex.strip() == '':
    367     return 0, 0, 0
--> 368 dvifile = cls.make_dvi(tex, fontsize)
    369 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
    370 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:300, in TexManager.make_dvi(cls, tex, fontsize)
    298     with TemporaryDirectory(dir=cwd) as tmpdir:
    299         tmppath = Path(tmpdir)
--> 300         cls._run_checked_subprocess(
    301             ["latex", "-interaction=nonstopmode", "--halt-on-error",
    302              f"--output-directory={tmppath.name}",
    303              f"{texfile.name}"], tex, cwd=cwd)
    304         (tmppath / Path(dvifile).name).replace(dvifile)
    305 return dvifile

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:259, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:
--> 259     raise RuntimeError(
    260         'Failed to process string with tex because {} could not be '
    261         'found'.format(command[0])) from exc
    262 except subprocess.CalledProcessError as exc:
    263     raise RuntimeError(
    264         '{prog} was not able to process the following string:\n'
    265         '{tex!r}\n\n'
   (...)
    272             exc=exc.output.decode('utf-8', 'backslashreplace'))
    273         ) from None

RuntimeError: Failed to process string with tex because latex could not be found
<Figure size 900x520 with 1 Axes>

inventory_sdd.py#

Hide code cell source
"""

Inventory management model with state-dependent discounting. The discount
factor takes the form β_t = Z_t, where (Z_t) is a discretization of a
Gaussian AR(1) process

    X_t = ρ X_{t-1} + b + ν W_t.

"""

from quantecon import compute_fixed_point
from quantecon.markov import tauchen, MarkovChain

import numpy as np
from time import time
from numba import njit, prange
from collections import namedtuple

# NamedTuple Model
Model = namedtuple("Model", ("K", "c", "κ", "p", "r", 
                             "R", "y_vals", "z_vals", "Q"))


@njit
def ϕ(p, d):
    return (1 - p)**d * p

@njit
def f(y, a, d):
    return np.maximum(y - d, 0) + a  # Inventory update

def create_sdd_inventory_model(
            ρ=0.98, ν=0.002, n_z=20, b=0.97,  # Z state parameters
            K=40, c=0.2, κ=0.8, p=0.6,        # firm and demand parameters
            d_max=100):                        # truncation of demand shock
    d_vals = np.arange(d_max+1)
    ϕ_vals = ϕ(p, d_vals)
    y_vals = np.arange(K+1)
    n_y = len(y_vals)
    mc = tauchen(n_z, ρ, ν)
    z_vals, Q = mc.state_values + b, mc.P
    ρL = np.max(np.abs(np.linalg.eigvals(z_vals * Q)))
    assert ρL < 1, "Error: ρ(L) >= 1."    # check r(L) < 1

    R = np.zeros((n_y, n_y, n_y))
    for i_y, y in enumerate(y_vals):
        for i_y_1, y_1 in enumerate(y_vals):
            for i_a, a in enumerate(range(K - y + 1)):
                hits = [f(y, a, d) == y_1 for d in d_vals]
                R[i_y, i_a, i_y_1] = np.dot(hits, ϕ_vals)


    r = np.empty((n_y, n_y))
    for i_y, y in enumerate(y_vals):
        for i_a, a in enumerate(range(K - y + 1)):
            cost = c * a + κ * (a > 0)
            r[i_y, i_a] = np.dot(np.minimum(y, d_vals),  ϕ_vals) - cost


    return Model(K=K, c=c, κ=κ, p=p, r=r, R=R, 
                 y_vals=y_vals, z_vals=z_vals, Q=Q)

@njit
def B(i_y, i_z, i_a, v, model):
    """
    The function B(x, z, a, v) = r(x, a) + β(z) Σ_x′ v(x′) P(x, a, x′).
    """
    K, c, κ, p, r, R, y_vals, z_vals, Q = model
    β = z_vals[i_z]
    cv = 0.0

    for i_z_1 in prange(len(z_vals)):
        for i_y_1 in prange(len(y_vals)):
            cv += v[i_y_1, i_z_1] * R[i_y, i_a, i_y_1] * Q[i_z, i_z_1]
    return r[i_y, i_a] + β * cv

@njit(parallel=True)
def T(v, model):
    """The Bellman operator."""
    K, c, κ, p, r, R, y_vals, z_vals, Q = model
    new_v = np.empty_like(v)
    for i_z in prange(len(z_vals)):
        for (i_y, y) in enumerate(y_vals):
            Γy = np.arange(K - y + 1)
            new_v[i_y, i_z] = np.max(np.array([B(i_y, i_z, i_a, v, model) 
                               for i_a in Γy]))
    return new_v

@njit
def T_σ(v, σ, model):
    """The policy operator."""
    K, c, κ, p, r, R, y_vals, z_vals, Q = model
    new_v = np.empty_like(v)
    for (i_z, z) in enumerate(z_vals):
        for (i_y, y) in enumerate(y_vals):
            new_v[i_y, i_z] = B(i_y, i_z, σ[i_y, i_z], v, model)
    return new_v

@njit(parallel=True)
def get_greedy(v, model):
    """Get a v-greedy policy.  Returns a zero-based array."""
    K, c, κ, p, r, R, y_vals, z_vals, Q = model
    n_z = len(z_vals)
    σ_star = np.zeros((K+1, n_z), dtype=np.int32)
    for (i_z, z) in enumerate(z_vals):
        for (i_y, y) in enumerate(y_vals):
            Γy = np.arange(K - y + 1)
            i_a = np.argmax(np.array([B(i_y, i_z, i_a, v, model) 
                               for i_a in Γy]))
            σ_star[i_y, i_z] = Γy[i_a]
    return σ_star

@njit
def get_value(v_init, σ, m, model):
    """Approximate lifetime value of policy σ."""
    v = v_init
    for _ in range(m):
        v = T_σ(v, σ, model)
    return v

def solve_inventory_model(v_init, model):
    """Use successive_approx to get v_star and then compute greedy."""
    v_star = compute_fixed_point(lambda v: T(v, model), v_init,
                                 error_tol=1e-5, max_iter=1000, print_skip=25)
    σ_star = get_greedy(v_star, model)
    return v_star, σ_star

def optimistic_policy_iteration(v_init, 
                                model,
                                tolerance=1e-6, 
                                max_iter=1_000,
                                print_step=10,
                                m=60):
    v = v_init
    error = tolerance + 1
    k = 1
    while (error > tolerance) and (k < max_iter):
        last_v = v
        σ = get_greedy(v, model)
        v = get_value(v, σ, m, model)
        error = np.max(np.abs(v - last_v))
        if k % print_step == 0:
            print(f"Completed iteration {k} with error {error}.")
        k += 1
    return v, get_greedy(v, model)


# == Plots == #

import matplotlib.pyplot as plt
import matplotlib.pyplot as plt

plt.rcParams.update({"text.usetex": True, "font.size": 14})

# Create an instance of the model and solve it
model = create_sdd_inventory_model()
K, c, κ, p, r, R, y_vals, z_vals, Q = model
n_z = len(z_vals)
v_init = np.zeros((K+1, n_z), dtype=float)
print("Solving model.")
v_star, σ_star = optimistic_policy_iteration(v_init, model)
z_mc = MarkovChain(Q, z_vals)

def sim_inventories(ts_length, X_init=0):
    """Simulate given the optimal policy."""
    global p, z_mc
    i_z = z_mc.simulate_indices(ts_length, init=1)
    X = np.zeros(ts_length, dtype=np.int32)
    X[0] = X_init
    rand = np.random.default_rng().geometric(p=p, size=ts_length-1) - 1
    for t in range(ts_length-1):
        X[t+1] = f(X[t], σ_star[X[t], i_z[t]], rand[t])
    return X, z_vals[i_z]

def plot_ts(ts_length=400,
            fontsize=10,
            figname="figures/inventory_sdd_ts.pdf",
            savefig=False):
    
    X, Z = sim_inventories(ts_length)
    fig, axes = plt.subplots(2, 1, figsize=(9, 5.5))

    ax = axes[0]
    ax.plot(X, label="inventory", alpha=0.7)
    ax.set_xlabel(r"$t$", fontsize=fontsize)
    ax.legend(fontsize=fontsize, frameon=False)
    ax.set_ylim(0, np.max(X)+3)

    # calculate interest rate from discount factors
    r = (1 / Z) - 1

    ax = axes[1]
    ax.plot(r, label=r"$r_t$", alpha=0.7)
    ax.set_xlabel(r"$t$", fontsize=fontsize)
    ax.legend(fontsize=fontsize, frameon=False)

    plt.tight_layout()
    if savefig:
        fig.savefig(figname)

def plot_timing(m_vals=np.arange(1, 400, 10),
                fontsize=16,
                savefig=False):
    print("Running value function iteration.")
    t_start = time()
    solve_inventory_model(v_init, model)
    vfi_time = time() - t_start
    print(f"VFI completed in {vfi_time} seconds.")
    opi_times = []
    for m in m_vals:
        print(f"Running optimistic policy iteration with m = {m}.")
        t_start = time()
        optimistic_policy_iteration(v_init, model, m=m)
        opi_time = time() - t_start
        print(f"OPI with m = {m} completed in {opi_time} seconds.")
        opi_times.append(opi_time)
    fig, ax = plt.subplots(figsize=(9, 5.2))
    ax.plot(m_vals, np.full(len(m_vals), vfi_time),
            lw=2, label="value function iteration")
    ax.plot(m_vals, opi_times, lw=2, label="optimistic policy iteration")
    ax.legend(fontsize=fontsize, frameon=False)
    ax.set_xlabel(r"$m$", fontsize=fontsize)
    ax.set_ylabel("time", fontsize=fontsize)
    if savefig:
        fig.savefig("figures/inventory_sdd_timing.pdf")
    return (opi_time, vfi_time, opi_times)
Solving model.
Completed iteration 10 with error 0.0013695502548856098.
plot_ts()
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:255, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    254 try:
--> 255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:421, in check_output(timeout, *popenargs, **kwargs)
    419     kwargs['input'] = empty
--> 421 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
    422            **kwargs).stdout

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:503, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
    501     kwargs['stderr'] = PIPE
--> 503 with Popen(*popenargs, **kwargs) as process:
    504     try:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:971, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize)
    968             self.stderr = io.TextIOWrapper(self.stderr,
    969                     encoding=encoding, errors=errors)
--> 971     self._execute_child(args, executable, preexec_fn, close_fds,
    972                         pass_fds, cwd, env,
    973                         startupinfo, creationflags, shell,
    974                         p2cread, p2cwrite,
    975                         c2pread, c2pwrite,
    976                         errread, errwrite,
    977                         restore_signals,
    978                         gid, gids, uid, umask,
    979                         start_new_session)
    980 except:
    981     # Cleanup if the child failed starting.

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:1863, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session)
   1862         err_msg = os.strerror(errno_num)
-> 1863     raise child_exception_type(errno_num, err_msg, err_filename)
   1864 raise child_exception_type(err_msg)

FileNotFoundError: [Errno 2] No such file or directory: 'latex'

The above exception was the direct cause of the following exception:

RuntimeError                              Traceback (most recent call last)
Cell In[7], line 1
----> 1 plot_ts()

Cell In[6], line 197, in plot_ts(ts_length, fontsize, figname, savefig)
    194 ax.set_xlabel(r"$t$", fontsize=fontsize)
    195 ax.legend(fontsize=fontsize, frameon=False)
--> 197 plt.tight_layout()
    198 if savefig:
    199     fig.savefig(figname)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/pyplot.py:2349, in tight_layout(pad, h_pad, w_pad, rect)
   2347 @_copy_docstring_and_deprecators(Figure.tight_layout)
   2348 def tight_layout(*, pad=1.08, h_pad=None, w_pad=None, rect=None):
-> 2349     return gcf().tight_layout(pad=pad, h_pad=h_pad, w_pad=w_pad, rect=rect)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/figure.py:3509, in Figure.tight_layout(self, pad, h_pad, w_pad, rect)
   3507 previous_engine = self.get_layout_engine()
   3508 self.set_layout_engine(engine)
-> 3509 engine.execute(self)
   3510 if not isinstance(previous_engine, TightLayoutEngine) \
   3511         and previous_engine is not None:
   3512     _api.warn_external('The figure layout has changed to tight')

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/layout_engine.py:178, in TightLayoutEngine.execute(self, fig)
    176 renderer = fig._get_renderer()
    177 with getattr(renderer, "_draw_disabled", nullcontext)():
--> 178     kwargs = get_tight_layout_figure(
    179         fig, fig.axes, get_subplotspec_list(fig.axes), renderer,
    180         pad=info['pad'], h_pad=info['h_pad'], w_pad=info['w_pad'],
    181         rect=info['rect'])
    182 if kwargs:
    183     fig.subplots_adjust(**kwargs)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/_tight_layout.py:266, in get_tight_layout_figure(fig, axes_list, subplotspec_list, renderer, pad, h_pad, w_pad, rect)
    261         return {}
    262     span_pairs.append((
    263         slice(ss.rowspan.start * div_row, ss.rowspan.stop * div_row),
    264         slice(ss.colspan.start * div_col, ss.colspan.stop * div_col)))
--> 266 kwargs = _auto_adjust_subplotpars(fig, renderer,
    267                                   shape=(max_nrows, max_ncols),
    268                                   span_pairs=span_pairs,
    269                                   subplot_list=subplot_list,
    270                                   ax_bbox_list=ax_bbox_list,
    271                                   pad=pad, h_pad=h_pad, w_pad=w_pad)
    273 # kwargs can be none if tight_layout fails...
    274 if rect is not None and kwargs is not None:
    275     # if rect is given, the whole subplots area (including
    276     # labels) will fit into the rect instead of the
   (...)
    280     # auto_adjust_subplotpars twice, where the second run
    281     # with adjusted rect parameters.

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/_tight_layout.py:82, in _auto_adjust_subplotpars(fig, renderer, shape, span_pairs, subplot_list, ax_bbox_list, pad, h_pad, w_pad, rect)
     80 for ax in subplots:
     81     if ax.get_visible():
---> 82         bb += [martist._get_tightbbox_for_layout_only(ax, renderer)]
     84 tight_bbox_raw = Bbox.union(bb)
     85 tight_bbox = fig.transFigure.inverted().transform_bbox(tight_bbox_raw)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:1415, in _get_tightbbox_for_layout_only(obj, *args, **kwargs)
   1409 """
   1410 Matplotlib's `.Axes.get_tightbbox` and `.Axis.get_tightbbox` support a
   1411 *for_layout_only* kwarg; this helper tries to use the kwarg but skips it
   1412 when encountering third-party subclasses that do not support it.
   1413 """
   1414 try:
-> 1415     return obj.get_tightbbox(*args, **{**kwargs, "for_layout_only": True})
   1416 except TypeError:
   1417     return obj.get_tightbbox(*args, **kwargs)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axes/_base.py:4385, in _AxesBase.get_tightbbox(self, renderer, call_axes_locator, bbox_extra_artists, for_layout_only)
   4383 for axis in self._axis_map.values():
   4384     if self.axison and axis.get_visible():
-> 4385         ba = martist._get_tightbbox_for_layout_only(axis, renderer)
   4386         if ba:
   4387             bb.append(ba)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:1415, in _get_tightbbox_for_layout_only(obj, *args, **kwargs)
   1409 """
   1410 Matplotlib's `.Axes.get_tightbbox` and `.Axis.get_tightbbox` support a
   1411 *for_layout_only* kwarg; this helper tries to use the kwarg but skips it
   1412 when encountering third-party subclasses that do not support it.
   1413 """
   1414 try:
-> 1415     return obj.get_tightbbox(*args, **{**kwargs, "for_layout_only": True})
   1416 except TypeError:
   1417     return obj.get_tightbbox(*args, **kwargs)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1325, in Axis.get_tightbbox(self, renderer, for_layout_only)
   1322     renderer = self.figure._get_renderer()
   1323 ticks_to_draw = self._update_ticks()
-> 1325 self._update_label_position(renderer)
   1327 # go back to just this axis's tick labels
   1328 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:2304, in XAxis._update_label_position(self, renderer)
   2300     return
   2302 # get bounding boxes for this axis and any siblings
   2303 # that have been set by `fig.align_xlabels()`
-> 2304 bboxes, bboxes2 = self._get_tick_boxes_siblings(renderer=renderer)
   2306 x, y = self.label.get_position()
   2307 if self.label_position == 'bottom':

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:2100, in Axis._get_tick_boxes_siblings(self, renderer)
   2098 axis = getattr(ax, f"{axis_name}axis")
   2099 ticks_to_draw = axis._update_ticks()
-> 2100 tlb, tlb2 = axis._get_ticklabel_bboxes(ticks_to_draw, renderer)
   2101 bboxes.extend(tlb)
   2102 bboxes2.extend(tlb2)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in <listcomp>(.0)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:959, in Text.get_window_extent(self, renderer, dpi)
    954     raise RuntimeError(
    955         "Cannot get window extent of text w/o renderer. You likely "
    956         "want to call 'figure.draw_without_rendering()' first.")
    958 with cbook._setattr_cm(self.figure, dpi=dpi):
--> 959     bbox, info, descent = self._get_layout(self._renderer)
    960     x, y = self.get_unitless_position()
    961     x, y = self.get_transform().transform((x, y))

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:378, in Text._get_layout(self, renderer)
    375 ys = []
    377 # Full vertical extent of font, including ascenders and descenders:
--> 378 _, lp_h, lp_d = _get_text_metrics_with_cache(
    379     renderer, "lp", self._fontproperties,
    380     ismath="TeX" if self.get_usetex() else False, dpi=self.figure.dpi)
    381 min_dy = (lp_h - lp_d) * self._linespacing
    383 for i, line in enumerate(lines):

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:97, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
     94 """Call ``renderer.get_text_width_height_descent``, caching the results."""
     95 # Cached based on a copy of fontprop so that later in-place mutations of
     96 # the passed-in argument do not mess up the cache.
---> 97 return _get_text_metrics_with_cache_impl(
     98     weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:105, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
    101 @functools.lru_cache(4096)
    102 def _get_text_metrics_with_cache_impl(
    103         renderer_ref, text, fontprop, ismath, dpi):
    104     # dpi is unused, but participates in cache invalidation (via the renderer).
--> 105     return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:226, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
    224 _api.check_in_list(["TeX", True, False], ismath=ismath)
    225 if ismath == "TeX":
--> 226     return super().get_text_width_height_descent(s, prop, ismath)
    228 if ismath:
    229     ox, oy, width, height, descent, font_image = \
    230         self.mathtext_parser.parse(s, self.dpi, prop)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:645, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
    641 fontsize = prop.get_size_in_points()
    643 if ismath == 'TeX':
    644     # todo: handle properties
--> 645     return self.get_texmanager().get_text_width_height_descent(
    646         s, fontsize, renderer=self)
    648 dpi = self.points_to_pixels(72)
    649 if ismath:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:368, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
    366 if tex.strip() == '':
    367     return 0, 0, 0
--> 368 dvifile = cls.make_dvi(tex, fontsize)
    369 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
    370 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:300, in TexManager.make_dvi(cls, tex, fontsize)
    298     with TemporaryDirectory(dir=cwd) as tmpdir:
    299         tmppath = Path(tmpdir)
--> 300         cls._run_checked_subprocess(
    301             ["latex", "-interaction=nonstopmode", "--halt-on-error",
    302              f"--output-directory={tmppath.name}",
    303              f"{texfile.name}"], tex, cwd=cwd)
    304         (tmppath / Path(dvifile).name).replace(dvifile)
    305 return dvifile

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:259, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:
--> 259     raise RuntimeError(
    260         'Failed to process string with tex because {} could not be '
    261         'found'.format(command[0])) from exc
    262 except subprocess.CalledProcessError as exc:
    263     raise RuntimeError(
    264         '{prog} was not able to process the following string:\n'
    265         '{tex!r}\n\n'
   (...)
    272             exc=exc.output.decode('utf-8', 'backslashreplace'))
    273         ) from None

RuntimeError: Failed to process string with tex because latex could not be found
Error in callback <function _draw_all_if_interactive at 0x7fd4ee9a9360> (for post_execute):
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:255, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    254 try:
--> 255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:421, in check_output(timeout, *popenargs, **kwargs)
    419     kwargs['input'] = empty
--> 421 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
    422            **kwargs).stdout

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:503, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
    501     kwargs['stderr'] = PIPE
--> 503 with Popen(*popenargs, **kwargs) as process:
    504     try:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:971, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize)
    968             self.stderr = io.TextIOWrapper(self.stderr,
    969                     encoding=encoding, errors=errors)
--> 971     self._execute_child(args, executable, preexec_fn, close_fds,
    972                         pass_fds, cwd, env,
    973                         startupinfo, creationflags, shell,
    974                         p2cread, p2cwrite,
    975                         c2pread, c2pwrite,
    976                         errread, errwrite,
    977                         restore_signals,
    978                         gid, gids, uid, umask,
    979                         start_new_session)
    980 except:
    981     # Cleanup if the child failed starting.

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:1863, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session)
   1862         err_msg = os.strerror(errno_num)
-> 1863     raise child_exception_type(errno_num, err_msg, err_filename)
   1864 raise child_exception_type(err_msg)

FileNotFoundError: [Errno 2] No such file or directory: 'latex'

The above exception was the direct cause of the following exception:

RuntimeError                              Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/pyplot.py:120, in _draw_all_if_interactive()
    118 def _draw_all_if_interactive():
    119     if matplotlib.is_interactive():
--> 120         draw_all()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/_pylab_helpers.py:132, in Gcf.draw_all(cls, force)
    130 for manager in cls.get_all_fig_managers():
    131     if force or manager.canvas.figure.stale:
--> 132         manager.canvas.draw_idle()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:2082, in FigureCanvasBase.draw_idle(self, *args, **kwargs)
   2080 if not self._is_idle_drawing:
   2081     with self._idle_draw_cntx():
-> 2082         self.draw(*args, **kwargs)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:400, in FigureCanvasAgg.draw(self)
    396 # Acquire a lock on the shared font cache.
    397 with RendererAgg.lock, \
    398      (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar
    399       else nullcontext()):
--> 400     self.figure.draw(self.renderer)
    401     # A GUI class may be need to update a window using this draw, so
    402     # don't forget to call the superclass.
    403     super().draw()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:95, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
     93 @wraps(draw)
     94 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 95     result = draw(artist, renderer, *args, **kwargs)
     96     if renderer._rasterizing:
     97         renderer.stop_rasterizing()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/figure.py:3140, in Figure.draw(self, renderer)
   3137         # ValueError can occur when resizing a window.
   3139 self.patch.draw(renderer)
-> 3140 mimage._draw_list_compositing_images(
   3141     renderer, self, artists, self.suppressComposite)
   3143 for sfig in self.subfigs:
   3144     sfig.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axes/_base.py:3064, in _AxesBase.draw(self, renderer)
   3061 if artists_rasterized:
   3062     _draw_rasterized(self.figure, artists_rasterized, renderer)
-> 3064 mimage._draw_list_compositing_images(
   3065     renderer, self, artists, self.figure.suppressComposite)
   3067 renderer.close_group('axes')
   3068 self.stale = False

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1377, in Axis.draw(self, renderer, *args, **kwargs)
   1374 renderer.open_group(__name__, gid=self.get_gid())
   1376 ticks_to_draw = self._update_ticks()
-> 1377 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
   1379 for tick in ticks_to_draw:
   1380     tick.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in <listcomp>(.0)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:959, in Text.get_window_extent(self, renderer, dpi)
    954     raise RuntimeError(
    955         "Cannot get window extent of text w/o renderer. You likely "
    956         "want to call 'figure.draw_without_rendering()' first.")
    958 with cbook._setattr_cm(self.figure, dpi=dpi):
--> 959     bbox, info, descent = self._get_layout(self._renderer)
    960     x, y = self.get_unitless_position()
    961     x, y = self.get_transform().transform((x, y))

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:378, in Text._get_layout(self, renderer)
    375 ys = []
    377 # Full vertical extent of font, including ascenders and descenders:
--> 378 _, lp_h, lp_d = _get_text_metrics_with_cache(
    379     renderer, "lp", self._fontproperties,
    380     ismath="TeX" if self.get_usetex() else False, dpi=self.figure.dpi)
    381 min_dy = (lp_h - lp_d) * self._linespacing
    383 for i, line in enumerate(lines):

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:97, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
     94 """Call ``renderer.get_text_width_height_descent``, caching the results."""
     95 # Cached based on a copy of fontprop so that later in-place mutations of
     96 # the passed-in argument do not mess up the cache.
---> 97 return _get_text_metrics_with_cache_impl(
     98     weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:105, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
    101 @functools.lru_cache(4096)
    102 def _get_text_metrics_with_cache_impl(
    103         renderer_ref, text, fontprop, ismath, dpi):
    104     # dpi is unused, but participates in cache invalidation (via the renderer).
--> 105     return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:226, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
    224 _api.check_in_list(["TeX", True, False], ismath=ismath)
    225 if ismath == "TeX":
--> 226     return super().get_text_width_height_descent(s, prop, ismath)
    228 if ismath:
    229     ox, oy, width, height, descent, font_image = \
    230         self.mathtext_parser.parse(s, self.dpi, prop)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:645, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
    641 fontsize = prop.get_size_in_points()
    643 if ismath == 'TeX':
    644     # todo: handle properties
--> 645     return self.get_texmanager().get_text_width_height_descent(
    646         s, fontsize, renderer=self)
    648 dpi = self.points_to_pixels(72)
    649 if ismath:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:368, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
    366 if tex.strip() == '':
    367     return 0, 0, 0
--> 368 dvifile = cls.make_dvi(tex, fontsize)
    369 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
    370 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:300, in TexManager.make_dvi(cls, tex, fontsize)
    298     with TemporaryDirectory(dir=cwd) as tmpdir:
    299         tmppath = Path(tmpdir)
--> 300         cls._run_checked_subprocess(
    301             ["latex", "-interaction=nonstopmode", "--halt-on-error",
    302              f"--output-directory={tmppath.name}",
    303              f"{texfile.name}"], tex, cwd=cwd)
    304         (tmppath / Path(dvifile).name).replace(dvifile)
    305 return dvifile

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:259, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:
--> 259     raise RuntimeError(
    260         'Failed to process string with tex because {} could not be '
    261         'found'.format(command[0])) from exc
    262 except subprocess.CalledProcessError as exc:
    263     raise RuntimeError(
    264         '{prog} was not able to process the following string:\n'
    265         '{tex!r}\n\n'
   (...)
    272             exc=exc.output.decode('utf-8', 'backslashreplace'))
    273         ) from None

RuntimeError: Failed to process string with tex because latex could not be found
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:255, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    254 try:
--> 255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:421, in check_output(timeout, *popenargs, **kwargs)
    419     kwargs['input'] = empty
--> 421 return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
    422            **kwargs).stdout

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:503, in run(input, capture_output, timeout, check, *popenargs, **kwargs)
    501     kwargs['stderr'] = PIPE
--> 503 with Popen(*popenargs, **kwargs) as process:
    504     try:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:971, in Popen.__init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags, restore_signals, start_new_session, pass_fds, user, group, extra_groups, encoding, errors, text, umask, pipesize)
    968             self.stderr = io.TextIOWrapper(self.stderr,
    969                     encoding=encoding, errors=errors)
--> 971     self._execute_child(args, executable, preexec_fn, close_fds,
    972                         pass_fds, cwd, env,
    973                         startupinfo, creationflags, shell,
    974                         p2cread, p2cwrite,
    975                         c2pread, c2pwrite,
    976                         errread, errwrite,
    977                         restore_signals,
    978                         gid, gids, uid, umask,
    979                         start_new_session)
    980 except:
    981     # Cleanup if the child failed starting.

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/subprocess.py:1863, in Popen._execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session)
   1862         err_msg = os.strerror(errno_num)
-> 1863     raise child_exception_type(errno_num, err_msg, err_filename)
   1864 raise child_exception_type(err_msg)

FileNotFoundError: [Errno 2] No such file or directory: 'latex'

The above exception was the direct cause of the following exception:

RuntimeError                              Traceback (most recent call last)
File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/IPython/core/formatters.py:340, in BaseFormatter.__call__(self, obj)
    338     pass
    339 else:
--> 340     return printer(obj)
    341 # Finally look for special method names
    342 method = get_real_method(obj, self.print_method)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/IPython/core/pylabtools.py:152, in print_figure(fig, fmt, bbox_inches, base64, **kwargs)
    149     from matplotlib.backend_bases import FigureCanvasBase
    150     FigureCanvasBase(fig)
--> 152 fig.canvas.print_figure(bytes_io, **kw)
    153 data = bytes_io.getvalue()
    154 if fmt == 'svg':

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:2342, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
   2336     renderer = _get_renderer(
   2337         self.figure,
   2338         functools.partial(
   2339             print_method, orientation=orientation)
   2340     )
   2341     with getattr(renderer, "_draw_disabled", nullcontext)():
-> 2342         self.figure.draw(renderer)
   2344 if bbox_inches:
   2345     if bbox_inches == "tight":

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:95, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
     93 @wraps(draw)
     94 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 95     result = draw(artist, renderer, *args, **kwargs)
     96     if renderer._rasterizing:
     97         renderer.stop_rasterizing()

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/figure.py:3140, in Figure.draw(self, renderer)
   3137         # ValueError can occur when resizing a window.
   3139 self.patch.draw(renderer)
-> 3140 mimage._draw_list_compositing_images(
   3141     renderer, self, artists, self.suppressComposite)
   3143 for sfig in self.subfigs:
   3144     sfig.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axes/_base.py:3064, in _AxesBase.draw(self, renderer)
   3061 if artists_rasterized:
   3062     _draw_rasterized(self.figure, artists_rasterized, renderer)
-> 3064 mimage._draw_list_compositing_images(
   3065     renderer, self, artists, self.figure.suppressComposite)
   3067 renderer.close_group('axes')
   3068 self.stale = False

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/image.py:131, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    129 if not_composite or not has_images:
    130     for a in artists:
--> 131         a.draw(renderer)
    132 else:
    133     # Composite any adjacent images together
    134     image_group = []

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1377, in Axis.draw(self, renderer, *args, **kwargs)
   1374 renderer.open_group(__name__, gid=self.get_gid())
   1376 ticks_to_draw = self._update_ticks()
-> 1377 tlb1, tlb2 = self._get_ticklabel_bboxes(ticks_to_draw, renderer)
   1379 for tick in ticks_to_draw:
   1380     tick.draw(renderer)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in Axis._get_ticklabel_bboxes(self, ticks, renderer)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/axis.py:1304, in <listcomp>(.0)
   1302 if renderer is None:
   1303     renderer = self.figure._get_renderer()
-> 1304 return ([tick.label1.get_window_extent(renderer)
   1305          for tick in ticks if tick.label1.get_visible()],
   1306         [tick.label2.get_window_extent(renderer)
   1307          for tick in ticks if tick.label2.get_visible()])

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:959, in Text.get_window_extent(self, renderer, dpi)
    954     raise RuntimeError(
    955         "Cannot get window extent of text w/o renderer. You likely "
    956         "want to call 'figure.draw_without_rendering()' first.")
    958 with cbook._setattr_cm(self.figure, dpi=dpi):
--> 959     bbox, info, descent = self._get_layout(self._renderer)
    960     x, y = self.get_unitless_position()
    961     x, y = self.get_transform().transform((x, y))

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:378, in Text._get_layout(self, renderer)
    375 ys = []
    377 # Full vertical extent of font, including ascenders and descenders:
--> 378 _, lp_h, lp_d = _get_text_metrics_with_cache(
    379     renderer, "lp", self._fontproperties,
    380     ismath="TeX" if self.get_usetex() else False, dpi=self.figure.dpi)
    381 min_dy = (lp_h - lp_d) * self._linespacing
    383 for i, line in enumerate(lines):

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:97, in _get_text_metrics_with_cache(renderer, text, fontprop, ismath, dpi)
     94 """Call ``renderer.get_text_width_height_descent``, caching the results."""
     95 # Cached based on a copy of fontprop so that later in-place mutations of
     96 # the passed-in argument do not mess up the cache.
---> 97 return _get_text_metrics_with_cache_impl(
     98     weakref.ref(renderer), text, fontprop.copy(), ismath, dpi)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/text.py:105, in _get_text_metrics_with_cache_impl(renderer_ref, text, fontprop, ismath, dpi)
    101 @functools.lru_cache(4096)
    102 def _get_text_metrics_with_cache_impl(
    103         renderer_ref, text, fontprop, ismath, dpi):
    104     # dpi is unused, but participates in cache invalidation (via the renderer).
--> 105     return renderer_ref().get_text_width_height_descent(text, fontprop, ismath)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backends/backend_agg.py:226, in RendererAgg.get_text_width_height_descent(self, s, prop, ismath)
    224 _api.check_in_list(["TeX", True, False], ismath=ismath)
    225 if ismath == "TeX":
--> 226     return super().get_text_width_height_descent(s, prop, ismath)
    228 if ismath:
    229     ox, oy, width, height, descent, font_image = \
    230         self.mathtext_parser.parse(s, self.dpi, prop)

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/backend_bases.py:645, in RendererBase.get_text_width_height_descent(self, s, prop, ismath)
    641 fontsize = prop.get_size_in_points()
    643 if ismath == 'TeX':
    644     # todo: handle properties
--> 645     return self.get_texmanager().get_text_width_height_descent(
    646         s, fontsize, renderer=self)
    648 dpi = self.points_to_pixels(72)
    649 if ismath:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:368, in TexManager.get_text_width_height_descent(cls, tex, fontsize, renderer)
    366 if tex.strip() == '':
    367     return 0, 0, 0
--> 368 dvifile = cls.make_dvi(tex, fontsize)
    369 dpi_fraction = renderer.points_to_pixels(1.) if renderer else 1
    370 with dviread.Dvi(dvifile, 72 * dpi_fraction) as dvi:

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:300, in TexManager.make_dvi(cls, tex, fontsize)
    298     with TemporaryDirectory(dir=cwd) as tmpdir:
    299         tmppath = Path(tmpdir)
--> 300         cls._run_checked_subprocess(
    301             ["latex", "-interaction=nonstopmode", "--halt-on-error",
    302              f"--output-directory={tmppath.name}",
    303              f"{texfile.name}"], tex, cwd=cwd)
    304         (tmppath / Path(dvifile).name).replace(dvifile)
    305 return dvifile

File /usr/share/miniconda3/envs/dse2023/lib/python3.10/site-packages/matplotlib/texmanager.py:259, in TexManager._run_checked_subprocess(cls, command, tex, cwd)
    255     report = subprocess.check_output(
    256         command, cwd=cwd if cwd is not None else cls.texcache,
    257         stderr=subprocess.STDOUT)
    258 except FileNotFoundError as exc:
--> 259     raise RuntimeError(
    260         'Failed to process string with tex because {} could not be '
    261         'found'.format(command[0])) from exc
    262 except subprocess.CalledProcessError as exc:
    263     raise RuntimeError(
    264         '{prog} was not able to process the following string:\n'
    265         '{tex!r}\n\n'
   (...)
    272             exc=exc.output.decode('utf-8', 'backslashreplace'))
    273         ) from None

RuntimeError: Failed to process string with tex because latex could not be found
<Figure size 900x550 with 2 Axes>