Tên: Mai Huy

MSSV: 43.01.104.065

Số thứ tự: 08

1) Phân tích thông tin tập dữ liệu Smarket

# Load thư viện ISLR chứa tập dữ liệu Smarket
library(ISLR)
# load bộ dữ liệu Smarket trong package ISLR
data(Smarket)
# xem dữ liệu ở dạng cửa sổ
fix(Smarket)
#Xem có bao nhiêu dòng và cột
dim(Smarket)
[1] 1250    9
# Xem tên các biến trong dữ liệu Smarket
names(Smarket)
[1] "Year"      "Lag1"      "Lag2"      "Lag3"      "Lag4"      "Lag5"      "Volume"    "Today"     "Direction"
# xem mô tả thông tin của bộ dữ liệu Smarket, mô tả ý nghĩa của các biến
?Smarket
# Tính hệ số tương quan giữa các biến
#Câu lệnh này sẽ bị báo lỗi vì biến Direction là định tính.
cor(Smarket)
Error in cor(Smarket) : 'x' must be numeric
#Loại bỏ biến định tính Direction trước khi tính hệ số tương quan
cor (Smarket[,-9])
             Year         Lag1         Lag2         Lag3         Lag4         Lag5      Volume        Today
Year   1.00000000  0.029699649  0.030596422  0.033194581  0.035688718  0.029787995  0.53900647  0.030095229
Lag1   0.02969965  1.000000000 -0.026294328 -0.010803402 -0.002985911 -0.005674606  0.04090991 -0.026155045
Lag2   0.03059642 -0.026294328  1.000000000 -0.025896670 -0.010853533 -0.003557949 -0.04338321 -0.010250033
Lag3   0.03319458 -0.010803402 -0.025896670  1.000000000 -0.024051036 -0.018808338 -0.04182369 -0.002447647
Lag4   0.03568872 -0.002985911 -0.010853533 -0.024051036  1.000000000 -0.027083641 -0.04841425 -0.006899527
Lag5   0.02978799 -0.005674606 -0.003557949 -0.018808338 -0.027083641  1.000000000 -0.02200231 -0.034860083
Volume 0.53900647  0.040909908 -0.043383215 -0.041823686 -0.048414246 -0.022002315  1.00000000  0.014591823
Today  0.03009523 -0.026155045 -0.010250033 -0.002447647 -0.006899527 -0.034860083  0.01459182  1.000000000

Mối tương quan giữa những biến Lag và biến Today gần = 0, dường như có ít sự tương quan giữa giá trị trả về ngày nay và ngày xưa. Mối tương quan duy nhất có giá trị tương quan khá lớn là giữa biến Year và Volume.

# attach dùng để khiến cho những biến trong dữ liệu Smarket có sẵn trong R theo tên
attach ( Smarket)

2) Áp dụng Logistic Regression với tập kiểm tra cũng chính là tập huấn luyện.

Chúng ta sẽ fit mô hình logistic Regression để dự đoán biến đầu ra Direction và sử dụng các biến đầu vào là Lag1 -> Lag5 và Volume. Hàm glm() và đưa vào biến family =binomial dùng để chạy 1 mô hình Logistic Regression.

# Fit mô hình Logistic Regresion để dự đoán biến đầu ra Direction trong dữ liệu Smarket
glm.fits = glm(Direction~Lag1 + Lag2 + Lag3 + Lag4 + Lag5 + Volume ,
data=Smarket ,family=binomial)
# Hàm summary(model1) sẽ cho chúng ta biết thông tin p-values, Z-value, độ lệch chuẩn cho những hệ số của các biến đầu vào
summary(glm.fits)

Call:
glm(formula = Direction ~ Lag1 + Lag2 + Lag3 + Lag4 + Lag5 + 
    Volume, family = binomial, data = Smarket)

Deviance Residuals: 
   Min      1Q  Median      3Q     Max  
-1.446  -1.203   1.065   1.145   1.326  

Coefficients:
             Estimate Std. Error z value Pr(>|z|)
(Intercept) -0.126000   0.240736  -0.523    0.601
Lag1        -0.073074   0.050167  -1.457    0.145
Lag2        -0.042301   0.050086  -0.845    0.398
Lag3         0.011085   0.049939   0.222    0.824
Lag4         0.009359   0.049974   0.187    0.851
Lag5         0.010313   0.049511   0.208    0.835
Volume       0.135441   0.158360   0.855    0.392

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 1731.2  on 1249  degrees of freedom
Residual deviance: 1727.6  on 1243  degrees of freedom
AIC: 1741.6

Number of Fisher Scoring iterations: 3

Hàm summray cho biết thông tin về giá trị các hệ số của mô hình (B0->B6), thấy rằng Lag1 có hệ số nhỏ nhất = 0.145, tuy nhiên ở giá trị 0.145 vẫn là tương đối lớn, vì thế không có bằng chứng thống kê cho thấy rằng có mối quan hệ giữa Lag1 và biến đầu ra Direction.

# Sử dụng hàm coef() để chỉ hiển thị hệ số của mô hình (B0->B6)
coef(glm.fits)
 (Intercept)         Lag1         Lag2         Lag3         Lag4         Lag5       Volume 
-0.126000257 -0.073073746 -0.042301344  0.011085108  0.009358938  0.010313068  0.135440659 
#Sử dụng hàm summary để chỉ truy cập và hiển thị thông tin các hệ số của mô hình (B0-B6)
summary(glm.fits)$coef
                Estimate Std. Error    z value  Pr(>|z|)
(Intercept) -0.126000257 0.24073574 -0.5233966 0.6006983
Lag1        -0.073073746 0.05016739 -1.4565986 0.1452272
Lag2        -0.042301344 0.05008605 -0.8445733 0.3983491
Lag3         0.011085108 0.04993854  0.2219750 0.8243333
Lag4         0.009358938 0.04997413  0.1872757 0.8514445
Lag5         0.010313068 0.04951146  0.2082966 0.8349974
Volume       0.135440659 0.15835970  0.8552723 0.3924004
# CHỉ hiển thị cột thứ 4 là cột cho biết giá trị p-value của các hệ số
summary(glm.fits)$coef[,4]
(Intercept)        Lag1        Lag2        Lag3        Lag4        Lag5      Volume 
  0.6006983   0.1452272   0.3983491   0.8243333   0.8514445   0.8349974   0.3924004 
# Hàm predict dùng để dự đoán xác suất xu hướng thị trường sẽ đi lên (Directtion = Up), type = "response" để xuất ra xác xuất theo dạng P(Y = 1|X)
glm.probs=predict(glm.fits,type="response")
# Hàm contrast trả về những mã hoá mà R sử dụng cho những biến giả, biến giả ở đây là Up =1 khi direction = Up và Up = 0  khi direction = down
contrasts(Direction)
     Up
Down  0
Up    1
# Xác xuất xu hướng thị trường sẽ đi lên (Direction = Up) cho 10 dòng đầu tiên của dữ liệu
glm.probs[1:10]
        1         2         3         4         5         6         7         8         9        10 
0.5070841 0.4814679 0.4811388 0.5152224 0.5107812 0.5069565 0.4926509 0.5092292 0.5176135 0.4888378 
#Tạo một vecto gom 1250 thành phần down
glm.pred=rep("Down",1250)
#Chuyển các thành phần sang Up khi xác suất lớn hơn 0.5
glm.pred[glm.probs>.5]="Up"
# Dùng hàm table() để tạo ra một ma trận để quyết định xem có bao nhiêu quan sát được phân loại đúng, bao nhiêu bị phân loại sai
table(glm.pred,Direction)
        Direction
glm.pred Down  Up
    Down  145 141
    Up    457 507

Tỉ lệ số ngày dự đoán đúng = (507+145)/1250 = 0.5216

# Dự đoán %số ngày dự đoán đúng
mean(glm.pred==Direction)
[1] 0.5216

Hàm logistic dự đoán đúng 52,16% số ngày

3) Áp dụng Logistic Regression khi chia nhỏ tập dữ liệu thành 2 tập kiểm tra và huấn luyện khác nhau

#Vecto train gồm 1250 phần từ tương ướng với tập dữ liệu quan sát, dòng nào trong data có year <2005 sẽ trả về true, còn lại trả về false
train=(Year<2005)
# Tạo ra ma trận con của tập dữ liệu tương đương những giá trị sau năm 2005 trở về sau
Smarket.2005=Smarket [!train,]
# Bao gồm 252 số quan sát từ năm 2005 trở đi
dim(Smarket.2005)
[1] 252   9
# Tạo ra một vector gồm 252 giá trị Direction = Up hoặc Down từ năm 2005 trở đi
Direction.2005=Direction [!train]
# Thực hiện lại hồi qui logistic dựa trên tập huấn luyện (dữ liệu trước 2005) với subset =train (Year < 2005)
glm.fits = glm(Direction~Lag1 + Lag2 + Lag3 + Lag4 + Lag5
+ Volume , data=Smarket ,family = binomial,subset =train)
# Hàm predict dùng để dự đoán xác suất xu hướng thị trường sẽ đi lên (Directtion = Up) với tập data từ năm 2005 trở đi
glm.probs=predict(glm.fits,Smarket.2005,type="response")
#Tạo một vecto gom 252 thành phần down tương ứng với số quan sát từ năm 2005 trở đi
glm.pred=rep("Down",252)
#Chuyển các thành phần sang Up khi xác suất lớn hơn 0.5
glm.pred[glm.probs>.5]="Up"
# Dùng hàm table() để tạo ra một ma trận để quyết định xem có bao nhiêu quan sát được phân loại đúng, bao nhiêu bị phân loại sai
table(glm.pred,Direction.2005)
        Direction.2005
glm.pred Down Up
    Down   77 97
    Up     34 44

Có 77 + 44 = 121 quan sát được phân loại đúng

Tỉ lệ số ngày dự đoán đúng = (77+44)/252 = 0.4801587

# Dự đoán %số ngày dự đoán đúng
mean(glm.pred==Direction.2005)
[1] 0.4801587
# Dự đoán %số ngày dự đoán sai: test eror
mean(glm.pred!=Direction.2005)
[1] 0.5198413
# Hàm summary(model1) sẽ cho chúng ta biết thông tin p-values, Z-value, độ lệch chuẩn cho những hệ số của các biến đầu vào
summary(glm.fits)

Call:
glm(formula = Direction ~ Lag1 + Lag2 + Lag3 + Lag4 + Lag5 + 
    Volume, family = binomial, data = Smarket, subset = train)

Deviance Residuals: 
   Min      1Q  Median      3Q     Max  
-1.302  -1.190   1.079   1.160   1.350  

Coefficients:
             Estimate Std. Error z value Pr(>|z|)
(Intercept)  0.191213   0.333690   0.573    0.567
Lag1        -0.054178   0.051785  -1.046    0.295
Lag2        -0.045805   0.051797  -0.884    0.377
Lag3         0.007200   0.051644   0.139    0.889
Lag4         0.006441   0.051706   0.125    0.901
Lag5        -0.004223   0.051138  -0.083    0.934
Volume      -0.116257   0.239618  -0.485    0.628

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 1383.3  on 997  degrees of freedom
Residual deviance: 1381.1  on 991  degrees of freedom
AIC: 1395.1

Number of Fisher Scoring iterations: 3

Hàm summray cho biết thông tin về giá trị các hệ số của mô hình (B0->B6), thấy rằng Lag1 có hệ số nhỏ nhất = 0.295, tuy nhiên ở giá trị 0.295 vẫn là tương đối lớn, vì thế không có bằng chứng thống kê cho thấy rằng có mối quan hệ giữa Lag1 và biến đầu ra Direction.

4) Áp dụng Logistic Regression khi chia nhỏ tập dữ liệu và chỉ gồm 2 giá trị đầu vào là biến Lag1 và Lag2

#Thực hiện lại các bước với bộ dữ liệu chỉ có Lag1 và Lag 2 vì 2 biến này có p-value nhỏ nhất
glm.fits = glm (Direction~Lag1+Lag2,data=Smarket ,family =
binomial , subset =train)
# Hàm predict dùng để dự đoán xác suất xu hướng thị trường sẽ đi lên (Directtion = Up) với tập data từ năm 2005 trở đi
glm.probs=predict(glm.fits,Smarket.2005,type="response")
#Tạo một vecto gom 252 thành phần down tương ứng với số quan sát từ năm 2005 trở đi
glm.pred=rep("Down",252)
#Chuyển các thành phần sang Up khi xác suất lớn hơn 0.5
glm.pred[glm.probs>.5]="Up"
# Dùng hàm table() để tạo ra một ma trận để quyết định xem có bao nhiêu quan sát được phân loại đúng, bao nhiêu bị phân loại sai
table(glm.pred,Direction.2005)
        Direction.2005
glm.pred Down  Up
    Down   35  35
    Up     76 106

Có 35 + 106 = 141 quan sát được phân loại đúng

Tỉ lệ số ngày dự đoán đúng = (35+106)/252 = 0.5595238

# Dự đoán %số ngày dự đoán đúng
mean(glm.pred==Direction.2005)
[1] 0.5595238
LS0tDQp0aXRsZTogIkxvZ2lzdGljIFJlZ3Jlc3Npb24gduG7m2kgZGF0YSBTbWFya2V0Ig0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KIyMjIFTDqm46IE1haSBIdXkNCiMjIyBNU1NWOiA0My4wMS4xMDQuMDY1DQojIyMgU+G7kSB0aOG7qSB04buxOiAwOA0KDQojIDEpIFBow6JuIHTDrWNoIHRow7RuZyB0aW4gdOG6rXAgZOG7ryBsaeG7h3UgU21hcmtldCANCg0KYGBge3J9DQojIExvYWQgdGjGsCB2aeG7h24gSVNMUiBjaOG7qWEgdOG6rXAgZOG7ryBsaeG7h3UgU21hcmtldA0KbGlicmFyeShJU0xSKQ0KIyBsb2FkIGLhu5kgZOG7ryBsaeG7h3UgU21hcmtldCB0cm9uZyBwYWNrYWdlIElTTFINCmRhdGEoU21hcmtldCkNCiMgeGVtIGThu68gbGnhu4d1IOG7nyBk4bqhbmcgY+G7rWEgc+G7lQ0KZml4KFNtYXJrZXQpDQpgYGANCg0KDQpgYGB7cn0NCiNYZW0gY8OzIGJhbyBuaGnDqnUgZMOybmcgdsOgIGPhu5l0DQpkaW0oU21hcmtldCkNCiMgWGVtIHTDqm4gY8OhYyBiaeG6v24gdHJvbmcgZOG7ryBsaeG7h3UgU21hcmtldA0KbmFtZXMoU21hcmtldCkNCmBgYA0KDQpgYGB7cn0NCiMgeGVtIG3DtCB04bqjIHRow7RuZyB0aW4gY+G7p2EgYuG7mSBk4buvIGxp4buHdSBTbWFya2V0LCBtw7QgdOG6oyDDvSBuZ2jEqWEgY+G7p2EgY8OhYyBiaeG6v24NCj9TbWFya2V0DQpgYGANCg0KYGBge3J9DQojIFTDrW5oIGjhu4cgc+G7kSB0xrDGoW5nIHF1YW4gZ2nhu69hIGPDoWMgYmnhur9uDQojQ8OidSBs4buHbmggbsOgeSBz4bq9IGLhu4sgYsOhbyBs4buXaSB2w6wgDQpjb3IoU21hcmtldCkNCmBgYA0KDQpgYGB7cn0NCiNMb+G6oWkgYuG7jyBiaeG6v24gxJHhu4tuaCB0w61uaCBEaXJlY3Rpb24gdHLGsOG7m2Mga2hpIHTDrW5oIGjhu4cgc+G7kSB0xrDGoW5nIHF1YW4NCmNvciAoU21hcmtldFssLTldKQ0KYGBgDQoNCk3hu5FpIHTGsMahbmcgcXVhbiBnaeG7r2Egbmjhu69uZyBiaeG6v24gTGFnIHbDoCBiaeG6v24gVG9kYXkgZ+G6p24gPSAwLCBkxrDhu51uZyBuaMawIGPDsyDDrXQgc+G7sSB0xrDGoW5nIHF1YW4gZ2nhu69hIGdpw6EgdHLhu4sgdHLhuqMgduG7gSBuZ8OgeSBuYXkgdsOgIG5nw6B5IHjGsGEuIE3hu5FpIHTGsMahbmcgcXVhbiBkdXkgbmjhuqV0IGPDsyBnacOhIHRy4buLIHTGsMahbmcgcXVhbiBraMOhIGzhu5tuIGzDoCBnaeG7r2EgYmnhur9uIFllYXIgdsOgIFZvbHVtZS4NCg0KDQpgYGB7cn0NCiMgYXR0YWNoIGTDuW5nIMSR4buDIGtoaeG6v24gY2hvIG5o4buvbmcgYmnhur9uIHRyb25nIGThu68gbGnhu4d1IFNtYXJrZXQgY8OzIHPhurVuIHRyb25nIFIgdGhlbyB0w6puDQphdHRhY2ggKCBTbWFya2V0KQ0KYGBgDQoNCmBgYHtyfQ0KIyDEkOG7kyB0aOG7iyBwaMOibiB0w6FuIGJp4bq/biBWb2x1bWUsIGNow7puZyB0YSB0aOG6pXkgcuG6sW5nIGdpw6EgdHLhu4sgdm9sdW1lIHTEg25nIHRoZW8gdGjhu51pIGdpYW4gDQpwbG90KFZvbHVtZSkNCmBgYA0KDQojIDIpIMOBcCBk4bulbmcgTG9naXN0aWMgUmVncmVzc2lvbiB24bubaSB04bqtcCBraeG7g20gdHJhIGPFqW5nIGNow61uaCBsw6AgdOG6rXAgaHXhuqVuIGx1eeG7h24uDQoNCkNow7puZyB0YSBz4bq9IGZpdCBtw7QgaMOsbmggbG9naXN0aWMgUmVncmVzc2lvbiDEkeG7gyBk4buxIMSRb8OhbiBiaeG6v24gxJHhuqd1IHJhIERpcmVjdGlvbiB2w6Agc+G7rSBk4bulbmcgY8OhYyBiaeG6v24gxJHhuqd1IHbDoG8gbMOgIExhZzEgLT4gTGFnNSB2w6AgVm9sdW1lLiBIw6BtIGdsbSgpIHbDoCDEkcawYSB2w6BvIGJp4bq/biBmYW1pbHkgPWJpbm9taWFsIGTDuW5nIMSR4buDIGNo4bqheSAxIG3DtCBow6xuaCBMb2dpc3RpYyBSZWdyZXNzaW9uLg0KDQpgYGB7cn0NCiMgRml0IG3DtCBow6xuaCBMb2dpc3RpYyBSZWdyZXNpb24gxJHhu4MgZOG7sSDEkW/DoW4gYmnhur9uIMSR4bqndSByYSBEaXJlY3Rpb24gdHJvbmcgZOG7ryBsaeG7h3UgU21hcmtldA0KZ2xtLmZpdHMgPSBnbG0oRGlyZWN0aW9ufkxhZzEgKyBMYWcyICsgTGFnMyArIExhZzQgKyBMYWc1ICsgVm9sdW1lICwNCmRhdGE9U21hcmtldCAsZmFtaWx5PWJpbm9taWFsKQ0KYGBgDQoNCg0KYGBge3J9DQojIEjDoG0gc3VtbWFyeShtb2RlbDEpIHPhur0gY2hvIGNow7puZyB0YSBiaeG6v3QgdGjDtG5nIHRpbiBwLXZhbHVlcywgWi12YWx1ZSwgxJHhu5kgbOG7h2NoIGNodeG6qW4gY2hvIG5o4buvbmcgaOG7hyBz4buRIGPhu6dhIGPDoWMgYmnhur9uIMSR4bqndSB2w6BvDQpzdW1tYXJ5KGdsbS5maXRzKQ0KYGBgDQoNCkjDoG0gc3VtbXJheSBjaG8gYmnhur90IHRow7RuZyB0aW4gduG7gSBnacOhIHRy4buLIGPDoWMgaOG7hyBz4buRIGPhu6dhIG3DtCBow6xuaCAoQjAtPkI2KSwgdGjhuqV5IHLhurFuZyBMYWcxIGPDsyBo4buHIHPhu5Egbmjhu48gbmjhuqV0ID0gMC4xNDUsIA0KdHV5IG5oacOqbiDhu58gZ2nDoSB0cuG7iyAwLjE0NSB24bqrbiBsw6AgdMawxqFuZyDEkeG7kWkgbOG7m24sIHbDrCB0aOG6vyBraMO0bmcgY8OzIGLhurFuZyBjaOG7qW5nIHRo4buRbmcga8OqIGNobyB0aOG6pXkgcuG6sW5nIGPDsyBt4buRaSBxdWFuIGjhu4cgZ2nhu69hIExhZzEgdsOgIGJp4bq/biDEkeG6p3UgcmEgRGlyZWN0aW9uLg0KDQpgYGB7cn0NCiMgU+G7rSBk4bulbmcgaMOgbSBjb2VmKCkgxJHhu4MgY2jhu4kgaGnhu4NuIHRo4buLIGjhu4cgc+G7kSBj4bunYSBtw7QgaMOsbmggKEIwLT5CNikNCmNvZWYoZ2xtLmZpdHMpDQpgYGANCg0KDQpgYGB7cn0NCiNT4butIGThu6VuZyBow6BtIHN1bW1hcnkgxJHhu4MgY2jhu4kgdHJ1eSBj4bqtcCB2w6AgaGnhu4NuIHRo4buLIHRow7RuZyB0aW4gY8OhYyBo4buHIHPhu5EgY+G7p2EgbcO0IGjDrG5oIChCMC1CNikNCnN1bW1hcnkoZ2xtLmZpdHMpJGNvZWYNCmBgYA0KDQpgYGB7cn0NCiMgQ0jhu4kgaGnhu4NuIHRo4buLIGPhu5l0IHRo4bupIDQgbMOgIGPhu5l0IGNobyBiaeG6v3QgZ2nDoSB0cuG7iyBwLXZhbHVlIGPhu6dhIGPDoWMgaOG7hyBz4buRDQpzdW1tYXJ5KGdsbS5maXRzKSRjb2VmWyw0XQ0KYGBgDQoNCmBgYHtyfQ0KIyBIw6BtIHByZWRpY3QgZMO5bmcgxJHhu4MgZOG7sSDEkW/DoW4geMOhYyBzdeG6pXQgeHUgaMaw4bubbmcgdGjhu4sgdHLGsOG7nW5nIHPhur0gxJFpIGzDqm4gKERpcmVjdHRpb24gPSBVcCksIHR5cGUgPSAicmVzcG9uc2UiIMSR4buDIHh14bqldCByYSB4w6FjIHh14bqldCB0aGVvIGThuqFuZyBQKFkgPSAxfFgpDQpnbG0ucHJvYnM9cHJlZGljdChnbG0uZml0cyx0eXBlPSJyZXNwb25zZSIpDQpgYGANCg0KDQpgYGB7cn0NCiMgSMOgbSBjb250cmFzdCB0cuG6oyB24buBIG5o4buvbmcgbcOjIGhvw6EgbcOgIFIgc+G7rSBk4bulbmcgY2hvIG5o4buvbmcgYmnhur9uIGdp4bqjLCBiaeG6v24gZ2nhuqMg4bufIMSRw6J5IGzDoCBVcCA9MSBraGkgZGlyZWN0aW9uID0gVXAgdsOgIFVwID0gMCAga2hpIGRpcmVjdGlvbiA9IGRvd24NCmNvbnRyYXN0cyhEaXJlY3Rpb24pDQpgYGANCg0KDQpgYGB7cn0NCiMgWMOhYyB4deG6pXQgeHUgaMaw4bubbmcgdGjhu4sgdHLGsOG7nW5nIHPhur0gxJFpIGzDqm4gKERpcmVjdGlvbiA9IFVwKSBjaG8gMTAgZMOybmcgxJHhuqd1IHRpw6puIGPhu6dhIGThu68gbGnhu4d1DQpnbG0ucHJvYnNbMToxMF0NCmBgYA0KDQpgYGB7cn0NCiNU4bqhbyBt4buZdCB2ZWN0byBnb20gMTI1MCB0aMOgbmggcGjhuqduIGRvd24NCmdsbS5wcmVkPXJlcCgiRG93biIsMTI1MCkNCiNDaHV54buDbiBjw6FjIHRow6BuaCBwaOG6p24gc2FuZyBVcCBraGkgeMOhYyBzdeG6pXQgbOG7m24gaMahbiAwLjUNCmdsbS5wcmVkW2dsbS5wcm9icz4uNV09IlVwIg0KYGBgDQoNCg0KYGBge3J9DQojIETDuW5nIGjDoG0gdGFibGUoKSDEkeG7gyB04bqhbyByYSBt4buZdCBtYSB0cuG6rW4gxJHhu4MgcXV54bq/dCDEkeG7i25oIHhlbSBjw7MgYmFvIG5oacOqdSBxdWFuIHPDoXQgxJHGsOG7o2MgcGjDom4gbG/huqFpIMSRw7puZywgYmFvIG5oacOqdSBi4buLIHBow6JuIGxv4bqhaSBzYWkNCnRhYmxlKGdsbS5wcmVkLERpcmVjdGlvbikNCmBgYA0KDQpU4buJIGzhu4cgc+G7kSBuZ8OgeSBk4buxIMSRb8OhbiDEkcO6bmcgPSAoNTA3KzE0NSkvMTI1MCA9IDAuNTIxNg0KDQpgYGB7cn0NCiMgROG7sSDEkW/DoW4gJXPhu5EgbmfDoHkgZOG7sSDEkW/DoW4gxJHDum5nDQptZWFuKGdsbS5wcmVkPT1EaXJlY3Rpb24pDQpgYGANCg0KSMOgbSBsb2dpc3RpYyBk4buxIMSRb8OhbiDEkcO6bmcgNTIsMTYlIHPhu5EgbmfDoHkNCg0KIyAzKSDDgXAgZOG7pW5nIExvZ2lzdGljIFJlZ3Jlc3Npb24ga2hpIGNoaWEgbmjhu48gdOG6rXAgZOG7ryBsaeG7h3UgdGjDoG5oIDIgdOG6rXAga2nhu4NtIHRyYSB2w6AgaHXhuqVuIGx1eeG7h24ga2jDoWMgbmhhdQ0KDQpgYGB7cn0NCiNWZWN0byB0cmFpbiBn4buTbSAxMjUwIHBo4bqnbiB04burIHTGsMahbmcgxrDhu5tuZyB24bubaSB04bqtcCBk4buvIGxp4buHdSBxdWFuIHPDoXQsIGTDsm5nIG7DoG8gdHJvbmcgZGF0YSBjw7MgeWVhciA8MjAwNSBz4bq9IHRy4bqjIHbhu4EgdHJ1ZSwgY8OybiBs4bqhaSB0cuG6oyB24buBIGZhbHNlDQp0cmFpbj0oWWVhcjwyMDA1KQ0KYGBgDQoNCg0KYGBge3J9DQojIFThuqFvIHJhIG1hIHRy4bqtbiBjb24gY+G7p2EgdOG6rXAgZOG7ryBsaeG7h3UgdMawxqFuZyDEkcawxqFuZyBuaOG7r25nIGdpw6EgdHLhu4sgc2F1IG7Eg20gMjAwNSB0cuG7nyB24buBIHNhdQ0KU21hcmtldC4yMDA1PVNtYXJrZXQgWyF0cmFpbixdDQpgYGANCg0KYGBge3J9DQojIEJhbyBn4buTbSAyNTIgc+G7kSBxdWFuIHPDoXQgdOG7qyBuxINtIDIwMDUgdHLhu58gxJFpDQpkaW0oU21hcmtldC4yMDA1KQ0KYGBgDQoNCmBgYHtyfQ0KIyBU4bqhbyByYSBt4buZdCB2ZWN0b3IgZ+G7k20gMjUyIGdpw6EgdHLhu4sgRGlyZWN0aW9uID0gVXAgaG/hurdjIERvd24gdOG7qyBuxINtIDIwMDUgdHLhu58gxJFpDQpEaXJlY3Rpb24uMjAwNT1EaXJlY3Rpb24gWyF0cmFpbl0NCmBgYA0KDQpgYGB7cn0NCiMgVGjhu7FjIGhp4buHbiBs4bqhaSBo4buTaSBxdWkgbG9naXN0aWMgZOG7sWEgdHLDqm4gdOG6rXAgaHXhuqVuIGx1eeG7h24gKGThu68gbGnhu4d1IHRyxrDhu5tjIDIwMDUpIHbhu5tpIHN1YnNldCA9dHJhaW4gKFllYXIgPCAyMDA1KQ0KZ2xtLmZpdHMgPSBnbG0oRGlyZWN0aW9ufkxhZzEgKyBMYWcyICsgTGFnMyArIExhZzQgKyBMYWc1DQorIFZvbHVtZSAsIGRhdGE9U21hcmtldCAsZmFtaWx5ID0gYmlub21pYWwsc3Vic2V0ID10cmFpbikNCmBgYA0KDQpgYGB7cn0NCiMgSMOgbSBwcmVkaWN0IGTDuW5nIMSR4buDIGThu7EgxJFvw6FuIHjDoWMgc3XhuqV0IHh1IGjGsOG7m25nIHRo4buLIHRyxrDhu51uZyBz4bq9IMSRaSBsw6puIChEaXJlY3R0aW9uID0gVXApIHbhu5tpIHThuq1wIGRhdGEgdOG7qyBuxINtIDIwMDUgdHLhu58gxJFpDQpnbG0ucHJvYnM9cHJlZGljdChnbG0uZml0cyxTbWFya2V0LjIwMDUsdHlwZT0icmVzcG9uc2UiKQ0KYGBgDQoNCg0KYGBge3J9DQojVOG6oW8gbeG7mXQgdmVjdG8gZ29tIDI1MiB0aMOgbmggcGjhuqduIGRvd24gdMawxqFuZyDhu6luZyB24bubaSBz4buRIHF1YW4gc8OhdCB04burIG7Eg20gMjAwNSB0cuG7nyDEkWkNCmdsbS5wcmVkPXJlcCgiRG93biIsMjUyKQ0KYGBgDQoNCmBgYHtyfQ0KI0NodXnhu4NuIGPDoWMgdGjDoG5oIHBo4bqnbiBzYW5nIFVwIGtoaSB4w6FjIHN14bqldCBs4bubbiBoxqFuIDAuNQ0KZ2xtLnByZWRbZ2xtLnByb2JzPi41XT0iVXAiDQpgYGANCg0KDQpgYGB7cn0NCiMgRMO5bmcgaMOgbSB0YWJsZSgpIMSR4buDIHThuqFvIHJhIG3hu5l0IG1hIHRy4bqtbiDEkeG7gyBxdXnhur90IMSR4buLbmggeGVtIGPDsyBiYW8gbmhpw6p1IHF1YW4gc8OhdCDEkcaw4bujYyBwaMOibiBsb+G6oWkgxJHDum5nLCBiYW8gbmhpw6p1IGLhu4sgcGjDom4gbG/huqFpIHNhaQ0KdGFibGUoZ2xtLnByZWQsRGlyZWN0aW9uLjIwMDUpDQpgYGANCg0KQ8OzIDc3ICsgNDQgPSAxMjEgcXVhbiBzw6F0IMSRxrDhu6NjIHBow6JuIGxv4bqhaSDEkcO6bmcNCg0KVOG7iSBs4buHIHPhu5EgbmfDoHkgZOG7sSDEkW/DoW4gxJHDum5nID0gKDc3KzQ0KS8yNTIgPSAwLjQ4MDE1ODcNCg0KYGBge3J9DQojIEThu7EgxJFvw6FuICVz4buRIG5nw6B5IGThu7EgxJFvw6FuIMSRw7puZw0KbWVhbihnbG0ucHJlZD09RGlyZWN0aW9uLjIwMDUpDQpgYGANCg0KYGBge3J9DQojIEThu7EgxJFvw6FuICVz4buRIG5nw6B5IGThu7EgxJFvw6FuIHNhaTogdGVzdCBlcm9yDQptZWFuKGdsbS5wcmVkIT1EaXJlY3Rpb24uMjAwNSkNCmBgYA0KDQpgYGB7cn0NCiMgSMOgbSBzdW1tYXJ5KG1vZGVsMSkgc+G6vSBjaG8gY2jDum5nIHRhIGJp4bq/dCB0aMO0bmcgdGluIHAtdmFsdWVzLCBaLXZhbHVlLCDEkeG7mSBs4buHY2ggY2h14bqpbiBjaG8gbmjhu69uZyBo4buHIHPhu5EgY+G7p2EgY8OhYyBiaeG6v24gxJHhuqd1IHbDoG8NCnN1bW1hcnkoZ2xtLmZpdHMpDQpgYGANCg0KDQpIw6BtIHN1bW1yYXkgY2hvIGJp4bq/dCB0aMO0bmcgdGluIHbhu4EgZ2nDoSB0cuG7iyBjw6FjIGjhu4cgc+G7kSBj4bunYSBtw7QgaMOsbmggKEIwLT5CNiksIHRo4bqleSBy4bqxbmcgTGFnMSBjw7MgaOG7hyBz4buRIG5o4buPIG5o4bqldCA9IDAuMjk1LCANCnR1eSBuaGnDqm4g4bufIGdpw6EgdHLhu4sgMC4yOTUgduG6q24gbMOgIHTGsMahbmcgxJHhu5FpIGzhu5tuLCB2w6wgdGjhur8ga2jDtG5nIGPDsyBi4bqxbmcgY2jhu6luZyB0aOG7kW5nIGvDqiBjaG8gdGjhuqV5IHLhurFuZyBjw7MgbeG7kWkgcXVhbiBo4buHIGdp4buvYSBMYWcxIHbDoCBiaeG6v24gxJHhuqd1IHJhIERpcmVjdGlvbi4NCg0KIyA0KSDDgXAgZOG7pW5nIExvZ2lzdGljIFJlZ3Jlc3Npb24ga2hpIGNoaWEgbmjhu48gdOG6rXAgZOG7ryBsaeG7h3UgdsOgIGNo4buJIGfhu5NtIDIgZ2nDoSB0cuG7iyDEkeG6p3UgdsOgbyBsw6AgYmnhur9uIExhZzEgdsOgIExhZzINCg0KDQpgYGB7cn0NCiNUaOG7sWMgaGnhu4duIGzhuqFpIGPDoWMgYsaw4bubYyB24bubaSBi4buZIGThu68gbGnhu4d1IGNo4buJIGPDsyBMYWcxIHbDoCBMYWcgMiB2w6wgMiBiaeG6v24gbsOgeSBjw7MgcC12YWx1ZSBuaOG7jyBuaOG6pXQNCmdsbS5maXRzID0gZ2xtIChEaXJlY3Rpb25+TGFnMStMYWcyLGRhdGE9U21hcmtldCAsZmFtaWx5ID0NCmJpbm9taWFsICwgc3Vic2V0ID10cmFpbikNCmBgYA0KDQpgYGB7cn0NCiMgSMOgbSBwcmVkaWN0IGTDuW5nIMSR4buDIGThu7EgxJFvw6FuIHjDoWMgc3XhuqV0IHh1IGjGsOG7m25nIHRo4buLIHRyxrDhu51uZyBz4bq9IMSRaSBsw6puIChEaXJlY3R0aW9uID0gVXApIHbhu5tpIHThuq1wIGRhdGEgdOG7qyBuxINtIDIwMDUgdHLhu58gxJFpDQpnbG0ucHJvYnM9cHJlZGljdChnbG0uZml0cyxTbWFya2V0LjIwMDUsdHlwZT0icmVzcG9uc2UiKQ0KYGBgDQoNCg0KYGBge3J9DQojVOG6oW8gbeG7mXQgdmVjdG8gZ29tIDI1MiB0aMOgbmggcGjhuqduIGRvd24gdMawxqFuZyDhu6luZyB24bubaSBz4buRIHF1YW4gc8OhdCB04burIG7Eg20gMjAwNSB0cuG7nyDEkWkNCmdsbS5wcmVkPXJlcCgiRG93biIsMjUyKQ0KYGBgDQoNCmBgYHtyfQ0KI0NodXnhu4NuIGPDoWMgdGjDoG5oIHBo4bqnbiBzYW5nIFVwIGtoaSB4w6FjIHN14bqldCBs4bubbiBoxqFuIDAuNQ0KZ2xtLnByZWRbZ2xtLnByb2JzPi41XT0iVXAiDQpgYGANCg0KDQpgYGB7cn0NCiMgRMO5bmcgaMOgbSB0YWJsZSgpIMSR4buDIHThuqFvIHJhIG3hu5l0IG1hIHRy4bqtbiDEkeG7gyBxdXnhur90IMSR4buLbmggeGVtIGPDsyBiYW8gbmhpw6p1IHF1YW4gc8OhdCDEkcaw4bujYyBwaMOibiBsb+G6oWkgxJHDum5nLCBiYW8gbmhpw6p1IGLhu4sgcGjDom4gbG/huqFpIHNhaQ0KdGFibGUoZ2xtLnByZWQsRGlyZWN0aW9uLjIwMDUpDQpgYGANCg0KQ8OzIDM1ICsgMTA2ID0gMTQxIHF1YW4gc8OhdCDEkcaw4bujYyBwaMOibiBsb+G6oWkgxJHDum5nDQoNClThu4kgbOG7hyBz4buRIG5nw6B5IGThu7EgxJFvw6FuIMSRw7puZyA9ICgzNSsxMDYpLzI1MiA9IDAuNTU5NTIzOA0KDQoNCmBgYHtyfQ0KIyBE4buxIMSRb8OhbiAlc+G7kSBuZ8OgeSBk4buxIMSRb8OhbiDEkcO6bmcNCm1lYW4oZ2xtLnByZWQ9PURpcmVjdGlvbi4yMDA1KQ0KYGBgDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg==