{
"cells": [
{
"cell_type": "markdown",
"id": "5b16d34a",
"metadata": {},
"source": [
"\n",
""
]
},
{
"cell_type": "markdown",
"id": "df5809ac",
"metadata": {},
"source": [
"# Robustness\n",
"\n",
"\n",
""
]
},
{
"cell_type": "markdown",
"id": "a2033b4b",
"metadata": {},
"source": [
"## Contents\n",
"\n",
"- [Robustness](#Robustness) \n",
" - [Overview](#Overview) \n",
" - [The Model](#The-Model) \n",
" - [Constructing More Robust Policies](#Constructing-More-Robust-Policies) \n",
" - [Robustness as Outcome of a Two-Person Zero-Sum Game](#Robustness-as-Outcome-of-a-Two-Person-Zero-Sum-Game) \n",
" - [The Stochastic Case](#The-Stochastic-Case) \n",
" - [Implementation](#Implementation) \n",
" - [Application](#Application) \n",
" - [Appendix](#Appendix) "
]
},
{
"cell_type": "markdown",
"id": "7e0fa4fd",
"metadata": {},
"source": [
"In addition to what’s in Anaconda, this lecture will need the following libraries:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "eee41c8b",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"!pip install --upgrade quantecon"
]
},
{
"cell_type": "markdown",
"id": "bad3ebbe",
"metadata": {},
"source": [
"## Overview\n",
"\n",
"\n",
"\n",
"This lecture modifies a Bellman equation to express a decision-maker’s doubts about transition dynamics.\n",
"\n",
"His specification doubts make the decision-maker want a *robust* decision rule.\n",
"\n",
"*Robust* means insensitive to misspecification of transition dynamics.\n",
"\n",
"The decision-maker has a single *approximating model*.\n",
"\n",
"He calls it *approximating* to acknowledge that he doesn’t completely trust it.\n",
"\n",
"He fears that outcomes will actually be determined by another model that he cannot describe explicitly.\n",
"\n",
"All that he knows is that the actual data-generating model is in some (uncountable) set of models that surrounds his approximating model.\n",
"\n",
"He quantifies the discrepancy between his approximating model and the genuine data-generating model by using a quantity called *entropy*.\n",
"\n",
"(We’ll explain what entropy means below)\n",
"\n",
"He wants a decision rule that will work well enough no matter which of those other models actually governs outcomes.\n",
"\n",
"This is what it means for his decision rule to be “robust to misspecification of an approximating model”.\n",
"\n",
"This may sound like too much to ask for, but $ \\ldots $.\n",
"\n",
"$ \\ldots $ a *secret weapon* is available to design robust decision rules.\n",
"\n",
"The secret weapon is max-min control theory.\n",
"\n",
"A value-maximizing decision-maker enlists the aid of an (imaginary) value-minimizing model chooser to construct *bounds* on the value attained by a given decision rule under different models of the transition dynamics.\n",
"\n",
"The original decision-maker uses those bounds to construct a decision rule with an assured performance level, no matter which model actually governs outcomes.\n",
"\n",
">**Note**\n",
">\n",
">In reading this lecture, please don’t think that our decision-maker is paranoid when he conducts a worst-case analysis. By designing a rule that works well against a worst-case, his intention is to construct a rule that will work well across a *set* of models.\n",
"\n",
"Let’s start with some imports:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "46d2b912",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"from scipy.linalg import eig\n",
"import matplotlib.pyplot as plt\n",
"%matplotlib inline\n",
"import quantecon as qe"
]
},
{
"cell_type": "markdown",
"id": "e0f7a4e0",
"metadata": {},
"source": [
"\n",
""
]
},
{
"cell_type": "markdown",
"id": "3fb5a053",
"metadata": {},
"source": [
"### Sets of Models Imply Sets Of Values\n",
"\n",
"Our “robust” decision-maker wants to know how well a given rule will work when he does not *know* a single transition law $ \\ldots $.\n",
"\n",
"$ \\ldots $ he wants to know *sets* of values that will be attained by a given decision rule $ F $ under a *set* of transition laws.\n",
"\n",
"Ultimately, he wants to design a decision rule $ F $ that shapes these *sets* of values in ways that he prefers.\n",
"\n",
"With this in mind, consider the following graph, which relates to a particular decision problem to be explained below\n",
"\n",
"![https://python-advanced.quantecon.org/_static/lecture_specific/robustness/kg0.png](https://python-advanced.quantecon.org/_static/lecture_specific/robustness/kg0.png)\n",
"\n",
" \n",
"The figure shows a *value-entropy correspondence* for a particular decision rule $ F $.\n",
"\n",
"The shaded set is the graph of the correspondence, which maps entropy to a set of values associated with a set of models that surround the decision-maker’s approximating model.\n",
"\n",
"Here\n",
"\n",
"- *Value* refers to a sum of discounted rewards obtained by applying the decision rule $ F $ when the state starts at some fixed initial state $ x_0 $. \n",
"- *Entropy* is a non-negative number that measures the size of a set of models surrounding the decision-maker’s approximating model. \n",
" - Entropy is zero when the set includes only the approximating model, indicating that the decision-maker completely trusts the approximating model. \n",
" - Entropy is bigger, and the set of surrounding models is bigger, the less the decision-maker trusts the approximating model. \n",
"\n",
"\n",
"The shaded region indicates that for **all** models having entropy less than or equal to the number on the horizontal axis, the value obtained will be somewhere within the indicated set of values.\n",
"\n",
"Now let’s compare sets of values associated with two different decision rules, $ F_r $ and $ F_b $.\n",
"\n",
"In the next figure,\n",
"\n",
"- The red set shows the value-entropy correspondence for decision rule $ F_r $. \n",
"- The blue set shows the value-entropy correspondence for decision rule $ F_b $. \n",
"\n",
"\n",
"![https://python-advanced.quantecon.org/_static/lecture_specific/robustness/kg.png](https://python-advanced.quantecon.org/_static/lecture_specific/robustness/kg.png)\n",
"\n",
" \n",
"The blue correspondence is skinnier than the red correspondence.\n",
"\n",
"This conveys the sense in which the decision rule $ F_b $ is *more robust* than the decision rule $ F_r $\n",
"\n",
"- *more robust* means that the set of values is less sensitive to *increasing misspecification* as measured by entropy \n",
"\n",
"\n",
"Notice that the less robust rule $ F_r $ promises higher values for small misspecifications (small entropy).\n",
"\n",
"(But it is more fragile in the sense that it is more sensitive to perturbations of the approximating model)\n",
"\n",
"Below we’ll explain in detail how to construct these sets of values for a given $ F $, but for now $ \\ldots $.\n",
"\n",
"Here is a hint about the *secret weapons* we’ll use to construct these sets\n",
"\n",
"- We’ll use some min problems to construct the lower bounds \n",
"- We’ll use some max problems to construct the upper bounds \n",
"\n",
"\n",
"We will also describe how to choose $ F $ to shape the sets of values.\n",
"\n",
"This will involve crafting a *skinnier* set at the cost of a lower *level* (at least for low values of entropy)."
]
},
{
"cell_type": "markdown",
"id": "c47480d8",
"metadata": {},
"source": [
"### Inspiring Video\n",
"\n",
"If you want to understand more about why one serious quantitative researcher is interested in this approach, we recommend [Lars Peter Hansen’s Nobel lecture](https://www.nobelprize.org/prizes/economic-sciences/2013/hansen/lecture/)."
]
},
{
"cell_type": "markdown",
"id": "31d19b22",
"metadata": {},
"source": [
"### Other References\n",
"\n",
"Our discussion in this lecture is based on\n",
"\n",
"- [[HS00](https://python-advanced.quantecon.org/zreferences.html#id158)] \n",
"- [[HS08a](https://python-advanced.quantecon.org/zreferences.html#id157)] "
]
},
{
"cell_type": "markdown",
"id": "e194b0af",
"metadata": {},
"source": [
"## The Model\n",
"\n",
"For simplicity, we present ideas in the context of a class of problems with linear transition laws and quadratic objective functions.\n",
"\n",
"To fit in with [our earlier lecture on LQ control](https://python-intro.quantecon.org/lqcontrol.html), we will treat loss minimization rather than value maximization.\n",
"\n",
"To begin, recall the [infinite horizon LQ problem](https://python.quantecon.org/lqcontrol.html#infinite-horizon), where an agent chooses a sequence of controls $ \\{u_t\\} $ to minimize\n",
"\n",
"\n",
"\n",
"$$\n",
"\\sum_{t=0}^{\\infty} \\beta^t\n",
" \\left\\{\n",
" x_t' R x_t + u_t' Q u_t\n",
" \\right\\} \\tag{26.1}\n",
"$$\n",
"\n",
"subject to the linear law of motion\n",
"\n",
"\n",
"\n",
"$$\n",
"x_{t+1} = A x_t + B u_t + C w_{t+1},\n",
"\\qquad t = 0, 1, 2, \\ldots \\tag{26.2}\n",
"$$\n",
"\n",
"As before,\n",
"\n",
"- $ x_t $ is $ n \\times 1 $, $ A $ is $ n \\times n $ \n",
"- $ u_t $ is $ k \\times 1 $, $ B $ is $ n \\times k $ \n",
"- $ w_t $ is $ j \\times 1 $, $ C $ is $ n \\times j $ \n",
"- $ R $ is $ n \\times n $ and $ Q $ is $ k \\times k $ \n",
"\n",
"\n",
"Here $ x_t $ is the state, $ u_t $ is the control, and $ w_t $ is a shock vector.\n",
"\n",
"For now, we take $ \\{ w_t \\} := \\{ w_t \\}_{t=1}^{\\infty} $ to be deterministic — a single fixed sequence.\n",
"\n",
"We also allow for *model uncertainty* on the part of the agent solving this optimization problem.\n",
"\n",
"In particular, the agent takes $ w_t = 0 $ for all $ t \\geq 0 $ as a benchmark model but admits the possibility that this model might be wrong.\n",
"\n",
"As a consequence, she also considers a set of alternative models expressed in terms of sequences $ \\{ w_t \\} $ that are “close” to the zero sequence.\n",
"\n",
"She seeks a policy that will do well enough for a set of alternative models whose members are pinned down by sequences $ \\{ w_t \\} $.\n",
"\n",
"Soon we’ll quantify the quality of a model specification in terms of the maximal size of the expression $ \\sum_{t=0}^{\\infty} \\beta^{t+1}w_{t+1}' w_{t+1} $."
]
},
{
"cell_type": "markdown",
"id": "26756914",
"metadata": {},
"source": [
"## Constructing More Robust Policies\n",
"\n",
"If our agent takes $ \\{ w_t \\} $ as a given deterministic sequence, then, drawing on intuition from earlier lectures on dynamic programming, we can anticipate Bellman equations such as\n",
"\n",
"$$\n",
"J_{t-1} (x)\n",
"= \\min_u\n",
"\\{\n",
" x' R x + u' Q u + \\beta \\,\n",
" J_t (Ax + B u + C w_t)\n",
"\\}\n",
"$$\n",
"\n",
"(Here $ J $ depends on $ t $ because the sequence $ \\{w_t\\} $ is not recursive)\n",
"\n",
"Our tool for studying robustness is to construct a rule that works well even if an adverse sequence $ \\{ w_t \\} $ occurs.\n",
"\n",
"In our framework, “adverse” means “loss increasing”.\n",
"\n",
"As we’ll see, this will eventually lead us to construct the Bellman equation\n",
"\n",
"\n",
"\n",
"$$\n",
"J (x) =\n",
"\\min_u\n",
"\\max_w\n",
"\\{\n",
" x' R x + u' Q u + \\beta \\,\n",
" [J (Ax + B u + C w) - \\theta w'w]\n",
"\\} \\tag{26.3}\n",
"$$\n",
"\n",
"Notice that we’ve added the penalty term $ - \\theta w'w $.\n",
"\n",
"Since $ w'w = \\| w \\|^2 $, this term becomes influential when $ w $ moves away from the origin.\n",
"\n",
"The penalty parameter $ \\theta $ controls how much we penalize the maximizing agent for “harming” the minimizing agent.\n",
"\n",
"By raising $ \\theta $ more and more, we more and more limit the ability of maximizing agent to distort outcomes relative to the approximating model.\n",
"\n",
"So bigger $ \\theta $ is implicitly associated with smaller distortion sequences $ \\{w_t \\} $."
]
},
{
"cell_type": "markdown",
"id": "3dee2173",
"metadata": {},
"source": [
"### Analyzing the Bellman Equation\n",
"\n",
"So what does $ J $ in [(26.3)](#equation-rb-wcb0) look like?\n",
"\n",
"As with the [ordinary LQ control model](https://python-intro.quantecon.org/lqcontrol.html), $ J $ takes the form $ J(x) = x' P x $ for some symmetric positive definite matrix $ P $.\n",
"\n",
"One of our main tasks will be to analyze and compute the matrix $ P $.\n",
"\n",
"Related tasks will be to study associated feedback rules for $ u_t $ and $ w_{t+1} $.\n",
"\n",
"First, using [matrix calculus](https://python-intro.quantecon.org/linear_algebra.html#la-mcalc), you will be able to verify that\n",
"\n",
"\n",
"\n",
"$$\n",
"\\begin{aligned}\n",
"\\max_w\n",
"&\\{\n",
" (Ax + B u + C w)' P (Ax + B u + C w) - \\theta w'w\n",
"\\}\n",
"\\\\\n",
"& \\hspace{20mm} = (Ax + Bu)' \\mathcal D(P) (Ax + Bu)\n",
"\\end{aligned} \\tag{26.4}\n",
"$$\n",
"\n",
"where\n",
"\n",
"\n",
"\n",
"$$\n",
"\\mathcal D(P) := P + PC (\\theta I - C' P C)^{-1} C' P \\tag{26.5}\n",
"$$\n",
"\n",
"and $ I $ is a $ j \\times j $ identity matrix. Substituting this expression for the maximum into [(26.3)](#equation-rb-wcb0) yields\n",
"\n",
"\n",
"\n",
"$$\n",
"x'Px =\n",
"\\min_u\n",
"\\{\n",
" x' R x + u' Q u + \\beta \\,\n",
" (Ax + Bu)' \\mathcal D(P) (Ax + Bu)\n",
"\\} \\tag{26.6}\n",
"$$\n",
"\n",
"Using similar mathematics, the solution to this minimization problem is $ u = - F x $ where $ F := (Q + \\beta B' \\mathcal D (P) B)^{-1} \\beta B' \\mathcal D(P) A $.\n",
"\n",
"Substituting this minimizer back into [(26.6)](#equation-rb-owb) and working through the algebra gives\n",
"$ x' P x = x' \\mathcal B ( \\mathcal D( P )) x $ for all $ x $, or, equivalently,\n",
"\n",
"$$\n",
"P = \\mathcal B ( \\mathcal D( P ))\n",
"$$\n",
"\n",
"where $ \\mathcal D $ is the operator defined in [(26.5)](#equation-rb-d) and\n",
"\n",
"$$\n",
"\\mathcal B(P)\n",
":= R - \\beta^2 A' P B (Q + \\beta B' P B)^{-1} B' P A + \\beta A' P A\n",
"$$\n",
"\n",
"The operator $ \\mathcal B $ is the standard (i.e., non-robust) LQ Bellman operator, and $ P = \\mathcal B(P) $ is the standard matrix Riccati equation coming from the\n",
"Bellman equation — see [this discussion](https://python.quantecon.org/lqcontrol.html#infinite-horizon).\n",
"\n",
"Under some regularity conditions (see [[HS08a](https://python-advanced.quantecon.org/zreferences.html#id157)]), the operator $ \\mathcal B \\circ \\mathcal D $\n",
"has a unique positive definite fixed point, which we denote below by $ \\hat P $.\n",
"\n",
"A robust policy, indexed by $ \\theta $, is $ u = - \\hat F x $ where\n",
"\n",
"\n",
"\n",
"$$\n",
"\\hat F\n",
":= (Q + \\beta B' \\mathcal D (\\hat P) B)^{-1} \\beta B' \\mathcal D(\\hat P) A \\tag{26.7}\n",
"$$\n",
"\n",
"We also define\n",
"\n",
"\n",
"\n",
"$$\n",
"\\hat K\n",
":= (\\theta I - C' \\hat PC)^{-1} C' \\hat P (A - B \\hat F) \\tag{26.8}\n",
"$$\n",
"\n",
"The interpretation of $ \\hat K $ is that $ w_{t+1} = \\hat K x_t $ on the worst-case path of $ \\{x_t \\} $, in the sense that this vector is the maximizer of [(26.4)](#equation-rb-mp0) evaluated at the fixed rule $ u = - \\hat F x $.\n",
"\n",
"Note that $ \\hat P, \\hat F, \\hat K $ are all determined by the\n",
"primitives and $ \\theta $.\n",
"\n",
"Note also that if $ \\theta $ is very large, then $ \\mathcal D $ is\n",
"approximately equal to the identity mapping.\n",
"\n",
"Hence, when $ \\theta $ is large, $ \\hat P $ and $ \\hat F $ are approximately equal to their standard LQ values.\n",
"\n",
"Furthermore, when $ \\theta $ is large, $ \\hat K $ is approximately equal to zero.\n",
"\n",
"Conversely, smaller $ \\theta $ is associated with greater fear of model misspecification and greater concern for robustness."
]
},
{
"cell_type": "markdown",
"id": "52595d55",
"metadata": {},
"source": [
"## Robustness as Outcome of a Two-Person Zero-Sum Game\n",
"\n",
"What we have done above can be interpreted in terms of a two-person zero-sum game in which $ \\hat F, \\hat K $ are Nash equilibrium objects.\n",
"\n",
"Agent 1 is our original agent, who seeks to minimize loss in the LQ program while admitting the possibility of misspecification.\n",
"\n",
"Agent 2 is an imaginary malevolent player.\n",
"\n",
"Agent 2’s malevolence helps the original agent to compute bounds on his value function across a set of models.\n",
"\n",
"We begin with agent 2’s problem.\n",
"\n",
"\n",
""
]
},
{
"cell_type": "markdown",
"id": "c2fc2dc3",
"metadata": {},
"source": [
"### Agent 2’s Problem\n",
"\n",
"Agent 2\n",
"\n",
"1. knows a fixed policy $ F $ specifying the behavior of agent 1, in the sense that $ u_t = - F x_t $ for all $ t $ \n",
"1. responds by choosing a shock sequence $ \\{ w_t \\} $ from a set of paths sufficiently close to the benchmark sequence $ \\{0, 0, 0, \\ldots\\} $ \n",
"\n",
"\n",
"A natural way to say “sufficiently close to the zero sequence” is to restrict the\n",
"summed inner product $ \\sum_{t=1}^{\\infty} w_t' w_t $ to be small.\n",
"\n",
"However, to obtain a time-invariant recursive formulation, it turns out to be convenient to\n",
"restrict a discounted inner product\n",
"\n",
"\n",
"\n",
"$$\n",
"\\sum_{t=1}^{\\infty} \\beta^t w_t' w_t \\leq \\eta \\tag{26.9}\n",
"$$\n",
"\n",
"Now let $ F $ be a fixed policy, and let $ J_F(x_0, \\mathbf w) $ be the\n",
"present-value cost of that policy given sequence $ \\mathbf w := \\{w_t\\} $\n",
"and initial condition $ x_0 \\in \\mathbb R^n $.\n",
"\n",
"Substituting $ -F x_t $ for $ u_t $ in [(26.1)](#equation-rob-sih), this value can be written as\n",
"\n",
"\n",
"\n",
"$$\n",
"J_F(x_0, \\mathbf w) :=\n",
" \\sum_{t=0}^{\\infty} \\beta^t\n",
" x_t' (R + F' Q F) x_t \\tag{26.10}\n",
"$$\n",
"\n",
"where\n",
"\n",
"\n",
"\n",
"$$\n",
"x_{t+1} = (A - B F) x_t + C w_{t+1} \\tag{26.11}\n",
"$$\n",
"\n",
"and the initial condition $ x_0 $ is as specified in the left side of [(26.10)](#equation-rob-fpv).\n",
"\n",
"Agent 2 chooses $ {\\mathbf w} $ to maximize agent 1’s loss $ J_F(x_0, \\mathbf w) $ subject to [(26.9)](#equation-rb-dec).\n",
"\n",
"Using a Lagrangian formulation, we can express this problem as\n",
"\n",
"$$\n",
"\\max_{\\mathbf w}\n",
" \\sum_{t=0}^{\\infty} \\beta^t\n",
" \\left\\{\n",
" x_t' (R + F' Q F) x_t - \\beta \\theta (w_{t+1}' w_{t+1} - \\eta)\n",
" \\right\\}\n",
"$$\n",
"\n",
"where $ \\{x_t\\} $ satisfied [(26.11)](#equation-rob-lomf) and $ \\theta $ is a Lagrange multiplier on constraint [(26.9)](#equation-rb-dec).\n",
"\n",
"For the moment, let’s take $ \\theta $ as fixed, allowing us to drop the constant $ \\beta \\theta \\eta $ term in the objective function, and hence write the problem as\n",
"\n",
"$$\n",
"\\max_{\\mathbf w}\n",
" \\sum_{t=0}^{\\infty} \\beta^t\n",
" \\left\\{\n",
" x_t' (R + F' Q F) x_t - \\beta \\theta w_{t+1}' w_{t+1}\n",
" \\right\\}\n",
"$$\n",
"\n",
"or, equivalently,\n",
"\n",
"\n",
"\n",
"$$\n",
"\\min_{\\mathbf w}\n",
"\\sum_{t=0}^{\\infty} \\beta^t\n",
"\\left\\{\n",
" -x_t' (R + F' Q F) x_t + \\beta \\theta w_{t+1}' w_{t+1}\n",
"\\right\\} \\tag{26.12}\n",
"$$\n",
"\n",
"subject to [(26.11)](#equation-rob-lomf).\n",
"\n",
"What’s striking about this optimization problem is that it is once again an LQ discounted dynamic programming problem, with $ \\mathbf w = \\{ w_t \\} $ as the sequence of controls.\n",
"\n",
"The expression for the optimal policy can be found by applying the usual LQ formula ([see here](https://python.quantecon.org/lqcontrol.html#infinite-horizon)).\n",
"\n",
"We denote it by $ K(F, \\theta) $, with the interpretation $ w_{t+1} = K(F, \\theta) x_t $.\n",
"\n",
"The remaining step for agent 2’s problem is to set $ \\theta $ to enforce the constraint [(26.9)](#equation-rb-dec), which can be done by choosing $ \\theta = \\theta_{\\eta} $ such that\n",
"\n",
"\n",
"\n",
"$$\n",
"\\beta \\sum_{t=0}^{\\infty} \\beta^t x_t' K(F, \\theta_\\eta)' K(F, \\theta_\\eta) x_t = \\eta \\tag{26.13}\n",
"$$\n",
"\n",
"Here $ x_t $ is given by [(26.11)](#equation-rob-lomf) — which in this case becomes $ x_{t+1} = (A - B F + CK(F, \\theta)) x_t $.\n",
"\n",
"\n",
""
]
},
{
"cell_type": "markdown",
"id": "62917bf8",
"metadata": {},
"source": [
"### Using Agent 2’s Problem to Construct Bounds on the Value Sets"
]
},
{
"cell_type": "markdown",
"id": "9a19f51d",
"metadata": {},
"source": [
"#### The Lower Bound\n",
"\n",
"Define the minimized object on the right side of problem [(26.12)](#equation-rb-a2o) as $ R_\\theta(x_0, F) $.\n",
"\n",
"Because “minimizers minimize” we have\n",
"\n",
"$$\n",
"R_\\theta(x_0, F) \\leq \\sum_{t=0}^\\infty \\beta^t \\left\\{ - x_t' (R + F' Q F) x_t \\right\\} + \\beta \\theta \\sum_{t=0}^\\infty \\beta^t w_{t+1}' w_{t+1},\n",
"$$\n",
"\n",
"where $ x_{t+1} = (A - B F + CK(F, \\theta)) x_t $ and $ x_0 $ is a given initial condition.\n",
"\n",
"This inequality in turn implies the inequality\n",
"\n",
"\n",
"\n",
"$$\n",
"R_\\theta(x_0, F) - \\theta \\ {\\rm ent}\n",
"\\leq \\sum_{t=0}^\\infty \\beta^t \\left\\{ - x_t' (R + F' Q F) x_t \\right\\} \\tag{26.14}\n",
"$$\n",
"\n",
"where\n",
"\n",
"$$\n",
"{\\rm ent} := \\beta \\sum_{t=0}^\\infty \\beta^t w_{t+1}' w_{t+1}\n",
"$$\n",
"\n",
"The left side of inequality [(26.14)](#equation-rob-bound) is a straight line with slope $ -\\theta $.\n",
"\n",
"Technically, it is a “separating hyperplane”.\n",
"\n",
"At a particular value of entropy, the line is tangent to the lower bound of values as a function of entropy.\n",
"\n",
"In particular, the lower bound on the left side of [(26.14)](#equation-rob-bound) is attained when\n",
"\n",
"\n",
"\n",
"$$\n",
"{\\rm ent} = \\beta \\sum_{t=0}^{\\infty} \\beta^t x_t' K(F, \\theta)' K(F, \\theta) x_t \\tag{26.15}\n",
"$$\n",
"\n",
"To construct the *lower bound* on the set of values associated with all perturbations $ {\\mathbf w} $ satisfying the entropy constraint [(26.9)](#equation-rb-dec) at a given entropy level, we proceed as follows:\n",
"\n",
"- For a given $ \\theta $, solve the minimization problem [(26.12)](#equation-rb-a2o). \n",
"- Compute the minimizer $ R_\\theta(x_0, F) $ and the associated entropy using [(26.15)](#equation-rb-pdt22). \n",
"- Compute the lower bound on the value function $ R_\\theta(x_0, F) - \\theta \\ {\\rm ent} $ and plot it against $ {\\rm ent} $. \n",
"- Repeat the preceding three steps for a range of values of $ \\theta $ to trace out the lower bound. \n",
"\n",
"\n",
">**Note**\n",
">\n",
">This procedure sweeps out a set of separating hyperplanes indexed by different values for the Lagrange multiplier $ \\theta $."
]
},
{
"cell_type": "markdown",
"id": "21b5ac24",
"metadata": {},
"source": [
"#### The Upper Bound\n",
"\n",
"To construct an *upper bound* we use a very similar procedure.\n",
"\n",
"We simply replace the *minimization* problem [(26.12)](#equation-rb-a2o) with the *maximization* problem\n",
"\n",
"\n",
"\n",
"$$\n",
"V_{\\tilde \\theta}(x_0, F) = \\max_{\\mathbf w}\n",
" \\sum_{t=0}^{\\infty} \\beta^t\n",
" \\left\\{\n",
" -x_t' (R + F' Q F) x_t - \\beta \\tilde \\theta w_{t+1}' w_{t+1}\n",
" \\right\\} \\tag{26.16}\n",
"$$\n",
"\n",
"where now $ \\tilde \\theta >0 $ penalizes the choice of $ {\\mathbf w} $ with larger entropy.\n",
"\n",
"(Notice that $ \\tilde \\theta = - \\theta $ in problem [(26.12)](#equation-rb-a2o))\n",
"\n",
"Because “maximizers maximize” we have\n",
"\n",
"$$\n",
"V_{\\tilde \\theta}(x_0, F) \\geq \\sum_{t=0}^\\infty \\beta^t \\left\\{ - x_t' (R + F' Q F) x_t \\right\\} - \\beta \\tilde \\theta \\sum_{t=0}^\\infty \\beta^t w_{t+1}' w_{t+1}\n",
"$$\n",
"\n",
"which in turn implies the inequality\n",
"\n",
"\n",
"\n",
"$$\n",
"V_{\\tilde \\theta}(x_0, F) + \\tilde \\theta \\ {\\rm ent} \\geq \\sum_{t=0}^\\infty \\beta^t \\left\\{ - x_t' (R + F' Q F) x_t \\right\\} \\tag{26.17}\n",
"$$\n",
"\n",
"where\n",
"\n",
"$$\n",
"{\\rm ent} \\equiv \\beta \\sum_{t=0}^\\infty \\beta^t w_{t+1}' w_{t+1}\n",
"$$\n",
"\n",
"The left side of inequality [(26.17)](#equation-robboundmax) is a straight line with slope $ \\tilde \\theta $.\n",
"\n",
"The upper bound on the left side of [(26.17)](#equation-robboundmax) is attained when\n",
"\n",
"\n",
"\n",
"$$\n",
"{\\rm ent} = \\beta \\sum_{t=0}^{\\infty} \\beta^t x_t' K(F, \\tilde \\theta)' K(F, \\tilde \\theta) x_t \\tag{26.18}\n",
"$$\n",
"\n",
"To construct the *upper bound* on the set of values associated all perturbations $ {\\mathbf w} $ with a given entropy we proceed much as we did for the lower bound\n",
"\n",
"- For a given $ \\tilde \\theta $, solve the maximization problem [(26.16)](#equation-rba2omax). \n",
"- Compute the maximizer $ V_{\\tilde \\theta}(x_0, F) $ and the associated entropy using [(26.18)](#equation-rbpdt223). \n",
"- Compute the upper bound on the value function $ V_{\\tilde \\theta}(x_0, F) + \\tilde \\theta \\ {\\rm ent} $ and plot it against $ {\\rm ent} $. \n",
"- Repeat the preceding three steps for a range of values of $ \\tilde \\theta $ to trace out the upper bound. "
]
},
{
"cell_type": "markdown",
"id": "713fe663",
"metadata": {},
"source": [
"#### Reshaping the Set of Values\n",
"\n",
"Now in the interest of *reshaping* these sets of values by choosing $ F $, we turn to agent 1’s problem."
]
},
{
"cell_type": "markdown",
"id": "358f07f9",
"metadata": {},
"source": [
"### Agent 1’s Problem\n",
"\n",
"Now we turn to agent 1, who solves\n",
"\n",
"\n",
"\n",
"$$\n",
"\\min_{\\{u_t\\}}\n",
" \\sum_{t=0}^{\\infty} \\beta^t\n",
" \\left\\{\n",
" x_t' R x_t + u_t' Q u_t - \\beta \\theta w_{t+1}' w_{t+1}\n",
" \\right\\} \\tag{26.19}\n",
"$$\n",
"\n",
"where $ \\{ w_{t+1} \\} $ satisfies $ w_{t+1} = K x_t $.\n",
"\n",
"In other words, agent 1 minimizes\n",
"\n",
"\n",
"\n",
"$$\n",
"\\sum_{t=0}^{\\infty} \\beta^t\n",
" \\left\\{\n",
" x_t' (R - \\beta \\theta K' K ) x_t + u_t' Q u_t\n",
" \\right\\} \\tag{26.20}\n",
"$$\n",
"\n",
"subject to\n",
"\n",
"\n",
"\n",
"$$\n",
"x_{t+1} = (A + C K) x_t + B u_t \\tag{26.21}\n",
"$$\n",
"\n",
"Once again, the expression for the optimal policy can be found [here](https://python.quantecon.org/lqcontrol.html#infinite-horizon) — we denote\n",
"it by $ \\tilde F $.\n",
"\n",
"\n",
""
]
},
{
"cell_type": "markdown",
"id": "dd6fbd93",
"metadata": {},
"source": [
"### Nash Equilibrium\n",
"\n",
"Clearly, the $ \\tilde F $ we have obtained depends on $ K $, which, in agent 2’s problem,\n",
"depended on an initial policy $ F $.\n",
"\n",
"Holding all other parameters fixed, we can represent this relationship as a mapping $ \\Phi $, where\n",
"\n",
"$$\n",
"\\tilde F = \\Phi(K(F, \\theta))\n",
"$$\n",
"\n",
"The map $ F \\mapsto \\Phi (K(F, \\theta)) $ corresponds to a situation in which\n",
"\n",
"1. agent 1 uses an arbitrary initial policy $ F $ \n",
"1. agent 2 best responds to agent 1 by choosing $ K(F, \\theta) $ \n",
"1. agent 1 best responds to agent 2 by choosing $ \\tilde F = \\Phi (K(F, \\theta)) $ \n",
"\n",
"\n",
"As you may have already guessed, the robust policy $ \\hat F $ defined in [(26.7)](#equation-rb-oc-ih) is a fixed point of the mapping $ \\Phi $.\n",
"\n",
"In particular, for any given $ \\theta $,\n",
"\n",
"1. $ K(\\hat F, \\theta) = \\hat K $, where $ \\hat K $ is as given in [(26.8)](#equation-rb-kd) \n",
"1. $ \\Phi(\\hat K) = \\hat F $ \n",
"\n",
"\n",
"A sketch of the proof is given in [the appendix](#rb-appendix)."
]
},
{
"cell_type": "markdown",
"id": "da76fdeb",
"metadata": {},
"source": [
"## The Stochastic Case\n",
"\n",
"Now we turn to the stochastic case, where the sequence $ \\{w_t\\} $ is treated as an IID sequence of random vectors.\n",
"\n",
"In this setting, we suppose that our agent is uncertain about the *conditional probability distribution* of $ w_{t+1} $.\n",
"\n",
"The agent takes the standard normal distribution $ N(0, I) $ as the baseline conditional distribution, while admitting the possibility that other “nearby” distributions prevail.\n",
"\n",
"These alternative conditional distributions of $ w_{t+1} $ might depend nonlinearly on the history $ x_s, s \\leq t $.\n",
"\n",
"To implement this idea, we need a notion of what it means for one distribution\n",
"to be near another one.\n",
"\n",
"Here we adopt a very useful measure of closeness for distributions known as the *relative entropy*, or [Kullback-Leibler divergence](https://en.wikipedia.org/wiki/Kullback%E2%80%93Leibler_divergence).\n",
"\n",
"For densities $ p, q $, the Kullback-Leibler divergence of $ q $ from $ p $ is defined as\n",
"\n",
"$$\n",
"D_{KL} (p, q) := \\int \\ln \\left[ \\frac{p(x)}{q(x)} \\right] p(x) \\, dx\n",
"$$\n",
"\n",
"Using this notation, we replace [(26.3)](#equation-rb-wcb0) with the stochastic analog\n",
"\n",
"\n",
"\n",
"$$\n",
"J (x) =\n",
"\\min_u\n",
"\\max_{\\psi \\in \\mathcal P}\n",
"\\left\\{\n",
" x' R x + u' Q u + \\beta \\,\n",
" \\left[\n",
" \\int J (Ax + B u + C w) \\, \\psi(dw) - \\theta D_{KL}(\\psi, \\phi)\n",
" \\right]\n",
"\\right\\} \\tag{26.22}\n",
"$$\n",
"\n",
"Here $ \\mathcal P $ represents the set of all densities on $ \\mathbb R^n $ and $ \\phi $ is the benchmark distribution $ N(0, I) $.\n",
"\n",
"The distribution $ \\phi $ is chosen as the least desirable conditional distribution in terms of next period outcomes, while taking into account the penalty term $ \\theta D_{KL}(\\psi, \\phi) $.\n",
"\n",
"This penalty term plays a role analogous to the one played by the deterministic penalty $ \\theta w'w $ in [(26.3)](#equation-rb-wcb0), since it discourages large deviations from the benchmark."
]
},
{
"cell_type": "markdown",
"id": "cbf0f40e",
"metadata": {},
"source": [
"### Solving the Model\n",
"\n",
"The maximization problem in [(26.22)](#equation-rb-wcb1) appears highly nontrivial — after all,\n",
"we are maximizing over an infinite dimensional space consisting of the entire set of densities.\n",
"\n",
"However, it turns out that the solution is tractable, and in fact also falls within the class of normal distributions.\n",
"\n",
"First, we note that $ J $ has the form $ J(x) = x' P x + d $ for some positive definite matrix $ P $ and constant real number $ d $.\n",
"\n",
"Moreover, it turns out that if $ (I - \\theta^{-1} C' P C)^{-1} $ is nonsingular, then\n",
"\n",
"\n",
"\n",
"$$\n",
"\\begin{aligned}\n",
"\\max_{\\psi \\in \\mathcal P}\n",
"&\\left\\{\n",
" \\int (Ax + B u + C w)' P (Ax + B u + C w) \\, \\psi(dw) - \\theta D_{KL}(\\psi, \\phi)\n",
"\\right\\}\n",
"\\\\\n",
"& \\hspace{20mm} = (Ax + Bu)' \\mathcal D (P) (Ax + Bu) + \\kappa(\\theta, P)\n",
"\\end{aligned} \\tag{26.23}\n",
"$$\n",
"\n",
"where\n",
"\n",
"$$\n",
"\\kappa(\\theta, P) := \\theta \\ln [ \\det(I - \\theta^{-1} C' P C)^{-1} ]\n",
"$$\n",
"\n",
"and the maximizer is the Gaussian distribution\n",
"\n",
"\n",
"\n",
"$$\n",
"\\psi = N\n",
"\\left(\n",
" (\\theta I - C' P C)^{-1} C' P (Ax + Bu), (I - \\theta^{-1} C' P C)^{-1}\n",
"\\right) \\tag{26.24}\n",
"$$\n",
"\n",
"Substituting the expression for the maximum into Bellman equation\n",
"[(26.22)](#equation-rb-wcb1) and using $ J(x) = x'Px + d $ gives\n",
"\n",
"\n",
"\n",
"$$\n",
"x' P x + d =\n",
"\\min_u\n",
"\\left\\{\n",
" x' R x + u' Q u + \\beta \\,\n",
" (Ax + Bu)' \\mathcal D (P) (Ax + Bu) + \\beta \\, [d + \\kappa(\\theta, P)]\n",
"\\right\\} \\tag{26.25}\n",
"$$\n",
"\n",
"Since constant terms do not affect minimizers, the solution is the same as\n",
"[(26.6)](#equation-rb-owb), leading to\n",
"\n",
"$$\n",
"x' P x + d\n",
"= x' \\mathcal B( \\mathcal D(P)) x + \\beta \\, [d + \\kappa(\\theta, P)]\n",
"$$\n",
"\n",
"To solve this Bellman equation, we take $ \\hat P $ to be the positive definite fixed point of\n",
"$ \\mathcal B \\circ \\mathcal D $.\n",
"\n",
"In addition, we take $ \\hat d $ as the real number solving $ d = \\beta \\, [d + \\kappa(\\theta, P)] $, which is\n",
"\n",
"\n",
"\n",
"$$\n",
"\\hat d := \\frac{\\beta}{1 - \\beta} \\kappa(\\theta, P) \\tag{26.26}\n",
"$$\n",
"\n",
"The robust policy in this stochastic case is the minimizer in\n",
"[(26.25)](#equation-rb-wcb2), which is once again $ u = - \\hat F x $ for $ \\hat F $ given by [(26.7)](#equation-rb-oc-ih).\n",
"\n",
"Substituting the robust policy into [(26.24)](#equation-rb-md) we obtain the worst-case shock\n",
"distribution:\n",
"\n",
"$$\n",
"w_{t+1} \\sim\n",
"N( \\hat K x_t, (I - \\theta^{-1} C' \\hat PC)^{-1} )\n",
"$$\n",
"\n",
"where $ \\hat K $ is given by [(26.8)](#equation-rb-kd).\n",
"\n",
"Note that the mean of the worst-case shock distribution is equal to the same worst-case $ w_{t+1} $ as in the earlier deterministic setting.\n",
"\n",
"\n",
""
]
},
{
"cell_type": "markdown",
"id": "414c0627",
"metadata": {},
"source": [
"### Computing Other Quantities\n",
"\n",
"Before turning to implementation, we briefly outline how to compute several other quantities of interest."
]
},
{
"cell_type": "markdown",
"id": "9d9fa055",
"metadata": {},
"source": [
"#### Worst-Case Value of a Policy\n",
"\n",
"One thing we will be interested in doing is holding a policy fixed and\n",
"computing the discounted loss associated with that policy.\n",
"\n",
"So let $ F $ be a given policy and let $ J_F(x) $ be\n",
"the associated loss, which, by analogy with [(26.22)](#equation-rb-wcb1), satisfies\n",
"\n",
"$$\n",
"J_F(x) =\n",
"\\max_{\\psi \\in \\mathcal P}\n",
"\\left\\{\n",
" x' (R + F'QF) x + \\beta \\,\n",
" \\left[\n",
" \\int J_F ( (A - BF)x + C w) \\, \\psi(dw) - \\theta D_{KL}(\\psi, \\phi)\n",
" \\right]\n",
"\\right\\}\n",
"$$\n",
"\n",
"Writing $ J_F(x) = x'P_Fx + d_F $ and applying the same argument used to\n",
"derive [(26.23)](#equation-rb-mls) we get\n",
"\n",
"$$\n",
"x' P_F x + d_F =\n",
"x' (R + F'QF) x + \\beta \\,\n",
"\\left[\n",
" x' (A - BF)' \\mathcal D(P_F) (A - BF) x + d_F + \\kappa(\\theta, P_F)\n",
"\\right]\n",
"$$\n",
"\n",
"To solve this we take $ P_F $ to be the fixed point\n",
"\n",
"$$\n",
"P_F = R + F'QF + \\beta (A - BF)' \\mathcal D(P_F) (A - BF)\n",
"$$\n",
"\n",
"and\n",
"\n",
"\n",
"\n",
"$$\n",
"d_F\n",
":= \\frac{\\beta}{1 - \\beta} \\kappa(\\theta, P_F)\n",
"= \\frac{\\beta}{1 - \\beta}\n",
" \\theta \\ln [ \\det(I - \\theta^{-1} C' P_F C)^{-1} ] \\tag{26.27}\n",
"$$\n",
"\n",
"If you skip ahead to [the appendix](#rb-appendix), you will be able to\n",
"verify that $ -P_F $ is the solution to the Bellman equation in\n",
"agent 2’s problem [discussed above](#rb-a2) — we use this in our\n",
"computations."
]
},
{
"cell_type": "markdown",
"id": "e3e662ff",
"metadata": {},
"source": [
"## Implementation\n",
"\n",
"The [QuantEcon.py](http://quantecon.org/quantecon-py) package provides a class called `RBLQ` for implementation of robust LQ optimal control.\n",
"\n",
"The code can be found [on GitHub](https://github.com/QuantEcon/QuantEcon.py/blob/master/quantecon/robustlq.py).\n",
"\n",
"Here is a brief description of the methods of the class\n",
"\n",
"- `d_operator()` and `b_operator()` implement $ \\mathcal D $\n",
" and $ \\mathcal B $ respectively \n",
"- `robust_rule()` and `robust_rule_simple()` both solve for the\n",
" triple $ \\hat F, \\hat K, \\hat P $, as described in equations [(26.7)](#equation-rb-oc-ih) – [(26.8)](#equation-rb-kd) and the surrounding discussion \n",
" - `robust_rule()` is more efficient \n",
" - `robust_rule_simple()` is more transparent and easier to follow \n",
"- `K_to_F()` and `F_to_K()` solve the decision problems\n",
" of [agent 1](#rb-a1) and [agent 2](#rb-a2) respectively \n",
"- `compute_deterministic_entropy()` computes the left-hand side of [(26.13)](#equation-rb-pdt) \n",
"- `evaluate_F()` computes the loss and entropy associated with a given\n",
" policy — see [this discussion](#rb-coq) "
]
},
{
"cell_type": "markdown",
"id": "8b7ac63a",
"metadata": {},
"source": [
"## Application\n",
"\n",
"Let us consider a monopolist similar to [this one](https://python-intro.quantecon.org/lqcontrol.html#lqc-mwac), but now facing model uncertainty.\n",
"\n",
"The inverse demand function is $ p_t = a_0 - a_1 y_t + d_t $.\n",
"\n",
"where\n",
"\n",
"$$\n",
"d_{t+1} = \\rho d_t + \\sigma_d w_{t+1},\n",
"\\quad \\{w_t\\} \\stackrel{\\textrm{IID}}{\\sim} N(0,1)\n",
"$$\n",
"\n",
"and all parameters are strictly positive.\n",
"\n",
"The period return function for the monopolist is\n",
"\n",
"$$\n",
"r_t = p_t y_t - \\gamma \\frac{(y_{t+1} - y_t)^2}{2} - c y_t\n",
"$$\n",
"\n",
"Its objective is to maximize expected discounted profits, or, equivalently, to minimize $ \\mathbb E \\sum_{t=0}^\\infty \\beta^t (- r_t) $.\n",
"\n",
"To form a linear regulator problem, we take the state and control to be\n",
"\n",
"$$\n",
"x_t\n",
"= \\begin{bmatrix}\n",
" 1 \\\\ y_t \\\\ d_t\n",
" \\end{bmatrix}\n",
" \\quad \\text{and} \\quad\n",
" u_t = y_{t+1} - y_t\n",
"$$\n",
"\n",
"Setting $ b := (a_0 - c) / 2 $ we define\n",
"\n",
"$$\n",
"R\n",
"= -\n",
"\\begin{bmatrix}\n",
" 0 & b & 0 \\\\\n",
" b & -a_1 & 1/2 \\\\\n",
" 0 & 1/2 & 0\n",
"\\end{bmatrix}\n",
"\\quad \\text{and} \\quad\n",
"Q = \\gamma / 2\n",
"$$\n",
"\n",
"For the transition matrices, we set\n",
"\n",
"$$\n",
"A\n",
"= \\begin{bmatrix}\n",
" 1 & 0 & 0 \\\\\n",
" 0 & 1 & 0 \\\\\n",
" 0 & 0 & \\rho\n",
" \\end{bmatrix},\n",
"\\qquad\n",
"B\n",
"= \\begin{bmatrix}\n",
" 0 \\\\\n",
" 1 \\\\\n",
" 0\n",
" \\end{bmatrix},\n",
"\\qquad\n",
"C\n",
"= \\begin{bmatrix}\n",
" 0 \\\\\n",
" 0 \\\\\n",
" \\sigma_d\n",
" \\end{bmatrix}\n",
"$$\n",
"\n",
"Our aim is to compute the value-entropy correspondences [shown above](#rb-vec).\n",
"\n",
"The parameters are\n",
"\n",
"$$\n",
"a_0 = 100, a_1 = 0.5, \\rho = 0.9, \\sigma_d = 0.05, \\beta = 0.95, c = 2, \\gamma = 50.0\n",
"$$\n",
"\n",
"The standard normal distribution for $ w_t $ is understood as the\n",
"agent’s baseline, with uncertainty parameterized by $ \\theta $.\n",
"\n",
"We compute value-entropy correspondences for two policies\n",
"\n",
"1. The no concern for robustness policy $ F_0 $, which is the ordinary LQ\n",
" loss minimizer. \n",
"1. A “moderate” concern for robustness policy $ F_b $, with $ \\theta = 0.02 $. \n",
"\n",
"\n",
"The code for producing the graph shown above, with blue being for the robust policy, is as follows"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7b050316",
"metadata": {
"hide-output": false
},
"outputs": [],
"source": [
"# Model parameters\n",
"\n",
"a_0 = 100\n",
"a_1 = 0.5\n",
"ρ = 0.9\n",
"σ_d = 0.05\n",
"β = 0.95\n",
"c = 2\n",
"γ = 50.0\n",
"\n",
"θ = 0.002\n",
"ac = (a_0 - c) / 2.0\n",
"\n",
"# Define LQ matrices\n",
"\n",
"R = np.array([[0., ac, 0.],\n",
" [ac, -a_1, 0.5],\n",
" [0., 0.5, 0.]])\n",
"\n",
"R = -R # For minimization\n",
"Q = γ / 2\n",
"\n",
"A = np.array([[1., 0., 0.],\n",
" [0., 1., 0.],\n",
" [0., 0., ρ]])\n",
"B = np.array([[0.],\n",
" [1.],\n",
" [0.]])\n",
"C = np.array([[0.],\n",
" [0.],\n",
" [σ_d]])\n",
"\n",
"# ----------------------------------------------------------------------- #\n",
"# Functions\n",
"# ----------------------------------------------------------------------- #\n",
"\n",
"\n",
"def evaluate_policy(θ, F):\n",
"\n",
" \"\"\"\n",
" Given θ (scalar, dtype=float) and policy F (array_like), returns the\n",
" value associated with that policy under the worst case path for {w_t},\n",
" as well as the entropy level.\n",
" \"\"\"\n",
"\n",
" rlq = qe.RBLQ(Q, R, A, B, C, β, θ)\n",
" K_F, P_F, d_F, O_F, o_F = rlq.evaluate_F(F)\n",
" x0 = np.array([[1.], [0.], [0.]])\n",
" value = - x0.T @ P_F @ x0 - d_F\n",
" entropy = x0.T @ O_F @ x0 + o_F\n",
" return list(map(float, (value, entropy)))\n",
"\n",
"\n",
"def value_and_entropy(emax, F, bw, grid_size=1000):\n",
"\n",
" \"\"\"\n",
" Compute the value function and entropy levels for a θ path\n",
" increasing until it reaches the specified target entropy value.\n",
"\n",
" Parameters\n",
" ==========\n",
" emax: scalar\n",
" The target entropy value\n",
"\n",
" F: array_like\n",
" The policy function to be evaluated\n",
"\n",
" bw: str\n",
" A string specifying whether the implied shock path follows best\n",
" or worst assumptions. The only acceptable values are 'best' and\n",
" 'worst'.\n",
"\n",
" Returns\n",
" =======\n",
" df: pd.DataFrame\n",
" A pandas DataFrame containing the value function and entropy\n",
" values up to the emax parameter. The columns are 'value' and\n",
" 'entropy'.\n",
" \"\"\"\n",
"\n",
" if bw == 'worst':\n",
" θs = 1 / np.linspace(1e-8, 1000, grid_size)\n",
" else:\n",
" θs = -1 / np.linspace(1e-8, 1000, grid_size)\n",
"\n",
" df = pd.DataFrame(index=θs, columns=('value', 'entropy'))\n",
"\n",
" for θ in θs:\n",
" df.loc[θ] = evaluate_policy(θ, F)\n",
" if df.loc[θ, 'entropy'] >= emax:\n",
" break\n",
"\n",
" df = df.dropna(how='any')\n",
" return df\n",
"\n",
"\n",
"# ------------------------------------------------------------------------ #\n",
"# Main\n",
"# ------------------------------------------------------------------------ #\n",
"\n",
"\n",
"# Compute the optimal rule\n",
"optimal_lq = qe.LQ(Q, R, A, B, C, beta=β)\n",
"Po, Fo, do = optimal_lq.stationary_values()\n",
"\n",
"# Compute a robust rule given θ\n",
"baseline_robust = qe.RBLQ(Q, R, A, B, C, β, θ)\n",
"Fb, Kb, Pb = baseline_robust.robust_rule()\n",
"\n",
"# Check the positive definiteness of worst-case covariance matrix to\n",
"# ensure that θ exceeds the breakdown point\n",
"test_matrix = np.identity(Pb.shape[0]) - (C.T @ Pb @ C) / θ\n",
"eigenvals, eigenvecs = eig(test_matrix)\n",
"assert (eigenvals >= 0).all(), 'θ below breakdown point.'\n",
"\n",
"\n",
"emax = 1.6e6\n",
"\n",
"optimal_best_case = value_and_entropy(emax, Fo, 'best')\n",
"robust_best_case = value_and_entropy(emax, Fb, 'best')\n",
"optimal_worst_case = value_and_entropy(emax, Fo, 'worst')\n",
"robust_worst_case = value_and_entropy(emax, Fb, 'worst')\n",
"\n",
"fig, ax = plt.subplots()\n",
"\n",
"ax.set_xlim(0, emax)\n",
"ax.set_ylabel(\"Value\")\n",
"ax.set_xlabel(\"Entropy\")\n",
"ax.grid()\n",
"\n",
"for axis in 'x', 'y':\n",
" plt.ticklabel_format(style='sci', axis=axis, scilimits=(0, 0))\n",
"\n",
"plot_args = {'lw': 2, 'alpha': 0.7}\n",
"\n",
"colors = 'r', 'b'\n",
"\n",
"df_pairs = ((optimal_best_case, optimal_worst_case),\n",
" (robust_best_case, robust_worst_case))\n",
"\n",
"\n",
"class Curve:\n",
"\n",
" def __init__(self, x, y):\n",
" self.x, self.y = x, y\n",
"\n",
" def __call__(self, z):\n",
" return np.interp(z, self.x, self.y)\n",
"\n",
"\n",
"for c, df_pair in zip(colors, df_pairs):\n",
" curves = []\n",
" for df in df_pair:\n",
" # Plot curves\n",
" x, y = df['entropy'], df['value']\n",
" x, y = (np.asarray(a, dtype='float') for a in (x, y))\n",
" egrid = np.linspace(0, emax, 100)\n",
" curve = Curve(x, y)\n",
" print(ax.plot(egrid, curve(egrid), color=c, **plot_args))\n",
" curves.append(curve)\n",
" # Color fill between curves\n",
" ax.fill_between(egrid,\n",
" curves[0](egrid),\n",
" curves[1](egrid),\n",
" color=c, alpha=0.1)\n",
"\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "f415a9d4",
"metadata": {},
"source": [
"Here’s another such figure, with $ \\theta = 0.002 $ instead of $ 0.02 $\n",
"\n",
"![https://python-advanced.quantecon.org/_static/lecture_specific/robustness/kg_small_theta.png](https://python-advanced.quantecon.org/_static/lecture_specific/robustness/kg_small_theta.png)\n",
"\n",
" \n",
"Can you explain the different shape of the value-entropy correspondence for the robust policy?\n",
"\n",
"\n",
""
]
},
{
"cell_type": "markdown",
"id": "b4a64bfa",
"metadata": {},
"source": [
"## Appendix\n",
"\n",
"We sketch the proof only of the first claim in [this section](#rb-eq),\n",
"which is that, for any given $ \\theta $, $ K(\\hat F, \\theta) = \\hat K $,\n",
"where $ \\hat K $ is as given in [(26.8)](#equation-rb-kd).\n",
"\n",
"This is the content of the next lemma.\n",
"\n",
"**Lemma.** If $ \\hat P $ is the fixed point of the map $ \\mathcal B \\circ \\mathcal D $ and $ \\hat F $ is the robust policy as given in [(26.7)](#equation-rb-oc-ih), then\n",
"\n",
"\n",
"\n",
"$$\n",
"K(\\hat F, \\theta) = (\\theta I - C'\\hat P C)^{-1} C' \\hat P (A - B \\hat F) \\tag{26.28}\n",
"$$\n",
"\n",
"*Proof:* As a first step, observe that when $ F = \\hat F $, the Bellman equation associated with the LQ problem [(26.11)](#equation-rob-lomf) – [(26.12)](#equation-rb-a2o) is\n",
"\n",
"\n",
"\n",
"$$\n",
"\\tilde P = -R - \\hat F' Q \\hat F -\n",
"\\beta^2 (A - B \\hat F)' \\tilde P C\n",
"(\\beta \\theta I + \\beta C' \\tilde P C)^{-1} C' \\tilde P (A - B \\hat F) +\n",
"\\beta (A - B \\hat F)' \\tilde P (A - B \\hat F) \\tag{26.29}\n",
"$$\n",
"\n",
"(revisit [this discussion](https://python.quantecon.org/lqcontrol.html#infinite-horizon) if you don’t know where [(26.29)](#equation-rb-a2be) comes from) and the optimal policy is\n",
"\n",
"$$\n",
"w_{t+1} = - \\beta (\\beta \\theta I + \\beta C' \\tilde P C)^{-1}\n",
"C' \\tilde P (A - B \\hat F) x_t\n",
"$$\n",
"\n",
"Suppose for a moment that $ - \\hat P $ solves the Bellman equation [(26.29)](#equation-rb-a2be).\n",
"\n",
"In this case, the policy becomes\n",
"\n",
"$$\n",
"w_{t+1} = (\\theta I - C' \\hat P C)^{-1} C' \\hat P (A - B \\hat F) x_t\n",
"$$\n",
"\n",
"which is exactly the claim in [(26.28)](#equation-rb-kft).\n",
"\n",
"Hence it remains only to show that $ - \\hat P $ solves [(26.29)](#equation-rb-a2be),\n",
"or, in other words,\n",
"\n",
"$$\n",
"\\hat P =\n",
"R + \\hat F' Q \\hat F +\n",
"\\beta (A - B \\hat F)' \\hat P C\n",
"(\\theta I - C' \\hat P C)^{-1} C' \\hat P (A - B \\hat F) +\n",
"\\beta (A - B \\hat F)' \\hat P (A - B \\hat F)\n",
"$$\n",
"\n",
"Using the definition of $ \\mathcal D $, we can rewrite the right-hand\n",
"side more simply as\n",
"\n",
"$$\n",
"R + \\hat F' Q \\hat F +\n",
"\\beta (A - B \\hat F)' \\mathcal D(\\hat P) (A - B \\hat F)\n",
"$$\n",
"\n",
"Although it involves a substantial amount of algebra, it can be shown that the\n",
"latter is just $ \\hat P $.\n",
"\n",
"Use the fact that $ \\hat P = \\mathcal B( \\mathcal D( \\hat P)) $"
]
}
],
"metadata": {
"date": 1705369587.2528408,
"filename": "robustness.md",
"kernelspec": {
"display_name": "Python",
"language": "python3",
"name": "python3"
},
"title": "Robustness"
},
"nbformat": 4,
"nbformat_minor": 5
}