We first clear the workspace using rm(list = ls())and
then include all packages we need. If a package is missing in your R
distribution (which is quite likely initially), just use
install.packages("package_name") with the respective
package name to install it on your system. If you execute the code in
the file install_packages.R, then all necessary packages
will be installed into your R distribution.
rm(list = ls())
library(reshape2)
library(base)
library(ggplot2)
library(grid)
library(stringr)
library(tidyverse)
library(gridExtra)
Now we generate a function that allows us to simulate the DE forward.
Input arguments to this function are a starting value y_0
as well as the curvature parameter of the function that governs the
non-linear difference equation \(f(y) =
y^\alpha\). Finally, the function should simulate T
periods of the difference equation.
diff_eq <- function(y_0, alpha, T) {
y <- y_0
if(T > 0) {
for (t in 2:(T+1)) {
y[t] = y[t-1]^alpha
}
}
return(y)
}
We next provide a function plot_phase that allows to
draw a phase diagram of the difference equation specified in the above
function. It receives the same input arguments as the function above.
This function proceeds in several steps to construct the phase
diagram:
In a first step, we simulate the difference equation forward
until date T.
Next, we want to plot the functional form of the difference
equation as well as a \(45°\)-line. We
therefore construct a data frame that contains an equally spaced set of
points on the interval \([0, 2]\) as
well as the corresponding function values of \(f(y) = y^\alpha\). We plot the function and
the \(45°\)-line by means of
ggplot.
Next we successively add the arrows for each step of the phase
diagram. We do this using a for-loop that allows us to
repeat the same steps over and over again. For each step of the phase
diagram, we have to draw a vertical line (the arrow from the \(45°\)-line to the function \(f(y)\)) as well as a horizontal line (the
arrow from the the function \(f(y)\)
back to the \(45°\)-line). For each of
the arrows, we construct a separate data frame dat and use
the geom_path plot statement to add the arrow to the
plot.
Note that, when all T arrow sets are added to the plot,
we do not print the plot, but return the plot to the function that will
call plot_phase, as we want to combine a phase diagram as
well as the time diagram of the difference equation into one plot.
plot_phase <- function(y_0, alpha, T) {
# simulate equation forward
y <- diff_eq(y_0, alpha, T)
# First plot the function itself
dat <- data.frame(
x = seq(0.0, 2, by=0.01),
f = seq(0.0, 2, by=0.01)^alpha
)
myplot <- ggplot(data=dat) +
geom_line(aes(x=x, y=f), color="darkblue", linewidth=1) +
geom_line(aes(x=x, y=x), color="darkblue", linewidth=0.5) +
coord_cartesian(xlim=c(0, 2), ylim=c(0, 2)) +
scale_x_continuous(breaks=seq(0, 2, 0.2)) +
labs(x = expression('y'['t']),
y = expression('y'['t+1']),
title= bquote("Phase Diagram: " ~ alpha == .(alpha) ~ " , " ~ y[0] == .(y_0))) +
theme_bw()
# add single steps to the phase diagram
if(T >= 1) {
for (t in 1:T) {
# add the vertical line
dat <- data.frame(d1 = c(y[t], y[t]),
d2 = c(y[t], y[t+1]))
myplot <- myplot + geom_path(data=dat, aes(x=d1, y=d2), color = "red", linewidth=0.5, arrow = arrow(length = unit(0.02, "npc")))
# add the horizontal line
dat <- data.frame(d1 = c(y[t], y[t+1]),
d2 = c(y[t+1], y[t+1]))
myplot <- myplot + geom_path(data=dat, aes(x=d1, y=d2), color = "red", linewidth=0.5, arrow = arrow(length = unit(0.02, "npc")))
}
}
# print the plot
return(myplot)
}
In addition to the phase diagram, we again want to plot a time
diagram, as we did for linear difference equations. The function
plot_diff is almost identical to the one we used for
plotting linear DEs. The only differences are in the input values as
well as the fact that we do not print the plot, but return the created
plot through the return statement.
plot_diff <- function(y_0, alpha, T) {
# simulate equation forward
y <- diff_eq(y_0, alpha, T)
# generate plotting data
dat <- data.frame(
time = seq(0, T, 1),
DE = y,
stst = array(1, c(T+1))
)
aval <- sprintf("%5.2f", alpha)
yval <- sprintf("%5.2f", y_0)
# now generate the plot
myplot <- ggplot(data=dat) +
geom_line(aes(x=time, y=stst), color="red", linewidth=1) +
geom_line(aes(x=time, y=DE), color="darkblue", linewidth=1) +
geom_point(aes(x=time, y=DE), color="darkblue", size=3, show.legend = FALSE) +
coord_cartesian(xlim=c(0, T), ylim=c(0,2)) +
scale_x_continuous(breaks=seq(0, T, 2)) +
labs(x = "Time t",
y = expression(paste("Solution of non-linear DE ", y[t])),
title= bquote("Non-Linear Difference Equation: " ~ alpha == .(alpha) ~ " , " ~ y[0] == .(y_0))) +
theme_bw()
# print the plot
return(myplot)
}
Now we want to print two plots next to each other. To do this, we
first have to generate the phase diagram as well as the time diagram
using the functions plot_phase and
time_diagram we constructed above. To show two graphs next
to each other, we can use the function grid.arrange out of
the gridExtra package. This function takes the plots we
want to show. The statement ncol=2 ensures that the two
plots are arranged in two different columns, meaning next to each
other.
plot_both <- function(y_0, alpha, T) {
# phase diagram
phase_diagram <- plot_phase(y_0, alpha, T)
# time diagram
time_diagram <- plot_diff(y_0, alpha, T)
# plot one next to the other
grid.arrange(phase_diagram, time_diagram, ncol=2)
}
Now we can start generating plots. We want to simulate 15 periods of
the solution to the linear difference equation. We therefore define a
variable T = 15. We then define different parameter values
for alpha and y_0 and want to see how the
solution to the DE behaves. We start out with \(\alpha = 0.5\) and a starting value that
ensures monotone convergence to the steady state from the left.
T = 14;
plot_both(0.25, 0.5, T)
When we chose a starting point on the right of the steady
state of \(\bar y = 1\), we get
monotone convergence from the right.
plot_both(1.75, 0.5, T)
With a value of \(\alpha \in
(-1,0)\), we get alternating convergence to the steady state.
plot_both(0.25, -0.5, T)
For \(\alpha > 1\), the
steady state at \(\bar y = 1\) is
instable. But the steady state at \(\bar y =
0\) is locally stable for starting value \(y_0 \in (0, 1)\).
plot_both(0.9, 1.5, T)
If we start above the steady state of \(\bar y = 1\), the sequence diverges
monotonically.
plot_both(1.01, 1.5, T)
Finally, the sequence diverges in an alternating way for \(\alpha < -1\).
plot_both(1.01, -1.5, T)