library(datasets)
library(fUnitRoots)
library(forecast)
library(astsa)
?UKgas
ukgas_ts <- UKgas
class(ukgas_ts)
[1] "ts"

No need to convert to time series– it already is in time series format “ts”.

Preliminary Discussion and Analysis

First, we will plot the uk_gas time series data and observe trends

par(mfrow = c(1,1), cex.axis = 0.9)

plot(ukgas_ts,
     main = "Gas Consumption in the UK (Quarterly, 1960-1986)",
     xlab = 'Year', ylab = 'Millions of Therms (Natural Gas)',
     cex.axis = 0.5)

axis(1, at = time(ukgas_ts)[cycle(ukgas_ts) == 1], labels = FALSE) #has marks for year

Inititial Plot an Brief Discussion: Quarterly time series data From Q1 1960 to Q4 1986 Natural gas consumption is measured in millions of therms

Variance is increasing as mean increases. from 1960 to 1967, variance appears roughly the same. Then it seems to increase exponentially once mean starts to increase. Seaonality is a key factor here. Perhaps more people using natural gas to heat their homes, starting in the 70s.

UK National project to convert from town gas (made from coal) to natural gas between 1966 and 1977. In 1970 a huge supply of Natural gas discovered in North Sea.

This change in variance, along with trend and seasonality, may make this fairly complex to model.

There is an upward trend. Seemingly flat from 1960-1066, but then increaing in future years.

A variance transformation is absolutely necessary here

First, we will try to stabilize variance with a log transformation

# Take log transformation in attempts to stabilize variance
log_ukgas_ts <- log(ukgas_ts)
plot(log_ukgas_ts, main = "Log ukgas Prices", ylab = "Log Price") 

axis(1, at = time(ukgas_ts)[cycle(ukgas_ts) == 1], labels = FALSE) #has marks for year

Variance doesnt appear to be fully stabilized with a log transformation.

So we will do a box cox transformation instead.

Estimate value for lambda. This function finds the best lambda.

lambda <- BoxCox.lambda(ukgas_ts)
lambda
[1] -0.4457023

Apply a box cox transformation (using best lambda) to the data

bc_ukgas_ts <- BoxCox(ukgas_ts, lambda = lambda)
plot(bc_ukgas_ts,
     main = "Box-Cox Transformed UKgas Time Series (lambda = -0.445)", 
     ylab = "Transformed gas consumption",
     xlab = "Year")

# Add tick marks for every year
axis(1, at = time(bc_ukgas_ts)[cycle(bc_ukgas_ts) == 1], labels = FALSE)

This looks much better than the log transformation. Variance appears to be much more stabilized.

However, we still have seasonality and trend that must be accounted for to achieve stationarity.

We can test for stationarity about the mean with the ADF Test.

Its obviously not stationary right now; there’s a clear trend up. But let’s do it anyway.

# Get the number of observations in the TS
(length(ukgas_ts)-1)^(1/3)
[1] 4.747459

So we will round down and go with lag=4 for adfTest()

library(fUnitRoots)
adfTest(bc_ukgas_ts, lags = 4, type = 'c')

Title:
 Augmented Dickey-Fuller Test

Test Results:
  PARAMETER:
    Lag Order: 4
  STATISTIC:
    Dickey-Fuller: -0.4562
  P VALUE:
    0.8866 

Description:
 Wed Jul 23 17:46:09 2025 by user: Sferg

With p-value > 0.05,

Not stationary. Must difference again. Trend is still there.

There is both seasonality and trend. To account for quarterly seasonality, a lag 4 difference will be applied. Although the primary purporse of taking a lag 4 difference is to remove seasonality, the lag 4 difference might be enough to also take care of the trend.

First, I’ll take the lag 4 difference. Then, I’ll use the ADF test to determine if we must difference again to remove trend.

In efforts to be parsimonious, it is ideal to only take one difference if possible.

# Seasonal difference only
diff4_bc_ukgas_ts <- diff(bc_ukgas_ts, lag=4)
plot(diff4_bc_ukgas_ts,
     main = "Seasonally Differenced, Box-Cox Transformed \n UKgas Time Series (lambda = -0.445)", 
     ylab = "Transformed gas consumption",
     xlab = "Year")

# Line at y=0
abline(h = 0, col = "red", lwd = .5)

# Add tick marks for every year
axis(1, at = time(bc_ukgas_ts)[cycle(bc_ukgas_ts) == 1], labels = FALSE)

Note: Spike in volatility post-1970. Outlier period 1970-1972. In 1970 BP discovered a huge supply of natural gas in the North Sea. This volatility could be a consequence of that, combined with developing infrastructure. ” While the spike around 1970–1972 aligns more with North Sea gas development, any lingering post-1973 anomalies could reflect the broader 1973–1974 energy crisis, including demand shocks, hoarding behavior, or changes in industrial output. ”

All in all, weird stuff was happening in the UK natural gas market around 1970.

adfTest(diff4_bc_ukgas_ts, lags=4, type = 'nc')

Title:
 Augmented Dickey-Fuller Test

Test Results:
  PARAMETER:
    Lag Order: 4
  STATISTIC:
    Dickey-Fuller: -2.0099
  P VALUE:
    0.04484 

Description:
 Wed Jul 23 17:46:09 2025 by user: Sferg

Using a conservative ADF specification with no constant, the p-value was < 0.05, indicating that the Box-Cox transformed and lag-4 differenced UKgas series is stationary.”

The ADF test result narrowly rejects the null hypothesis of a unit root at the 0.05 significance level. This suggests that the Box-Cox transformation (\(\lambda\) = –0.4457) and seasonal lag-4 differencing were sufficient to stabilize the mean and achieve stationarity — at least according to the test.

That said, the result is borderline, and some residual trend may still be present. We’ll note this as a possible limitation, but proceed with modeling under the assumption of weak stationarity based on this result.

Note, we could apply a regular difference to the data that has already been lag4 difference and bc transformed. If we did that, the p-value would shrink, and there would be no doubt that this would make our data stationary about the mean.

However, in efforts to avoid conducting any unnecessary transformations, we lean on the results of the ADF test. The p-value is 0.0448. Although that is close to 0.05, we will conclude that we conducted sufficient transformations to conclude stationarity.

In order to speculate on the ARIMA structure of the time series data, we’ll look at the ACF and PACF plots of our transformed data.

#Look at ACF and PACF of the lag-4 differenced data
par(mfrow = c(1,2))
acf(diff4_bc_ukgas_ts, lag.max = 20, xlab = "LAG ÷ 4") # 4 years
pacf(diff4_bc_ukgas_ts, lag.max = 20, xlab = "LAG ÷ 4")

Each unit on the x-axis represents 1 year, since the data is quarterly and the seasonal period is 4.

In athe ACF plot, Lags 1, 4, and 5 show significant autocorrelations. While seasonal differencings (of lag=4) removed much of the seasonality, some residual seasonal structure reamains.

Lag 1 spike suggests short-term autocorellation : Perhaps MA(1) or AR(1) With a spike again at Lag 4, this suggests some seasonal autocorrelation. So maybe an SAR(1) or SMA(1) term

The PACF has signicant spikes at quarters 1, 4, 5, 9

Therefore, there is some residual seasonal structure even after the seasonal (lag4) differencing. However, the remaining lags fall mostly within the 95% CIs. This suggests weak/no autocorrelation after 1 year (4 lags).

So what we did: 1. Box Cox transformation with lamda = -0.445 2. Seasonal differencing, lag = 4

Based on my model transformations and the resulting ACF and PACF plots, we can speculate the structure of the models that auto.arima() will generate for us.

We applied a seasonal difference of lag 4. Therefore, D=1 and the lag term [4] We did not apply a regular difference. Therefore, d=1.

Make some predictions of what our model might look like

We now use auto.arima on the Box-Cox transformed data. We decided to feed auto.arima() the un-differenced data. The auto-arima function should handle seasonal differencing on its own (with a D=1 term).

We are allowing drift and we display the trace of auto.arima() to evaluate other potentially suitable models with similar AICc values.

After reviewing the documenation for auto.arima(), we decided to add the command “stepwise=FALSE”: giving us a much more comprehensive model search.

We will evaluate 4 models. 4 Arima models before choosing 1 to accept and use for forecasting.

# Apply the 
auto.arima(bc_ukgas_ts, trace = TRUE, approximation = FALSE, allowdrift = TRUE, stepwise=FALSE)

 ARIMA(0,0,0)(0,1,0)[4]                    : -637.6961
 ARIMA(0,0,0)(0,1,0)[4] with drift         : -663.1634
 ARIMA(0,0,0)(0,1,1)[4]                    : -635.6722
 ARIMA(0,0,0)(0,1,1)[4] with drift         : -668.4061
 ARIMA(0,0,0)(0,1,2)[4]                    : -639.1875
 ARIMA(0,0,0)(0,1,2)[4] with drift         : -666.6154
 ARIMA(0,0,0)(1,1,0)[4]                    : -635.7008
 ARIMA(0,0,0)(1,1,0)[4] with drift         : -668.7646
 ARIMA(0,0,0)(1,1,1)[4]                    : Inf
 ARIMA(0,0,0)(1,1,1)[4] with drift         : -666.6188
 ARIMA(0,0,0)(1,1,2)[4]                    : Inf
 ARIMA(0,0,0)(1,1,2)[4] with drift         : -664.4158
 ARIMA(0,0,0)(2,1,0)[4]                    : -641.0757
 ARIMA(0,0,0)(2,1,0)[4] with drift         : -666.6203
 ARIMA(0,0,0)(2,1,1)[4]                    : Inf
 ARIMA(0,0,0)(2,1,1)[4] with drift         : Inf
 ARIMA(0,0,0)(2,1,2)[4]                    : Inf
 ARIMA(0,0,0)(2,1,2)[4] with drift         : Inf
 ARIMA(0,0,1)(0,1,0)[4]                    : -636.0145
 ARIMA(0,0,1)(0,1,0)[4] with drift         : -665.4598
 ARIMA(0,0,1)(0,1,1)[4]                    : -633.9025
 ARIMA(0,0,1)(0,1,1)[4] with drift         : -667.8465
 ARIMA(0,0,1)(0,1,2)[4]                    : -637.0249
 ARIMA(0,0,1)(0,1,2)[4] with drift         : -666.3497
 ARIMA(0,0,1)(1,1,0)[4]                    : -633.9094
 ARIMA(0,0,1)(1,1,0)[4] with drift         : -668.4184
 ARIMA(0,0,1)(1,1,1)[4]                    : -632.3564
 ARIMA(0,0,1)(1,1,1)[4] with drift         : -666.2778
 ARIMA(0,0,1)(1,1,2)[4]                    : -650.412
 ARIMA(0,0,1)(1,1,2)[4] with drift         : -664.0973
 ARIMA(0,0,1)(2,1,0)[4]                    : -639.7273
 ARIMA(0,0,1)(2,1,0)[4] with drift         : -666.2982
 ARIMA(0,0,1)(2,1,1)[4]                    : Inf
 ARIMA(0,0,1)(2,1,1)[4] with drift         : -664.0747
 ARIMA(0,0,1)(2,1,2)[4]                    : Inf
 ARIMA(0,0,1)(2,1,2)[4] with drift         : Inf
 ARIMA(0,0,2)(0,1,0)[4]                    : -641.0514
 ARIMA(0,0,2)(0,1,0)[4] with drift         : -663.6582
 ARIMA(0,0,2)(0,1,1)[4]                    : -638.8933
 ARIMA(0,0,2)(0,1,1)[4] with drift         : -665.8615
 ARIMA(0,0,2)(0,1,2)[4]                    : -639.5629
 ARIMA(0,0,2)(0,1,2)[4] with drift         : -664.1997
 ARIMA(0,0,2)(1,1,0)[4]                    : -638.8963
 ARIMA(0,0,2)(1,1,0)[4] with drift         : -666.3627
 ARIMA(0,0,2)(1,1,1)[4]                    : -636.9265
 ARIMA(0,0,2)(1,1,1)[4] with drift         : -664.1691
 ARIMA(0,0,2)(1,1,2)[4]                    : Inf
 ARIMA(0,0,2)(1,1,2)[4] with drift         : -661.9109
 ARIMA(0,0,2)(2,1,0)[4]                    : -640.5805
 ARIMA(0,0,2)(2,1,0)[4] with drift         : -664.183
 ARIMA(0,0,2)(2,1,1)[4]                    : Inf
 ARIMA(0,0,2)(2,1,1)[4] with drift         : -661.8972
 ARIMA(0,0,3)(0,1,0)[4]                    : -642.0466
 ARIMA(0,0,3)(0,1,0)[4] with drift         : -661.4649
 ARIMA(0,0,3)(0,1,1)[4]                    : -639.9556
 ARIMA(0,0,3)(0,1,1)[4] with drift         : -664.5459
 ARIMA(0,0,3)(0,1,2)[4]                    : -638.8165
 ARIMA(0,0,3)(0,1,2)[4] with drift         : -662.5133
 ARIMA(0,0,3)(1,1,0)[4]                    : -639.977
 ARIMA(0,0,3)(1,1,0)[4] with drift         : -664.8335
 ARIMA(0,0,3)(1,1,1)[4]                    : -637.8841
 ARIMA(0,0,3)(1,1,1)[4] with drift         : -662.5329
 ARIMA(0,0,3)(2,1,0)[4]                    : -639.1253
 ARIMA(0,0,3)(2,1,0)[4] with drift         : -662.5329
 ARIMA(1,0,0)(0,1,0)[4]                    : -636.2003
 ARIMA(1,0,0)(0,1,0)[4] with drift         : -665.6442
 ARIMA(1,0,0)(0,1,1)[4]                    : -634.1766
 ARIMA(1,0,0)(0,1,1)[4] with drift         : -667.9443
 ARIMA(1,0,0)(0,1,2)[4]                    : -637.0258
 ARIMA(1,0,0)(0,1,2)[4] with drift         : -666.4038
 ARIMA(1,0,0)(1,1,0)[4]                    : -634.2753
 ARIMA(1,0,0)(1,1,0)[4] with drift         : -668.4951
 ARIMA(1,0,0)(1,1,1)[4]                    : -632.88
 ARIMA(1,0,0)(1,1,1)[4] with drift         : -666.3547
 ARIMA(1,0,0)(1,1,2)[4]                    : -650.5238
 ARIMA(1,0,0)(1,1,2)[4] with drift         : -664.1574
 ARIMA(1,0,0)(2,1,0)[4]                    : -640.0935
 ARIMA(1,0,0)(2,1,0)[4] with drift         : -666.3727
 ARIMA(1,0,0)(2,1,1)[4]                    : Inf
 ARIMA(1,0,0)(2,1,1)[4] with drift         : -664.141
 ARIMA(1,0,0)(2,1,2)[4]                    : Inf
 ARIMA(1,0,0)(2,1,2)[4] with drift         : -662.6872
 ARIMA(1,0,1)(0,1,0)[4]                    : Inf
 ARIMA(1,0,1)(0,1,0)[4] with drift         : -663.4946
 ARIMA(1,0,1)(0,1,1)[4]                    : Inf
 ARIMA(1,0,1)(0,1,1)[4] with drift         : -665.737
 ARIMA(1,0,1)(0,1,2)[4]                    : Inf
 ARIMA(1,0,1)(0,1,2)[4] with drift         : -664.1545
 ARIMA(1,0,1)(1,1,0)[4]                    : Inf
 ARIMA(1,0,1)(1,1,0)[4] with drift         : -666.2868
 ARIMA(1,0,1)(1,1,1)[4]                    : Inf
 ARIMA(1,0,1)(1,1,1)[4] with drift         : -664.1015
 ARIMA(1,0,1)(1,1,2)[4]                    : Inf
 ARIMA(1,0,1)(1,1,2)[4] with drift         : -661.8597
 ARIMA(1,0,1)(2,1,0)[4]                    : -638.1237
 ARIMA(1,0,1)(2,1,0)[4] with drift         : -664.1202
 ARIMA(1,0,1)(2,1,1)[4]                    : Inf
 ARIMA(1,0,1)(2,1,1)[4] with drift         : -661.8426
 ARIMA(1,0,2)(0,1,0)[4]                    : Inf
 ARIMA(1,0,2)(0,1,0)[4] with drift         : -662.4704
 ARIMA(1,0,2)(0,1,1)[4]                    : Inf
 ARIMA(1,0,2)(0,1,1)[4] with drift         : -669.0158
 ARIMA(1,0,2)(0,1,2)[4]                    : Inf
 ARIMA(1,0,2)(0,1,2)[4] with drift         : -666.7169
 ARIMA(1,0,2)(1,1,0)[4]                    : Inf
 ARIMA(1,0,2)(1,1,0)[4] with drift         : -668.6219
 ARIMA(1,0,2)(1,1,1)[4]                    : Inf
 ARIMA(1,0,2)(1,1,1)[4] with drift         : -666.7189
 ARIMA(1,0,2)(2,1,0)[4]                    : Inf
 ARIMA(1,0,2)(2,1,0)[4] with drift         : -666.5477
 ARIMA(1,0,3)(0,1,0)[4]                    : -647.0667
 ARIMA(1,0,3)(0,1,0)[4] with drift         : -667.3772
 ARIMA(1,0,3)(0,1,1)[4]                    : -645.7353
 ARIMA(1,0,3)(0,1,1)[4] with drift         : -669.6911
 ARIMA(1,0,3)(1,1,0)[4]                    : -646.1064
 ARIMA(1,0,3)(1,1,0)[4] with drift         : -668.2139
 ARIMA(2,0,0)(0,1,0)[4]                    : -640.7587
 ARIMA(2,0,0)(0,1,0)[4] with drift         : -663.5107
 ARIMA(2,0,0)(0,1,1)[4]                    : -640.3374
 ARIMA(2,0,0)(0,1,1)[4] with drift         : -665.7382
 ARIMA(2,0,0)(0,1,2)[4]                    : -639.9964
 ARIMA(2,0,0)(0,1,2)[4] with drift         : -664.1586
 ARIMA(2,0,0)(1,1,0)[4]                    : -640.9128
 ARIMA(2,0,0)(1,1,0)[4] with drift         : -666.287
 ARIMA(2,0,0)(1,1,1)[4]                    : -639.0462
 ARIMA(2,0,0)(1,1,1)[4] with drift         : -664.1022
 ARIMA(2,0,0)(1,1,2)[4]                    : Inf
 ARIMA(2,0,0)(1,1,2)[4] with drift         : -661.863
 ARIMA(2,0,0)(2,1,0)[4]                    : -639.8233
 ARIMA(2,0,0)(2,1,0)[4] with drift         : -664.1214
 ARIMA(2,0,0)(2,1,1)[4]                    : Inf
 ARIMA(2,0,0)(2,1,1)[4] with drift         : -661.8453
 ARIMA(2,0,1)(0,1,0)[4]                    : Inf
 ARIMA(2,0,1)(0,1,0)[4] with drift         : -662.0475
 ARIMA(2,0,1)(0,1,1)[4]                    : Inf
 ARIMA(2,0,1)(0,1,1)[4] with drift         : -667.3595
 ARIMA(2,0,1)(0,1,2)[4]                    : Inf
 ARIMA(2,0,1)(0,1,2)[4] with drift         : -665.0689
 ARIMA(2,0,1)(1,1,0)[4]                    : Inf
 ARIMA(2,0,1)(1,1,0)[4] with drift         : -667.1479
 ARIMA(2,0,1)(1,1,1)[4]                    : Inf
 ARIMA(2,0,1)(1,1,1)[4] with drift         : -667.1735
 ARIMA(2,0,1)(2,1,0)[4]                    : Inf
 ARIMA(2,0,1)(2,1,0)[4] with drift         : -667.6303
 ARIMA(2,0,2)(0,1,0)[4]                    : -659.2616
 ARIMA(2,0,2)(0,1,0)[4] with drift         : -661.5539
 ARIMA(2,0,2)(0,1,1)[4]                    : -667.5618
 ARIMA(2,0,2)(0,1,1)[4] with drift         : Inf
 ARIMA(2,0,2)(1,1,0)[4]                    : -666.0228
 ARIMA(2,0,2)(1,1,0)[4] with drift         : -668.579
 ARIMA(2,0,3)(0,1,0)[4]                    : Inf
 ARIMA(2,0,3)(0,1,0)[4] with drift         : -665.0431
 ARIMA(3,0,0)(0,1,0)[4]                    : -649.1576
 ARIMA(3,0,0)(0,1,0)[4] with drift         : -662.9122
 ARIMA(3,0,0)(0,1,1)[4]                    : -648.5549
 ARIMA(3,0,0)(0,1,1)[4] with drift         : -664.5061
 ARIMA(3,0,0)(0,1,2)[4]                    : -646.3036
 ARIMA(3,0,0)(0,1,2)[4] with drift         : -662.4044
 ARIMA(3,0,0)(1,1,0)[4]                    : -648.5489
 ARIMA(3,0,0)(1,1,0)[4] with drift         : -664.7273
 ARIMA(3,0,0)(1,1,1)[4]                    : -646.3043
 ARIMA(3,0,0)(1,1,1)[4] with drift         : -662.4341
 ARIMA(3,0,0)(2,1,0)[4]                    : -646.3013
 ARIMA(3,0,0)(2,1,0)[4] with drift         : -662.4342
 ARIMA(3,0,1)(0,1,0)[4]                    : -652.7626
 ARIMA(3,0,1)(0,1,0)[4] with drift         : -670.0218
 ARIMA(3,0,1)(0,1,1)[4]                    : Inf
 ARIMA(3,0,1)(0,1,1)[4] with drift         : -667.1187
 ARIMA(3,0,1)(1,1,0)[4]                    : Inf
 ARIMA(3,0,1)(1,1,0)[4] with drift         : -666.4217
 ARIMA(3,0,2)(0,1,0)[4]                    : Inf
 ARIMA(3,0,2)(0,1,0)[4] with drift         : -667.1087



 Best model: ARIMA(3,0,1)(0,1,0)[4] with drift         

Series: bc_ukgas_ts 
ARIMA(3,0,1)(0,1,0)[4] with drift 

Coefficients:
          ar1      ar2     ar3     ma1   drift
      -0.9933  -0.1473  0.1618  0.8785  0.0013
s.e.   0.1281   0.1397  0.1059  0.0953  0.0002

sigma^2 = 8.615e-05:  log likelihood = 341.44
AIC=-670.89   AICc=-670.02   BIC=-655.02

Note: All models will be fit to Box-Cox transformed data with \(\lambda\) = -0.445. All coefficients and terms are expressed in terms of the transformed series. Therefore, model selection, diagnostic plots, and equation reporting will all be expressed on the transformed scale. Much Later, we will back transform the model during the forecast step.

Model 1: ARIMA(3,0,1)(0,1,0)[4]

#no.constant = false because we plan to include a drift term
ukgas_model1 <-sarima(bc_ukgas_ts,3,0,1,0,1,0, 4, no.constant = FALSE) #with drift
initial  value -4.620128 
iter   2 value -4.627296
iter   3 value -4.652077
iter   4 value -4.652266
iter   5 value -4.652405
iter   6 value -4.654876
iter   7 value -4.656638
iter   8 value -4.657831
iter   9 value -4.658959
iter  10 value -4.665969
iter  11 value -4.667491
iter  12 value -4.672409
iter  13 value -4.675827
iter  14 value -4.681157
iter  15 value -4.686161
iter  16 value -4.687814
iter  17 value -4.688371
iter  18 value -4.688390
iter  19 value -4.688430
iter  20 value -4.688439
iter  21 value -4.688439
iter  22 value -4.688439
iter  22 value -4.688440
iter  22 value -4.688440
final  value -4.688440 
converged
initial  value -4.700013 
iter   2 value -4.700020
iter   3 value -4.701327
iter   4 value -4.701804
iter   5 value -4.702037
iter   6 value -4.702052
iter   7 value -4.702053
iter   7 value -4.702053
iter   7 value -4.702053
final  value -4.702053 
converged
<><><><><><><><><><><><><><>
 
Coefficients: 
         Estimate     SE t.value p.value
ar1       -0.9933 0.1281 -7.7553  0.0000
ar2       -0.1473 0.1397 -1.0544  0.2943
ar3        0.1618 0.1059  1.5279  0.1297
ma1        0.8785 0.0953  9.2151  0.0000
constant   0.0013 0.0002  5.8031  0.0000

sigma^2 estimated as 8.185962e-05 on 99 degrees of freedom 
 
AIC = -6.450844  AICc = -6.444957  BIC = -6.298283 
 

n <- length(bc_ukgas_ts)
ukgas_model1$ICs*n
      AIC      AICc       BIC 
-696.6912 -696.0554 -680.2146 

Equation of Model 1:

\[(1 + 0.9933B + 0.1473B^2 - 0.1618B^3)(1 - B^4)X_t = (1 + 0.8785B)W_t + 0.0013\] where \[W_t \sim \mathcal{N}(0,\ 8.19 \times 10^{-5})\]

We note that AR2 and AR3 coefficients, with p values of 0.2943 and 0.1297 are not significant at the .05 level.

Comments on the diagnostic plots:

There’s quite a bit of complexity to this model, with 3 AR terms, an MA term, a box-cox transformation, and a seasonal difference.

And with AR2 and AR3 terms with such high p-values, this begs the question can we achieve similar model fit with a less complex model?

One way to limit complexity is by “fixing” terms to 0. It’s kind of a guess and check procedure. We mute a term for a similar, less complex model, and do a sarima() and see if the diagnostic plots and AICc values are acceptable.

This is good practice, as it keeps the principle of parsimony in mind.

In model 2, we will observe a model that still performs well when we fix the AR2 term to 0: with good p-values on terms, diagnostic plots, and a strong AICc value

Trying less complex models by fixing coefficients to 0

Model 2: ARIMA(3,0,1)(0,1,0)[4]

Where AR2 coefficient is fixed to 0

ukgas_model2 <- sarima(bc_ukgas_ts, 3,0,1, 0,1,0, 4,
                       fixed = c(NA, 0, NA, NA, NA), #fix AR2 to 0
                       no.constant = FALSE) # With Drift
initial  value -4.620128 
iter   2 value -4.626558
iter   3 value -4.651955
iter   4 value -4.652138
iter   5 value -4.652621
iter   6 value -4.654474
iter   7 value -4.657568
iter   8 value -4.661965
iter   9 value -4.681535
iter  10 value -4.684121
iter  11 value -4.685097
iter  12 value -4.685157
iter  13 value -4.685183
iter  14 value -4.685190
iter  15 value -4.685191
iter  15 value -4.685191
iter  15 value -4.685191
final  value -4.685191 
converged
initial  value -4.695617 
iter   2 value -4.695968
iter   3 value -4.696223
iter   4 value -4.696637
iter   5 value -4.696647
iter   5 value -4.696647
iter   5 value -4.696647
final  value -4.696647 
converged
<><><><><><><><><><><><><><>
 
Coefficients: 
         Estimate     SE t.value p.value
ar1       -0.9042 0.1001 -9.0333   0e+00
ar3        0.2441 0.0704  3.4685   8e-04
ma1        0.8617 0.1050  8.2101   0e+00
constant   0.0013 0.0003  5.0138   0e+00

sigma^2 estimated as 8.277297e-05 on 100 degrees of freedom 
 
AIC = -6.459263  AICc = -6.455378  BIC = -6.332129 
 

ukgas_model2$ICs*n
      AIC      AICc       BIC 
-697.6004 -697.1808 -683.8699 

Oh WOW!!!!AICc is even lower, when i Exclude AR2, all the p values are 0 now. plots look great. THIS is my model!!! Winner winner

Equation of Model2 (with fixed AR2)

\[(1 + 0.9042B - 0.2441B^3)(1 - B^4)X_t = (1 + 0.8617B)W_t + 0.0013\] where \[W_t \sim \mathcal{N}(0,\ 8.28 \times 10^{-5})\]

Model 3: (3,0,1)(0,1,0)[4]

Where AR1 and AR2 are fixed to 0

Now let’s try to simplify further. Perhaps an AR3 term is all we need.

ukgas_model3 <- sarima(bc_ukgas_ts, 3,0,1, 0,1,0, 4,
                       fixed = c(0, 0, NA, NA, NA),
                       no.constant = FALSE)
initial  value -4.620128 
iter   2 value -4.649588
iter   3 value -4.650255
iter   4 value -4.650265
iter   5 value -4.650266
iter   5 value -4.650266
iter   5 value -4.650266
final  value -4.650266 
converged
initial  value -4.651069 
iter   2 value -4.651822
iter   3 value -4.651886
iter   4 value -4.651886
iter   4 value -4.651886
iter   4 value -4.651886
final  value -4.651886 
converged
<><><><><><><><><><><><><><>
 
Coefficients: 
         Estimate     SE t.value p.value
ar3        0.0858 0.0986  0.8696  0.3866
ma1       -0.1909 0.0961 -1.9859  0.0498
constant   0.0013 0.0002  5.8910  0.0000

sigma^2 estimated as 9.102914e-05 on 101 degrees of freedom 
 
AIC = -6.388972  AICc = -6.386665  BIC = -6.287265 
 

ukgas_model3$ICs*n
      AIC      AICc       BIC 
-690.0090 -689.7598 -679.0246 

Equation of Model 3:

\[(1 - 0.0858B^3)(1 - B^4)X_t = (1 - 0.1909B)W_t + 0.0013\] where

\[W_t \sim \mathcal{N}(0,\ 9.10 \times 10^{-5})\]

Ljung box looks poor, and 2 at lags 4 and 5 are significant. p values of coefficients deteriorated.

Therefore, we will reject this model.

Model 4: ARIMA(2,0,1)(0,1,0)[4]

ukgas_model4 <-sarima(bc_ukgas_ts, 2,0,1,0,1,0, 4, no.constant = FALSE)
initial  value -4.623576 
iter   2 value -4.625806
iter   3 value -4.648436
iter   4 value -4.648742
iter   5 value -4.648798
iter   6 value -4.649516
iter   7 value -4.650346
iter   8 value -4.651391
iter   9 value -4.652433
iter  10 value -4.652576
iter  11 value -4.652584
iter  12 value -4.652586
iter  13 value -4.652587
iter  14 value -4.652587
iter  15 value -4.652588
iter  16 value -4.652590
iter  17 value -4.652591
iter  18 value -4.652591
iter  18 value -4.652591
iter  18 value -4.652591
final  value -4.652591 
converged
initial  value -4.648542 
iter   2 value -4.648798
iter   3 value -4.649273
iter   4 value -4.649294
iter   5 value -4.649306
iter   6 value -4.649307
iter   7 value -4.649327
iter   8 value -4.649359
iter   9 value -4.649410
iter  10 value -4.649481
iter  11 value -4.649634
iter  12 value -4.649700
iter  13 value -4.649710
iter  14 value -4.649738
iter  15 value -4.649970
iter  16 value -4.650039
iter  17 value -4.650092
iter  18 value -4.650114
iter  19 value -4.650372
iter  20 value -4.650639
iter  21 value -4.651265
iter  22 value -4.651698
iter  23 value -4.652403
iter  24 value -4.652840
iter  25 value -4.652851
iter  26 value -4.652861
iter  27 value -4.652862
iter  28 value -4.652869
iter  29 value -4.652874
iter  30 value -4.652879
iter  31 value -4.652880
iter  32 value -4.652880
iter  32 value -4.652880
iter  32 value -4.652880
final  value -4.652880 
converged
<><><><><><><><><><><><><><>
 
Coefficients: 
         Estimate     SE t.value p.value
ar1        0.6776 0.1387  4.8871  0.0000
ar2        0.2231 0.0955  2.3370  0.0214
ma1       -0.8831 0.1052 -8.3927  0.0000
constant   0.0013 0.0003  4.6307  0.0000

sigma^2 estimated as 9.082442e-05 on 100 degrees of freedom 
 
AIC = -6.371728  AICc = -6.367843  BIC = -6.244594 
 

ukgas_model4$ICs*n
      AIC      AICc       BIC 
-688.1467 -687.7271 -674.4162 

Model 4 Equation:

\[(1 - 0.6776B - 0.2231B^2)(1 - B^4)X_t = (1 - 0.8831B)W_t + 0.0013\] Where \[W_t \sim \mathcal{N}(0,\ 9.08 \times 10^{-5})\]

Summary table of values (I’ve already created this in word and can send to you)

Model Specification AIC AICc All Terms Significant (p < 0.05)? Ljung-Box Test Result
Model 1 ARIMA(3,0,1)(0,1,0)[4] -696.691 -696.055 ❌ AR2 (p = 0.29), AR3 (p = 0.13) ✅ Most p-values > 0.05 – Pass
Model 2 ARIMA(3,0,1)(0,1,0)[4], AR2 fixed to 0 -697.600 -697.181 ✅ Yes ✅ Most p-values > 0.05 – Pass
Model 3 ARIMA(3,0,1)(0,1,0)[4], AR1 & AR2 fixed to 0 -690.009 -689.760 ❌ AR3 (p = 0.39) ❌ Several p-values < 0.05 – Fail
Model 4 ARIMA(2,0,1)(0,1,0)[4] -688.147 -687.727 ✅ Yes ❌ Several p-values < 0.05 – Fail

So, We are going to select Model 2!!!

Forecasting using Model 2

# have to use Arima(){forecast} not arima(){stats}. 
# arima() kept dropping my drift term! Was quite frustrating
library(forecast) 

# Fit the model
ukgas.fit.model2 <- Arima(bc_ukgas_ts, 
             order = c(3,0,1), seasonal = c(0,1,0),
             fixed = c(NA, 0, NA, NA, NA),
             include.drift = TRUE)

# Check all terms are present in model, and AR2 is 0
ukgas.fit.model2$coef
         ar1          ar2          ar3          ma1        drift 
-0.904234264  0.000000000  0.244118969  0.861675905  0.001342957 
# Forecast using ARIMA model fit on Box-Cox data
ukgas.forecast.M2.bc <- forecast(ukgas.fit.model2, h = 12)

# Plot with Transformed Scale
par(mfrow = c(1,1))
plot(ukgas.forecast.M2.bc, 
     main = "ARIMA Forecast on Transformed Scale (with Fitted + History)",
     xlab = 'Year', ylab = 'BC Transformed Scale')

# Tick marks
axis(1, at = c(time(ukgas_ts)[cycle(ukgas_ts) == 1], 1986, 1987, 1988, 1989), labels = FALSE)

The plot is difficult to interpret with the Gas consumption data in this format. The data on the y axis is the Box-Cox transformed data.

A better visualization would inverse transform the y data.

# Forecast using ARIMA model fit on Box-Cox data
ukgas.forecast.M2 <- forecast(ukgas.fit.model2, h = 12)

# Inverse transform forecast components
ukgas.forecast.M2$mean   <- InvBoxCox(ukgas.forecast.M2$mean, lambda)
ukgas.forecast.M2$lower  <- InvBoxCox(ukgas.forecast.M2$lower, lambda)
ukgas.forecast.M2$upper  <- InvBoxCox(ukgas.forecast.M2$upper, lambda)
ukgas.forecast.M2$fitted <- InvBoxCox(ukgas.forecast.M2$fitted, lambda)

# Replace x (the original series used for plotting) with the true original data
ukgas.forecast.M2$x <- ukgas_ts  # ← this is key!

# Plot everything on the correct scale
par(mfrow = c(1,1))
plot(ukgas.forecast.M2, 
     main = "ARIMA Forecast on Original Scale (with Fitted + History)",
     xlab = 'Year', ylab = 'Millions of Therms (Natural Gas)')


axis(1, at = c(time(ukgas_ts)[cycle(ukgas_ts) == 1], 1986, 1987, 1988, 1989), labels = FALSE)

plot(ukgas.forecast.M2, xlim = c(1982, 1990),
     main = "ARIMA Forecast on Original Scale (with Fitted + History)",
     xlab = 'Year', ylab = 'Millions of Therms (Natural Gas)')
     
axis(1, at = c(time(ukgas_ts)[cycle(ukgas_ts) == 1], 1986, 1987, 1988, 1989), labels = TRUE)

Conclusions:

We will end here– ignore below

HOLT WINTERS Actually, this is extra. This isn’t mentioned in the prompt at all. So, lets drop it. An evaluation of 4 ARIMA models is absolutely more than enough.

HW_bc_ukgas_ts <- HoltWinters(bc_ukgas_ts) # fitting HoltWinters model to the RAW data
plot(HW_bc_ukgas_ts)

axis(1, at = time(ukgas_ts)[cycle(ukgas_ts) == 1], labels = FALSE)


forecast_HW_bc_ukgas_ts <- forecast(HW_bc_ukgas_ts)
plot(forecast_HW_bc_ukgas_ts,
     xlim = c(1982, 1990),
     ylim = c(2.00, 2.20))

axis(1, at = time(ukgas_ts)[cycle(ukgas_ts) == 1], labels = FALSE)

checkresiduals(HW_bc_ukgas_ts)

    Ljung-Box test

data:  Residuals from HoltWinters
Q* = 11.466, df = 8, p-value = 0.1767

Model df: 0.   Total lags used: 8

Since the p-value is greater than 0.05, we fail to reject the null hypothesis. This suggests there’s no significant autocorrelation left in the residuals, meaning the model fits reasonably well.

LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KYGBge3J9DQpsaWJyYXJ5KGRhdGFzZXRzKQ0KbGlicmFyeShmVW5pdFJvb3RzKQ0KbGlicmFyeShmb3JlY2FzdCkNCmxpYnJhcnkoYXN0c2EpDQo/VUtnYXMNCnVrZ2FzX3RzIDwtIFVLZ2FzDQpjbGFzcyh1a2dhc190cykNCmBgYA0KTm8gbmVlZCB0byBjb252ZXJ0IHRvIHRpbWUgc2VyaWVzLS0gaXQgYWxyZWFkeSBpcyBpbiB0aW1lIHNlcmllcyBmb3JtYXQgInRzIi4NCg0KIyMgUHJlbGltaW5hcnkgRGlzY3Vzc2lvbiBhbmQgQW5hbHlzaXMNCg0KRmlyc3QsIHdlIHdpbGwgcGxvdCB0aGUgdWtfZ2FzIHRpbWUgc2VyaWVzIGRhdGEgYW5kIG9ic2VydmUgdHJlbmRzDQpgYGB7cn0NCnBhcihtZnJvdyA9IGMoMSwxKSwgY2V4LmF4aXMgPSAwLjkpDQoNCnBsb3QodWtnYXNfdHMsDQogICAgIG1haW4gPSAiR2FzIENvbnN1bXB0aW9uIGluIHRoZSBVSyAoUXVhcnRlcmx5LCAxOTYwLTE5ODYpIiwNCiAgICAgeGxhYiA9ICdZZWFyJywgeWxhYiA9ICdNaWxsaW9ucyBvZiBUaGVybXMgKE5hdHVyYWwgR2FzKScsDQogICAgIGNleC5heGlzID0gMC41KQ0KDQpheGlzKDEsIGF0ID0gdGltZSh1a2dhc190cylbY3ljbGUodWtnYXNfdHMpID09IDFdLCBsYWJlbHMgPSBGQUxTRSkgI2hhcyBtYXJrcyBmb3IgeWVhcg0KYGBgDQoNCkluaXRpdGlhbCBQbG90IGFuIEJyaWVmIERpc2N1c3Npb246DQpRdWFydGVybHkgdGltZSBzZXJpZXMgZGF0YQ0KRnJvbSBRMSAxOTYwIHRvIFE0IDE5ODYNCk5hdHVyYWwgZ2FzIGNvbnN1bXB0aW9uIGlzIG1lYXN1cmVkIGluIG1pbGxpb25zIG9mIHRoZXJtcw0KDQpWYXJpYW5jZSBpcyBpbmNyZWFzaW5nIGFzIG1lYW4gaW5jcmVhc2VzLg0KZnJvbSAxOTYwIHRvIDE5NjcsIHZhcmlhbmNlIGFwcGVhcnMgcm91Z2hseSB0aGUgc2FtZS4gVGhlbiBpdCBzZWVtcyB0byBpbmNyZWFzZSBleHBvbmVudGlhbGx5IG9uY2UgbWVhbiBzdGFydHMgdG8gaW5jcmVhc2UuDQpTZWFvbmFsaXR5IGlzIGEga2V5IGZhY3RvciBoZXJlLiBQZXJoYXBzIG1vcmUgcGVvcGxlIHVzaW5nIG5hdHVyYWwgZ2FzIHRvIGhlYXQgdGhlaXIgaG9tZXMsIHN0YXJ0aW5nIGluIHRoZSA3MHMuDQoNCg0KVUsgTmF0aW9uYWwgcHJvamVjdCB0byBjb252ZXJ0IGZyb20gdG93biBnYXMgKG1hZGUgZnJvbSBjb2FsKSB0byBuYXR1cmFsIGdhcyBiZXR3ZWVuIDE5NjYgYW5kIDE5NzcuDQpJbiAxOTcwIGEgaHVnZSBzdXBwbHkgb2YgTmF0dXJhbCBnYXMgZGlzY292ZXJlZCBpbiBOb3J0aCBTZWEuDQoNClRoaXMgY2hhbmdlIGluIHZhcmlhbmNlLCBhbG9uZyB3aXRoIHRyZW5kIGFuZCBzZWFzb25hbGl0eSwgbWF5IG1ha2UgdGhpcyBmYWlybHkgY29tcGxleCB0byBtb2RlbC4NCg0KDQoNClRoZXJlIGlzIGFuIHVwd2FyZCB0cmVuZC4gU2VlbWluZ2x5IGZsYXQgZnJvbSAxOTYwLTEwNjYsIGJ1dCB0aGVuIGluY3JlYWluZyBpbiBmdXR1cmUgeWVhcnMuDQoNCkEgdmFyaWFuY2UgdHJhbnNmb3JtYXRpb24gaXMgYWJzb2x1dGVseSBuZWNlc3NhcnkgaGVyZQ0KDQpGaXJzdCwgd2Ugd2lsbCB0cnkgdG8gc3RhYmlsaXplIHZhcmlhbmNlIHdpdGggYSBsb2cgdHJhbnNmb3JtYXRpb24NCmBgYHtyfQ0KIyBUYWtlIGxvZyB0cmFuc2Zvcm1hdGlvbiBpbiBhdHRlbXB0cyB0byBzdGFiaWxpemUgdmFyaWFuY2UNCmxvZ191a2dhc190cyA8LSBsb2codWtnYXNfdHMpDQpwbG90KGxvZ191a2dhc190cywgbWFpbiA9ICJMb2cgdWtnYXMgUHJpY2VzIiwgeWxhYiA9ICJMb2cgUHJpY2UiKSANCg0KYXhpcygxLCBhdCA9IHRpbWUodWtnYXNfdHMpW2N5Y2xlKHVrZ2FzX3RzKSA9PSAxXSwgbGFiZWxzID0gRkFMU0UpICNoYXMgbWFya3MgZm9yIHllYXINCmBgYA0KVmFyaWFuY2UgZG9lc250IGFwcGVhciB0byBiZSBmdWxseSBzdGFiaWxpemVkIHdpdGggYSBsb2cgdHJhbnNmb3JtYXRpb24uIA0KDQpTbyB3ZSB3aWxsIGRvIGEgYm94IGNveCB0cmFuc2Zvcm1hdGlvbiBpbnN0ZWFkLg0KDQpFc3RpbWF0ZSB2YWx1ZSBmb3IgbGFtYmRhLiBUaGlzIGZ1bmN0aW9uIGZpbmRzIHRoZSBiZXN0IGxhbWJkYS4NCmBgYHtyfQ0KbGFtYmRhIDwtIEJveENveC5sYW1iZGEodWtnYXNfdHMpDQpsYW1iZGENCmBgYA0KDQojIyBBcHBseSBhIGJveCBjb3ggdHJhbnNmb3JtYXRpb24gKHVzaW5nIGJlc3QgbGFtYmRhKSB0byB0aGUgZGF0YQ0KDQpgYGB7cn0NCmJjX3VrZ2FzX3RzIDwtIEJveENveCh1a2dhc190cywgbGFtYmRhID0gbGFtYmRhKQ0KcGxvdChiY191a2dhc190cywNCiAgICAgbWFpbiA9ICJCb3gtQ294IFRyYW5zZm9ybWVkIFVLZ2FzIFRpbWUgU2VyaWVzIChsYW1iZGEgPSAtMC40NDUpIiwgDQogICAgIHlsYWIgPSAiVHJhbnNmb3JtZWQgZ2FzIGNvbnN1bXB0aW9uIiwNCiAgICAgeGxhYiA9ICJZZWFyIikNCg0KIyBBZGQgdGljayBtYXJrcyBmb3IgZXZlcnkgeWVhcg0KYXhpcygxLCBhdCA9IHRpbWUoYmNfdWtnYXNfdHMpW2N5Y2xlKGJjX3VrZ2FzX3RzKSA9PSAxXSwgbGFiZWxzID0gRkFMU0UpDQpgYGANClRoaXMgbG9va3MgbXVjaCBiZXR0ZXIgdGhhbiB0aGUgbG9nIHRyYW5zZm9ybWF0aW9uLiBWYXJpYW5jZSBhcHBlYXJzIHRvIGJlIG11Y2ggbW9yZSBzdGFiaWxpemVkLg0KDQpIb3dldmVyLCB3ZSBzdGlsbCBoYXZlIHNlYXNvbmFsaXR5IGFuZCB0cmVuZCB0aGF0IG11c3QgYmUgYWNjb3VudGVkIGZvciB0byBhY2hpZXZlIHN0YXRpb25hcml0eS4NCg0KV2UgY2FuIHRlc3QgZm9yIHN0YXRpb25hcml0eSBhYm91dCB0aGUgbWVhbiB3aXRoIHRoZSBBREYgVGVzdC4NCg0KSXRzIG9idmlvdXNseSBub3Qgc3RhdGlvbmFyeSByaWdodCBub3c7IHRoZXJlJ3MgYSBjbGVhciB0cmVuZCB1cC4gQnV0IGxldCdzIGRvIGl0IGFueXdheS4NCg0KYGBge3J9DQojIEdldCB0aGUgbnVtYmVyIG9mIG9ic2VydmF0aW9ucyBpbiB0aGUgVFMNCihsZW5ndGgodWtnYXNfdHMpLTEpXigxLzMpDQpgYGANClNvIHdlIHdpbGwgcm91bmQgZG93biBhbmQgZ28gd2l0aCBsYWc9NCBmb3IgYWRmVGVzdCgpDQoNCmBgYHtyfQ0KbGlicmFyeShmVW5pdFJvb3RzKQ0KYWRmVGVzdChiY191a2dhc190cywgbGFncyA9IDQsIHR5cGUgPSAnYycpDQpgYGANCldpdGggcC12YWx1ZSA+IDAuMDUsIA0KDQpOb3Qgc3RhdGlvbmFyeS4gTXVzdCBkaWZmZXJlbmNlIGFnYWluLiBUcmVuZCBpcyBzdGlsbCB0aGVyZS4gDQoNClRoZXJlIGlzIGJvdGggc2Vhc29uYWxpdHkgYW5kIHRyZW5kLiBUbyBhY2NvdW50IGZvciBxdWFydGVybHkgc2Vhc29uYWxpdHksIGEgbGFnIDQgZGlmZmVyZW5jZSB3aWxsIGJlIGFwcGxpZWQuIA0KQWx0aG91Z2ggdGhlIHByaW1hcnkgcHVycG9yc2Ugb2YgdGFraW5nIGEgbGFnIDQgZGlmZmVyZW5jZSBpcyB0byByZW1vdmUgc2Vhc29uYWxpdHksIHRoZSBsYWcgNCBkaWZmZXJlbmNlIG1pZ2h0IGJlIGVub3VnaCB0byBhbHNvIHRha2UgY2FyZSBvZiB0aGUgdHJlbmQuDQoNCkZpcnN0LCBJJ2xsIHRha2UgdGhlIGxhZyA0IGRpZmZlcmVuY2UuDQpUaGVuLCBJJ2xsIHVzZSB0aGUgQURGIHRlc3QgdG8gZGV0ZXJtaW5lIGlmIHdlIG11c3QgZGlmZmVyZW5jZSBhZ2FpbiB0byByZW1vdmUgdHJlbmQuDQoNCkluIGVmZm9ydHMgdG8gYmUgcGFyc2ltb25pb3VzLCBpdCBpcyBpZGVhbCB0byBvbmx5IHRha2Ugb25lIGRpZmZlcmVuY2UgaWYgcG9zc2libGUuDQoNCg0KDQpgYGB7cn0NCiMgU2Vhc29uYWwgZGlmZmVyZW5jZSBvbmx5DQpkaWZmNF9iY191a2dhc190cyA8LSBkaWZmKGJjX3VrZ2FzX3RzLCBsYWc9NCkNCnBsb3QoZGlmZjRfYmNfdWtnYXNfdHMsDQogICAgIG1haW4gPSAiU2Vhc29uYWxseSBEaWZmZXJlbmNlZCwgQm94LUNveCBUcmFuc2Zvcm1lZCBcbiBVS2dhcyBUaW1lIFNlcmllcyAobGFtYmRhID0gLTAuNDQ1KSIsIA0KICAgICB5bGFiID0gIlRyYW5zZm9ybWVkIGdhcyBjb25zdW1wdGlvbiIsDQogICAgIHhsYWIgPSAiWWVhciIpDQoNCiMgTGluZSBhdCB5PTANCmFibGluZShoID0gMCwgY29sID0gInJlZCIsIGx3ZCA9IC41KQ0KDQojIEFkZCB0aWNrIG1hcmtzIGZvciBldmVyeSB5ZWFyDQpheGlzKDEsIGF0ID0gdGltZShiY191a2dhc190cylbY3ljbGUoYmNfdWtnYXNfdHMpID09IDFdLCBsYWJlbHMgPSBGQUxTRSkNCmBgYA0KTm90ZTogU3Bpa2UgaW4gdm9sYXRpbGl0eSBwb3N0LTE5NzAuIE91dGxpZXIgcGVyaW9kIDE5NzAtMTk3Mi4gSW4gMTk3MCBCUCBkaXNjb3ZlcmVkIGEgaHVnZSBzdXBwbHkgb2YgbmF0dXJhbCBnYXMgaW4gdGhlIE5vcnRoIFNlYS4gVGhpcyB2b2xhdGlsaXR5IGNvdWxkIGJlIGEgY29uc2VxdWVuY2Ugb2YgdGhhdCwgY29tYmluZWQgd2l0aCBkZXZlbG9waW5nIGluZnJhc3RydWN0dXJlLg0KIg0KV2hpbGUgdGhlIHNwaWtlIGFyb3VuZCAxOTcw4oCTMTk3MiBhbGlnbnMgbW9yZSB3aXRoIE5vcnRoIFNlYSBnYXMgZGV2ZWxvcG1lbnQsIGFueSBsaW5nZXJpbmcgcG9zdC0xOTczIGFub21hbGllcyBjb3VsZCByZWZsZWN0IHRoZSBicm9hZGVyIDE5NzPigJMxOTc0IGVuZXJneSBjcmlzaXMsIGluY2x1ZGluZyBkZW1hbmQgc2hvY2tzLCBob2FyZGluZyBiZWhhdmlvciwgb3IgY2hhbmdlcyBpbiBpbmR1c3RyaWFsIG91dHB1dC4NCiINCg0KQWxsIGluIGFsbCwgd2VpcmQgc3R1ZmYgd2FzIGhhcHBlbmluZyBpbiB0aGUgVUsgbmF0dXJhbCBnYXMgbWFya2V0IGFyb3VuZCAxOTcwLg0KDQpgYGB7cn0NCmFkZlRlc3QoZGlmZjRfYmNfdWtnYXNfdHMsIGxhZ3M9NCwgdHlwZSA9ICduYycpDQpgYGANClVzaW5nIGEgY29uc2VydmF0aXZlIEFERiBzcGVjaWZpY2F0aW9uIHdpdGggbm8gY29uc3RhbnQsIHRoZSBwLXZhbHVlIHdhcyA8IDAuMDUsIGluZGljYXRpbmcgdGhhdCB0aGUgQm94LUNveCB0cmFuc2Zvcm1lZCBhbmQgbGFnLTQgZGlmZmVyZW5jZWQgVUtnYXMgc2VyaWVzIGlzIHN0YXRpb25hcnku4oCdDQoNCg0KVGhlIEFERiB0ZXN0IHJlc3VsdCBuYXJyb3dseSByZWplY3RzIHRoZSBudWxsIGh5cG90aGVzaXMgb2YgYSB1bml0IHJvb3QgYXQgdGhlIDAuMDUgc2lnbmlmaWNhbmNlIGxldmVsLiBUaGlzIHN1Z2dlc3RzIHRoYXQgdGhlIEJveC1Db3ggdHJhbnNmb3JtYXRpb24gKCRcbGFtYmRhJCA9IOKAkzAuNDQ1NykgYW5kIHNlYXNvbmFsIGxhZy00IGRpZmZlcmVuY2luZyB3ZXJlIHN1ZmZpY2llbnQgdG8gc3RhYmlsaXplIHRoZSBtZWFuIGFuZCBhY2hpZXZlIHN0YXRpb25hcml0eSDigJQgYXQgbGVhc3QgYWNjb3JkaW5nIHRvIHRoZSB0ZXN0Lg0KDQpUaGF0IHNhaWQsIHRoZSByZXN1bHQgaXMgYm9yZGVybGluZSwgYW5kIHNvbWUgcmVzaWR1YWwgdHJlbmQgbWF5IHN0aWxsIGJlIHByZXNlbnQuIFdlJ2xsIG5vdGUgdGhpcyBhcyBhIHBvc3NpYmxlIGxpbWl0YXRpb24sIGJ1dCBwcm9jZWVkIHdpdGggbW9kZWxpbmcgdW5kZXIgdGhlIGFzc3VtcHRpb24gb2Ygd2VhayBzdGF0aW9uYXJpdHkgYmFzZWQgb24gdGhpcyByZXN1bHQuDQoNCk5vdGUsIHdlIGNvdWxkIGFwcGx5IGEgcmVndWxhciBkaWZmZXJlbmNlIHRvIHRoZSBkYXRhIHRoYXQgaGFzIGFscmVhZHkgYmVlbiBsYWc0IGRpZmZlcmVuY2UgYW5kIGJjIHRyYW5zZm9ybWVkLiBJZiB3ZSBkaWQgdGhhdCwgdGhlIHAtdmFsdWUgd291bGQgc2hyaW5rLCBhbmQgdGhlcmUgd291bGQgYmUgbm8gZG91YnQgdGhhdCB0aGlzIHdvdWxkIG1ha2Ugb3VyIGRhdGEgc3RhdGlvbmFyeSBhYm91dCB0aGUgbWVhbi4gDQoNCkhvd2V2ZXIsIGluIGVmZm9ydHMgdG8gYXZvaWQgY29uZHVjdGluZyBhbnkgdW5uZWNlc3NhcnkgdHJhbnNmb3JtYXRpb25zLCB3ZSBsZWFuIG9uIHRoZSByZXN1bHRzIG9mIHRoZSBBREYgdGVzdC4gVGhlIHAtdmFsdWUgaXMgMC4wNDQ4LiBBbHRob3VnaCB0aGF0IGlzIGNsb3NlIHRvIDAuMDUsIHdlIHdpbGwgY29uY2x1ZGUgdGhhdCB3ZSBjb25kdWN0ZWQgc3VmZmljaWVudCB0cmFuc2Zvcm1hdGlvbnMgdG8gY29uY2x1ZGUgc3RhdGlvbmFyaXR5Lg0KDQpJbiBvcmRlciB0byBzcGVjdWxhdGUgb24gdGhlIEFSSU1BIHN0cnVjdHVyZSBvZiB0aGUgdGltZSBzZXJpZXMgZGF0YSwgd2UnbGwgbG9vayBhdCB0aGUgQUNGIGFuZCBQQUNGIHBsb3RzIG9mIG91ciB0cmFuc2Zvcm1lZCBkYXRhLg0KDQoNCmBgYHtyfQ0KI0xvb2sgYXQgQUNGIGFuZCBQQUNGIG9mIHRoZSBsYWctNCBkaWZmZXJlbmNlZCBkYXRhDQpwYXIobWZyb3cgPSBjKDEsMikpDQphY2YoZGlmZjRfYmNfdWtnYXNfdHMsIGxhZy5tYXggPSAyMCwgeGxhYiA9ICJMQUcgw7cgNCIpICMgNCB5ZWFycw0KcGFjZihkaWZmNF9iY191a2dhc190cywgbGFnLm1heCA9IDIwLCB4bGFiID0gIkxBRyDDtyA0IikNCmBgYA0KRWFjaCB1bml0IG9uIHRoZSB4LWF4aXMgcmVwcmVzZW50cyAxIHllYXIsIHNpbmNlIHRoZSBkYXRhIGlzIHF1YXJ0ZXJseSBhbmQgdGhlIHNlYXNvbmFsIHBlcmlvZCBpcyA0Lg0KDQpJbiBhdGhlIEFDRiBwbG90LCBMYWdzIDEsIDQsIGFuZCA1IHNob3cgc2lnbmlmaWNhbnQgYXV0b2NvcnJlbGF0aW9ucy4gV2hpbGUgc2Vhc29uYWwgZGlmZmVyZW5jaW5ncyAob2YgbGFnPTQpIHJlbW92ZWQgbXVjaCBvZiB0aGUgc2Vhc29uYWxpdHksIHNvbWUgcmVzaWR1YWwgc2Vhc29uYWwgc3RydWN0dXJlIHJlYW1haW5zLiANCg0KTGFnIDEgc3Bpa2Ugc3VnZ2VzdHMgc2hvcnQtdGVybSBhdXRvY29yZWxsYXRpb24gOiBQZXJoYXBzIE1BKDEpIG9yIEFSKDEpDQpXaXRoIGEgc3Bpa2UgYWdhaW4gYXQgTGFnIDQsIHRoaXMgc3VnZ2VzdHMgc29tZSBzZWFzb25hbCBhdXRvY29ycmVsYXRpb24uIFNvIG1heWJlIGFuIFNBUigxKSBvciBTTUEoMSkgdGVybSANCg0KVGhlIFBBQ0YgaGFzIHNpZ25pY2FudCBzcGlrZXMgYXQgcXVhcnRlcnMgMSwgNCwgNSwgOQ0KDQpUaGVyZWZvcmUsIHRoZXJlIGlzIHNvbWUgcmVzaWR1YWwgc2Vhc29uYWwgc3RydWN0dXJlIGV2ZW4gYWZ0ZXIgdGhlIHNlYXNvbmFsIChsYWc0KSBkaWZmZXJlbmNpbmcuIEhvd2V2ZXIsIHRoZSByZW1haW5pbmcgbGFncyBmYWxsIG1vc3RseSB3aXRoaW4gdGhlIDk1JSBDSXMuIFRoaXMgc3VnZ2VzdHMgd2Vhay9ubyBhdXRvY29ycmVsYXRpb24gYWZ0ZXIgMSB5ZWFyICg0IGxhZ3MpLg0KDQpTbyB3aGF0IHdlIGRpZDoNCjEuIEJveCBDb3ggdHJhbnNmb3JtYXRpb24gd2l0aCBsYW1kYSA9IC0wLjQ0NQ0KMi4gU2Vhc29uYWwgZGlmZmVyZW5jaW5nLCBsYWcgPSA0DQoNCkJhc2VkIG9uIG15IG1vZGVsIHRyYW5zZm9ybWF0aW9ucyBhbmQgdGhlIHJlc3VsdGluZyBBQ0YgYW5kIFBBQ0YgcGxvdHMsIHdlIGNhbiBzcGVjdWxhdGUgdGhlIHN0cnVjdHVyZSBvZiB0aGUgbW9kZWxzIHRoYXQgYXV0by5hcmltYSgpIHdpbGwgZ2VuZXJhdGUgZm9yIHVzLiANCg0KV2UgYXBwbGllZCBhIHNlYXNvbmFsIGRpZmZlcmVuY2Ugb2YgbGFnIDQuIFRoZXJlZm9yZSwgRD0xIGFuZCB0aGUgbGFnIHRlcm0gWzRdDQpXZSBkaWQgbm90IGFwcGx5IGEgcmVndWxhciBkaWZmZXJlbmNlLiBUaGVyZWZvcmUsIGQ9MS4NCg0KTWFrZSBzb21lIHByZWRpY3Rpb25zIG9mIHdoYXQgb3VyIG1vZGVsIG1pZ2h0IGxvb2sgbGlrZQ0KDQpXZSBub3cgdXNlIGF1dG8uYXJpbWEgb24gdGhlIEJveC1Db3ggdHJhbnNmb3JtZWQgZGF0YS4gV2UgZGVjaWRlZCB0byBmZWVkIGF1dG8uYXJpbWEoKSB0aGUgdW4tZGlmZmVyZW5jZWQgZGF0YS4gVGhlIGF1dG8tYXJpbWEgZnVuY3Rpb24gc2hvdWxkIGhhbmRsZSBzZWFzb25hbCBkaWZmZXJlbmNpbmcgb24gaXRzIG93biAod2l0aCBhIEQ9MSB0ZXJtKS4NCg0KV2UgYXJlIGFsbG93aW5nIGRyaWZ0IGFuZCB3ZSBkaXNwbGF5IHRoZSB0cmFjZSBvZiBhdXRvLmFyaW1hKCkgdG8gZXZhbHVhdGUgb3RoZXIgcG90ZW50aWFsbHkgc3VpdGFibGUgbW9kZWxzIHdpdGggc2ltaWxhciBBSUNjIHZhbHVlcy4NCg0KQWZ0ZXIgcmV2aWV3aW5nIHRoZSBkb2N1bWVuYXRpb24gZm9yIGF1dG8uYXJpbWEoKSwgd2UgZGVjaWRlZCB0byBhZGQgdGhlIGNvbW1hbmQgInN0ZXB3aXNlPUZBTFNFIjogZ2l2aW5nIHVzIGEgbXVjaCBtb3JlIGNvbXByZWhlbnNpdmUgbW9kZWwgc2VhcmNoLg0KDQpXZSB3aWxsIGV2YWx1YXRlIDQgbW9kZWxzLiA0IEFyaW1hIG1vZGVscyBiZWZvcmUgY2hvb3NpbmcgMSB0byBhY2NlcHQgYW5kIHVzZSBmb3IgZm9yZWNhc3RpbmcuDQoNCmBgYHtyfQ0KIyBBcHBseSB0aGUgDQphdXRvLmFyaW1hKGJjX3VrZ2FzX3RzLCB0cmFjZSA9IFRSVUUsIGFwcHJveGltYXRpb24gPSBGQUxTRSwgYWxsb3dkcmlmdCA9IFRSVUUsIHN0ZXB3aXNlPUZBTFNFKQ0KYGBgDQpOb3RlOiBBbGwgbW9kZWxzIHdpbGwgYmUgZml0IHRvIEJveC1Db3ggdHJhbnNmb3JtZWQgZGF0YSB3aXRoICRcbGFtYmRhJCA9IC0wLjQ0NS4gQWxsIGNvZWZmaWNpZW50cyBhbmQgdGVybXMgYXJlIGV4cHJlc3NlZCBpbiB0ZXJtcyBvZiB0aGUgdHJhbnNmb3JtZWQgc2VyaWVzLiBUaGVyZWZvcmUsIG1vZGVsIHNlbGVjdGlvbiwgZGlhZ25vc3RpYyBwbG90cywgYW5kIGVxdWF0aW9uIHJlcG9ydGluZyB3aWxsIGFsbCBiZSBleHByZXNzZWQgb24gdGhlIHRyYW5zZm9ybWVkIHNjYWxlLiBNdWNoIExhdGVyLCB3ZSB3aWxsIGJhY2sgdHJhbnNmb3JtIHRoZSBtb2RlbCBkdXJpbmcgdGhlIGZvcmVjYXN0IHN0ZXAuDQoNCiMjIE1vZGVsIDE6IEFSSU1BKDMsMCwxKSgwLDEsMClbNF0NCmBgYHtyfQ0KI25vLmNvbnN0YW50ID0gZmFsc2UgYmVjYXVzZSB3ZSBwbGFuIHRvIGluY2x1ZGUgYSBkcmlmdCB0ZXJtDQp1a2dhc19tb2RlbDEgPC1zYXJpbWEoYmNfdWtnYXNfdHMsMywwLDEsMCwxLDAsIDQsIG5vLmNvbnN0YW50ID0gRkFMU0UpICN3aXRoIGRyaWZ0DQoNCm4gPC0gbGVuZ3RoKGJjX3VrZ2FzX3RzKQ0KdWtnYXNfbW9kZWwxJElDcypuDQpgYGANCkVxdWF0aW9uIG9mIE1vZGVsIDE6DQoNCiQkKDEgKyAwLjk5MzNCICsgMC4xNDczQl4yIC0gMC4xNjE4Ql4zKSgxIC0gQl40KVhfdCA9ICgxICsgMC44Nzg1QilXX3QgKyAwLjAwMTMkJA0Kd2hlcmUNCiQkV190IFxzaW0gXG1hdGhjYWx7Tn0oMCxcIDguMTkgXHRpbWVzIDEwXnstNX0pJCQNCg0KDQpXZSBub3RlIHRoYXQgQVIyIGFuZCBBUjMgY29lZmZpY2llbnRzLCB3aXRoIHAgdmFsdWVzIG9mIDAuMjk0MyBhbmQgMC4xMjk3IGFyZSBub3Qgc2lnbmlmaWNhbnQgYXQgdGhlIC4wNSBsZXZlbC4gDQoNCkNvbW1lbnRzIG9uIHRoZSBkaWFnbm9zdGljIHBsb3RzOg0KDQoNClRoZXJlJ3MgcXVpdGUgYSBiaXQgb2YgY29tcGxleGl0eSB0byB0aGlzIG1vZGVsLCB3aXRoIDMgQVIgdGVybXMsIGFuIE1BIHRlcm0sIGEgYm94LWNveCB0cmFuc2Zvcm1hdGlvbiwgYW5kIGEgc2Vhc29uYWwgZGlmZmVyZW5jZS4gDQoNCkFuZCB3aXRoIEFSMiBhbmQgQVIzIHRlcm1zIHdpdGggc3VjaCBoaWdoIHAtdmFsdWVzLCB0aGlzIGJlZ3MgdGhlIHF1ZXN0aW9uICoqY2FuIHdlIGFjaGlldmUgc2ltaWxhciBtb2RlbCBmaXQgd2l0aCBhIGxlc3MgY29tcGxleCBtb2RlbD8qKg0KDQpPbmUgd2F5IHRvIGxpbWl0IGNvbXBsZXhpdHkgaXMgYnkgImZpeGluZyIgdGVybXMgdG8gMC4gSXQncyBraW5kIG9mIGEgZ3Vlc3MgYW5kIGNoZWNrIHByb2NlZHVyZS4gV2UgbXV0ZSBhIHRlcm0gZm9yIGEgc2ltaWxhciwgbGVzcyBjb21wbGV4IG1vZGVsLCBhbmQgZG8gYSBzYXJpbWEoKSBhbmQgc2VlIGlmIHRoZSBkaWFnbm9zdGljIHBsb3RzIGFuZCBBSUNjIHZhbHVlcyBhcmUgYWNjZXB0YWJsZS4gDQoNClRoaXMgaXMgZ29vZCBwcmFjdGljZSwgYXMgaXQga2VlcHMgdGhlIHByaW5jaXBsZSBvZiBwYXJzaW1vbnkgaW4gbWluZC4NCg0KSW4gbW9kZWwgMiwgd2Ugd2lsbCBvYnNlcnZlIGEgbW9kZWwgdGhhdCBzdGlsbCBwZXJmb3JtcyB3ZWxsIHdoZW4gd2UgZml4IHRoZSBBUjIgdGVybSB0byAwOiB3aXRoIGdvb2QgcC12YWx1ZXMgb24gdGVybXMsIGRpYWdub3N0aWMgcGxvdHMsIGFuZCBhIHN0cm9uZyBBSUNjIHZhbHVlDQoNClRyeWluZyBsZXNzIGNvbXBsZXggbW9kZWxzIGJ5IGZpeGluZyBjb2VmZmljaWVudHMgdG8gMA0KDQojIyBNb2RlbCAyOiBBUklNQSgzLDAsMSkoMCwxLDApWzRdDQpXaGVyZSBBUjIgY29lZmZpY2llbnQgaXMgZml4ZWQgdG8gMA0KDQpgYGB7cn0NCnVrZ2FzX21vZGVsMiA8LSBzYXJpbWEoYmNfdWtnYXNfdHMsIDMsMCwxLCAwLDEsMCwgNCwNCiAgICAgICAgICAgICAgICAgICAgICAgZml4ZWQgPSBjKE5BLCAwLCBOQSwgTkEsIE5BKSwgI2ZpeCBBUjIgdG8gMA0KICAgICAgICAgICAgICAgICAgICAgICBuby5jb25zdGFudCA9IEZBTFNFKSAjIFdpdGggRHJpZnQNCnVrZ2FzX21vZGVsMiRJQ3Mqbg0KYGBgDQpPaCBXT1chISEhQUlDYyBpcyBldmVuIGxvd2VyLCB3aGVuIGkgRXhjbHVkZSBBUjIsIGFsbCB0aGUgcCB2YWx1ZXMgYXJlIDAgbm93LiBwbG90cyBsb29rIGdyZWF0Lg0KVEhJUyBpcyBteSBtb2RlbCEhIQ0KV2lubmVyIHdpbm5lcg0KDQpFcXVhdGlvbiBvZiBNb2RlbDIgKHdpdGggZml4ZWQgQVIyKQ0KDQokJCgxICsgMC45MDQyQiAtIDAuMjQ0MUJeMykoMSAtIEJeNClYX3QgPSAoMSArIDAuODYxN0IpV190ICsgMC4wMDEzJCQNCndoZXJlDQokJFdfdCBcc2ltIFxtYXRoY2Fse059KDAsXCA4LjI4IFx0aW1lcyAxMF57LTV9KSQkDQoNCiMjIE1vZGVsIDM6ICgzLDAsMSkoMCwxLDApWzRdDQpXaGVyZSBBUjEgYW5kIEFSMiBhcmUgZml4ZWQgdG8gMA0KDQpOb3cgbGV0J3MgdHJ5IHRvIHNpbXBsaWZ5IGZ1cnRoZXIuICBQZXJoYXBzIGFuIEFSMyB0ZXJtIGlzIGFsbCB3ZSBuZWVkLg0KYGBge3J9DQp1a2dhc19tb2RlbDMgPC0gc2FyaW1hKGJjX3VrZ2FzX3RzLCAzLDAsMSwgMCwxLDAsIDQsDQogICAgICAgICAgICAgICAgICAgICAgIGZpeGVkID0gYygwLCAwLCBOQSwgTkEsIE5BKSwNCiAgICAgICAgICAgICAgICAgICAgICAgbm8uY29uc3RhbnQgPSBGQUxTRSkNCnVrZ2FzX21vZGVsMyRJQ3Mqbg0KYGBgDQoNCkVxdWF0aW9uIG9mIE1vZGVsIDM6DQoNCiQkKDEgLSAwLjA4NThCXjMpKDEgLSBCXjQpWF90ID0gKDEgLSAwLjE5MDlCKVdfdCArIDAuMDAxMyQkDQp3aGVyZQ0KDQokJFdfdCBcc2ltIFxtYXRoY2Fse059KDAsXCA5LjEwIFx0aW1lcyAxMF57LTV9KSQkDQoNCkxqdW5nIGJveCBsb29rcyBwb29yLCBhbmQgMiBhdCBsYWdzIDQgYW5kIDUgYXJlIHNpZ25pZmljYW50LiBwIHZhbHVlcyBvZiBjb2VmZmljaWVudHMgZGV0ZXJpb3JhdGVkLiANCg0KVGhlcmVmb3JlLCB3ZSB3aWxsIHJlamVjdCB0aGlzIG1vZGVsLg0KDQojIyBNb2RlbCA0OiBBUklNQSgyLDAsMSkoMCwxLDApWzRdDQpgYGB7cn0NCnVrZ2FzX21vZGVsNCA8LXNhcmltYShiY191a2dhc190cywgMiwwLDEsMCwxLDAsIDQsIG5vLmNvbnN0YW50ID0gRkFMU0UpDQp1a2dhc19tb2RlbDQkSUNzKm4NCmBgYA0KTW9kZWwgNCBFcXVhdGlvbjoNCg0KJCQoMSAtIDAuNjc3NkIgLSAwLjIyMzFCXjIpKDEgLSBCXjQpWF90ID0gKDEgLSAwLjg4MzFCKVdfdCArIDAuMDAxMyQkDQpXaGVyZQ0KJCRXX3QgXHNpbSBcbWF0aGNhbHtOfSgwLFwgOS4wOCBcdGltZXMgMTBeey01fSkkJA0KDQoNClN1bW1hcnkgdGFibGUgb2YgdmFsdWVzIChJJ3ZlIGFscmVhZHkgY3JlYXRlZCB0aGlzIGluIHdvcmQgYW5kIGNhbiBzZW5kIHRvIHlvdSkNCg0KfCBNb2RlbCAgIHwgU3BlY2lmaWNhdGlvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgQUlDICAgICAgIHwgQUlDYyAgICAgIHwgQWxsIFRlcm1zIFNpZ25pZmljYW50IChwIDwgMC4wNSk/ICAgICAgICAgIHwgTGp1bmctQm94IFRlc3QgUmVzdWx0ICAgICAgIHwNCnwtLS0tLS0tLS18LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tfC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXwtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18DQp8IE1vZGVsIDEgfCBBUklNQSgzLDAsMSkoMCwxLDApWzRdICAgICAgICAgICAgICAgICAgICAgIHwgLTY5Ni42OTEgIHwgLTY5Ni4wNTUgIHwg4p2MIEFSMiAocCA9IDAuMjkpLCBBUjMgKHAgPSAwLjEzKSAgICAgICAgICAgIHwg4pyFIE1vc3QgcC12YWx1ZXMgPiAwLjA1IOKAkyBQYXNzIHwNCnwgTW9kZWwgMiB8IEFSSU1BKDMsMCwxKSgwLDEsMClbNF0sIEFSMiBmaXhlZCB0byAwICAgICAgfCAqKi02OTcuNjAwKiogfCAqKi02OTcuMTgxKiogfCDinIUgWWVzICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwg4pyFIE1vc3QgcC12YWx1ZXMgPiAwLjA1IOKAkyBQYXNzIHwNCnwgTW9kZWwgMyB8IEFSSU1BKDMsMCwxKSgwLDEsMClbNF0sIEFSMSAmIEFSMiBmaXhlZCB0byAwfCAtNjkwLjAwOSAgfCAtNjg5Ljc2MCAgfCDinYwgQVIzIChwID0gMC4zOSkgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCDinYwgU2V2ZXJhbCBwLXZhbHVlcyA8IDAuMDUg4oCTIEZhaWwgfA0KfCBNb2RlbCA0IHwgQVJJTUEoMiwwLDEpKDAsMSwwKVs0XSAgICAgICAgICAgICAgICAgICAgICB8IC02ODguMTQ3ICB8IC02ODcuNzI3ICB8IOKchSBZZXMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfCDinYwgU2V2ZXJhbCBwLXZhbHVlcyA8IDAuMDUg4oCTIEZhaWwgfA0KDQoNClNvLCBXZSBhcmUgZ29pbmcgdG8gc2VsZWN0IE1vZGVsIDIhISENCg0KDQoNCg0KIyBGb3JlY2FzdGluZyB1c2luZyBNb2RlbCAyDQoNCmBgYHtyfQ0KIyBoYXZlIHRvIHVzZSBBcmltYSgpe2ZvcmVjYXN0fSBub3QgYXJpbWEoKXtzdGF0c30uIA0KIyBhcmltYSgpIGtlcHQgZHJvcHBpbmcgbXkgZHJpZnQgdGVybSEgV2FzIHF1aXRlIGZydXN0cmF0aW5nDQpsaWJyYXJ5KGZvcmVjYXN0KSANCg0KIyBGaXQgdGhlIG1vZGVsDQp1a2dhcy5maXQubW9kZWwyIDwtIEFyaW1hKGJjX3VrZ2FzX3RzLCANCiAgICAgICAgICAgICBvcmRlciA9IGMoMywwLDEpLCBzZWFzb25hbCA9IGMoMCwxLDApLA0KICAgICAgICAgICAgIGZpeGVkID0gYyhOQSwgMCwgTkEsIE5BLCBOQSksDQogICAgICAgICAgICAgaW5jbHVkZS5kcmlmdCA9IFRSVUUpDQoNCiMgQ2hlY2sgYWxsIHRlcm1zIGFyZSBwcmVzZW50IGluIG1vZGVsLCBhbmQgQVIyIGlzIDANCnVrZ2FzLmZpdC5tb2RlbDIkY29lZg0KYGBgDQpgYGB7cn0NCiMgRm9yZWNhc3QgdXNpbmcgQVJJTUEgbW9kZWwgZml0IG9uIEJveC1Db3ggZGF0YQ0KdWtnYXMuZm9yZWNhc3QuTTIuYmMgPC0gZm9yZWNhc3QodWtnYXMuZml0Lm1vZGVsMiwgaCA9IDEyKQ0KDQojIFBsb3Qgd2l0aCBUcmFuc2Zvcm1lZCBTY2FsZQ0KcGFyKG1mcm93ID0gYygxLDEpKQ0KcGxvdCh1a2dhcy5mb3JlY2FzdC5NMi5iYywgDQogICAgIG1haW4gPSAiQVJJTUEgRm9yZWNhc3Qgb24gVHJhbnNmb3JtZWQgU2NhbGUgKHdpdGggRml0dGVkICsgSGlzdG9yeSkiLA0KICAgICB4bGFiID0gJ1llYXInLCB5bGFiID0gJ0JDIFRyYW5zZm9ybWVkIFNjYWxlJykNCg0KIyBUaWNrIG1hcmtzDQpheGlzKDEsIGF0ID0gYyh0aW1lKHVrZ2FzX3RzKVtjeWNsZSh1a2dhc190cykgPT0gMV0sIDE5ODYsIDE5ODcsIDE5ODgsIDE5ODkpLCBsYWJlbHMgPSBGQUxTRSkNCmBgYA0KVGhlIHBsb3QgaXMgZGlmZmljdWx0IHRvIGludGVycHJldCB3aXRoIHRoZSBHYXMgY29uc3VtcHRpb24gZGF0YSBpbiB0aGlzIGZvcm1hdC4gVGhlIGRhdGEgb24gdGhlIHkgYXhpcyBpcyB0aGUgQm94LUNveCB0cmFuc2Zvcm1lZCBkYXRhLg0KDQpBIGJldHRlciB2aXN1YWxpemF0aW9uIHdvdWxkIGludmVyc2UgdHJhbnNmb3JtIHRoZSB5IGRhdGEuDQoNCmBgYHtyfQ0KIyBGb3JlY2FzdCB1c2luZyBBUklNQSBtb2RlbCBmaXQgb24gQm94LUNveCBkYXRhDQp1a2dhcy5mb3JlY2FzdC5NMiA8LSBmb3JlY2FzdCh1a2dhcy5maXQubW9kZWwyLCBoID0gMTIpDQoNCiMgSW52ZXJzZSB0cmFuc2Zvcm0gZm9yZWNhc3QgY29tcG9uZW50cw0KdWtnYXMuZm9yZWNhc3QuTTIkbWVhbiAgIDwtIEludkJveENveCh1a2dhcy5mb3JlY2FzdC5NMiRtZWFuLCBsYW1iZGEpDQp1a2dhcy5mb3JlY2FzdC5NMiRsb3dlciAgPC0gSW52Qm94Q294KHVrZ2FzLmZvcmVjYXN0Lk0yJGxvd2VyLCBsYW1iZGEpDQp1a2dhcy5mb3JlY2FzdC5NMiR1cHBlciAgPC0gSW52Qm94Q294KHVrZ2FzLmZvcmVjYXN0Lk0yJHVwcGVyLCBsYW1iZGEpDQp1a2dhcy5mb3JlY2FzdC5NMiRmaXR0ZWQgPC0gSW52Qm94Q294KHVrZ2FzLmZvcmVjYXN0Lk0yJGZpdHRlZCwgbGFtYmRhKQ0KDQojIFJlcGxhY2UgeCAodGhlIG9yaWdpbmFsIHNlcmllcyB1c2VkIGZvciBwbG90dGluZykgd2l0aCB0aGUgdHJ1ZSBvcmlnaW5hbCBkYXRhDQp1a2dhcy5mb3JlY2FzdC5NMiR4IDwtIHVrZ2FzX3RzICAjIOKGkCB0aGlzIGlzIGtleSENCg0KIyBQbG90IGV2ZXJ5dGhpbmcgb24gdGhlIGNvcnJlY3Qgc2NhbGUNCnBhcihtZnJvdyA9IGMoMSwxKSkNCnBsb3QodWtnYXMuZm9yZWNhc3QuTTIsIA0KICAgICBtYWluID0gIkFSSU1BIEZvcmVjYXN0IG9uIE9yaWdpbmFsIFNjYWxlICh3aXRoIEZpdHRlZCArIEhpc3RvcnkpIiwNCiAgICAgeGxhYiA9ICdZZWFyJywgeWxhYiA9ICdNaWxsaW9ucyBvZiBUaGVybXMgKE5hdHVyYWwgR2FzKScpDQoNCg0KYXhpcygxLCBhdCA9IGModGltZSh1a2dhc190cylbY3ljbGUodWtnYXNfdHMpID09IDFdLCAxOTg2LCAxOTg3LCAxOTg4LCAxOTg5KSwgbGFiZWxzID0gRkFMU0UpDQpgYGANCg0KDQoNCmBgYHtyfQ0KcGxvdCh1a2dhcy5mb3JlY2FzdC5NMiwgeGxpbSA9IGMoMTk4MiwgMTk5MCksDQogICAgIG1haW4gPSAiQVJJTUEgRm9yZWNhc3Qgb24gT3JpZ2luYWwgU2NhbGUgKHdpdGggRml0dGVkICsgSGlzdG9yeSkiLA0KICAgICB4bGFiID0gJ1llYXInLCB5bGFiID0gJ01pbGxpb25zIG9mIFRoZXJtcyAoTmF0dXJhbCBHYXMpJykNCiAgICAgDQpheGlzKDEsIGF0ID0gYyh0aW1lKHVrZ2FzX3RzKVtjeWNsZSh1a2dhc190cykgPT0gMV0sIDE5ODYsIDE5ODcsIDE5ODgsIDE5ODkpLCBsYWJlbHMgPSBUUlVFKQ0KYGBgDQoNCkNvbmNsdXNpb25zOiANCg0KDQoNCg0KDQoNCg0KDQoNCg0KV2Ugd2lsbCBlbmQgaGVyZS0tIGlnbm9yZSBiZWxvdw0KDQoNCg0KSE9MVCBXSU5URVJTDQpBY3R1YWxseSwgdGhpcyBpcyBleHRyYS4gVGhpcyBpc24ndCBtZW50aW9uZWQgaW4gdGhlIHByb21wdCBhdCBhbGwuIFNvLCBsZXRzIGRyb3AgaXQuIEFuIGV2YWx1YXRpb24gb2YgNCBBUklNQSBtb2RlbHMgaXMgYWJzb2x1dGVseSBtb3JlIHRoYW4gZW5vdWdoLg0KDQpgYGB7cn0NCkhXX2JjX3VrZ2FzX3RzIDwtIEhvbHRXaW50ZXJzKGJjX3VrZ2FzX3RzKSAjIGZpdHRpbmcgSG9sdFdpbnRlcnMgbW9kZWwgdG8gdGhlIFJBVyBkYXRhDQpwbG90KEhXX2JjX3VrZ2FzX3RzKQ0KDQpheGlzKDEsIGF0ID0gdGltZSh1a2dhc190cylbY3ljbGUodWtnYXNfdHMpID09IDFdLCBsYWJlbHMgPSBGQUxTRSkNCg0KZm9yZWNhc3RfSFdfYmNfdWtnYXNfdHMgPC0gZm9yZWNhc3QoSFdfYmNfdWtnYXNfdHMpDQpwbG90KGZvcmVjYXN0X0hXX2JjX3VrZ2FzX3RzLA0KICAgICB4bGltID0gYygxOTgyLCAxOTkwKSwNCiAgICAgeWxpbSA9IGMoMi4wMCwgMi4yMCkpDQoNCmF4aXMoMSwgYXQgPSB0aW1lKHVrZ2FzX3RzKVtjeWNsZSh1a2dhc190cykgPT0gMV0sIGxhYmVscyA9IEZBTFNFKQ0KYGBgDQoNCg0KDQoNCg0KYGBge3J9DQpjaGVja3Jlc2lkdWFscyhIV19iY191a2dhc190cykNCmBgYA0KDQpTaW5jZSB0aGUgcC12YWx1ZSBpcyBncmVhdGVyIHRoYW4gMC4wNSwgd2UgZmFpbCB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy4gVGhpcyBzdWdnZXN0cyB0aGVyZSdzIG5vIHNpZ25pZmljYW50IGF1dG9jb3JyZWxhdGlvbiBsZWZ0IGluIHRoZSByZXNpZHVhbHMsIG1lYW5pbmcgdGhlIG1vZGVsIGZpdHMgcmVhc29uYWJseSB3ZWxsLg0KDQoNCg0KDQoNCg0K