Tên: Mai Huy

MSSV: 43.01.104.065

Số thứ tự: 08

1) Nhập thư viện và tìm hiểu tập dữ liệu

# Load thư viện Mass chứa tập dữ liệu Boston
library(MASS)
# Liệt kê tên các biến thuộc tính của dữ liệu Boston
names(Boston)
 [1] "crim"    "zn"      "indus"   "chas"    "nox"     "rm"      "age"     "dis"     "rad"     "tax"    
[11] "ptratio" "black"   "lstat"   "medv"   
# Tìm hiểu thêm về thông tin tập dữ liệu Boston
?Boston

Sử dụng câu lệnh ?Boston giúp chúng ta tìm hiểu rõ hơn về các biến thuộc tính trong dữ liệu Boston (có 506 dòng và 14 cột), chẳng hạn như là:

2) Phân tích, dự đoán, cách thức hoạt động một mô hình hồi quy đơn giản

# lm(medv~lstat) là hàm dùng để fit một mô hình hồi quy tuyến tính đơn giản với medv là giá trị đầu ra cần được dự đoán  và lstat là giá trị đầu vào trong tập dữ liệu Boston
# Tuy nhiên hệ thống sẽ báo lỗi do R không nhận dạng được 2 biến medv và lstat 
lm.fit=lm(medv~lstat)
Error in eval(predvars, data, env) : object 'medv' not found
# Do đó chúng ta cần truyền vào tập dữ liệu Boston để R có nhận dạng được 2 biến medv và lstat
# R đã nhận dạng được 2 biến medv và lstat trong dữ liệu Boston
lm.fit=lm(medv~lstat, data=Boston)

Dưới đây là cách không cần truyền vào tập dữ liệu Boston nhưng R vẫn có thể nhận dạng được các biến của dữ liệu

# attach dùng để khiến cho những biến feature trong dữ liệu có sẵn trong Rstudio theo tên
attach(Boston)
# Giờ đây hàm lm() vẫn có thể sử dụng được khi không cần truyền vào tập dữ liệu nào cả 
lm.fit=lm(medv~lstat)
# Biến lm.fit dùng để hiển thị một số thông tin cơ bản về mô hình đầu ra như thông tin về hàm lm() đã sử dũng trước đó cũng như là những hệ số B0 = 34.55 và B1= -0.95 với medv = 34.55-0.95 lstat
lm.fit

Call:
lm(formula = medv ~ lstat)

Coefficients:
(Intercept)        lstat  
      34.55        -0.95  
# Và để hiển thị thông tin chi tiết hơn , chúng ta sử dụng hàm summary(lm.fit)
# Hàm sẽ cho chúng ta biết thông tin về p-values, thống kê t(t-statistic), độ lệch chuẩn cho những hệ số của biến lstat , cũng như là thống kê R^2, sai số chuẩn (standard errors) và thống kê F (F-statistic) cho mô hình
summary(lm.fit)

Call:
lm(formula = medv ~ lstat)

Residuals:
    Min      1Q  Median      3Q     Max 
-15.168  -3.990  -1.318   2.034  24.500 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 34.55384    0.56263   61.41   <2e-16 ***
lstat       -0.95005    0.03873  -24.53   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 6.216 on 504 degrees of freedom
Multiple R-squared:  0.5441,    Adjusted R-squared:  0.5432 
F-statistic: 601.6 on 1 and 504 DF,  p-value: < 2.2e-16
# Xem các biến được lưu trữ trong lm.fit
names(lm.fit)
 [1] "coefficients"  "residuals"     "effects"       "rank"          "fitted.values" "assign"       
 [7] "qr"            "df.residual"   "xlevels"       "call"          "terms"         "model"        
# Xem giá trị của biến hệ số (coefficients) cho biết thông tin về B0 và B1
lm.fit$coefficients
(Intercept)       lstat 
 34.5538409  -0.9500494 
# Cũng được dùng để Xem giá trị của biến hệ số (coefficients) cho biết thông tin về B0 và B1
coef(lm.fit)
(Intercept)       lstat 
 34.5538409  -0.9500494 
# Hàm confint cho biết khoảng tin cậy của các hệ số B0 và B1 đang ước lượng
confint(lm.fit)
                2.5 %     97.5 %
(Intercept) 33.448457 35.6592247
lstat       -1.026148 -0.8739505

Hàm predict tạo ra khoảng tin cậy

# Cột fit là giá trị medv được dự đoán khi đưa vào dữ liệu (data) mới là biến lstat được gán cho 3 giá trị lần lượt là 5,10,15, lwr và upr là khoảng trên và khoảng dưới của khoảng tin cậy.
predict(lm.fit, data.frame(lstat=c(5,10,15)), interval="confidence")
       fit      lwr      upr
1 29.80359 29.00741 30.59978
2 25.05335 24.47413 25.63256
3 20.30310 19.73159 20.87461

Hàm predict tạo ra khoảng dự đoán

# Cột fit là giá trị medv được dự đoán khi đưa vào dữ liệu (data) mới là biến lstat được gán cho 3 giá trị lần lượt là 5,10,15, lwr và upr là khoảng trên và khoảng dưới của khoảng dự đoán.
predict(lm.fit, data.frame(lstat=c(5,10,15)),
interval="prediction")
       fit       lwr      upr
1 29.80359 17.565675 42.04151
2 25.05335 12.827626 37.27907
3 20.30310  8.077742 32.52846

3) Biểu đồ phân tán minh hoạ mô hình hồi quy đơn giản

# attach dùng để khiến cho những biến feature trong dữ liệu có sẵn trong Rstudio theo tên
attach(Boston)
The following objects are masked from Boston (pos = 3):

    age, black, chas, crim, dis, indus, lstat, medv, nox, ptratio, rad, rm, tax, zn

The following objects are masked from Boston (pos = 4):

    age, black, chas, crim, dis, indus, lstat, medv, nox, ptratio, rad, rm, tax, zn

The following objects are masked from Boston (pos = 5):

    age, black, chas, crim, dis, indus, lstat, medv, nox, ptratio, rad, rm, tax, zn

The following objects are masked from Boston (pos = 6):

    age, black, chas, crim, dis, indus, lstat, medv, nox, ptratio, rad, rm, tax, zn

The following objects are masked from Boston (pos = 7):

    age, black, chas, crim, dis, indus, lstat, medv, nox, ptratio, rad, rm, tax, zn
# Hàm plot để tạo một đồ thị phân tán với giá trị đầu vào x= lstat và đầu ra y= medv
plot(lstat,medv)
# abline tạo ra 1 đường tuyến tính fit với mô hình hồi quy hiện tại với giá trị đầu vào là lstat và đầu ra là medv
abline(lm.fit)
# Điều chỉnh độ rộng hay độ dày của đường tuyến tính để chúng ta nhìn thấy đường thẳng rõ nét hơn
abline(lm.fit,lwd=3)

# Điều chỉnh độ rộng hay độ dày của đường tuyến tính để chúng ta nhìn thấy đường thẳng rõ nét hơn
plot(lstat,medv)
abline(lm.fit,lwd=3)

# Thay đổi màu sắc đường tuyến tính thành màu đỏ
plot(lstat,medv)
abline(lm.fit,lwd=3,col="red")

# Thay đổi các điểm dữ liệu của đồ thị phân tán thành màu xanh với đầu vào là lstat và đầu ra là medv 
plot(lstat,medv,col="blue")

# Thay đổi hình dạng những điểm dữ liệu dưới dạng những viên đạn và có vòng tròn nhỏ hơn
plot(lstat,medv,pch=20)

# Thay đổi hình dạng những điểm dữ liệu những dấu + 
plot(lstat,medv,pch="+")

# Biểu diễn những điểm dữ liệu với x và y từ 1->20 và hình dạng những điểm dữ liệu cũng thay đổi liên tục từ dạng 1->20
plot(1:20,1:20,pch=1:20)

#Biểu đồ phân tán của các biến  dữ liệu với các dữ liệu cột được chia thành cửa sổ 2x2 bằng cách sử dụng hàm mfrow=c(2,2)
par(mfrow=c(2,2))

plot(lm.fit)

# Mô hình phân tán điểm dữ liệu được dự đoán và giá trị sai lệch dư thừa được tính từ mô hình hồi quy sử dụng hàm residuals()
plot(predict(lm.fit),residuals(lm.fit))

# Mô hình phân tán điểm dữ liệu được dự đoán và giá trị sai lệch dư thừa được tính từ phân phối student sử dụng hàm rstudent()
plot(predict(lm.fit),rstudent(lm.fit))

#Trên cơ sở các mô hình plot các giá trị dư thừa, có một số bằng chứng về phi tuyến tính. Thống kê đòn bẩy(leverage statistics) có thể được tính cho bất kỳ giá trị dự đoán nào bằng cách sử dụng Hàm hatvalues ()
plot(hatvalues(lm.fit))

# Chỉ mục cho chúng ta dòng nào có giá trị thống kê đòn đòn bẩy (leverage statistics) là lớn nhất
which.max(hatvalues(lm.fit))
375 
375 
LS0tDQp0aXRsZTogIk3DtCBow6xuaCBo4buTaSBxdXkgdHV54bq/biB0w61uaCDEkcahbiBnaeG6o24iDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQoNCiMjIyBUw6puOiBNYWkgSHV5DQojIyMgTVNTVjogNDMuMDEuMTA0LjA2NQ0KIyMjIFPhu5EgdGjhu6kgdOG7sTogMDgNCg0KIyAxKSBOaOG6rXAgdGjGsCB2aeG7h24gdsOgIHTDrG0gaGnhu4N1IHThuq1wIGThu68gbGnhu4d1DQoNCmBgYHtyfQ0KIyBMb2FkIHRoxrAgdmnhu4duIE1hc3MgY2jhu6lhIHThuq1wIGThu68gbGnhu4d1IEJvc3Rvbg0KbGlicmFyeShNQVNTKQ0KIyBMaeG7h3Qga8OqIHTDqm4gY8OhYyBiaeG6v24gdGh14buZYyB0w61uaCBj4bunYSBk4buvIGxp4buHdSBCb3N0b24NCm5hbWVzKEJvc3RvbikNCiMgVMOsbSBoaeG7g3UgdGjDqm0gduG7gSB0aMO0bmcgdGluIHThuq1wIGThu68gbGnhu4d1IEJvc3Rvbg0KP0Jvc3Rvbg0KDQpgYGANCg0KU+G7rSBk4bulbmcgY8OidSBs4buHbmggP0Jvc3RvbiBnacO6cCBjaMO6bmcgdGEgdMOsbSBoaeG7g3UgcsO1IGjGoW4gduG7gSBjw6FjIGJp4bq/biB0aHXhu5ljIHTDrW5oIHRyb25nIGThu68gbGnhu4d1IEJvc3RvbiAoY8OzIDUwNiBkw7JuZyB2w6AgMTQgY+G7mXQpLCBjaOG6s25nIGjhuqFuIG5oxrAgbMOgOg0KDQogIC0gbWVkdiBsw6AgZ2nDoSB0cuG7iyBuaMOgIGPhu61hIHRydW5nIGLDrG5oDQogIA0KICAtIHJtIGzDoCBz4buRIHBow7JuZyB0cnVuZyBiw6xuaCBt4buXaSBuaMOgDQogIA0KICAtIGFnZSBsw6AgdHJ1bmcgYsOsbmggxJHhu5kgdHXhu5VpIGPhu6dhIGPDoWMgY8SDbiBuaMOgDQogIA0KICAtIGxzdGF0IGzDoCB04buJIGzhu4cgaOG7mSBnaWEgxJHDrG5oIGPDsyDEkeG7i2EgduG7iyBraW5oIHThur8geMOjIGjhu5lpIHRo4bqlcA0KDQoNCiMgMikgUGjDom4gdMOtY2gsIGThu7EgxJFvw6FuLCBjw6FjaCB0aOG7qWMgaG/huqF0IMSR4buZbmcgbeG7mXQgbcO0IGjDrG5oIGjhu5NpIHF1eSDEkcahbiBnaeG6o24NCg0KDQpgYGB7cn0NCiMgbG0obWVkdn5sc3RhdCkgbMOgIGjDoG0gZMO5bmcgxJHhu4MgZml0IG3hu5l0IG3DtCBow6xuaCBo4buTaSBxdXkgdHV54bq/biB0w61uaCDEkcahbiBnaeG6o24gduG7m2kgbWVkdiBsw6AgZ2nDoSB0cuG7iyDEkeG6p3UgcmEgY+G6p24gxJHGsOG7o2MgZOG7sSDEkW/DoW4gIHbDoCBsc3RhdCBsw6AgZ2nDoSB0cuG7iyDEkeG6p3UgdsOgbyB0cm9uZyB04bqtcCBk4buvIGxp4buHdSBCb3N0b24NCiMgVHV5IG5oacOqbiBo4buHIHRo4buRbmcgc+G6vSBiw6FvIGzhu5dpIGRvIFIga2jDtG5nIG5o4bqtbiBk4bqhbmcgxJHGsOG7o2MgMiBiaeG6v24gbWVkdiB2w6AgbHN0YXQgDQpsbS5maXQ9bG0obWVkdn5sc3RhdCkNCmBgYA0KDQoNCg0KYGBge3J9DQojIERvIMSRw7MgY2jDum5nIHRhIGPhuqduIHRydXnhu4FuIHbDoG8gdOG6rXAgZOG7ryBsaeG7h3UgQm9zdG9uIMSR4buDIFIgY8OzIG5o4bqtbiBk4bqhbmcgxJHGsOG7o2MgMiBiaeG6v24gbWVkdiB2w6AgbHN0YXQNCiMgUiDEkcOjIG5o4bqtbiBk4bqhbmcgxJHGsOG7o2MgMiBiaeG6v24gbWVkdiB2w6AgbHN0YXQgdHJvbmcgZOG7ryBsaeG7h3UgQm9zdG9uDQpsbS5maXQ9bG0obWVkdn5sc3RhdCwgZGF0YT1Cb3N0b24pDQpgYGANCg0KIyMjIETGsOG7m2kgxJHDonkgbMOgIGPDoWNoIGtow7RuZyBj4bqnbiB0cnV54buBbiB2w6BvIHThuq1wIGThu68gbGnhu4d1IEJvc3RvbiBuaMawbmcgUiB24bqrbiBjw7MgdGjhu4Mgbmjhuq1uIGThuqFuZyDEkcaw4bujYyBjw6FjIGJp4bq/biBj4bunYSBk4buvIGxp4buHdQ0KDQpgYGB7cn0NCiMgYXR0YWNoIGTDuW5nIMSR4buDIGtoaeG6v24gY2hvIG5o4buvbmcgYmnhur9uIGZlYXR1cmUgdHJvbmcgZOG7ryBsaeG7h3UgY8OzIHPhurVuIHRyb25nIFJzdHVkaW8gdGhlbyB0w6puDQphdHRhY2goQm9zdG9uKQ0KIyBHaeG7nSDEkcOieSBow6BtIGxtKCkgduG6q24gY8OzIHRo4buDIHPhu60gZOG7pW5nIMSRxrDhu6NjIGtoaSBraMO0bmcgY+G6p24gdHJ1eeG7gW4gdsOgbyB04bqtcCBk4buvIGxp4buHdSBuw6BvIGPhuqMgDQpsbS5maXQ9bG0obWVkdn5sc3RhdCkNCmBgYA0KDQoNCmBgYHtyfQ0KIyBCaeG6v24gbG0uZml0IGTDuW5nIMSR4buDIGhp4buDbiB0aOG7iyBt4buZdCBz4buRIHRow7RuZyB0aW4gY8ahIGLhuqNuIHbhu4EgbcO0IGjDrG5oIMSR4bqndSByYSBuaMawIHRow7RuZyB0aW4gduG7gSBow6BtIGxtKCkgxJHDoyBz4butIGTFqW5nIHRyxrDhu5tjIMSRw7MgY8WpbmcgbmjGsCBsw6Agbmjhu69uZyBo4buHIHPhu5EgQjAgPSAzNC41NSB2w6AgQjE9IC0wLjk1IHbhu5tpIG1lZHYgPSAzNC41NS0wLjk1IGxzdGF0DQpsbS5maXQNCmBgYA0KDQpgYGB7cn0NCiMgVsOgIMSR4buDIGhp4buDbiB0aOG7iyB0aMO0bmcgdGluIGNoaSB0aeG6v3QgaMahbiAsIGNow7puZyB0YSBz4butIGThu6VuZyBow6BtIHN1bW1hcnkobG0uZml0KQ0KIyBIw6BtIHPhur0gY2hvIGNow7puZyB0YSBiaeG6v3QgdGjDtG5nIHRpbiB24buBIHAtdmFsdWVzLCB0aOG7kW5nIGvDqiB0KHQtc3RhdGlzdGljKSwgxJHhu5kgbOG7h2NoIGNodeG6qW4gY2hvIG5o4buvbmcgaOG7hyBz4buRIGPhu6dhIGJp4bq/biBsc3RhdCAsIGPFqW5nIG5oxrAgbMOgIHRo4buRbmcga8OqIFJeMiwgc2FpIHPhu5EgY2h14bqpbiAoc3RhbmRhcmQgZXJyb3JzKSB2w6AgdGjhu5FuZyBrw6ogRiAoRi1zdGF0aXN0aWMpIGNobyBtw7QgaMOsbmgNCnN1bW1hcnkobG0uZml0KQ0KYGBgDQoNCmBgYHtyfQ0KIyBYZW0gY8OhYyBiaeG6v24gxJHGsOG7o2MgbMawdSB0cuG7ryB0cm9uZyBsbS5maXQNCm5hbWVzKGxtLmZpdCkNCiMgWGVtIGdpw6EgdHLhu4sgY+G7p2EgYmnhur9uIGjhu4cgc+G7kSAoY29lZmZpY2llbnRzKSBjaG8gYmnhur90IHRow7RuZyB0aW4gduG7gSBCMCB2w6AgQjENCmxtLmZpdCRjb2VmZmljaWVudHMNCmBgYA0KDQpgYGB7cn0NCiMgQ8WpbmcgxJHGsOG7o2MgZMO5bmcgxJHhu4MgWGVtIGdpw6EgdHLhu4sgY+G7p2EgYmnhur9uIGjhu4cgc+G7kSAoY29lZmZpY2llbnRzKSBjaG8gYmnhur90IHRow7RuZyB0aW4gduG7gSBCMCB2w6AgQjENCmNvZWYobG0uZml0KQ0KYGBgDQoNCmBgYHtyfQ0KIyBIw6BtIGNvbmZpbnQgY2hvIGJp4bq/dCBraG/huqNuZyB0aW4gY+G6rXkgY+G7p2EgY8OhYyBo4buHIHPhu5EgQjAgdsOgIEIxIMSRYW5nIMaw4bubYyBsxrDhu6NuZw0KY29uZmludChsbS5maXQpDQpgYGANCg0KIyMjIEjDoG0gcHJlZGljdCB04bqhbyByYSBraG/huqNuZyB0aW4gY+G6rXkgDQoNCmBgYHtyfQ0KIyBD4buZdCBmaXQgbMOgIGdpw6EgdHLhu4sgbWVkdiDEkcaw4bujYyBk4buxIMSRb8OhbiBraGkgxJHGsGEgdsOgbyBk4buvIGxp4buHdSAoZGF0YSkgbeG7m2kgbMOgIGJp4bq/biBsc3RhdCDEkcaw4bujYyBnw6FuIGNobyAzIGdpw6EgdHLhu4sgbOG6p24gbMaw4bujdCBsw6AgNSwxMCwxNSwgbHdyIHbDoCB1cHIgbMOgIGtob+G6o25nIHRyw6puIHbDoCBraG/huqNuZyBkxrDhu5tpIGPhu6dhIGtob+G6o25nIHRpbiBj4bqteS4NCnByZWRpY3QobG0uZml0LCBkYXRhLmZyYW1lKGxzdGF0PWMoNSwxMCwxNSkpLCBpbnRlcnZhbD0iY29uZmlkZW5jZSIpDQpgYGANCg0KIyMjIEjDoG0gcHJlZGljdCB04bqhbyByYSBraG/huqNuZyBk4buxIMSRb8Ohbg0KDQpgYGB7cn0NCiMgQ+G7mXQgZml0IGzDoCBnacOhIHRy4buLIG1lZHYgxJHGsOG7o2MgZOG7sSDEkW/DoW4ga2hpIMSRxrBhIHbDoG8gZOG7ryBsaeG7h3UgKGRhdGEpIG3hu5tpIGzDoCBiaeG6v24gbHN0YXQgxJHGsOG7o2MgZ8OhbiBjaG8gMyBnacOhIHRy4buLIGzhuqduIGzGsOG7o3QgbMOgIDUsMTAsMTUsIGx3ciB2w6AgdXByIGzDoCBraG/huqNuZyB0csOqbiB2w6Aga2hv4bqjbmcgZMaw4bubaSBj4bunYSBraG/huqNuZyBk4buxIMSRb8Ohbi4NCnByZWRpY3QobG0uZml0LCBkYXRhLmZyYW1lKGxzdGF0PWMoNSwxMCwxNSkpLA0KaW50ZXJ2YWw9InByZWRpY3Rpb24iKQ0KYGBgDQoNCiMgMykgQmnhu4N1IMSR4buTIHBow6JuIHTDoW4gbWluaCBob+G6oSBtw7QgaMOsbmggaOG7k2kgcXV5IMSRxqFuIGdp4bqjbg0KDQpgYGB7cn0NCiMgYXR0YWNoIGTDuW5nIMSR4buDIGtoaeG6v24gY2hvIG5o4buvbmcgYmnhur9uIGZlYXR1cmUgdHJvbmcgZOG7ryBsaeG7h3UgY8OzIHPhurVuIHRyb25nIFJzdHVkaW8gdGhlbyB0w6puDQphdHRhY2goQm9zdG9uKQ0KIyBIw6BtIHBsb3QgxJHhu4MgdOG6oW8gbeG7mXQgxJHhu5MgdGjhu4sgcGjDom4gdMOhbiB24bubaSBnacOhIHRy4buLIMSR4bqndSB2w6BvIHg9IGxzdGF0IHbDoCDEkeG6p3UgcmEgeT0gbWVkdg0KcGxvdChsc3RhdCxtZWR2KQ0KIyBhYmxpbmUgdOG6oW8gcmEgMSDEkcaw4budbmcgdHV54bq/biB0w61uaCBmaXQgduG7m2kgbcO0IGjDrG5oIGjhu5NpIHF1eSBoaeG7h24gdOG6oWkgduG7m2kgZ2nDoSB0cuG7iyDEkeG6p3UgdsOgbyBsw6AgbHN0YXQgdsOgIMSR4bqndSByYSBsw6AgbWVkdg0KYWJsaW5lKGxtLmZpdCkNCiMgxJBp4buBdSBjaOG7iW5oIMSR4buZIHLhu5luZyBoYXkgxJHhu5kgZMOgeSBj4bunYSDEkcaw4budbmcgdHV54bq/biB0w61uaCDEkeG7gyBjaMO6bmcgdGEgbmjDrG4gdGjhuqV5IMSRxrDhu51uZyB0aOG6s25nIHLDtSBuw6l0IGjGoW4NCmFibGluZShsbS5maXQsbHdkPTMpDQojIMSQaeG7gXUgY2jhu4luaCBtw6B1IHNhbg0KDQpgYGANCg0KYGBge3J9DQojIMSQaeG7gXUgY2jhu4luaCDEkeG7mSBy4buZbmcgaGF5IMSR4buZIGTDoHkgY+G7p2EgxJHGsOG7nW5nIHR1eeG6v24gdMOtbmggPTMgxJHhu4MgY2jDum5nIHRhIG5ow6xuIHRo4bqleSDEkcaw4budbmcgdGjhurNuZyByw7UgbsOpdCBoxqFuDQpwbG90KGxzdGF0LG1lZHYpDQphYmxpbmUobG0uZml0LGx3ZD0zKQ0KYGBgDQoNCmBgYHtyfQ0KIyBUaGF5IMSR4buVaSBtw6B1IHPhuq9jIMSRxrDhu51uZyB0dXnhur9uIHTDrW5oIHRow6BuaCBtw6B1IMSR4buPDQpwbG90KGxzdGF0LG1lZHYpDQphYmxpbmUobG0uZml0LGx3ZD0zLGNvbD0icmVkIikNCmBgYA0KDQpgYGB7cn0NCiMgVGhheSDEkeG7lWkgY8OhYyDEkWnhu4NtIGThu68gbGnhu4d1IGPhu6dhIMSR4buTIHRo4buLIHBow6JuIHTDoW4gdGjDoG5oIG3DoHUgeGFuaCB24bubaSDEkeG6p3UgdsOgbyBsw6AgbHN0YXQgdsOgIMSR4bqndSByYSBsw6AgbWVkdiANCnBsb3QobHN0YXQsbWVkdixjb2w9ImJsdWUiKQ0KIyBUaGF5IMSR4buVaSBow6xuaCBk4bqhbmcgbmjhu69uZyDEkWnhu4NtIGThu68gbGnhu4d1IGTGsOG7m2kgZOG6oW5nIG5o4buvbmcgdmnDqm4gxJHhuqFuIHbDoCBjw7MgdsOybmcgdHLDsm4gbmjhu48gaMahbg0KcGxvdChsc3RhdCxtZWR2LHBjaD0yMCkNCiMgVGhheSDEkeG7lWkgaMOsbmggZOG6oW5nIG5o4buvbmcgxJFp4buDbSBk4buvIGxp4buHdSBuaOG7r25nIGThuqV1ICsgDQpwbG90KGxzdGF0LG1lZHYscGNoPSIrIikNCiMgQmnhu4N1IGRp4buFbiBuaOG7r25nIMSRaeG7g20gZOG7ryBsaeG7h3UgduG7m2kgeCB2w6AgeSB04burIDEtPjIwIHbDoCBow6xuaCBk4bqhbmcgbmjhu69uZyDEkWnhu4NtIGThu68gbGnhu4d1IGPFqW5nIHRoYXkgxJHhu5VpIGxpw6puIHThu6VjIHThu6sgZOG6oW5nIDEtPjIwDQpwbG90KDE6MjAsMToyMCxwY2g9MToyMCkNCmBgYA0KDQoNCmBgYHtyfQ0KI0Jp4buDdSDEkeG7kyBwaMOibiB0w6FuIGPhu6dhIGPDoWMgYmnhur9uICBk4buvIGxp4buHdSB24bubaSBjw6FjIGThu68gbGnhu4d1IGPhu5l0IMSRxrDhu6NjIGNoaWEgdGjDoG5oIGPhu61hIHPhu5UgMngyIGLhurFuZyBjw6FjaCBz4butIGThu6VuZyBow6BtIG1mcm93PWMoMiwyKQ0KcGFyKG1mcm93PWMoMiwyKSkNCiMgUGxvdCA0IGJp4buDdSDEkeG7kyBjaOG6qW4gxJFvw6FuIA0KcGxvdChsbS5maXQpDQpgYGANCg0KLSBCaeG7g3UgxJHhu5MgMSAoUmVzaWR1YWxzIHZzIEZpdHRlZCkgZ2nDunAgcXVhbiBzw6F0IG5o4buvbmcgxJFp4buDbSBnacOhIHRy4buLIMSRxrDhu6NjIGThu7EgxJFvw6FuKGZpdCkgdsOgIGdpw6EgdHLhu4sgc2FpIGzhu4djaCBkxrAgdGjhu6thIGPhu6dhIG5o4buvbmcgxJFp4buDbSBk4buxIMSRb8OhbiBuw6B5IHNvIHbhu5tpIG5o4buvbmcgxJFp4buDbSB0aOG6rXQNCg0KLSBCaeG7g3UgxJHhu5MgMiAoTm9ybWFsIFEtUSkgZ2nDunAgc28gc8OhbmggMiBwaMOibiBwaOG7kWkgeMOhYyBzdeG6pXQgYuG6sW5nIGPDoWNoIHbhur0gY8OhYyBsxrDhu6NuZyB04butIGPhu6dhIGNow7puZyB24bubaSBuaGF1IA0KDQotIEJp4buDdSDEkeG7kyAzIChTY2FsZS0gTG9jYXRpb24pIHTGsMahbmcgdOG7sSBuaMawIGJp4buDdSDEkeG7kyAxIG5oxrBuZyBraMOhYyBsw6AgbOG6pXkgY8SDbiBi4bqtYyAyIGdpw6EgdHLhu4sgZMawIHRo4burYSBjaHXhuqluIGhvw6ENCg0KLSBCaeG7g3UgxJHhu5MgNCAoUmVzaWR1YWxzIHZzIExldmVyYWdlKSBnacO6cCBwaMOhdCBoaeG7h24gbmjhu69uZyBuZ2/huqFpIGzhu4cgdHJvbmcgbcO0IGjDrG5oIGjhu5NpIHF1eSDEkcahbiBnaeG6o24sIGNobyBwaMOpcCBxdWFuIHPDoXQgc+G7sSBsYW4gcuG7mW5nIGPhu6dhIG5o4buvbmcga2hv4bqjbmcgZMawIHRo4burYSB0aGF5IMSR4buVaSB0aGVvIGdpw6EgdHLhu4sgbGV2ZXJhZ2UoIHPhu7EgbmjhuqF5IGPhuqNtIGPhu6dhIGdpw6EgdHLhu4sgZOG7sSBkb8OhbiDEkeG7kWkgduG7m2kgc+G7sSB0aGF5IMSR4buVaSBj4bunYSBuaOG7r25nIGdpw6EgdHLhu4sgdGjhuq10KQ0KDQpgYGB7cn0NCiMgTcO0IGjDrG5oIHBow6JuIHTDoW4gxJFp4buDbSBk4buvIGxp4buHdSDEkcaw4bujYyBk4buxIMSRb8OhbiB2w6AgZ2nDoSB0cuG7iyBzYWkgbOG7h2NoIGTGsCB0aOG7q2EgxJHGsOG7o2MgdMOtbmggdOG7qyBtw7QgaMOsbmggaOG7k2kgcXV5IHPhu60gZOG7pW5nIGjDoG0gcmVzaWR1YWxzKCkNCnBsb3QocHJlZGljdChsbS5maXQpLHJlc2lkdWFscyhsbS5maXQpKQ0KYGBgDQoNCmBgYHtyfQ0KIyBNw7QgaMOsbmggcGjDom4gdMOhbiDEkWnhu4NtIGThu68gbGnhu4d1IMSRxrDhu6NjIGThu7EgxJFvw6FuIHbDoCBnacOhIHRy4buLIHNhaSBs4buHY2ggZMawIHRo4burYSDEkcaw4bujYyB0w61uaCB04burIHBow6JuIHBo4buRaSBzdHVkZW50IHPhu60gZOG7pW5nIGjDoG0gcnN0dWRlbnQoKQ0KcGxvdChwcmVkaWN0KGxtLmZpdCkscnN0dWRlbnQobG0uZml0KSkNCmBgYA0KDQpgYGB7cn0NCiNUcsOqbiBjxqEgc+G7nyBjw6FjIG3DtCBow6xuaCBwbG90IGPDoWMgZ2nDoSB0cuG7iyBkxrAgdGjhu6thLCBjw7MgbeG7mXQgc+G7kSBi4bqxbmcgY2jhu6luZyB24buBIHBoaSB0dXnhur9uIHTDrW5oLiBUaOG7kW5nIGvDqiDEkcOybiBi4bqpeShsZXZlcmFnZSBzdGF0aXN0aWNzKSBjw7MgdGjhu4MgxJHGsOG7o2MgdMOtbmggY2hvIGLhuqV0IGvhu7MgZ2nDoSB0cuG7iyBk4buxIMSRb8OhbiBuw6BvIGLhurFuZyBjw6FjaCBz4butIGThu6VuZyBIw6BtIGhhdHZhbHVlcyALCygpDQpwbG90KGhhdHZhbHVlcyhsbS5maXQpKQ0KYGBgDQoNCmBgYHtyfQ0KIyBDaOG7iSBt4bulYyBjaG8gY2jDum5nIHRhIGTDsm5nIG7DoG8gY8OzIGdpw6EgdHLhu4sgdGjhu5FuZyBrw6ogxJHDsm4gxJHDsm4gYuG6qXkgKGxldmVyYWdlIHN0YXRpc3RpY3MpIGzDoCBs4bubbiBuaOG6pXQNCndoaWNoLm1heChoYXR2YWx1ZXMobG0uZml0KSkNCmBgYA0KDQo=