1 Introduction

This article is looking at state-space models in macroeconomic forecasting, particularly a regime switching model. Regime switching models use the hypothesis that there are hidden states or characteristic equations that model the data generating process. Thus this is truly a subset of Hidden Markov Models with two states. An example would be a market rally vs normal market movement. Here, a hypothetical new equation could be used to model rally (as the behavior during these times is markedly different than during normal operation).

In the case of macroeconomic forecasting, the states one might be interested in would be expansion and contraction in the Gross Domestic Product (GDP). Knowing if we are moving into an expansion or recession hidden Markov state would be very interesting to the Federal Reserve in order to change policy in order to steer the economy. However, it must be mentioned that these types of models are hard. Why? Well we really don’t know if the two hidden states exist as we have modeled them (hence hidden). Additionally, these models have a problem with identifiability, i.e. we really don’t know if we can mathematically determine when the data are representing one hidden state versus another.

Regardless of these challenges, I will represent some of these models and the power of using Bayesian modeling for these types of problems. Here I’ll model these this process, largely borrowing from work already done by James Savage in his blog post(“Regime-Switching,” n.d.).

2 Data

First we are going to pull the GDP data using the ‘fredr’ package. We’ll get the GDP since 2010 and return the percent change quarter over quarter.

Always important when modeling data is to make sure that you visualize the data. Here we can build a simple graph to ensure that our data match our expectations and that we don’t see anything strange as shown in Figure ??.

US GDP Evolution Since Jan 1, 2010

Figure 2.1: US GDP Evolution Since Jan 1, 2010

Everything looks as expected, so we can move onto modeling.

Figure 2.2: And an interactive looks at GDP

3 Method

In order to model our regime switching, state-space model, we will use Bayesian methods. Additionally, we will parameterize our model using the Stan language. In order to get started we will first load ‘rstan’ and set some general defaults to help us with our modeling.

3.1 Model

We will use a Bayesian modeling approach to model regime switching. Here there are two hypothesized regimes, a random walk state which will be represented as:

\[\text{GDP}_{t}\sim N(\alpha_{rw}, \sigma_{rw})\]

The second state will be a momentum state which will have an auto-regressive term as follows:

\[\text{GDP}_{t} \sim N(\alpha_{mo} + \rho*GDP_{t-1}, \sigma_{mo})\]

Additionally, we will have our different hidden states. As shown in Figure ??, there are four different transitions that can occur. A random walk can move to another random walk state or transition to a momentum state. This is similar for the momentum state which can transition out to random walk or stay in the momentum state.

[Random Walk]-[Momentum]
[Momentum]-[Random Walk]
[Momentum]-[Momentum]
[Random Walk]-[Random Walk]

3.1.1 Our Model

Now we can code our model using Stan.

//https://khakieconomics.github.io/2018/02/24/Regime-switching-models.html
data {
  int N;
  vector[N] y;
  int sticky;
}
parameters {
  vector<lower = 0, upper = 1>[2] p;
  real<lower = 0> rho;
  vector[2] alpha;
  vector<lower = 0>[2] sigma;
  real<lower = 0, upper = 1> xi1_init;
  real y_tm1_init;
}
transformed parameters {
  matrix[N, 2] eta;
  matrix[N, 2] xi;
  vector[N] f;

  // fill in etas
  for(t in 1:N) {
    eta[t,1] = exp(normal_lpdf(y[t]| alpha[1], sigma[1]));
    if(t==1) {
      eta[t,2] = exp(normal_lpdf(y[t]| alpha[2] + rho * y_tm1_init, sigma[2]));
    } else {
      eta[t,2] = exp(normal_lpdf(y[t]| alpha[2] + rho * y[t-1], sigma[2]));
    }
  }

  // work out likelihood contributions

  for(t in 1:N) {
    // for the first observation
    if(t==1) {
      f[t] = p[1]*xi1_init*eta[t,1] + // stay in state 1
             (1 - p[1])*xi1_init*eta[t,2] + // transition from 1 to 2
             p[2]*(1 - xi1_init)*eta[t,2] + // stay in state 2
             (1 - p[2])*(1 - xi1_init)*eta[t,1]; // transition from 2 to 1

      xi[t,1] = (p[1]*xi1_init*eta[t,1] +(1 - p[2])*(1 - xi1_init)*eta[t,1])/f[t];
      xi[t,2] = 1.0 - xi[t,1];

    } else {
    // and for the rest

      f[t] = p[1]*xi[t-1,1]*eta[t,1] + // stay in state 1
             (1 - p[1])*xi[t-1,1]*eta[t,2] + // transition from 1 to 2
             p[2]*xi[t-1,2]*eta[t,2] + // stay in state 2
             (1 - p[2])*xi[t-1,2]*eta[t,1]; // transition from 2 to 1

      // work out xi

      xi[t,1] = (p[1]*xi[t-1,1]*eta[t,1] +(1 - p[2])*xi[t-1,2]*eta[t,1])/f[t];

      // there are only two states so the probability of the other state is 1 - prob of the first
      xi[t,2] = 1.0 - xi[t,1];
    }
  }

}
model {
  // priors
  p ~ beta(sticky, 2);
  rho ~ normal(1, .1);
  alpha ~ normal(0, .1);
  sigma ~ cauchy(0, 1);
  xi1_init ~ beta(2, 2);
  y_tm1_init ~ normal(0, .1);


  // likelihood is really easy here!
  target += sum(log(f));
}

Now we can compile the model.

3.1.2 Our Priors

The priors set for the model should be derived from subject matter expertise. As I don’t have a ton of that regarding these types of problem, we can go with relatively uninformative priors.

One prior that I would like to talk about is the transition probability, which is parameterized as \(p\) in the model. This represents the probability at any given step that the state will transition to another hidden state. This is currently modeled as a beta distribution. Beta distributions have several nice properties, one of which is that they are bounded between 0 and 1 and thus make a nice prior for probabilities. What matters for this model is that the value of \(p\) indicates how “sticky” a given state is (i.e. how likely or probably a shift to another state is). Higher values indicate that the state is “sticky” and unlikely to change while lower values indicate that the system favors change.

Figure 3.1 shows different values of the first shape parameter (often called \(\alpha\)) for the distribution. As this value increases, the distribution becomes more and more skewed with higher probabilities favored. The other interesting thing about the Beta distribution is that if both values of the shape parameters are less than 1, the distribution becomes bathtub-shaped.

Beta Distribution for Different Values of Shape Parameters

Figure 3.1: Beta Distribution for Different Values of Shape Parameters

I have elected to make this a parameter in our model so that we can see if the results change for stickier state changes.

3.2 Data Prep

Stan requires that we format our data in a list format with names exactly matching those in the Stan file.

3.3 Running Model

Now that we have our model compiled, we can sample from the posterior distribution. It is always a good practice to set the seed for reproducibility. I am turning off the updates from Stan as I know the code run. If you want to see the progress, you can remove the refresh = 0 line.

I am going to go ahead and sample from a model with a stickier probability function as well.

3.4 Diagnostics

As with all (Bayesian) modeling, it is important to assess that your model actually fits your data. Here we will look at the traceplots to verify that there aren’t any clearly diverging chains which would indicate a chain mixing/ convergence issue.

Traceplots of Parameters

Figure 3.2: Traceplots of Parameters

Additionally, we can look at the pairs plots of the parameters and confirm that we have general convergence.

Pairs Plot for Parameter Estimates

Figure 3.3: Pairs Plot for Parameter Estimates

These results look pretty good, though the \(\sigma\)s for the momentum state look strange which indicates that we might not be modeling our data generating process well. We could go back and look at our parameterization where we have the cauchy distribution prior on \(\sigma\).

Finally, we can print the output of the model which shows our parameter estimate but don’t look at those yet! Here we look at our effective samples (n_eff) and our Rhat (Gelman-Rubin statistic) which help us understand how many effective samples we have from our posterior (higher is better) and our chain mixing (Rhat <= 1.1 is good).

## Inference for Stan model: regime_switch.
## 2 chains, each with iter=2000; warmup=1000; thin=1; 
## post-warmup draws per chain=1000, total post-warmup draws=2000.
## 
##          mean se_mean   sd  2.5%   25%  50%  75% 97.5% n_eff Rhat
## alpha[1] 0.21    0.00 0.12 -0.03  0.13 0.21 0.29  0.42  1011    1
## alpha[2] 0.02    0.00 0.07 -0.13 -0.02 0.02 0.07  0.15  1547    1
## rho      0.92    0.00 0.09  0.74  0.85 0.92 0.98  1.10  1123    1
## p[1]     0.77    0.00 0.12  0.49  0.69 0.78 0.86  0.95  1497    1
## p[2]     0.75    0.00 0.15  0.40  0.66 0.78 0.86  0.95  1255    1
## sigma[1] 0.59    0.00 0.15  0.37  0.48 0.56 0.66  0.97   981    1
## sigma[2] 0.27    0.01 0.18  0.10  0.21 0.26 0.31  0.44   554    1
## 
## Samples were drawn using NUTS(diag_e) at Tue Jan 21 16:49:08 2020.
## For each parameter, n_eff is a crude measure of effective sample size,
## and Rhat is the potential scale reduction factor on split chains (at 
## convergence, Rhat=1).

All in all the model is fit.

4 Results

Now we can look at our parameter estimates as shown in Table ??.

Table 4.1: Estimates and 90% Interval Estimates
term estimate std.error conf.low conf.high
alpha[1] 0.207 0.119 0.005 0.390
alpha[2] 0.020 0.071 -0.106 0.134
rho 0.915 0.092 0.765 1.068
p[1] 0.765 0.123 0.538 0.940
p[2] 0.747 0.147 0.457 0.935
sigma[1] 0.588 0.155 0.394 0.881
sigma[2] 0.273 0.185 0.137 0.403

We see that during the momentum state that there is a strong auto-regressive parameter with \(\rho\) equal to nearly one. As we saw in our convergence diagnostics, \(\sigma\) for our momentum state has a very large standard error which is concerning.

4.1 Interpretation

It’s best to visualize the output of this model.

State Probability and Actual GDP Evolution

Figure 4.1: State Probability and Actual GDP Evolution

So here we can see that our model isn’t great. There are only a few periods in which the probability of being in a random walk is high (sometime around Q1 2012 and since the end of 2018). This could indicate that the current growth we are seeing now is in a random walk random state while previous periods were probably in this rally state. This might be a harbinger of a slow down, but this model doesn’t fit the data that well.

5 Next Steps

The fun part with these types of models is that you don’t have to stop here. Two states may not be appropriate. Additionally, there is definitely more information in the world than just GDP. This model could be enhanced by using different times series models as well as bring in additional data to use to help forecast GDP and identify the the hidden state. We also saw the issue with identifiability with our model not really being able to discern distinct states.

References

“Regime-Switching.” n.d. https://khakieconomics.github.io/2018/02/24/Regime-switching-models.html.

LS0tCnRpdGxlOiBTdGF0ZS1TcGFjZQpjb2RlX2ZvbGRpbmc6ICJoaWRlIgpiaWJsaW9ncmFwaHk6IGxpYnJhcnkuYmliCi0tLQoKYGBge3IgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0Kc291cmNlKCJSL2hlbHBlcnMuUiIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGZyZWRyKQpsaWJyYXJ5KG5vbW5vbWwpCmtuaXRyOjpvcHRzX2NodW5rJHNldCh3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgZmlnLmFsaWduID0gImNlbnRlciIsIG91dC53aWR0aCA9ICI4MCUiKQpgYGAKCiMgSW50cm9kdWN0aW9uCgpUaGlzIGFydGljbGUgaXMgbG9va2luZyBhdCBzdGF0ZS1zcGFjZSBtb2RlbHMgaW4gbWFjcm9lY29ub21pYyBmb3JlY2FzdGluZywgcGFydGljdWxhcmx5IGEgcmVnaW1lIHN3aXRjaGluZyBtb2RlbC4gClJlZ2ltZSBzd2l0Y2hpbmcgbW9kZWxzIHVzZSB0aGUgaHlwb3RoZXNpcyB0aGF0IHRoZXJlIGFyZSBoaWRkZW4gc3RhdGVzIG9yIGNoYXJhY3RlcmlzdGljIGVxdWF0aW9ucyB0aGF0IG1vZGVsIHRoZSBkYXRhIGdlbmVyYXRpbmcgcHJvY2Vzcy4KVGh1cyB0aGlzIGlzIHRydWx5IGEgc3Vic2V0IG9mIFtIaWRkZW4gTWFya292IE1vZGVsc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSGlkZGVuX01hcmtvdl9tb2RlbCkgd2l0aCB0d28gc3RhdGVzLgpBbiBleGFtcGxlIHdvdWxkIGJlIGEgbWFya2V0IHJhbGx5IHZzIG5vcm1hbCBtYXJrZXQgbW92ZW1lbnQuIApIZXJlLCBhIGh5cG90aGV0aWNhbCBuZXcgZXF1YXRpb24gY291bGQgYmUgdXNlZCB0byBtb2RlbCByYWxseSAoYXMgdGhlIGJlaGF2aW9yIGR1cmluZyB0aGVzZSB0aW1lcyBpcyBtYXJrZWRseSBkaWZmZXJlbnQgdGhhbiBkdXJpbmcgbm9ybWFsIG9wZXJhdGlvbikuCgpJbiB0aGUgY2FzZSBvZiBtYWNyb2Vjb25vbWljIGZvcmVjYXN0aW5nLCB0aGUgc3RhdGVzIG9uZSBtaWdodCBiZSBpbnRlcmVzdGVkIGluIHdvdWxkIGJlIGV4cGFuc2lvbiBhbmQgY29udHJhY3Rpb24gaW4gdGhlIEdyb3NzIERvbWVzdGljIFByb2R1Y3QgKEdEUCkuIApLbm93aW5nIGlmIHdlIGFyZSBtb3ZpbmcgaW50byBhbiBleHBhbnNpb24gb3IgcmVjZXNzaW9uIGhpZGRlbiBNYXJrb3Ygc3RhdGUgd291bGQgYmUgdmVyeSBpbnRlcmVzdGluZyB0byB0aGUgRmVkZXJhbCBSZXNlcnZlIGluIG9yZGVyIHRvIGNoYW5nZSBwb2xpY3kgaW4gb3JkZXIgdG8gc3RlZXIgdGhlIGVjb25vbXkuCkhvd2V2ZXIsIGl0IG11c3QgYmUgbWVudGlvbmVkIHRoYXQgdGhlc2UgdHlwZXMgb2YgbW9kZWxzIGFyZSBoYXJkLgpXaHk/IApXZWxsIHdlIHJlYWxseSBkb24ndCBrbm93IGlmIHRoZSB0d28gaGlkZGVuIHN0YXRlcyBleGlzdCBhcyB3ZSBoYXZlIG1vZGVsZWQgdGhlbSAoaGVuY2UgaGlkZGVuKS4KQWRkaXRpb25hbGx5LCB0aGVzZSBtb2RlbHMgaGF2ZSBhIHByb2JsZW0gd2l0aCBbaWRlbnRpZmlhYmlsaXR5XShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9JZGVudGlmaWFiaWxpdHkpLCBpLmUuIHdlIHJlYWxseSBkb24ndCBrbm93IGlmIHdlIGNhbiBtYXRoZW1hdGljYWxseSBkZXRlcm1pbmUgd2hlbiB0aGUgZGF0YSBhcmUgcmVwcmVzZW50aW5nIG9uZSBoaWRkZW4gc3RhdGUgdmVyc3VzIGFub3RoZXIuCgpSZWdhcmRsZXNzIG9mIHRoZXNlIGNoYWxsZW5nZXMsIEkgd2lsbCByZXByZXNlbnQgc29tZSBvZiB0aGVzZSBtb2RlbHMgYW5kIHRoZSBwb3dlciBvZiB1c2luZyBCYXllc2lhbiBtb2RlbGluZyBmb3IgdGhlc2UgdHlwZXMgb2YgcHJvYmxlbXMuIApIZXJlIEknbGwgbW9kZWwgdGhlc2UgdGhpcyBwcm9jZXNzLCBsYXJnZWx5IGJvcnJvd2luZyBmcm9tIHdvcmsgYWxyZWFkeSBkb25lIGJ5IEphbWVzIFNhdmFnZSBpbiBoaXMgW2Jsb2cgcG9zdF0oaHR0cHM6Ly9raGFraWVjb25vbWljcy5naXRodWIuaW8vMjAxOC8wMi8yNC9SZWdpbWUtc3dpdGNoaW5nLW1vZGVscy5odG1sKVtAc2F2YWdlUmVnaW1lXS4KCiMgRGF0YQoKRmlyc3Qgd2UgYXJlIGdvaW5nIHRvIHB1bGwgdGhlIEdEUCBkYXRhIHVzaW5nIHRoZSBbJ2ZyZWRyJ10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2ZyZWRyL3ZpZ25ldHRlcy9mcmVkci5odG1sKSBwYWNrYWdlLgpXZSdsbCBnZXQgdGhlIEdEUCBzaW5jZSAyMDEwIGFuZCByZXR1cm4gdGhlIHBlcmNlbnQgY2hhbmdlIHF1YXJ0ZXIgb3ZlciBxdWFydGVyLgoKYGBge3J9CmxpYnJhcnkocGF0Y2h3b3JrKQpnZHBfZGF0IDwtIGZyZWRyKHNlcmllc19pZCA9ICJHRFBDMSIsCgkJCQkJCQkJIG9ic2VydmF0aW9uX3N0YXJ0ID0gYXMuRGF0ZSgiMjAxMC0wMS0wMSIpLAoJCQkJCQkJCSB1bml0cyA9ICJwY2giKQpgYGAKCkFsd2F5cyBpbXBvcnRhbnQgd2hlbiBtb2RlbGluZyBkYXRhIGlzIHRvIG1ha2Ugc3VyZSB0aGF0IHlvdSB2aXN1YWxpemUgdGhlIGRhdGEuCkhlcmUgd2UgY2FuIGJ1aWxkIGEgc2ltcGxlIGdyYXBoIHRvIGVuc3VyZSB0aGF0IG91ciBkYXRhIG1hdGNoIG91ciBleHBlY3RhdGlvbnMgYW5kIHRoYXQgd2UgZG9uJ3Qgc2VlIGFueXRoaW5nIHN0cmFuZ2UgYXMgc2hvd24gaW4gRmlndXJlIFxAcmVmKGZpZzpncGQtdHJlbmQpLgoKYGBge3IgZ2RwLXRyZW5kLCBmaWcuY2FwPSJVUyBHRFAgRXZvbHV0aW9uIFNpbmNlIEphbiAxLCAyMDEwIn0KKGdkcF90cmVuZCA8LSBnZHBfZGF0ICU+JSAKCWdncGxvdChhZXMoZGF0ZSwgdmFsdWUpKSsKCWdlb21fbGluZShjb2xvciA9IHVuY2dfcGFsW1sxXV0pKwoJZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbHR5ID0gImRhc2hlZCIsIGNvbG9yID0gInJlZCIpKwoJbGFicygKCQl0aXRsZSA9ICJVUyBHRFAgKCUgQ2hhbmdlKSIsCgkJeSA9ICIlIiwKCQljYXB0aW9uID0gIkRhdGE6IEZSRUQgU3QuIExvdWlzIEZlZGVyYWwgUmVzZXJ2ZSIKCSkpCmBgYAoKRXZlcnl0aGluZyBsb29rcyBhcyBleHBlY3RlZCwgc28gd2UgY2FuIG1vdmUgb250byBtb2RlbGluZy4KCmBgYHtyIGZpZy5jYXA9IkFuZCBhbiBpbnRlcmFjdGl2ZSBsb29rcyBhdCBHRFAifQpsaWJyYXJ5KGhpZ2hjaGFydGVyKQpoY2hhcnQoZ2RwX2RhdCwgImxpbmUiLCBoY2Flcyh4ID0gZGF0ZSwgeSA9IHZhbHVlKSwKICAgICAgIGNvbG9yID0gdW5jZ19wYWxbWzFdXSkgJT4lIAoJaGNfdGl0bGUoCiAgICB0ZXh0ID0gIlVTIEdEUCAoJSBDaGFuZ2UpIiwKICAgIHVzZUhUTUwgPSBUUlVFKSAlPiUgCgloY190b29sdGlwKHRhYmxlID0gVFJVRSwgc29ydCA9IFRSVUUpICU+JSAKCWhjX3lBeGlzKHRpY2tQb3NpdGlvbnMgPSBjKC0yLCAtMSwwLDEsMiksCiAgICAgICAgICAgZ3JpZExpbmVDb2xvciA9ICIjQjcxQzFDIiwKICAgICAgICAgICBsYWJlbHMgPSBsaXN0KGZvcm1hdCA9ICJ7dmFsdWV9ICUiLCB1c2VIVE1MID0gVFJVRSkpICU+JSAKCWhjX2NyZWRpdHMoCiAgICBlbmFibGVkID0gVFJVRSwKICAgIHRleHQgPSAiU291cmNlOiBGUkVEIiwKICAgIGhyZWYgPSAiaHR0cHM6Ly9mcmVkLnN0bG91aXNmZWQub3JnL3Nlcmllcy9HRFBDMSIpICU+JSAKCWhjX2FkZF90aGVtZShoY190aGVtZV90dWZ0ZTIoKSkKCmBgYAoKCiMgTWV0aG9kCgpJbiBvcmRlciB0byBtb2RlbCBvdXIgcmVnaW1lIHN3aXRjaGluZywgc3RhdGUtc3BhY2UgbW9kZWwsIHdlIHdpbGwgdXNlIEJheWVzaWFuIG1ldGhvZHMuCkFkZGl0aW9uYWxseSwgd2Ugd2lsbCBwYXJhbWV0ZXJpemUgb3VyIG1vZGVsIHVzaW5nIHRoZSBbU3Rhbl0oc3Rhbm1jLm9yZykgbGFuZ3VhZ2UuCkluIG9yZGVyIHRvIGdldCBzdGFydGVkIHdlIHdpbGwgZmlyc3QgbG9hZCAncnN0YW4nIGFuZCBzZXQgc29tZSBnZW5lcmFsIGRlZmF1bHRzIHRvIGhlbHAgdXMgd2l0aCBvdXIgbW9kZWxpbmcuCgpgYGB7cn0KbGlicmFyeShyc3RhbikKb3B0aW9ucyhtYy5jb3JlcyA9IHBhcmFsbGVsOjpkZXRlY3RDb3JlcygpKQpyc3Rhbl9vcHRpb25zKGF1dG9fd3JpdGUgPSBUUlVFKQpgYGAKCiMjIE1vZGVsCgpXZSB3aWxsIHVzZSBhIEJheWVzaWFuIG1vZGVsaW5nIGFwcHJvYWNoIHRvIG1vZGVsIHJlZ2ltZSBzd2l0Y2hpbmcuIApIZXJlIHRoZXJlIGFyZSB0d28gaHlwb3RoZXNpemVkIHJlZ2ltZXMsIGEgW3JhbmRvbSB3YWxrIHN0YXRlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9SYW5kb21fd2Fsaykgd2hpY2ggd2lsbCBiZSByZXByZXNlbnRlZCBhczoKCiQkXHRleHR7R0RQfV97dH1cc2ltIE4oXGFscGhhX3tyd30sIFxzaWdtYV97cnd9KSQkCgpUaGUgc2Vjb25kIHN0YXRlIHdpbGwgYmUgYSBtb21lbnR1bSBzdGF0ZSB3aGljaCB3aWxsIGhhdmUgYW4gYXV0by1yZWdyZXNzaXZlIHRlcm0gYXMgZm9sbG93czoKCiQkXHRleHR7R0RQfV97dH0gXHNpbSBOKFxhbHBoYV97bW99ICsgXHJobypHRFBfe3QtMX0sIFxzaWdtYV97bW99KSQkCgpBZGRpdGlvbmFsbHksIHdlIHdpbGwgaGF2ZSBvdXIgZGlmZmVyZW50IGhpZGRlbiBzdGF0ZXMuCkFzIHNob3duIGluIEZpZ3VyZSBcQHJlZihmaWc6dHJhbnNpdGlvbnMpLCB0aGVyZSBhcmUgZm91ciBkaWZmZXJlbnQgdHJhbnNpdGlvbnMgdGhhdCBjYW4gb2NjdXIuIApBIHJhbmRvbSB3YWxrIGNhbiBtb3ZlIHRvIGFub3RoZXIgcmFuZG9tIHdhbGsgc3RhdGUgb3IgdHJhbnNpdGlvbiB0byBhIG1vbWVudHVtIHN0YXRlLgpUaGlzIGlzIHNpbWlsYXIgZm9yIHRoZSBtb21lbnR1bSBzdGF0ZSB3aGljaCBjYW4gdHJhbnNpdGlvbiBvdXQgdG8gcmFuZG9tIHdhbGsgb3Igc3RheSBpbiB0aGUgbW9tZW50dW0gc3RhdGUuCgpgYGB7bm9tbm9tbCB0cmFuc2l0aW9ucywgZmlnLmNhcCA9ICJEaWZmZXJlbnQgVHJhbnNpdGlvbiBTdGF0ZXMifQpbUmFuZG9tIFdhbGtdLVtNb21lbnR1bV0KW01vbWVudHVtXS1bUmFuZG9tIFdhbGtdCltNb21lbnR1bV0tW01vbWVudHVtXQpbUmFuZG9tIFdhbGtdLVtSYW5kb20gV2Fsa10KYGBgCgoKIyMjIE91ciBNb2RlbAoKTm93IHdlIGNhbiBjb2RlIG91ciBtb2RlbCB1c2luZyBTdGFuLgoKYGBge3IgY29tbWVudD0nJywgZWNobz1UUlVFfQp3cml0ZUxpbmVzKHJlYWRMaW5lcygicmVnaW1lX3N3aXRjaC5zdGFuIikpCmBgYAoKTm93IHdlIGNhbiBjb21waWxlIHRoZSBtb2RlbC4KCmBgYHtyfQptb2RlbF9yZWdpbWUgPC0gc3Rhbl9tb2RlbChmaWxlID0gInJlZ2ltZV9zd2l0Y2guc3RhbiIpCmBgYAoKIyMjIE91ciBQcmlvcnMKClRoZSBwcmlvcnMgc2V0IGZvciB0aGUgbW9kZWwgc2hvdWxkIGJlIGRlcml2ZWQgZnJvbSBzdWJqZWN0IG1hdHRlciBleHBlcnRpc2UuCkFzIEkgZG9uJ3QgaGF2ZSBhIHRvbiBvZiB0aGF0IHJlZ2FyZGluZyB0aGVzZSB0eXBlcyBvZiBwcm9ibGVtLCB3ZSBjYW4gZ28gd2l0aCByZWxhdGl2ZWx5IHVuaW5mb3JtYXRpdmUgcHJpb3JzLiAKCk9uZSBwcmlvciB0aGF0IEkgd291bGQgbGlrZSB0byB0YWxrIGFib3V0IGlzIHRoZSB0cmFuc2l0aW9uIHByb2JhYmlsaXR5LCB3aGljaCBpcyBwYXJhbWV0ZXJpemVkIGFzICRwJCBpbiB0aGUgbW9kZWwuClRoaXMgcmVwcmVzZW50cyB0aGUgcHJvYmFiaWxpdHkgYXQgYW55IGdpdmVuIHN0ZXAgdGhhdCB0aGUgc3RhdGUgd2lsbCB0cmFuc2l0aW9uIHRvIGFub3RoZXIgaGlkZGVuIHN0YXRlLgpUaGlzIGlzIGN1cnJlbnRseSBtb2RlbGVkIGFzIGEgYmV0YSBkaXN0cmlidXRpb24uCkJldGEgZGlzdHJpYnV0aW9ucyBoYXZlIHNldmVyYWwgbmljZSBwcm9wZXJ0aWVzLCBvbmUgb2Ygd2hpY2ggaXMgdGhhdCB0aGV5IGFyZSBib3VuZGVkIGJldHdlZW4gMCBhbmQgMSBhbmQgdGh1cyBtYWtlIGEgbmljZSBwcmlvciBmb3IgcHJvYmFiaWxpdGllcy4KV2hhdCBtYXR0ZXJzIGZvciB0aGlzIG1vZGVsIGlzIHRoYXQgdGhlIHZhbHVlIG9mICRwJCBpbmRpY2F0ZXMgaG93ICJzdGlja3kiIGEgZ2l2ZW4gc3RhdGUgaXMgKGkuZS4gaG93IGxpa2VseSBvciBfcHJvYmFibHlfIGEgc2hpZnQgdG8gYW5vdGhlciBzdGF0ZSBpcykuCkhpZ2hlciB2YWx1ZXMgaW5kaWNhdGUgdGhhdCB0aGUgc3RhdGUgaXMgInN0aWNreSIgYW5kIHVubGlrZWx5IHRvIGNoYW5nZSB3aGlsZSBsb3dlciB2YWx1ZXMgaW5kaWNhdGUgdGhhdCB0aGUgc3lzdGVtIGZhdm9ycyBjaGFuZ2UuCgpGaWd1cmUgXEByZWYoZmlnOmJldGEtZGlzdCkgc2hvd3MgZGlmZmVyZW50IHZhbHVlcyBvZiB0aGUgZmlyc3Qgc2hhcGUgcGFyYW1ldGVyIChvZnRlbiBjYWxsZWQgJFxhbHBoYSQpIGZvciB0aGUgZGlzdHJpYnV0aW9uLgpBcyB0aGlzIHZhbHVlIGluY3JlYXNlcywgdGhlIGRpc3RyaWJ1dGlvbiBiZWNvbWVzIG1vcmUgYW5kIG1vcmUgc2tld2VkIHdpdGggaGlnaGVyIHByb2JhYmlsaXRpZXMgZmF2b3JlZC4KVGhlIG90aGVyIGludGVyZXN0aW5nIHRoaW5nIGFib3V0IHRoZSBCZXRhIGRpc3RyaWJ1dGlvbiBpcyB0aGF0IGlmIGJvdGggdmFsdWVzIG9mIHRoZSBzaGFwZSBwYXJhbWV0ZXJzIGFyZSBsZXNzIHRoYW4gMSwgdGhlIGRpc3RyaWJ1dGlvbiBiZWNvbWVzIGJhdGh0dWItc2hhcGVkLgoKYGBge3IgYmV0YS1kaXN0LCBmaWcuY2FwPSJCZXRhIERpc3RyaWJ1dGlvbiBmb3IgRGlmZmVyZW50IFZhbHVlcyBvZiBTaGFwZSBQYXJhbWV0ZXJzIn0KcCA8LSAgc2VxKDAsMSwgbGVuZ3RoPTEwMCkKcGxvdChwLCBkYmV0YShwLCAuNSwgLjUpLCB5bGFiPSJkZW5zaXR5IiwgdHlwZSA9ImwiLCBjb2w9NCwgeWxpbT1jKDAsMTApKQpsaW5lcyhwLCBkYmV0YShwLCAyLCAyKSwgdHlwZSA9ImwiLCBjb2w9NSkKbGluZXMocCwgZGJldGEocCwgNSwgMiksIHR5cGUgPSJsIiwgY29sPTMpCmxpbmVzKHAsIGRiZXRhKHAsIDEwLCAyKSwgY29sPTIpIApsaW5lcyhwLCBkYmV0YShwLCAyMCwgMiksIGNvbD0xKSAKbGVnZW5kKCJ0b3BsZWZ0IiwgYygiQmV0YSguNSwuNSkiLCJCZXRhKDIsMikiLCJCZXRhKDUsMikiLCJCZXRhKDEwLDIpIiwgIkJldGEoMjAsMikiKSxsdHk9YygxLDEsMSwxLDEpLGNvbD1jKDQsNSwzLDIsMSkpCmBgYAoKSSBoYXZlIGVsZWN0ZWQgdG8gbWFrZSB0aGlzIGEgcGFyYW1ldGVyIGluIG91ciBtb2RlbCBzbyB0aGF0IHdlIGNhbiBzZWUgaWYgdGhlIHJlc3VsdHMgY2hhbmdlIGZvciBzdGlja2llciBzdGF0ZSBjaGFuZ2VzLiAKCiMjIERhdGEgUHJlcAoKU3RhbiByZXF1aXJlcyB0aGF0IHdlIGZvcm1hdCBvdXIgZGF0YSBpbiBhIGxpc3QgZm9ybWF0IHdpdGggbmFtZXMgZXhhY3RseSBtYXRjaGluZyB0aG9zZSBpbiB0aGUgU3RhbiBmaWxlLgoKYGBge3J9CnN0YW5fZGF0IDwtIGxpc3QoTiA9IG5yb3coZ2RwX2RhdCksCgkJCQkJCQkJIHkgPSBkcGx5cjo6cHVsbChnZHBfZGF0LCB2YWx1ZSksCgkJCQkJCQkJIHN0aWNreSA9IDUpCmBgYAoKCiMjIFJ1bm5pbmcgTW9kZWwKCk5vdyB0aGF0IHdlIGhhdmUgb3VyIG1vZGVsIGNvbXBpbGVkLCB3ZSBjYW4gc2FtcGxlIGZyb20gdGhlIHBvc3RlcmlvciBkaXN0cmlidXRpb24uIApJdCBpcyBhbHdheXMgYSBnb29kIHByYWN0aWNlIHRvIHNldCB0aGUgc2VlZCBmb3IgcmVwcm9kdWNpYmlsaXR5LgpJIGFtIHR1cm5pbmcgb2ZmIHRoZSB1cGRhdGVzIGZyb20gU3RhbiBhcyBJIGtub3cgdGhlIGNvZGUgcnVuLiAKSWYgeW91IHdhbnQgdG8gc2VlIHRoZSBwcm9ncmVzcywgeW91IGNhbiByZW1vdmUgdGhlIGByZWZyZXNoID0gMGAgbGluZS4KCmBgYHtyfQpmaXRfcmVnaW1lIDwtIHNhbXBsaW5nKG1vZGVsX3JlZ2ltZSwgZGF0YSA9IHN0YW5fZGF0LCAKCQkJCQkJCQkJCQkgY2hhaW5zID0gMiwgcmVmcmVzaCA9IDAsCgkJCQkJCQkJCQkJIHNlZWQgPSA0MikKYGBgCgpJIGFtIGdvaW5nIHRvIGdvIGFoZWFkIGFuZCBzYW1wbGUgZnJvbSBhIG1vZGVsIHdpdGggYSBzdGlja2llciBwcm9iYWJpbGl0eSBmdW5jdGlvbiBhcyB3ZWxsLgoKYGBge3J9CmZpdF9yZWdpbWVfc3RpY2t5IDwtIHNhbXBsaW5nKG1vZGVsX3JlZ2ltZSwgZGF0YSA9IAoJCQkJCQkJCQkJCQkJCQkJbGlzdChOID0gbnJvdyhnZHBfZGF0KSwKCQkJCQkJCQkJCQkJCQkJCQkJIHkgPSBkcGx5cjo6cHVsbChnZHBfZGF0LCB2YWx1ZSksCgkJCQkJCQkJCQkJCQkJCQkJCSBzdGlja3kgPSAyMCksIAoJCQkJCQkJCQkJCSBjaGFpbnMgPSAyLCByZWZyZXNoID0gMCwKCQkJCQkJCQkJCQkgc2VlZCA9IDQyKQpgYGAKCiMjIERpYWdub3N0aWNzCgpBcyB3aXRoIGFsbCAoQmF5ZXNpYW4pIG1vZGVsaW5nLCBpdCBpcyBpbXBvcnRhbnQgdG8gYXNzZXNzIHRoYXQgeW91ciBtb2RlbCBhY3R1YWxseSBmaXRzIHlvdXIgZGF0YS4KSGVyZSB3ZSB3aWxsIGxvb2sgYXQgdGhlIHRyYWNlcGxvdHMgdG8gdmVyaWZ5IHRoYXQgdGhlcmUgYXJlbid0IGFueSBjbGVhcmx5IGRpdmVyZ2luZyBjaGFpbnMgd2hpY2ggd291bGQgaW5kaWNhdGUgYSBjaGFpbiBtaXhpbmcvIGNvbnZlcmdlbmNlIGlzc3VlLgoKYGBge3IgZmlnLmNhcD0iVHJhY2VwbG90cyBvZiBQYXJhbWV0ZXJzIn0KdHJhY2VwbG90KGZpdF9yZWdpbWUsIHBhcnMgPSBjKCJhbHBoYSIsICJyaG8iLCAic2lnbWEiKSkKYGBgCgpBZGRpdGlvbmFsbHksIHdlIGNhbiBsb29rIGF0IHRoZSBwYWlycyBwbG90cyBvZiB0aGUgcGFyYW1ldGVycyBhbmQgY29uZmlybSB0aGF0IHdlIGhhdmUgZ2VuZXJhbCBjb252ZXJnZW5jZS4KCmBgYHtyIGZpZy5jYXA9IlBhaXJzIFBsb3QgZm9yIFBhcmFtZXRlciBFc3RpbWF0ZXMifQpwYWlycyhmaXRfcmVnaW1lLCBwYXJzID0gYygiYWxwaGEiLCJyaG8iLCJzaWdtYSIpKQpgYGAKClRoZXNlIHJlc3VsdHMgbG9vayBwcmV0dHkgZ29vZCwgdGhvdWdoIHRoZSAkXHNpZ21hJHMgZm9yIHRoZSBtb21lbnR1bSBzdGF0ZSBsb29rIHN0cmFuZ2Ugd2hpY2ggaW5kaWNhdGVzIHRoYXQgd2UgbWlnaHQgbm90IGJlIG1vZGVsaW5nIG91ciBkYXRhIGdlbmVyYXRpbmcgcHJvY2VzcyB3ZWxsLiAKV2UgY291bGQgZ28gYmFjayBhbmQgbG9vayBhdCBvdXIgcGFyYW1ldGVyaXphdGlvbiB3aGVyZSB3ZSBoYXZlIHRoZSBjYXVjaHkgZGlzdHJpYnV0aW9uIHByaW9yIG9uICRcc2lnbWEkLgoKRmluYWxseSwgd2UgY2FuIHByaW50IHRoZSBvdXRwdXQgb2YgdGhlIG1vZGVsIHdoaWNoIHNob3dzIG91ciBwYXJhbWV0ZXIgZXN0aW1hdGUgX2J1dCBkb24ndCBsb29rIGF0IHRob3NlIHlldF8hIApIZXJlIHdlIGxvb2sgYXQgb3VyIGVmZmVjdGl2ZSBzYW1wbGVzIChuX2VmZikgYW5kIG91ciBSaGF0IChHZWxtYW4tUnViaW4gc3RhdGlzdGljKSB3aGljaCBoZWxwIHVzIHVuZGVyc3RhbmQgaG93IG1hbnkgZWZmZWN0aXZlIHNhbXBsZXMgd2UgaGF2ZSBmcm9tIG91ciBwb3N0ZXJpb3IgKGhpZ2hlciBpcyBiZXR0ZXIpIGFuZCBvdXIgY2hhaW4gbWl4aW5nIChSaGF0IDw9IDEuMSBpcyBnb29kKS4KCmBgYHtyfQpwcmludChmaXRfcmVnaW1lLCBwYXJzID0gYygiYWxwaGEiLCAicmhvIiwgInAiLCAic2lnbWEiKSkKYGBgCgpBbGwgaW4gYWxsIHRoZSBtb2RlbCBpcyBmaXQuCgojIFJlc3VsdHMKCl9Ob3dfIHdlIGNhbiBsb29rIGF0IG91ciBwYXJhbWV0ZXIgZXN0aW1hdGVzIGFzIHNob3duIGluIFRhYmxlIFxAcmVmKGZpZzpyZWdpbWUtb3V0KS4KCmBgYHtyIHJlZ2ltZS1vdXR9Cgpicm9vbTo6dGlkeU1DTUMoZml0X3JlZ2ltZSwgCgkJCQkJCQkJcGFycyA9IGMoImFscGhhIiwgInJobyIsICJwIiwgInNpZ21hIiksCgkJCQkJCQkJY29uZi5pbnQgPSBUUlVFLAoJCQkJCQkJCWNvbmYubGV2ZWwgPSAuOSkgJT4lIAoJbXV0YXRlX2lmKGlzLm51bWVyaWMsIHJvdW5kLCBkaWdpdHMgPSAzKSAlPiUgCglrbml0cjo6a2FibGUoY2FwdGlvbiA9ICJFc3RpbWF0ZXMgYW5kIDkwJSBJbnRlcnZhbCBFc3RpbWF0ZXMiKSAlPiUgCglrYWJsZUV4dHJhOjprYWJsZV9zdHlsaW5nKCkKYGBgCgpXZSBzZWUgdGhhdCBkdXJpbmcgdGhlIG1vbWVudHVtIHN0YXRlIHRoYXQgdGhlcmUgaXMgYSBzdHJvbmcgYXV0by1yZWdyZXNzaXZlIHBhcmFtZXRlciB3aXRoICRccmhvJCBlcXVhbCB0byBuZWFybHkgb25lLgpBcyB3ZSBzYXcgaW4gb3VyIGNvbnZlcmdlbmNlIGRpYWdub3N0aWNzLCAkXHNpZ21hJCBmb3Igb3VyIG1vbWVudHVtIHN0YXRlIGhhcyBhIHZlcnkgbGFyZ2Ugc3RhbmRhcmQgZXJyb3Igd2hpY2ggaXMgY29uY2VybmluZy4gCgojIyBJbnRlcnByZXRhdGlvbgoKSXQncyBiZXN0IHRvIHZpc3VhbGl6ZSB0aGUgb3V0cHV0IG9mIHRoaXMgbW9kZWwuIAoKYGBge3IgZmlnLmNhcD0iU3RhdGUgUHJvYmFiaWxpdHkgYW5kIEFjdHVhbCBHRFAgRXZvbHV0aW9uIn0Kc3RhdGVfc3VtbWFyeSA8LSBhcy5kYXRhLmZyYW1lKGZpdF9yZWdpbWUsIHBhcnMgPSAieGkiKSAlPiUgCiAgZ2F0aGVyKHBhciwgdmFsdWUpICU+JSAKICBmaWx0ZXIoZ3JlcGwoIiwxIiwgcGFyKSkgJT4lCiAgbXV0YXRlKHRpbWUgPSBwYXJzZV9udW1iZXIoc3RyX2V4dHJhY3QocGFyLCAiWzAtOV17MSwzfVssXSIpKSkgJT4lIAogIGdyb3VwX2J5KHBhcikgJT4lIAogIHN1bW1hcmlzZSh0aW1lID0gZmlyc3QodGltZSksIAogICAgICAgICAgICBtZWFuID0gbWVhbih2YWx1ZSksCiAgICAgICAgICAgIGxvd2VyID0gcXVhbnRpbGUodmFsdWUsIC4wNSksCiAgICAgICAgICAgIHVwcGVyID0gcXVhbnRpbGUodmFsdWUsIC45NSkpICU+JSAKICBhZGRfY29sdW1uKGRhdGUgPSBnZHBfZGF0JGRhdGUpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkYXRlLCB5ID0gbWVhbikpICsKCWdlb21fbGluZShjb2xvciA9IHVuY2dfcGFsW1sxXV0pKwoJZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gLjUsIGNvbG9yID0gdW5jZ19wYWxbWzVdXSwgbHR5ID0gImRhc2hlZCIpKwogIGdlb21fcmliYm9uKGFlcyh5bWluID0gbG93ZXIsIHltYXggPSB1cHBlciksIAogIAkJCQkJCWFscGhhID0gMC4zLCAgZmlsbCA9IHVuY2dfcGFsW1syXV0pICsKICBsYWJzKHRpdGxlID0iUHJvYmFiaWxpdHkgb2YgYmVpbmcgaW4gcmFuZG9tIHdhbGsgc3RhdGVcbiB2cyBtb21lbnR1bSBzdGF0ZSIsCiAgICAgICB5ID0gIlByb2JhYmlsaXR5IiwKICAgICAgIHN1YnRpdGxlID0gIlVTIEdEUCAoOTAlIENyZWRpYmlsaXR5IEludGVydmFscyBTaG93bikiKQoKc3RhdGVfc3VtbWFyeS9nZHBfdHJlbmQKYGBgCgpTbyBoZXJlIHdlIGNhbiBzZWUgdGhhdCBvdXIgbW9kZWwgaXNuJ3QgZ3JlYXQuClRoZXJlIGFyZSBvbmx5IGEgZmV3IHBlcmlvZHMgaW4gd2hpY2ggdGhlIHByb2JhYmlsaXR5IG9mIGJlaW5nIGluIGEgcmFuZG9tIHdhbGsgaXMgaGlnaCAoc29tZXRpbWUgYXJvdW5kIFExIDIwMTIgYW5kIHNpbmNlIHRoZSBlbmQgb2YgMjAxOCkuIApUaGlzIGNvdWxkIGluZGljYXRlIHRoYXQgdGhlIGN1cnJlbnQgZ3Jvd3RoIHdlIGFyZSBzZWVpbmcgbm93IGlzIGluIGEgcmFuZG9tIHdhbGsgcmFuZG9tIHN0YXRlIHdoaWxlIHByZXZpb3VzIHBlcmlvZHMgd2VyZSBwcm9iYWJseSBpbiB0aGlzIHJhbGx5IHN0YXRlLgpUaGlzIG1pZ2h0IGJlIGEgaGFyYmluZ2VyIG9mIGEgc2xvdyBkb3duLCBidXQgdGhpcyBtb2RlbCBkb2Vzbid0IGZpdCB0aGUgZGF0YSB0aGF0IHdlbGwuCgojIE5leHQgU3RlcHMKClRoZSBmdW4gcGFydCB3aXRoIHRoZXNlIHR5cGVzIG9mIG1vZGVscyBpcyB0aGF0IHlvdSBkb24ndCBoYXZlIHRvIHN0b3AgaGVyZS4KVHdvIHN0YXRlcyBtYXkgbm90IGJlIGFwcHJvcHJpYXRlLgpBZGRpdGlvbmFsbHksIHRoZXJlIGlzIGRlZmluaXRlbHkgbW9yZSBpbmZvcm1hdGlvbiBpbiB0aGUgd29ybGQgdGhhbiBqdXN0IEdEUC4KVGhpcyBtb2RlbCBjb3VsZCBiZSBlbmhhbmNlZCBieSB1c2luZyBkaWZmZXJlbnQgdGltZXMgc2VyaWVzIG1vZGVscyBhcyB3ZWxsIGFzIGJyaW5nIGluIGFkZGl0aW9uYWwgZGF0YSB0byB1c2UgdG8gaGVscCBmb3JlY2FzdCBHRFAgYW5kIGlkZW50aWZ5IHRoZSB0aGUgaGlkZGVuIHN0YXRlLgpXZSBhbHNvIHNhdyB0aGUgaXNzdWUgd2l0aCBpZGVudGlmaWFiaWxpdHkgd2l0aCBvdXIgbW9kZWwgbm90IHJlYWxseSBiZWluZyBhYmxlIHRvIGRpc2Nlcm4gZGlzdGluY3Qgc3RhdGVzLgoKCiMgQW5kIHdoYXQgYWJvdXQgdGhlIHN0aWNrZXIgbW9kZWw/CgpUaGUgc29tZXdoYXQgc3RpY2tlciBtb2RlbCBpbmRpY2F0ZXMgdmVyeSBzaW1pbGFyIHJlc3VsdHMgdG8gdGhlIGxlc3Mgc3RpY2tpZXIgcHJpb3IuCk5vIGJpZyBjaGFuZ2VzIG90aGVyIHRoYW4gYSBzbGlnaHRseSBoaWdoZXIgcHJvYmFiaWxpdHkgb2YgYSByYW5kb20gd2FsayBzdGF0ZSAyMDExLTIwMTIuCgpgYGB7ciBmaWcuY2FwPSJTdGF0ZSBQcm9iYWJpbGl0eSB3aXRoIFN0aWNraWVyIFByaW9yIn0KYXMuZGF0YS5mcmFtZShmaXRfcmVnaW1lX3N0aWNreSwgcGFycyA9ICJ4aSIpICU+JSAKICBnYXRoZXIocGFyLCB2YWx1ZSkgJT4lIAogIGZpbHRlcihncmVwbCgiLDEiLCBwYXIpKSAlPiUKICBtdXRhdGUodGltZSA9IHBhcnNlX251bWJlcihzdHJfZXh0cmFjdChwYXIsICJbMC05XXsxLDN9WyxdIikpKSAlPiUgCiAgZ3JvdXBfYnkocGFyKSAlPiUgCiAgc3VtbWFyaXNlKHRpbWUgPSBmaXJzdCh0aW1lKSwgCiAgICAgICAgICAgIG1lYW4gPSBtZWFuKHZhbHVlKSwKICAgICAgICAgICAgbG93ZXIgPSBxdWFudGlsZSh2YWx1ZSwgLjA1KSwKICAgICAgICAgICAgdXBwZXIgPSBxdWFudGlsZSh2YWx1ZSwgLjk1KSkgJT4lIAogIGFkZF9jb2x1bW4oZGF0ZSA9IGdkcF9kYXQkZGF0ZSkgJT4lIAogIGdncGxvdChhZXMoeCA9IGRhdGUsIHkgPSBtZWFuKSkgKwoJZ2VvbV9saW5lKGNvbG9yID0gdW5jZ19wYWxbWzFdXSkrCglnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAuNSwgY29sb3IgPSB1bmNnX3BhbFtbNV1dLCBsdHkgPSAiZGFzaGVkIikrCiAgZ2VvbV9yaWJib24oYWVzKHltaW4gPSBsb3dlciwgeW1heCA9IHVwcGVyKSwgCiAgCQkJCQkJYWxwaGEgPSAwLjMsICBmaWxsID0gdW5jZ19wYWxbWzJdXSkgKwogIGxhYnModGl0bGUgPSJQcm9iYWJpbGl0eSBvZiBiZWluZyBpbiByYW5kb20gd2FsayBzdGF0ZVxuIHZzIG1vbWVudHVtIHN0YXRlIiwKICAgICAgIHkgPSAiUHJvYmFiaWxpdHkiLAogICAgICAgc3VidGl0bGUgPSAiVVMgR0RQICg5MCUgQ3JlZGliaWxpdHkgSW50ZXJ2YWxzIFNob3duKSIpCmBgYAoKIyBSZWZlcmVuY2VzCg==


Intermediate Macroeconomics
me.dewitt.jr@gmail.com

Code licensed under the BSD 3-clause license
Text licensed under the CC-BY-ND-NC 4.0 license

See the Repository


Copyright © 2020 Michael DeWitt