###### Content under Creative Commons Attribution license CC-BY 4.0, code under MIT license (c)2014 L.A. Barba, C. Cooper, G.F. Forsyth, A. Krishnan.

# Phugoid Motion

Welcome to [**"Practical Numerical Methods with Python!"**](http://openedx.seas.gwu.edu/courses/GW/MAE6286/2014_fall/about) This course is a collaborative, online, open education project, where we aim to give a foundation in scientific computing. The focus is on numerical solution of problems modeled by ordinary and partial differential equations.

This IPython Notebook introduces the problem we'll be studying in the **first module** of the course: the _phugoid model of glider flight_. We'll start with some background, explaining the physics, and working out the mathematical model.

First, we'll look at an idealized motion where there is no drag, resulting in a simple harmonic motion. We can plot some interesting trajectories that will pique your imagination. In the next notebook, you'll learn to numerically integrate the differential equation using Euler's method. But hang on ... first things first.

The term "phugoid" is used in aeronautics to refer to a motion pattern where an aircraft oscillates up and down —nose-up and climb, then nose-down and descend— around an equilibrium trajectory.  The aircraft oscillates in altitude, speed and pitch, with only small (neglected) variations in the angle of attack, as it repeatedly exchanges kinetic and potential energy.

A low-amplitude phugoid motion can be just a nuisance, as the aircraft does not exceed the stall angle of attack and nothing bad happens. But the mode can also be unstable leading to a stall or even a loop!

Look at this video showing a Cessna single-engine airplane in phugoid motion:

```python
from IPython.display import YouTubeVideo
YouTubeVideo('ysdU4mnRYdM')
```

That doesn't look too good! What's happening?

It can get a lot worse when an aircraft enters one of these modes that is unstable. For example, one of [NASA's Helios Solar Powered Aircraft](http://www.nasa.gov/centers/dryden/history/pastprojects/Helios/) prototype broke up in mid air due to extreme phugoid oscillations!

Helios was a proof-of-concept solar electric-powered flying wing that broke the world altitude record for a non-rocket-powered aircraft in August 2001. But in June 26, 2003, it broke something else. The aircraft entered phugoid motion after encountering turbulence near the Hawaiian Island of Kauai. The high speed in the oscillatory movement exceeded the design limits, and it ended up wrecked in the Pacific Ocean. Luckily, the Helios was remotely operated, and nobody got hurt.

## The physics of phugoids

The phugoid oscillation has the aircraft pitching up and down, as it decelerates and accelerates. The trajectory might look like a sinusoid, as in the figure below. The assumption is that the forward velocity of the aircraft, $v$, varies in such a way that the angle of attack remains (nearly) constant, which means that we can assume a constant lift coefficient.

####Figure 1. Trajectory of an aircraft in phugoid motion.

In the descending portion of the trajectory, the aircraft's velocity increases as it proceeds from a peak to the minimum height—gaining kinetic energy at the expense of potential energy. The contrary happens in the upward segment, as its velocity decreases there.

We measure the pitch angle (between the aircraft's longitudinal axis and the horizontal) as positive when the aircraft's nose is pointing up. In the portion of the trajectory below the center-line, where it curves upwards, the pitch angle $\theta$ is increasing: $\dot{\theta}>0$. And where the trajectory curves down, the pitch angle is decreasing: $\dot{\theta}<0$, as shown in the figure.

Let's remind ourselves of the forces affecting an aircraft in a downward glide. Look at the figure below: we show the flight path, the forces on the glider (no thrust), and the _glide angle_ or flight path angle, $\gamma$, between the flight path and the horizontal.

####Figure 2. Forces on a glider.

The force of lift, $L$ —created by the airflow around the wings— is perpendicular to the trajectory, and the force of drag, $D$, is parallel to the trajectory. Both forces are expressed in terms of coefficients of lift and drag, $C_L$ and $C_D$, respectively, that depend on the wing design and _angle of attack_—the angle between the wing chord and the flight path.

If you are not familiar with airplane aerodynamics, you might be getting confused with some terms here ... and all those angles! But be patient and look things up, if you need to. We're giving you a quick summary here.

Lift and drag are proportional to a surface area, $S$, and the dynamic pressure: $1/2 \rho v^2$, where $\rho$ is the density of air, and $v$ the forward velocity of the aircraft. The equations for lift and drag are:

$$\begin{eqnarray}
L &=& C_L S \times \frac{1}{2} \rho v^2 \\
D &=& C_D S \times \frac{1}{2} \rho v^2
\end{eqnarray}$$

If the glider were in equilibrium, the forces would balance each other. We can equate the forces in the directions perpendicular and parallel to the trajectory, as follows:

$$\begin{equation}
L = W \cos \gamma \quad \text{and} \quad D = W \sin \gamma
\end{equation}$$

where $W$ repesents the weight of the glider.

In the figure, we've drawn the angle $\gamma$ as the _glide angle_, formed between the direction of motion and the horizontal. We are not bothered with the _sign_ of the angle, because we draw a free-body diagram and take the direction of the forces into account in writing our balance equations. But later on, we will need to be careful with the sign of the angles. It can cause you a real headache to keep this straight, so be patient!

It looks like we've set this up to do a little bit of mathematics. Are you ready?

But before, a short glimpse of the history.

## Lanchester's Aerodonetics

"Phugoid theory" was first described by the British engineer Frederick W. Lanchester in _"Aerodonetics"_ (1909). This book is so old that it is now in the public domain, so you can actually download [from Google Books](http://books.google.com/books?id=6hxDAAAAIAAJ&dq=%22phugoid%20theory%20deals%20with%20the%20longitudinal%20stability%22&pg=PA37#v=onepage&q=%22phugoid%20theory%20deals%20with%20the%20longitudinal%20stability%22&f=false) a PDF file of a scan, or read it online.

Lanchester defines phugoid theory as the study of longitudinal stability of a flying machine (aerodone). He first considered the simplification where drag and moment of inertia are neglected. Then he included these effects, obtaining an equation of stability. In addition to describing many experiments by himself and others, Lanchester also reports on _"numerical work ... done by the aid of an ordinary 25-cm slide rule."_ Go figure!

### Ideal case of zero drag

In this section, we follow the derivation given by Milne-Thompson (1966), which we find a little bit easier than that of the original in "Aerodonetics"!

An aircraft flying in a steady, straight horizontal flight has a lift equal to its weight. The velocity in this condition is sometimes called _trim velocity_ ("trim" is what pilots do to set the controls to just stay in a steady flight). Let's use $v_t$ for the trim velocity, and from $L=W$ deduce that:

$$\begin{equation}
W = C_L S \times\frac{1}{2} \rho v_t^2
\end{equation}$$

The weight $W$ is constant for the aircraft, but the lift at any other flight condition depends on the flight speed, $v$. We can use the expression for the weight in terms of $v_t$ to obtain the ratio $L/W$ at any other flight velocity, as follows:

$$\begin{equation}
\frac{L}{W}= \frac{v^2}{v_t^2}
\end{equation}$$

Imagine that the aircraft experienced a little upset, a wind gust, and it finds itself off the "trim" level, in a curved path with an instantaneous angle $\theta$. In the sketch below, we exaggerate the curved trajectory of flight to help you visualize what we'll do next. The angle $\theta$ (using the same name as Milne-Thompson) is between the _trajectory_ and the horizontal, positive up.

####Figure 3. Curved trajectory of the aircraft going up.

A balance of forces now has to take into account that our reference frame is moving with the aircraft, in a rotating frame: we have a centrifugal force. The balance in the direction of lift is thus:

$$\begin{equation}
L- W \cos \theta = \frac{W}{g} \frac{v^2}{R}
\end{equation}$$

where $R$ is the radius of curvature of the trajectory, and $g$ the acceleration of gravity. Recall that the centrifugal acceleration is $v^2/R$. Rearrange this by dividing the equation by the weight, and use the expression we found for $L/W$, above. The following equation results:

$$\begin{equation}
\frac{v^2}{v_t^2}-\cos \theta = \frac{v^2}{g R}
\end{equation}$$

Recall that we simplified the problem assuming that there is no friction, which means that the total energy is constant (the lift does no work). If $z$ represents the depth below a reference horizontal line, the energy per unit mass is (kinetic plus potential energy):

$$\begin{equation}
\frac{1}{2}v^2-g z = \text{constant}
\end{equation}$$

To get rid of that pesky constant, we can choose the reference horizontal line at the level that makes the constant energy equal to zero, so $v^2 = 2 g z$. That helps us re-write the phugoid equation in terms of $z$ as follows:

$$\begin{equation}
\frac{z}{z_t}-\cos \theta = \frac{2z}{R}
\end{equation}$$

Let $ds$ represent a small arc-length of the trajectory. We can write

$$\begin{equation}
\frac{1}{R} = \frac{d\theta}{ds} \quad \text{and}\quad  \sin\theta = -\frac{dz}{ds}
\end{equation}$$

Employing the chain rule of calculus,

$$\begin{equation}
\frac{1}{R} = \frac{d\theta}{ds} = \frac{dz}{ds}\frac{d\theta}{dz} = -\sin \theta\frac{d\theta}{dz}
\end{equation}$$

Multiply the phugoid equation by $\frac{1}{2\sqrt{z}}$ to get:

$$\begin{equation}
\frac{\sqrt{z}}{2z_t} - \frac{\cos\theta}{2\sqrt{z}} = \frac{\sqrt{z}}{R}
\end{equation}$$

Substituting for $1/R$ on the right hand side and bringing the cosine term over to the right, we get:

$$\begin{equation}
\frac{\sqrt{z}}{2z_t} = \frac{\cos \theta}{2 \sqrt{z}} - \sqrt{z} \sin \theta \frac{d\theta}{dz}
\end{equation}$$

The right-hand-side is an exact derivative! We can rewrite it as:

$$\begin{equation}
\frac{d}{dz} \left(\sqrt{z}\cos\theta \right) = \frac{\sqrt{z}}{2z_t}
\end{equation}$$

Integrating this equation, we add an arbitrary constant, chosen as $C\sqrt{z_t}$ which (after dividing through by $\sqrt{z}$) gives:

$$\begin{equation}
\cos \theta = \frac{1}{3}\frac{z}{z_t} + C\sqrt{\frac{z_t}{z}}
\end{equation}$$

Taking the derivative of both sides of equation (15) and applying the relations from equation (10) yields:

$$\begin{equation}
\frac{z_t}{R} = \frac{1}{3} - \frac{C}{2}\sqrt{\frac{z_t^3}{z^3}}
\end{equation}$$

Make sure you have followed the derivation, and perhaps write it out on paper!

## Phugoid Curves

Equation (15) is non-linear, which usually means we are hard-pressed to write a clean expression for the variable of interest, $z$.  In fact, Lanchester himself said that he was unable to _"reduce this expression to a form suitable for co-ordinate plotting."_ If the great polymath couldn't do it, we can't either!

But Lanchester _was_ able to plot a suitable approximation of the phugoid flight path using what he called the "trammel" method.  If you're interested in seeing how he did it, his explanation begins on page [48 of Aerodonetics](http://books.google.com/books?id=6hxDAAAAIAAJ&pg=PA49&lpg=PA48&dq=aerodonetics+the+use+of+the+trammel&source=bl&ots=lB6EVKYQuT&sig=aVE2kiDWZoWftaWczMIrcYftMOs&hl=en&sa=X&ei=gTD_U82fGYjzgwT3moGwCQ&ved=0CCAQ6AEwAA#v=onepage&q=aerodonetics%20the%20use%20of%20the%20trammel&f=false).  It's a trip.

Lanchester used Equations (15) and (16) to solve for the constant $C$ and the radius of curvature $R$ and then iteratively plotted small arcs of the phugoid path. By hand.

We wrote a neat little code that duplicates the manual trammel method, but it might be a bit much for you to absorb in the first lesson.  If you want to look it over, you are more than welcome to.  If you are just starting with Python, skip it for the moment and we'll return to it at the end of this module.

###Plotting the flight path

As we mentioned, we wrote a Python code to reproduce programmatically what Lanchester did graphically. Here's a neat feature of IPython Notebooks: you can run external programs with the magical keyword ... wait for it ... `run`. And the jargon of IPython _is_ to call this "magic." In fact, there are a bunch of [magic functions](http://ipython.org/ipython-doc/dev/interactive/tutorial.html) that you will learn about. They will make you a happy camper.

Let's do it:

```python
%run phugoid.py
%matplotlib inline
```

This code cell loaded our simulated-trammel code, `phugoid.py`. The code defined a function for you in the background, called `plot_flight_path`, taking three inputs: $z_t$, $z$ and $\theta$.

Look again at Equation (15), where we take the positive square root. There are several possibilities, depending on the value that the constant $C$ takes.

* There are no physical solutions for $C>2/3$, because it would result in $\cos\theta>1$.

* If $C=2/3$, then the solution is a horizontal straight line, because $\cos\theta=1$, $\theta=0$ and $R=\infty$.

* Any value of $C$ for which $0 < C < \frac{2}{3}$ will produce "trochoidal"-like paths.  What does this look like? Let's use our custom function `plot_flight_path` to find out!

```python
#zt = 64, z = 16, theta=0
plot_flight_path(64, 16, 0)
```

Cool!  Note that the plot title tells us what the calculated value of $C$ was for our input conditions.  We have a value of $C$ between $0$ and $\frac{2}{3}$ and our path is trochoidal, like we announced it would be.

* For negative values of $C$, the resultant flight path consists of a series of loops.  Let's try it out!

```python
plot_flight_path(64,16,numpy.pi)
```

You can play around with the input values and see what kind of behavior results.  Just note that any value of $C > \frac{2}{3}$ will result in $\cos \theta > 1$, which doesn't exist.  Python will probably throw a few errors if you hit that condition, but just try again!

* The last case is $C = 0$.  Take another look at Equation (16) and plug in $C = 0$, what should happen? It looks like it will just reduce to

$$R = 3z_t$$

It's a constant radius of curvature!  In fact, this solution is a series of semi-circles, with a cusp between them. One way to force $C = 0$ that we can figure out from Equation (15), is to make:

$$z = 3z_t\ \ \ ,\ \ \  \theta = 0$$

```python
plot_flight_path(16,48,0.)
```

That looks an awful lot like a quarter circle.  And what's the radius of the arc?  It's $$r = 48 = 3z_t.$$

We can also get a semi-circle out of our simulated trammel by changing to another configuration where $C$ is (near) zero. Here's one example:

```python
plot_flight_path(64,16,-numpy.pi/2)
```

That is so nice. We have reproduced the trajectories that Lanchester found more than a hundred years ago, painstakingly drawing them by hand with a contraption called a "trammel." It must have taken him days!

Here is how the different phugoid curves are drawn in von Kármán's book, _Aerodynamics_ (1957). He never says _how_ he drew them, but we're guessing by hand, also. We did pretty good!

####Figure 4. Phugoid curves in von Kármán (1957).

In the next notebook of this series, we'll look at the differential equation that arises when you consider small perturbations on the horizontal phugoid, and we'll learn to numerically integrate that to get the flight paths.

## References

1. Lanchester, F. W. _Aerodonetics_, D. van Nostrand Company: New York, 1909. On the public domain. [Get it from Google Books](http://books.google.com/books?id=6hxDAAAAIAAJ&pg=PP1#v=onepage&q&f=false).

2. Milne-Thompson, L. M. _Theoretical Aerodynamics_, Dover 2012 reprint of the revised 1966 edition. [Read on Google Books](http://books.google.com/books?id=EMfCAgAAQBAJ&lpg=PP1&pg=PP1#v=onepage&q&f=false) (see section 18.5)

3. Sinha, N. K. and Ananthkrishnan, N. _Elementary Flight Dynamics with an introduction to Bifurcation and Continuation Methods_, CRC Press, 2013. [Read on Google Books](http://books.google.com/books?id=yXL6AQAAQBAJ&lpg=PP1&pg=PP1#v=onepage&q&f=false) (see chapter 5)

4. von Kármán, T. _Aerodynamics_, Dover 2004 reprint of the 1957 2nd edition. (see pages 149–151)

## About this course

This course is a collaborative project in open education. Three professors across the world are teaching connected courses, developing and reviewing course materials, and interacting with the community of learners that follow the course online. They are:

* Lorena A. Barba, the George Washington University, United States
* Carlos Jerez, Pontificia Universidad Católica de Chile
* Ian Hawke, Southampton University, United Kingdom

---

######The cell below loads the style of this notebook.

```python
# Execute this cell to load the notebook's style sheet, then ignore it
from IPython.core.display import HTML
css_file = '../../styles/numericalmoocstyle.css'
HTML(open(css_file, "r").read())
```

<link href='http://fonts.googleapis.com/css?family=Alegreya+Sans:100,300,400,500,700,800,900,100italic,300italic,400italic,500italic,700italic,800italic,900italic' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Arvo:400,700,400italic' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=PT+Mono' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Shadows+Into+Light' rel='stylesheet' type='text/css'>
<link href='http://fonts.googleapis.com/css?family=Nixie+One' rel='stylesheet' type='text/css'>
<style>

@font-face {
    font-family: "Computer Modern";
    src: url('http://mirrors.ctan.org/fonts/cm-unicode/fonts/otf/cmunss.otf');
}

#notebook_panel { /* main background */
    background: rgb(245,245,245);
}

div.cell { /* set cell width */
    width: 750px;
}

div #notebook { /* centre the content */
    background: #fff; /* white background for content */
    width: 1000px;
    margin: auto;
    padding-left: 0em;
}

#notebook li { /* More space between bullet points */
margin-top:0.8em;
}

/* draw border around running cells */
div.cell.border-box-sizing.code_cell.running {
    border: 1px solid #111;
}

/* Put a solid color box around each cell and its output, visually linking them*/
div.cell.code_cell {
    background-color: rgb(256,256,256);
    border-radius: 0px;
    padding: 0.5em;
    margin-left:1em;
    margin-top: 1em;
}

div.text_cell_render{
    font-family: 'Alegreya Sans' sans-serif;
    line-height: 140%;
    font-size: 125%;
    font-weight: 400;
    width:600px;
    margin-left:auto;
    margin-right:auto;
}

/* Formatting for header cells */
.text_cell_render h1 {
    font-family: 'Nixie One', serif;
    font-style:regular;
    font-weight: 400;
    font-size: 45pt;
    line-height: 100%;
    color: rgb(0,51,102);
    margin-bottom: 0.5em;
    margin-top: 0.5em;
    display: block;
}
.text_cell_render h2 {
    font-family: 'Nixie One', serif;
    font-weight: 400;
    font-size: 30pt;
    line-height: 100%;
    color: rgb(0,51,102);
    margin-bottom: 0.1em;
    margin-top: 0.3em;
    display: block;
}

.text_cell_render h3 {
    font-family: 'Nixie One', serif;
    margin-top:16px;
	font-size: 22pt;
    font-weight: 600;
    margin-bottom: 3px;
    font-style: regular;
    color: rgb(102,102,0);
}

.text_cell_render h4 {    /*Use this for captions*/
    font-family: 'Nixie One', serif;
    font-size: 14pt;
    text-align: center;
    margin-top: 0em;
    margin-bottom: 2em;
    font-style: regular;
}

.text_cell_render h5 {  /*Use this for small titles*/
    font-family: 'Nixie One', sans-serif;
    font-weight: 400;
    font-size: 16pt;
    color: rgb(163,0,0);
    font-style: italic;
    margin-bottom: .1em;
    margin-top: 0.8em;
    display: block;
}

.text_cell_render h6 { /*use this for copyright note*/
    font-family: 'PT Mono', sans-serif;
    font-weight: 300;
    font-size: 9pt;
    line-height: 100%;
    color: grey;
    margin-bottom: 1px;
    margin-top: 1px;
}

.CodeMirror{
        font-family: "PT Mono";
        font-size: 90%;
}

</style>


**Course website**: https://github.com/leomiquelutti/UFU-geofisica-1

**Note**: This notebook is part of the course "Geofísica 1" of Geology program of the
[Universidade Federal de Uberlândia](http://www.ufu.br/).
All content can be freely used and adapted under the terms of the
[Creative Commons Attribution 4.0 International License](http://creativecommons.org/licenses/by/4.0/).

Agradecimentos especiais ao [Leonardo Uieda](www.leouieda.com) e ao [Grupo Geosci](http://geosci.xyz/)

Esse documento que você está usando é um [Jupyter notebook](http://jupyter.org/). É um documento interativo que mistura texto (como esse), código (como abaixo), e o resultado de executar o código (números, texto, figuras, videos, etc).

```python
from em_examples import DCLayers
from IPython.display import display
%matplotlib inline
```

```python
from matplotlib import rcParams
rcParams['font.size'] = 14
```

## Instruções

O notebook te fornecerá exemplos interativos que trabalham os temas abordados no questionário. Utilize esses exemplos para responder as perguntas.

As células com números ao lado, como `In [1]:`, são código [Python](http://python.org/). Algumas dessas células não produzem resultado e servem de preparação para os exemplos interativos. Outras, produzem gráficos interativos. **Você deve executar todas as células, uma de cada vez**, mesmo as que não produzem gráficos.

Para executar uma célula, clique em cima dela e aperte `Shift + Enter`. O foco (contorno verde ou cinza em torno da célula) deverá passar para a célula abaixo. Para rodá-la, aperte `Shift + Enter` novamente e assim por diante. Você pode executar células de texto que não acontecerá nada.

# Purpose

## Investigating DC Resistivity Data

Using the widgets contained in this notebook we will explore the physical principals governing DC resistivity including the behavior of currents, electric field, electric potentials in a two layer earth.

The measured data in a DC experiment are potential differences, we will demonstrate how these  provide information about subsurface physical properties.

### Background: Computing Apparent Resistivity

In practice we cannot measure the potentials everywhere, we are limited to those locations where we place electrodes. For each source (current electrode pair) many potential differences are measured between M and N electrode pairs to characterize the overall distribution of potentials. The widget below allows you to visualize the potentials, electric fields, and current densities from a dipole source in a simple model with 2 layers. For different electrode configurations you can measure the potential differences and see the calculated apparent resistivities.

In a uniform halfspace the potential differences can be computed by summing up the potentials at each measurement point from the different current sources based on the following equations:

\begin{align}
    V_M = \frac{\rho I}{2 \pi} \left[ \frac{1}{AM} - \frac{1}{MB} \right] \\
    V_N = \frac{\rho I}{2 \pi} \left[ \frac{1}{AN} - \frac{1}{NB} \right]
\end{align}
where $AM$, $MB$, $AN$, and $NB$ are the distances between the corresponding electrodes.

The potential difference $\Delta V_{MN}$ in a dipole-dipole survey can therefore be expressed as follows,

\begin{equation}
    \Delta V_{MN} = V_M - V_N = \rho I \underbrace{\frac{1}{2 \pi} \left[ \frac{1}{AM} - \frac{1}{MB} - \frac{1}{AN} + \frac{1}{NB} \right]}_{G}
\end{equation}

and the resistivity of the halfspace $\rho$ is equal to,

$$
    \rho = \frac{\Delta V_{MN}}{IG}
$$

In this equation $G$ is often referred to as the geometric factor.

In the case where we are not in a uniform halfspace the above equation is used to compute the apparent resistivity ($\rho_a$) which is the resistivity of the uniform halfspace which best reproduces the measured potential difference.

In the top plot the location of the A electrode is marked by the red +, the B electrode is marked by the blue -, and the M/N potential electrodes are marked by the black dots. The $V_M$ and $V_N$ potentials are printed just above and to the right of the black dots. The calculted apparent resistivity is shown in the grey box to the right. The bottom plot can show the resistivity model, the electric fields (e), potentials, or current densities (j) depending on which toggle button is selected. Some patience may be required for the plots to update after parameters have been changed.

# LayeredEarth app

## Parameters:

 - **A**: (+) Current electrode  location
 - **B**: (-) Current electrode  location
 - **M**: (+) Potential electrode  location
 - **N**: (-) Potential electrode  location
 - **$\rho_1$**: Resistivity of the first layer
 - **$\rho_2$**: Resistivity of the second layer
 - **h**: Thickness of the first layer
 - **Plot**: Choice of 2D plot (Model, Potential, Electric field, Currents)

```python
out = DCLayers.plot_layer_potentials_app()
display(out)
```

Failed to display Jupyter Widget of type MyApp.

  If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean
  that the widgets JavaScript is still loading. If this message persists, it
  likely means that the widgets JavaScript library is either not installed or
  not enabled. See the Jupyter
  Widgets Documentation for setup instructions.

  If you're reading this message in another frontend (for example, a static
  rendering on GitHub or NBViewer),
  it may mean that your frontend doesn't currently support widgets.

```python

```


```python
import numpy as np
import math
from scipy import optimize
import numba as nb
import scipy.stats as stats
import ps3_functions as func
# For plots:
import matplotlib as mpl
import matplotlib.pyplot as plt
%matplotlib inline
plt.style.use('seaborn-whitegrid')
mpl.style.use('seaborn')
prop_cycle = plt.rcParams["axes.prop_cycle"]
colors = prop_cycle.by_key()["color"]
import ipywidgets as widgets
from ipywidgets import interact, interact_manual
```

# PS3, part 1: Fire sales and multiple equilibria

The setup for part 1:

* Two period economy, $t=0,1$.
* Single consumption good, $(c)$.
* Continuum of entrepreneurs (E) and financiers (F).
* Fixed amount of capital $(\bar{k})$.
* Let $(q_t)$ denote the price of capital. Assume $q_1=\theta$ be the fixed liquidation price of capital (end of period 1).
* **Entrepreneurs:**
    * Risk-neutral, i.e. $u_E = c_0^e+c_1^e$.
    * At start-of-period $t=0$, $E$ has $b_0$ debt and $k^E_0$ capital.
    * Invests in capital for $t=1$ ($k_1^E$).
    * Due to a *temporary shock to cash flows* entrepreneurs do not receive any return on $k_0^E$.
    * In $t=1$ they apply a linear production technology i.e.
        $$\begin{align}
        f(k_1^E) = a k_1^E.
        \end{align}$$
    * At $t=0$ the entrepreneur either (1) repays his debt (if $b_0\leq q_0k_0)$) or (2) renegotiates the level of debt down to $q_0k_0$.
    * Faces a credit constraint of the *collateralized assets* type for period $t=1$: $b_1\leq \theta k_1$.
* **Financiers:**
    * Risk-neutral, i.e. $u_F = c_0^F+c_1^F$.
    * At the start of period $t=0$, F has capital $k^F_0$ (no debt).
    * Has *large* endowments of the consumption good, of size $(e_0,e_1)$ (we will come back to what *large* refers to).
    * Applies production technology using capital $(k_t^F)$ following
    $$\begin{align}
    G(k_t^F) = k_t^F-\dfrac{1}{2}\left(k_t^F\right)^2.
    \end{align}$$

Before we proceed to the questions, we note that:

* **Efficient allocation** of capital is defined as the level equalizes marginal product of capital across sectors, i.e.
    $$\begin{align}
        G'(k^F_1) = 1-k_1^F = a = f'(k_1^E)
    \end{align}$$
    In other words:
    $$\begin{align}
    k_F^* = 1-a, && k_E^* = \bar{k}+a-1
    \end{align}$$

* This might not be the equilibrium, because of the financial frictions in place (credit-constraint due to e.g. moral hazard).

## Q1: Optimization of entrepreneurs

First task is to translate the information above on E to a maximization problem (here we simply use $k_1$ to refer to $k_1^E$)

$$\begin{align}
\max_{c_0,c_1,k_1,b_1}\mbox{ }c_0+c_1\mbox{ }\mbox{ }\mbox{ }\mbox{ }&  \\
    \text{s.t. }\color{blue}{c_0+q_0k_1} &= \color{red}{\max\left\lbrace 0,\mbox{ }q_0k_0-b_0\right\rbrace +b_1} \\
    \color{blue}{c_1+b_1} &= \color{red}{(\theta+a)k_1} \\
    b_1&\leq \theta k_1
\end{align}$$

These states that:

1. Maximize consumption (risk-neutral),
2. At time $0$: $\color{blue}{\text{Expenditures}}$ equals $\color{red}{\text{wealth}}$. The max-operator states that (as explained in the introduction) if $b_0>q_0k_0$ E cannot repay his debt (without access to new credit $b_1$). In this case the level of debt is renegotiated. In this case the max-operator returns $0$.
3. At time $1$: $\color{blue}{\text{Expenditures}}$ equals available $\color{red}{\text{wealth/income}}$. $\color{red}{\text{Wealth}}$ consists of income from liquidation of capital $\theta k_1$ and the production $k_1a$.
4. Collateral constraint on borrowing.

#### Characterize E's demand for capital

Note that problem is linear in $k_1$. Thus we have corner solutions in general:

* If $q_0\leq \theta$: $E$ chooses $k_1=\infty$ (arbitrage from higher future capital prices).
* If $q_0\geq \theta+a$: $E$ chooses $k_1=0$.
* If $q_0 < b_0/k_0$: $E$ defaults on debt.
* If:
$$\begin{align}
    \max\left(\theta, \mbox{ }b_0/k_0\right)<q_0<\theta+a \tag{A1}
\end{align}$$
We thus have (1) No default on debt, (2) $E$ prefers to increase $k$ infinitely, **but** due to credit-constraint demand is finite.

Assumption $(A1)$ is assumed to hold in the following questions.

## Q2: Capital demand under assumption (A1)

Under $(A1)$ the return to capital $>1$. Thus $(E)$ prefers to maximize investments, thus choosing $c_0=0$:

$$\begin{align}
    b_1^* = q_0k_1-\max\left(0,\mbox{ }q_0k_0-b_0\right)
\end{align}$$

Using $(A1)$ (no default) and that the credit constraint is binding we have:

$$\begin{align}
    k_1 = \dfrac{b_1}{\theta} = \dfrac{q_0k_1-q_0k_0+b_0}{\theta} && \Rightarrow && k_1 = \dfrac{q_0k_0-b_0}{q_0-\theta}.
\end{align}$$

### Q3: Discuss expression for capital demand:

Rewrite slightly:

$$\begin{align}
    k_1 = k_0+\dfrac{k_0\theta -b_0}{q_0-\theta}.
\end{align}$$

Note:

$$\begin{align}
    \dfrac{\partial k_1}{\partial q_0} = -\dfrac{k_0\theta-b_0}{(q_0-\theta)^2} = -\dfrac{k_1-k_0}{q_0-\theta},
\end{align}$$
where the second equality comes from using the expression for $k_1$ above again.

The effect from $q_0$ is:

* $\color{red}{\text{Price effect:}}$ $q_0\uparrow$ price on $k_1\uparrow$ and demand for $k_1\downarrow$.
* $\color{blue}{\text{Wealth effect:}}$ $q_0\uparrow$ value of endowment $q_0k_0\uparrow$ and demand for $k_1\uparrow$.

The size of $\color{red}{k_1}$ determines the size of the $\color{red}{\text{price effect}}$, while the size of $\color{blue}{k_0}$ determines the size of the $\color{blue}{\text{wealth effect}}$.

## Q4: The financier problem and the market clearing condition for capital.

**Financier problem:**

Writing the introduction text as a mathematical problem:

$$\begin{align}
    \max_{c_0^F,c_1^F,k_1^F}\mbox{ }&c_0^F+c_1^F  \\
    \text{s.t. }&c_0^F+q_0k_1^F = k_0^F-\dfrac{1}{2}(k_0^F)^2+q_0k_0^F+e_0 \\
    & c_1^F = k_1^F-\dfrac{1}{2}(k_1^F)^2+\theta k_1^F+e_1
\end{align}$$

Similar setup to $E$, except that

* No borrowing (endowments are large enough to finance their optimal level $k_t^F$).
* Concave production function, not linear (and both in $t=0,1$).
* This yields a finite optimal level of $k_t^F$. Note that by saying that $e_0,e_1$ (endowment of capital) are sufficiently large, the interior solution for $k_t^F$ still ensures that $c_t^F>0$.

The solution here is straightforward (recall that $k_0^F$ is predetermined, not chosen):

$$\begin{align}
    \max_{k_1^F} k_1^F(1+\theta-q_0)-\dfrac{1}{2}k_1^F+constants
\end{align}$$

$F$ then chooses

$$\begin{align}
    (k_1^F)^* = \max\left(0, \mbox{ }1+\theta-q_0\right).
\end{align}$$

**Market clearing:**

With a fixed supply of capital the market clearing reads:

$$\begin{align}
    \bar{k} = k_1^F+k_1^E.
\end{align}$$

For convenience we will define the *residual supply curve* that entrepreneurs face, by substitution of $(k_1^F)^*$ into the market clearing condition:

$$\begin{align}
    k_1^E = \min\left(\bar{k}, \mbox{ }\bar{k}-(1+\theta-q_0)\right).
\end{align}$$

## Q5: Show and depict graphically that when $b_0<\theta k_0$ there is a unique equilibrium.

When $b_0<\theta k_0$:

* **Supply:** Around $q_0=0$ the (residual) supply enters through
    $$\begin{align}
    \min\left(\bar{k}, \bar{k}-(1+\theta-q_0)\right) = \bar{k}-1-\theta
    \end{align}$$
    Supply then increases linearly untill constant at $\bar{k}$. This occurs when:

    $$\begin{align}
    \bar{q}_0 = 1+\theta.
    \end{align}$$

* **Demand:** When $k_0\theta-b_0>0$ recall that

    $$\begin{align}
        k_1=k_0+\dfrac{k_0\theta-b_0}{q_0-\theta}.
    \end{align}$$

    Thus demand is **decreasing** in $q_0$ in this case. Note, however, from assumption $(A1)$ that demand only follows this form when $q_0\in(\theta, \theta+a)$.

On the relevant interval, $q_0\in(\theta, \theta+a)$ supply is linearly increasing on the range:

$$\begin{align}
    k^{rs} \in \left[\bar{k}-1,\mbox{ }\min\left(\bar{k},\mbox{ }\bar{k}-1+a\right)\right].
\end{align}$$

Demand is on this interval defined on the range:

$$\begin{align}
    k_1 \in \Bigg(k_0+\dfrac{\theta-b_0}{a},\mbox{ }\infty \Bigg)
\end{align}$$

## Q6: Show that when $b_0>\theta k_0$ there can be multiple equilibria: A 'bad' and a 'good' one. Explain.

* **Relevant interval of $q_0$ to consider:** $q_0\in(b_0/k_0, a+\theta)$.
* **Supply** increases linearly (potential kink when it reaches $\bar{k}$).
* **Demand** is now increasing as well in this region. In particular:
    $$\begin{align}
        \text{For }q_0\in(b_0/k_0,a+\theta): && k_1\in\left(0,\mbox{ }\dfrac{b_0-k_0\theta}{a}\right)
    \end{align}$$
    where the two limits are found by imposing $q_0=b_0/k_0$ and $q_0=\theta+a$ in the demand function.

Let us illustrate this.

```python
a, amin, amax = 1, 0.5, 1.5 # gives baseline value a, minimum and maximum in sliders below.
b_0, bmin, bmax =0.6, 0.1, 1 # gives baseline value b, minimum and maximum in sliders below.
k_0, kmin, kmax = 0.9, 0.1, 1 # gives baseline value k_0, minimum and maximum in sliders below.
theta, thetamin, thetamax = 0.5, 0, 1 # gives baseline value theta, minimum and maximum in sliders below.
kbar=1.1 # Fixed level of supply.
q_0 = np.linspace(0, 2, 1000) # range of q to consider.
kplot_max = 2 # Maximum
func.interactive_capdemand(q_0,a,a,amin,amax,b_0,b_0,bmin,bmax,k_0,k_0,kmin,kmax,theta,theta,thetamin,thetamax,kbar,kplot_max)
```

    interactive(children=(FloatSlider(value=0.5, description='$\\theta$', max=1.0, step=0.05), FloatSlider(value=1…

Note that with the parameter values (chosen as baseline above) there are 3 potential equilibria. However, one of them is not *stable* (medium level $k$).

The low equilibrium is given by $(k_1,q_0)=(0,\mbox{ }0.6)$. If capital prices are this low $E$ default on this debt, and thus demands no capital. At higher prices $E$ does not default on his debt. Furthermore, as $k_0>k_1$ in this range demand is increasing in $q_0$ (the 'wealth' effect from Q3 dominates).

## Q7: How can an appropriate reduction in $b_0$ eliminate the bad equilibrium?

Verify that it is the case in the figure above. Intuition:

* Reductio in $b_0$ increases demand for capital (for $E$),
* this increases wealth and thus relaxes borrowing constraint.
* This removes the bad equilibrium (and the unstable intermediate one).

## Q8: Suppose there were multiple equilibria and the government stands ready to buy assets at the good equilibrium price. How many assets would it have to buy to implement this policy?

It depends on the credibility of the policy, and if it is expected/public:

* The good price is a sulf-sustainable equilibrium.
* If the announcement of the policy to buy assets at that price, there is no need to actually buy any assets.

## Q9: Compare costs of Q7 and Q8 as policies for working in the financial crisis. Q7 interpreted as injecting capital into the banking system and Q8 as a plan to buy toxic securities with governnment money. Discuss.

More of an essay question. Some brief notes on the question:

* **Model evaluation:** Asset purchase is free (Q8), capital injection (Q7) is costly.
* **Why is it free in our model?** In our model assets are not really toxic; it's all a matter of signalling the right price. In the financial crisis this was probably not the case. Furthermore, there is no adjustment costs of going from one to the other equilibrium (no price or information frictions).
* **Adverse selection:** If the government buys up assets that are of varying degree of toxicity, they'll end up buying the most toxic ones.
* **Moral hazard:** Both strategies may induce unhealthy risk-taking.

# PS3, part 2: Impatient households and risky investments

The setup is a Diamond-Dybvig (1983) type of model. Specifically:

* Three periods $t=0,1,2$.
* Two storage technologies
    * One period tech. with return $1$.
    * Two period tech. with return $R>1$. Can be prematurely liquidated $L<1$.
* Continuum of agents with unit endowment.
* A fraction $\pi$ will be impatient, $1-\pi$ patient. However, there is uncertainty (at time $0$) about what type the agent'll be. The expected utility is then given by:
    $$\begin{align}
        u = \pi\sqrt{c_1}+(1-\pi)\rho \sqrt{c_2}.
    \end{align}$$
    At time $t=1$ when the type is known the utility is:
    $$\begin{align}
       \text{If impatient}: && u_1^{ip} &= \sqrt{c_1} \\
       \text{If patient}: && u_1^{p} &= \rho\sqrt{c_2}
    \end{align}$$
     where $\rho$ reflects standard discounting of the future.

## Q1: Characterize optimal allocation and market allocation.

We define the market allocation as in Diamond-Dybvig (1983):

* At time $t=0$ households choose long run investment $I$ (and short run investment $(1-I)$).
* At time $t=1$ they recognize their type.
* A bond market is included as follows:
    * Households that turns out to be patient: Use short run investment $1-I$ to purchase bonds at $t=1$, receiving $(1-I)/p$ at $t=2$.
    * Impatient consumers receive $p$ units of income at time $t=1$, for each unit of income they repay at $t=2$.
    * Equilibrium price: $p = 1/R$.

Using the information above the market outcome is given by:

$$\begin{align}
    c_1 &= \color{blue}{1-I}+\color{red}{pRI} \\
    c_2 &= \color{blue}{RI}+\color{red}{\dfrac{1-I}{p}}
\end{align}$$

* Impatient households receive their $\color{blue}{\text{short run investment}}$, and $\color{red}{\text{borrow against future income}}$ (by uss.
* Patient households receive return on $\color{blue}{\text{long run investment}}$, and receives the $\color{red}{\text{return on bonds}}$ from impatient households.

Imposing the equilibrium price $p=1/R$ this yields the market allocation (M):

$$\begin{align}
    c_1^M = 1, && c_2^M = R.
\end{align}$$

**Question:** In which step did we take care of the *utility-maximization* of the two types of households, and how?

### Social Planner solution (optimal):

A social planner allocates $I$ of the initial endowment to long run investments, and $1-I$ to short run investments. As the planner does not operate under uncertanity, $I$ is naturally chosen such that there is no premature liquidation of long run assets. This means that short run investments are allocated to impatient households (share $\pi$), and return on long run investments are allocated to patient households:

$$\begin{align}
    \pi c_1 = 1-I, && (1-\pi)c_2 = RI.
\end{align}$$

Combining the two the planner (assume utilitarian here) solves:

$$\begin{align}
    \max_{c_1,c_2}\mbox{ }\pi \sqrt{c_1} +(1-\pi)\rho\sqrt{c_2} && \text{s.t. }\pi c_1 +(1-\pi)\dfrac{c_2}{R} = 1
\end{align}$$

Thus the planner ensures that

$$\begin{align}
    (\rho R)^2c_1^* = c_2^*.
\end{align}$$

Using the planner's constraint we can rewrite this as

$$\begin{align}
    c_1^* = \dfrac{1}{\pi+(1-\pi)\rho^2R}, && c_2^* = \dfrac{(\rho R)^2}{\pi+(1-\pi)\rho^2R}.
\end{align}$$

The result is relatively straightforward here: If $(\rho R>1)$ the return on investments $(R)$ is larger than the degree of impatience $(\rho)$. In this case $c_2^*>c_1^*$ is optimal.

Comparing the efficient $(c_t^*)$ with the market allocation $(c_t^M)$ when we assume $(\rho R>1)$:

* **Same relative size:** Note that $c_2>c_1$ in both scenarios.
* **Generally not the same:** The two coincides exactly when $R=1/\rho^2$.
* If $R\rho^2>1$ then we have $c_2^*>c_2^M$ and $c_1^*<c_1^M$, i.e. underinvestments in the market allocation.

## Q2, part 1: Is it possible to introduce financial intermediaries, and does this implement the optimal allocation?

(*State-contingent contract: The outcome of the contract depends on the realization of some state (e.g. which type of agent the consumer is at $t=1$)).*

Yes. If the financial intermediaries offer **state-contingent contracts** the market is said to be **complete**, in which case the uncertainty no longer entails inefficiency. Consider the following very simple **first-best** state-contingent contract:

* An intermediary offer $c_1^*$ if you withdraw money at $t=1$, $c_2^*$ if you withdraw at $t=2$.
* This maximizes the expected utility (as it is the optimal outcome), thus the consumers enter this contract with all their endowment at $t=0$.
* The contract is **incentive compatible:** The two types have no incentive to lie and declare to be of the other type.
* The contract obeys **participation constraint:** The financial intermediary has non-negative profits from offering this contract.

**Question: The incentive compatibility depends crucially on $c_2^*>c_1^*$. Why?**

## Q2, part 2: Is it possible to have bank runs, and why are they inefficient?

Assume that a patient household expects all other households to withdraw early. If this expectation implies that the bank cannot finance the early withdrawals, the patient household has an incentive to withdraw early as well. If enough households have these expectations $\Rightarrow$ bank run.

**In our model:**

Recall that the bank invests $\pi c_1^*$ in short run technology and $1-\pi c_1^*$ in the long-run technology. If I expect all to withdraw early, the bank can liquidate its long run assets and get the return (recall liquidation of long run assets prematurely yields return $L$):

$$\begin{align}
 BR =  \pi c_1^* +(1-\pi c_1^*)L.
\end{align}$$

The bank run is thus a potential outcome if $BR<c_1^*$. Using the expression for $c_1^*$ derived earlier, this is the case when:

$$\begin{align}
    BR <c_1^* && \Rightarrow && L\rho^2 R<1.
\end{align}$$

This is obviously **inefficient** as the early liquidation of assets yield a return of $L<1$, where the alternative short-run technology yields a return of $1$. We say that the **run-equilibrium is pareto dominated** (more on this later).

## Q3: Assume from now on that $\rho R<1$. Characterize optimal and market allocation.

The formulas from Q1 are still valid. Now note that:

* $c_1^*>c_1^M$ and $c_2^*<c_2^M$: The market allocation over-invests compared to optimal allocation.
* Long-run investment is not 'worth it', discount-factor $(\rho)$ more than offsets productivity $(R)$ $\Rightarrow$ push consumption towards $t=1$.

**Question: Note that $c_1^*>c_1^M$ and $c_2^*<c_2^M$ depends on $(\rho^2 R)<1$ and not $(\rho R)<1$. Why?** (Hint: recall that utility from $t=0$ is concave).

## Q4: Can intermediaries implement optimal allocation? Bank runs?

In Q2 the answer was quite simply yes. Here let us consider a more formalized answer.

Consider the **constrained optimal contract problem**, of offering $c_1$ to households that withdraw at $t=1$ and $c_2$ to households that withdraw at $t=2$:

$$\begin{align}
    \max_{c_1,c_2}\mbox{ } \pi \sqrt{c_1} +(1-\pi)\rho\sqrt{c_2}& \\
    \text{s.t. } \pi c_1+(1-\pi c_1)\dfrac{c_2}{R}&=1 \\
    c_2&\geq c_1
\end{align}$$

This states that:

* Maximize expected utility, subject to
* the budget constraint from investing the unit endowment in short-run and long-run technologies (see planner solution for more on this constraint),
* and the **incentive compatibility constraint (IC)**. If the contract offers $c_2<c_1$, the patient consumer will withdraw at $t=1$, invest $c_1$ in the short run technology with return $1$ and receive $c_1$ at time $t=2$.

When $(\rho R<1)$ the unconstrained solution is not feasible, as it involves $c_1^*>c_2^*$. Thus the constrained optimal solution is given by the (IC) constraint. Imposing $c_1=c_2$ in the budget we have:

$$\begin{align}
c = \dfrac{R}{R\pi+(1-\pi)}\geq 1.
\end{align}$$

Now, is it possible to have **bank runs**? Yes. The requirement and the intuition is the same as in Q2:

$$\begin{align}
    \pi c_1+ (1-\pi c_1)L<c_1 && \Rightarrow && R>L, && \text{when }\rho R<1.
\end{align}$$

Note that the requirement $R>L$ always holds, thus the run-equilibrium is possible. It is not, however, the only equilibrium.

## Q5: Why can commitment to a 'pre-announced suspension of convertibility' eliminate the bank run equilibrium?

A few brief comments on this:

* Equilibria are **strategic:** Only optimal to withdraw early **if** other households do this as well.
* **Pareto-dominated equilibrium**: All households are better off in non-withdraw equilibrium.
* To avoid bank run equilibrium, send a signal that the early withdrawal cannot occur.

If the bank announces that only $\pi c_1^*$ can be paid out, impatient households can withdraw early, but the bank run is no longer expected by patient households, i.e. they will choose not to withdraw early.

## Q6: In absence of commitment, assume the CB can choose a threshold $\pi^B\geq \pi$ of deposits that get paid. What is the optimal ex post policy (threshold)? does it prevent bank runs?

Before we answer the question let's review the terms:

* *Ex ante* optimal policy: Implement policy from Q5, announce that at $t=1$ payments are stopped at $\pi c$.
* Assume that at time $t=1$, the bank observes $\pi c$ in withdrawals **and** that demand for early withdrawals is still present. This is a signal that (at least partially) a bank run has occurred.
* If the bank can choose a new level $\pi^s\geq \pi$, what is the optimal choice then? We denote this the *ex post* policy.
* Note that if the bank chooses to increase $\pi^S$ from the level $\pi$, it has to liquidate some long term investments prematurely. This means that it can no longer afford to pay the promised amount of consumption at $t=2$.

Note that this uncertainty creates a quite complicated setup. There are now $4$ types of agents at $t=1$: Impatient/patient, already withdrawn/not withdrawn.

* Denote the share of impatient households that have already withdrawn $\phi_1(\pi^S)$.
* Define the share of impatient households withdrawing early when increasing $\pi^S$ above the initial threshold $\pi$ as $\phi_2(\pi^S)$.
* Define impatient share of households that has not withdrawn yet $\pi_3(\pi^S)$.
* Implicit assumption: If $\pi^S=1$ all agents withdraw (everyone expect bank run to occur).
* Assumption: $\phi_1,\phi_2,\phi_3$ are constants.

*Consistency* then requires that (note the two consistency requirements only constitutes one identifying restriction, see "PS3slides" appendix for more):

$$\begin{align}
    \pi \phi_1+(\pi^S-\pi)\phi_2+(1-\pi^S)\phi_3 &= \pi \\
    \pi (1-\phi_1)+(\pi^S-pi)(1-\phi_2)+(1-\pi^S)(1-\phi_3) &= 1-\pi
\end{align}$$

The first line here states that there is a total of $\pi$ impatient households. These consists of:
* $\phi_1\pi$ of them have already withdrawn at $\pi^S=\pi$.
* When $\pi^S$ increases the impatient households $(\pi^S-\pi)\phi_2$ withdraw as well.
* Finally, of the last $1-\pi^S$ households that have not yet withdrawn, $\phi_3$ percent of them are impatient houesholds.

Second line states a similar story for the patient households.

Before we proceed to the solution, we assume for simplicity that $\phi_1=\phi_2=\phi_3=\pi$ **and** that $\rho=1$ (this is the setup used in Ennis and Keister (2009)).

**The objective function** for the bank is then

$$\begin{align}
    \max\mbox{ }\pi^S\sqrt{c}+(1-\pi^S)(1-\pi)\sqrt{c_2^S\left(\pi^S\right)},
\end{align}$$

where $c_2^S(\pi^S)$ denotes the consumption left at time $t=2$ for the patient households. We define this level from the zero-profit condition for the banks:

* **Bank expenditures:**
    * When $t=1$ the bank pays out $E_1 = \pi c+ \color{blue}{(\pi^S-\pi)c}$.
    * When $t=2$ the bank pays out $E_2 = (1-\pi^S)(1-\pi)c_2^S(\pi^S)$.
    * It is implicitly assumed at $t=2$ that only the patient households receive any payouts in $t=2$. (recall that consumption $c_2$ did not enter the utility function for impatient households)

* **Bank income:**
    * When $t=1$: $I_1= \pi c + \color{blue}{\theta(1-\pi c)L}$.
    * When $t=2$: $I_2= (1-\theta)(1-\pi c)R$.
    * To finance the unexpected early withdrawals, the bank liquidates the share $\theta$ of long run investments.

Finally, in order to characterize the residual payout $c_2^S(\pi^S)$, we need to determine $\theta$. We do this in a couple of steps.

Impose $I_1=E_1$ and isolate $\theta$:

$$\begin{align}
    \theta = \dfrac{\pi^S-\pi}{1-\pi c}\dfrac{c}{L}.
\end{align}$$

Use this in $I_2=E_2$:

$$\begin{align}
    c_2^s(\pi^S) = \dfrac{(1-\pi c)R-(\pi^S-\pi)c\frac{R}{L}}{(1-\pi^S)(1-\pi)}.
\end{align}$$

Finally this implies the objective function:

$$\begin{align}
        \max\mbox{ }\pi^S\sqrt{c}+\sqrt{(1-\pi^S)(1-\pi)\left[(1-\pi c)R-(\pi^S-\pi)c\dfrac{R}{L}\right]},
\end{align}$$

### Characterizing the solution:

We are not going to solve for an analytic value of the optimal $\pi^S$ policy. Instead we characterize it and conclude with some comments on consistency:

* Note that when $\pi^S=\pi$:
$$\begin{align}
    c_2^S(\pi^S) &= R\dfrac{1-\pi c}{(1-\pi)^2} \\
    &=\dfrac{c}{1-\pi}>c,
\end{align}$$
where the second equality comes from using the expression for $c$ derived in Q4. Thus if $\pi^S$ is kept around $\pi$, the patient households benefits from not withdrawing.
* Furthermore, $c_2^S$ is decreasing in $\pi^S$:
$$\begin{align}
    \dfrac{\partial c_2^s}{\partial \pi^S} = R\dfrac{1-\pi c-\frac{c}{L}(1-\pi)}{(1-\pi^s)^2(1-\pi)}<0
\end{align}$$
(and $\partial^2c_2^s/\partial (\pi^S)^2>0$)
Thus when $\pi^S$ is increased, the payoff for $t=2$ decreases.

* **Optimal policy** can be time inconsistent:
    * If optimal $\pi^S>\pi$, the *ex ante* and *ex post* optimal policies do not coincide. (time-inconsistent)
    * If this is the case, it can be rational for patient households to run the bank in $t=1$ even though the bank promised in $t=0$ to cap payouts to $\pi c$.
* **Optimal policy** might still eliminate bank runs:
    * If the optimal $\pi^S$ ensures $c_2^S>c$, the bank run equilibrium is not feasible.
    * Furthermore, if $c_2^S>c$ the first bank cannot occur either (under rational expectations of course): At the start of $t=1$ a patient households consider to run the bank. If he acknowledges that **even** if the others run the bank, the limit on convertability is only moved from $\pi$ to $\pi^S$: If $c_2^S>c$ in this state, there is no need to run the bank to start with.


```python
import cirq
import cirq_google
from cirq.contrib.svg import SVGCircuit
import sympy
import pandas
import datetime
import hashlib
```

```python
# print the cirq 54-qubit Sycamore chip
working_device = cirq_google.Sycamore
print(working_device)
```

                                                 (0, 5)───(0, 6)
                                                 │        │
                                                 │        │
                                        (1, 4)───(1, 5)───(1, 6)───(1, 7)
                                        │        │        │        │
                                        │        │        │        │
                               (2, 3)───(2, 4)───(2, 5)───(2, 6)───(2, 7)───(2, 8)
                               │        │        │        │        │        │
                               │        │        │        │        │        │
                      (3, 2)───(3, 3)───(3, 4)───(3, 5)───(3, 6)───(3, 7)───(3, 8)───(3, 9)
                      │        │        │        │        │        │        │        │
                      │        │        │        │        │        │        │        │
             (4, 1)───(4, 2)───(4, 3)───(4, 4)───(4, 5)───(4, 6)───(4, 7)───(4, 8)───(4, 9)
             │        │        │        │        │        │        │        │
             │        │        │        │        │        │        │        │
    (5, 0)───(5, 1)───(5, 2)───(5, 3)───(5, 4)───(5, 5)───(5, 6)───(5, 7)───(5, 8)
             │        │        │        │        │        │        │
             │        │        │        │        │        │        │
             (6, 1)───(6, 2)───(6, 3)───(6, 4)───(6, 5)───(6, 6)───(6, 7)
                      │        │        │        │        │
                      │        │        │        │        │
                      (7, 2)───(7, 3)───(7, 4)───(7, 5)───(7, 6)
                               │        │        │
                               │        │        │
                               (8, 3)───(8, 4)───(8, 5)
                                        │
                                        │
                                        (9, 4)

```python
# pick a qubit
my_qubit = cirq.GridQubit(2, 4)
```

```python
# build circuits that use your qubit

# Create a circuit with X, Ry(pi/2) and H.
my_circuit = cirq.Circuit(
    # Rotate the qubit pi/2 radians around the X axis.
    cirq.rx(3.141 / 2).on(my_qubit),
    # Measure the qubit.
    cirq.measure(my_qubit, key='out')
)
SVGCircuit(my_circuit)
```

    findfont: Font family ['Arial'] not found. Falling back to DejaVu Sans.

```python
# simulate
sim = cirq.Simulator()
samples = sim.sample(my_circuit, repetitions=10)
samples
```

      out

      0
      0

      1
      0

      2
      0

      3
      1

      4
      1

      5
      0

      6
      0

      7
      1

      8
      1

      9
      1

```python
# get properties of circuit (density matrix, state vectors, etc.)
state_vector_before_measurement = sim.simulate(my_circuit[:-1])
sampled_state_vector_after_measurement = sim.simulate(my_circuit)

print(f'State before measurement:')
print(state_vector_before_measurement)
print(f'State after measurement:')
print(sampled_state_vector_after_measurement)
```

    State before measurement:
    measurements: (no measurements)
    output vector: 0.707|0⟩ - 0.707j|1⟩
    State after measurement:
    measurements: out=1
    output vector: -1j|1⟩

```python
# noisy environment output (10% depolarization added)
noisy_sim = cirq.DensityMatrixSimulator(noise=cirq.depolarize(0.1))
noisy_post_measurement_state = noisy_sim.simulate(my_circuit)
noisy_pre_measurement_state = noisy_sim.simulate(my_circuit[:-1])

print('Noisy state after measurement:' + str(noisy_post_measurement_state))
print('Noisy state before measurement:' + str(noisy_pre_measurement_state))
```

    Noisy state after measurement:measurements: out=0
    final density matrix:
    [[0.9333334 +0.j 0.        +0.j]
     [0.        +0.j 0.06666666+0.j]]
    Noisy state before measurement:measurements: (no measurements)
    final density matrix:
    [[0.50012845+0.j         0.        +0.43333334j]
     [0.        -0.43333334j 0.49987155+0.j        ]]

```python
# create a parameterized circuit that rotates by angle theta
theta = sympy.Symbol('theta')

parameterized_circuit = cirq.Circuit(
    cirq.rx(theta).on(my_qubit),
    cirq.measure(my_qubit, key='out')
)
SVGCircuit(parameterized_circuit)
```

```python
# specify theta value for simulation
samples_at_theta_equals_2 = sim.sample(
    parameterized_circuit,
    params={theta: 2},
    repetitions=10)
samples_at_theta_equals_2
```

      theta
      out

      0
      2
      1

      1
      2
      1

      2
      2
      1

      3
      2
      0

      4
      2
      0

      5
      2
      1

      6
      2
      0

      7
      2
      0

      8
      2
      1

      9
      2
      1

```python
# multiple values for theta
samples_at_multiple_theta = sim.sample(
    parameterized_circuit,
    params=[{theta: 0.5}, {theta: 3.141}],
    repetitions=10)
samples_at_multiple_theta
```

      theta
      out

      0
      0.500
      0

      1
      0.500
      0

      2
      0.500
      0

      3
      0.500
      0

      4
      0.500
      0

      5
      0.500
      0

      6
      0.500
      0

      7
      0.500
      0

      8
      0.500
      0

      9
      0.500
      0

      0
      3.141
      1

      1
      3.141
      1

      2
      3.141
      1

      3
      3.141
      1

      4
      3.141
      1

      5
      3.141
      1

      6
      3.141
      1

      7
      3.141
      1

      8
      3.141
      1

      9
      3.141
      1

```python
# cirq shorthand for multiple values sweep
samples_at_swept_theta = sim.sample(
    parameterized_circuit,
    params=cirq.Linspace(theta, start=0, stop=3.14159, length=5),
    repetitions=5)
samples_at_swept_theta
```

      theta
      out

      0
      0.000000
      0

      1
      0.000000
      0

      2
      0.000000
      0

      3
      0.000000
      0

      4
      0.000000
      0

      0
      0.785397
      0

      1
      0.785397
      0

      2
      0.785397
      0

      3
      0.785397
      1

      4
      0.785397
      0

      0
      1.570795
      1

      1
      1.570795
      1

      2
      1.570795
      0

      3
      1.570795
      0

      4
      1.570795
      0

      0
      2.356192
      0

      1
      2.356192
      0

      2
      2.356192
      1

      3
      2.356192
      0

      4
      2.356192
      1

      0
      3.141590
      1

      1
      3.141590
      1

      2
      3.141590
      1

      3
      3.141590
      1

      4
      3.141590
      1

```python
# use pandas for analysis
big_results = sim.sample(
    parameterized_circuit,
    params=cirq.Linspace(theta, start=0, stop=3.14159, length=20),
    repetitions=10_000)

# big_results is too big to look at. Plot cross tabulated data instead.
pandas.crosstab(big_results.theta, big_results.out).plot()
```

```python
# cirq built-in rabi oscillation
result = cirq.experiments.rabi_oscillations(
    sampler=noisy_sim,
    qubit=my_qubit,
    num_points=50,
    repetitions=10000)
result.plot()
```

```python
# find the qubit with the lowest noise
class SecretNoiseModel(cirq.NoiseModel):
    def noisy_operation(self, op):
        # Hey! No peeking!
        q = op.qubits[0]
        v = hashlib.sha256(str(q).encode()).digest()[0] / 256
        yield cirq.depolarize(v).on(q)
        yield op

secret_noise_sampler = cirq.DensityMatrixSimulator(noise=SecretNoiseModel())
```

```python
q = cirq_google.Sycamore.qubits[3]
print('qubit', repr(q))
cirq.experiments.rabi_oscillations(
    sampler=secret_noise_sampler,
    qubit=q
).plot()
```

```python

```


***NOTE:***  This notebook conains some old fragments referring to `GWFrames.Wigner3jSingleton`, which was a complicated singleton that allowed me to just evaluate all the Wigner 3-j symbols once, store them, and retrieve them (memoization).  As implemented, this was actually a bit *slower* than direct evaluation.  Even worse, it seemed to be *wrong* for many combinations.  Therefore, I have removed the singleton object.

```
import sys
from sympy import N
from sympy.physics.wigner import wigner_3j
from SphericalFunctions import Wigner3j
```

```
%timeit Wigner3j(14,5,10,-11,3,8)
```

    1000000 loops, best of 3: 512 ns per loop

```
Wigner3j(3,4,1,-3,-4,0)
```

    0.0

```
from math import isnan
ellMax=16
for j_1 in range(ellMax+1):
    for m_1 in range(-j_1,j_1+1):
        for j_2 in range(ellMax+1):
            for m_2 in range(-j_2,j_2+1):
                m_3 = -m_1-m_2
                for j_3 in range(abs(j_1-j_2),min((j_1+j_2),ellMax)+1):
                    if(abs(m_3)>j_3):
                        continue
                    a=Wigner3j(j_1,j_2,j_3,m_1,m_2,m_3)
                    if(isnan(a)):
                        print(j_1,j_2,j_3,m_1,m_2,m_3)
```

```

```

```

```

```
%%time
ellMax=16
for j_1 in range(ellMax+1):
    for m_1 in range(-j_1,j_1+1):
        for j_2 in range(ellMax+1):
            for m_2 in range(-j_2,j_2+1):
                m_3 = -m_1-m_2
                for j_3 in range(max(abs(m_3),abs(j_1-j_2)),min((j_1+j_2),ellMax)+1):
                    a=Wigner3j(j_1,j_2,j_3,m_1,m_2,m_3)
```

    CPU times: user 1.83 s, sys: 9.52 ms, total: 1.84 s
    Wall time: 1.87 s

%%time
for j_1 in range(ellMax+1):
    for m_1 in range(-j_1,j_1+1):
        for j_2 in range(ellMax+1):
            for m_2 in range(-j_2,j_2+1):
                m_3 = -m_1-m_2
                for j_3 in range(max(abs(m_3),abs(j_1-j_2)),min((j_1+j_2),ellMax)+1):
                    a=Wigner3j(j_1,j_2,j_3,m_1,m_2,m_3)

```

```

```

```
%%time
i=0
i_bad=0
ellMax=4
for j_1 in range(ellMax+1):
    for m_1 in range(-j_1,j_1+1):
        for j_2 in range(ellMax+1):
            for m_2 in range(-j_2,j_2+1):
                m_3 = -m_1-m_2
                for j_3 in range(max(abs(m_3),abs(j_1-j_2)),min((j_1+j_2),ellMax)+1):
                    i = i+1
                    a,b = Wigner_3j(j_1,j_2,j_3,m_1,m_2,m_3),Wigner3j(j_1,j_2,j_3,m_1,m_2,m_3)
                    if(abs(a-b)>1e-12*abs(a+b) and abs(a+b)>1e-12):
                        print(j_1,j_2,j_3,m_1,m_2,m_3,a,b)
                        sys.stdout.flush()
                        i_bad=i_bad+1
print(i,i_bad)

```
%%time
ellMax=12
i=0
i_bad=0
for j_1 in range(ellMax+1):
    for m_1 in range(-j_1,j_1+1):
        for j_2 in range(ellMax+1):
            for m_2 in range(-j_2,j_2+1):
                m_3 = -m_1-m_2
                for j_3 in range(max(abs(m_3),abs(j_1-j_2)),min((j_1+j_2),ellMax)+1):
                    i = i+1
                    a,b = N(wigner_3j(j_1,j_2,j_3,m_1,m_2,m_3)),Wigner_3j(j_1,j_2,j_3,m_1,m_2,m_3)
                    if(abs(a-b)>1e-12*abs(a+b) and abs(a+b)>1e-12):
                        print(j_1,j_2,j_3,m_1,m_2,m_3,a,b)
                        sys.stdout.flush()
                        i_bad=i_bad+1
print(i,i_bad)
```

```
2.34/1419857
```

    1.6480532898735576e-06

```

```

# Summations

```
from sympy import summation, simplify, expand, horner, symbols, N
```

```
L,X,T,B,S,l,x,t,b,s,Lmax = symbols('L,X,T,B,S,l,x,t,b,s,Lmax', integer=True)
```

```
horner(simplify((L*(24+L*(50+L*(35+L*(10+L))))/120).subs({L:L+1}).expand())*120)
```

    L*(L*(L*(L*(L + 15) + 85) + 225) + 274) + 120

```
N((L*(24+L*(50+L*(35+L*(10+L))))/120).subs({L:16}))
```

    15504.0000000000

```
N((L*(274+L*(225+L*(85+L*(15+L))))/120+1).subs(L,16))
```

    20349.0000000000

```
N((L*(274+L*(225+L*(85+L*(15+L))))/120+1).subs(L,32))
```

    435897.000000000

```

```

```

```

```

```

```

```

```

```

```

```

```

```

```

```

```

```

```

```

```

```

```

```


```python
from IPython.display import HTML
tag = HTML('''
Toggle cell visibility <a href="javascript:code_toggle()">here</a>.''')
display(tag)
```

Toggle cell visibility here.

```python
# Erasmus+ ICCT project (2018-1-SI01-KA203-047081)

%matplotlib notebook
import numpy as np
import math
import matplotlib.pyplot as plt
from scipy import signal
import ipywidgets as widgets
import control as c
import sympy as sym
from IPython.display import Latex, display, Markdown # For displaying Markdown and LaTeX code
from fractions import Fraction
import matplotlib.patches as patches
```

## Sistemi prvega reda brez ničel

### Uvod

Sistemi prvega reda brez ničel so karakterizirani z naslednjo prenosno funkcijo:

\begin{equation}
    G(s)=\frac{k}{s+k}.
\end{equation}

Vrednost $k$ je pomembna, ker vpliva na vrednosti naslednjih parametrov:
- $1/k$ predstavlja *časovno konstanto* odziva sistema, ki določa čas, v katerem prehodna funkcija doseže $\approx$ 63% njene končne vrednosti.
- $t_v$ označuje *čas vzpona*, tj. čas, ki je potreben, da prehodna funkcija pride od 10\% do 90\% njene končne vrednosti.
- $t_p$ označuje *čas trajanja prehodnega pojava*, tj. čas pri katerem je prehodna funkcija zadnjič izven intervala sprejemljivih vrednosti (v tem interaktivnem primeru je ta interval nastavljen na $\pm2\%$ končne vrednosti).

Odziv sistemov prvega reda brez ničel na enotsko skočno funkcijo je določen kot:

\begin{equation}
    c(t)=1-e^{-at},
\end{equation}

kjer je naravni/nevsiljeni/lastni odziv (odziv na začetne pogoje) enak $1$ in vsiljeni odziv (odziv na vzbujanje) $-e^{-at}$.

---

### Kako upravljati s tem interaktivnim primerom?

Z uporabo drsnikov spreminjaj vrednost $k$, ki je del prenosne funkcije sistemov prvega reda $G(s)=\frac{k}{s+k}$, in opazuj odziv sistema na enotsko skočno funkcijo.

```python
# set up plot
fig, ax = plt.subplots(figsize=[9.8,4],num='Sistem prvega reda')
ax.set_ylim([-1, 2])
ax.set_xlim([0, 5])
ax.grid(True)
ax.set_title ('Časovni odziv')
ax.set_xlabel('$t$ [s]')
ax.set_ylabel('vhod, izhod')
xaxis = ax.axhline(y=0,color='k',lw=1)

response, = ax.plot([], [])
slope, = ax.plot([], [])
x1a, = ax.plot([], [])
y1a, = ax.plot([], [])
tr11, = ax.plot([], [])
trv1, = ax.plot([], [])
trv2, = ax.plot([], [])
trh1, = ax.plot([], [])
trh2, = ax.plot([], [])
ts11, = ax.plot([], [])
ts1, = ax.plot([], [])
ts2, = ax.plot([], [])
texttr=ax.text(0,0,'')
textts=ax.text(0,0,'')

ax.step([0,5],[0,1],color='C0',label='vhod')

# generate x values
t = np.linspace(0, 2 * np.pi, 10000)

def response_func(t, k):
    """"Return response function"""
    return 1-np.exp(-k*t)

@widgets.interact(k=(1, 5, 1))

def update(k=1):
    """Remove old lines from plot and plot new one"""
    global response,slope,x1a,y1a,tr11,trv1,trv2,trh1,trh2,ts11,ts1,ts2,texttr,textts
    ax.lines.remove(response)
    ax.lines.remove(slope)
    ax.lines.remove(x1a)
    ax.lines.remove(y1a)
    ax.lines.remove(tr11)
    ax.lines.remove(trv1)
    ax.lines.remove(trv2)
    ax.lines.remove(trh1)
    ax.lines.remove(trh2)
    ax.lines.remove(ts11)
    ax.lines.remove(ts1)
    ax.lines.remove(ts2)
    texttr.remove()
    textts.remove()
    response, = ax.plot(t, response_func(t,k), color='C1',lw=2)
    response.set_label('izhod')
    slope, = ax.plot([0,1/k], [0,1], color='C2',lw=2)
    slope.set_label('začetni naklon')
    x1a, = ax.plot([1/k,1/k],[0,1-np.exp(-1)],'--',color='k',lw=.8)
    y1a, = ax.plot([0,1/k],[1-np.exp(-1),1-np.exp(-1)],'--',color='k',lw=.8)
# rise time
    tr11, = ax.plot([-np.log(0.9)/k,-np.log(0.1)/k],[-0.5,-0.5],color='k',lw=.8)
    trv1, = ax.plot([-np.log(0.9)/k,-np.log(0.9)/k],[-0.5,0.1],'--',color='k',lw=.8)
    trv2, = ax.plot([-np.log(0.1)/k,-np.log(0.1)/k],[-0.5,0.9],'--',color='k',lw=.8)
    trh1, = ax.plot([0,-np.log(0.9)/k],[0.1,0.1],'--',color='k',lw=.8)
    trh2, = ax.plot([0,-np.log(0.1)/k],[0.9,0.9],'--',color='k',lw=.8)
# settling time
    ts11, = ax.plot([0,-np.log(0.02)/k],[-0.7,-0.7],color='k',lw=.8)
    ts1, = ax.plot([0,0],[-0.7,0],'--',color='k',lw=.8)
    ts2, = ax.plot([-np.log(0.02)/k,-np.log(0.02)/k],[-0.7,0.98],'--',color='k',lw=.8)
    ax.legend()
    texttr=ax.text((-np.log(0.1)/k-(-np.log(0.9)/k))/2,-0.45, '$t_r$',fontsize=13)
    textts=ax.text((-np.log(0.02)/k)/2-0.1,-0.65, '$t_s$',fontsize=13)

    plt.xticks([0,1/k,2,4], [0,'${1}/{%s}$'%k,2,4],fontsize=8)
    plt.yticks([0.1,0.5,0.63,0.9,1,1.5,2], [0.1,0.5,0.63,0.9,1,1.5,2],fontsize=8)

    num1=[k]
    den1=[1,k]
    display(Markdown('Prenosna funkcija sistema $G(s)$ je enaka:'))
    tf_sys1=c.TransferFunction(num1,den1)
    s=sym.Symbol('s')
    eq=(k/(s+k))
    display(eq)
```

    <IPython.core.display.Javascript object>

    interactive(children=(IntSlider(value=1, description='k', max=5, min=1), Output()), _dom_classes=('widget-inte…

## Sistemi drugega reda

### Uvod

Pri sistemih prvega reda, predstavljenimi na začetku tega interaktivnega primera, je vrednost parametra $k$ vplivala le na hitrost odziva. Pri sistemih drugega reda pa spremembe analognih parametrov vplivajo na obliko samega odziva. Možni so naslednji odzivi:
- *nadkritično dušen* odziv,
- *podkritično dušen* odziv,
- *nedušen* odziv,
- *kritično dušen* odziv.

### Kako upravljati s tem interaktivnim primerom?

Z uporabo drsnikov spreminjaj vrednosti parametrov $a$ and $b$, ki sta del prenosne funkcije sistemov drugega reda $G(s)=\frac{k}{s+k}$, in opazuj odziv sistema na enotsko skočno funkcijo ter spremembe v diagramu lege ničel in polov.

```python
# set up plot
fig1, ax1 = plt.subplots(1,2,figsize=[9.8,4],num='Sistem drugega reda')
ax1[0].set_ylim([-3.5, 3])
ax1[1].set_ylim([0, 2.5])
# ax1.set_xlim([0, 5])
ax1[0].grid(True)
ax1[1].grid(True)
ax1[0].axhline(y=0,color='k',lw=.8)
ax1[1].axhline(y=0,color='k',lw=.8)
ax1[0].axvline(x=0,color='k',lw=.8)
ax1[1].axvline(x=0,color='k',lw=.8)
ax1[0].set_xlabel('Re')
ax1[0].set_ylabel('Im')
ax1[1].set_xlabel('$t$ [s]')
ax1[1].set_ylabel('vhod, izhod')
ax1[0].set_title('Diagram lege ničel in polov')
ax1[1].set_title('Časovni odziv')

t = np.linspace(0, 20, 10000)

textGs = ax1[0].text(0,0,'')

ax1[1].step([0,20],[0,1],color='C0',label='vhod')

plotzero, = ax1[0].plot([], [])
response2, = ax1[1].plot([], [])

def response_func2(t, a, b):
    num_sys=np.array([b])
    den_sys=np.array([1,a,b])
    tf_sys=c.TransferFunction(num_sys,den_sys)
    poles_sys,zeros_sys=c.pzmap(tf_sys, Plot=False)
    T, yout = c.step_response(tf_sys,t)
    return T, yout, poles_sys, tf_sys

@widgets.interact(a=(0, 10, 1),b=(1,10,1))

def update(a=7,b=9):
    """ Update plots """
    global response2, plotzero, textGs
    ax1[0].lines.remove(plotzero)
    ax1[1].lines.remove(response2)
#     textGs.remove()
    T, yout, poles_sys, tf_sys = response_func2(t, a, b)
    plotzero, = ax1[0].plot(np.real(poles_sys), np.imag(poles_sys), 'xg', markersize=10, label = 'poli')
#     textGs = ax1[0].text(-7,1,tf_sys)
    response2, = ax1[1].plot(T,yout,color='C1',label='izhod')
    s=sym.Symbol('s')
    eq=b/(s**2+a*s+b)
    coeff = [1,a,b]
    rootsdenom=np.roots(coeff)
    eq2=b/((s-rootsdenom[0])*(s-rootsdenom[1]))
    display(Markdown('Prenosna funkcija sistema $G(s)$ je enaka:'))
    display(eq),display(Markdown('oz.')),display(eq2)

    if np.imag(poles_sys)[0] == 0 and np.imag(poles_sys)[1] == 0 and np.real(poles_sys)[0] < 0 and np.real(poles_sys)[1] < 0 and np.real(poles_sys)[0]!=np.real(poles_sys)[1]:
        display(Markdown('Sistem je **nadkritično dušen**, saj imajo poli zgolj negativen realno komponento.'))
    elif math.isclose(0, np.imag(poles_sys)[0], abs_tol=10**-6) and math.isclose(0, np.imag(poles_sys)[1], abs_tol=10**-6) and np.real(poles_sys)[1] < 0 and np.real(poles_sys)[0]==np.real(poles_sys)[1]:
        display(Markdown('Sistem je **kritično dušen**, saj ima sistem zgolj dvojni pol z negativno realno komponento.'))
    elif np.real(poles_sys)[0] == 0 and np.real(poles_sys)[1] == 0:
        display(Markdown('Sistem je **nedušen**, ker imajo poli zgolj imaginarno komponento.'))
    elif np.imag(poles_sys)[0] != 0 and np.imag(poles_sys)[1] != 0 and np.real(poles_sys)[0] != 0 and np.real(poles_sys)[1] != 0:
        display(Markdown('Sistem je **podkritično dušen**, ker imajo poli negativno realno komponennto in neničelno kompleksno komponento.'))
    ax1[0].legend()
    ax1[1].legend()
```

    <IPython.core.display.Javascript object>

    interactive(children=(IntSlider(value=7, description='a', max=10), IntSlider(value=9, description='b', max=10,…

```python

```