Email             :
RPubs            : https://www.rpubs.com/muhammad_naufal/
Jurusan          : Statistika Bisnis
Address         : Jalan Gunung Galunggung 5 Blok E9, No.21


1 Pendahuluan

Klasifikasi adalah proses pengelompokan objek atau data ke dalam kategori atau kelas berdasarkan ciri-ciri atau atribut tertentu. Metode klasifikasi merupakan algoritma atau teknik yang digunakan untuk melakukan proses klasifikasi tersebut.

Keterangan umum terkait metode Klasifikasi adalah sebagai berikut:

  • K-Nearest Neighbors (K-NN): Metode ini mengklasifikasikan objek berdasarkan mayoritas kelas tetangga terdekatnya. Jika suatu objek memiliki sebagian besar tetangga dari suatu kelas tertentu, maka objek tersebut diklasifikasikan ke dalam kelas tersebut.
  • Decision Trees: Decision trees adalah model prediktif yang menggunakan struktur pohon keputusan untuk melakukan klasifikasi. Pada setiap simpul pohon, keputusan dibuat berdasarkan nilai dari suatu atribut.
  • Naive Bayes: Metode klasifikasi ini berdasarkan teorema Bayes dengan asumsi independensi antara setiap pasangan atribut. Meskipun sederhana, Naive Bayes sering kali efektif dan cepat, terutama untuk dataset dengan jumlah atribut yang besar.
  • Support Vector Machines (SVM): SVM mencari hyperplane terbaik yang memisahkan dua kelas dalam ruang atribut. Tujuan utamanya adalah untuk mencari hyperplane yang memiliki margin terbesar antara dua kelas.
  • Random Forest: Random Forest adalah teknik ensemble learning yang menggabungkan banyak decision trees ke dalam satu model. Setiap decision tree dibangun secara independen, dan hasil klasifikasi akhir diperoleh dengan mengambil mayoritas suara dari semua pohon.
  • Neural Networks: Jaringan saraf tiruan (Neural Networks) adalah model komputasi yang terdiri dari neuron-neuron yang saling terhubung. Dalam konteks klasifikasi, neural networks dapat digunakan sebagai metode yang sangat kuat untuk mempelajari pola-pola yang kompleks dari data.
  • Logistic Regression: Logistic regression adalah metode statistik yang digunakan untuk klasifikasi biner, di mana model berusaha memprediksi probabilitas masuk ke dalam salah satu dari dua kelas.
  • Gradient Boosting Machines (GBM): Menggabungkan beberapa model lemah (misalnya, decision trees) secara bertahap untuk meningkatkan kinerja.
  • AdaBoost: Membuat model yang berurutan, di mana setiap model mencoba untuk memperbaiki kesalahan yang dilakukan oleh model sebelumnyaGradient Boosting Machines (GBM): Menggabungkan beberapa model lemah (misalnya, decision trees) secara bertahap untuk meningkatkan kinerja.
  • Ensemble Methods: Ensemble methods menggabungkan prediksi dari beberapa model klasifikasi untuk meningkatkan kinerja prediksi. Contoh lain dari ensemble methods adalah Boosting dan Bagging.

Setiap metode klasifikasi memiliki kelebihan dan kelemahan tertentu tergantung pada sifat data yang dihadapi dan tujuan dari klasifikasi tersebut. Pemilihan metode klasifikasi yang tepat memerlukan pemahaman yang baik tentang data yang digunakan serta eksperimen untuk menentukan metode yang paling cocok untuk kasus tertentu.

2 Decision Trees

Decision Trees (Pohon Keputusan) adalah model pembelajaran mesin yang sangat populer untuk tugas klasifikasi dan regresi. Mereka menghasilkan model yang mudah dipahami dan mudah diinterpretasikan, mirip dengan logika manusia.

2.1 Proses Kerja Decision Trees

Decision Trees (Pohon Keputusan) adalah algoritma pembelajaran mesin yang menggunakan struktur pohon berhierarki untuk melakukan prediksi. Di bawah ini adalah langkah-langkah umum tentang cara kerja algoritma Decision Trees:

  1. Pemilihan Fitur Algoritma Decision Trees memilih fitur mana yang akan digunakan untuk membagi data menjadi subgrup yang lebih kecil. Pemilihan fitur ini dilakukan berdasarkan kriteria tertentu seperti Gini Impurity atau Information Gain.

  2. Pembagian Data Setelah fitur dipilih, algoritma membagi data menjadi dua atau lebih subgrup berdasarkan nilai fitur yang dipilih. Setiap subgrup akan mewakili cabang-cabang dari pohon keputusan.

  3. Pengulangan Proses pembagian data di atas diulangi pada setiap cabang pohon secara rekursif hingga satu atau lebih kondisi berhenti terpenuhi, seperti mencapai jumlah data minimum dalam satu cabang atau kedalaman maksimum pohon.

  4. Penentuan Label Setelah pembagian data selesai, algoritma menentukan label (kelas atau nilai) untuk setiap daun pohon berdasarkan mayoritas kelas atau nilai dalam setiap subgrup.

  5. Pruning (Pemangkasan) Beberapa algoritma Decision Trees dapat melakukan pruning setelah pembangunan pohon untuk mencegah overfitting, yaitu dengan menghapus cabang-cabang yang tidak signifikan.

Berikut adalah beberapa konsep penting yang digunakan dalam algoritma Decision Trees:

  • Gini Impurity: Metrik yang mengukur seberapa seragam sebuah himpunan sampel dari kelas tertentu.
  • Information Gain: Metrik yang mengukur penurunan ketidakpastian setelah pemisahan himpunan sampel.
  • Entropy: Konsep dari teori informasi yang digunakan untuk menghitung Information Gain.

2.2 Penggunaan Decision Trees

Kita akan menggunakan dataset “Iris” yang tersedia dalam paket datasets di R. Dataset ini berisi informasi tentang atribut-atribut bunga Iris (panjang dan lebar sepal dan petal) serta label kelas (jenis spesies bunga Iris).

2.2.1 Persiapan Data

Pertama-tama, kita perlu memuat dataset dan mempersiapkan data:

# Load dataset
data(iris)

# Lihat struktur dataset
str(iris)
## 'data.frame':    150 obs. of  5 variables:
##  $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
##  $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
##  $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
##  $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
##  $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...

2.2.2 Pelatihan Model

Selanjutnya, kita melatih model klasifikasi menggunakan algoritma Decision Trees:

# Pisahkan fitur dan target
X <- iris[, 1:4]
y <- iris[, 5]

# Pelatihan model Decision Trees
library(rpart)
tree_model <- rpart(y ~ ., data = X, method = "class")

2.2.3 Evaluasi Model

Setelah melatih model, kita dapat mengevaluasi kinerjanya dengan menggunakan dataset yang sama:

# Prediksi kelas
prediksi <- predict(tree_model, X, type = "class")

# Hitung akurasi
akurasi <- sum(prediksi == y) / length(y)
print(paste("Akurasi model Decision Trees:", akurasi))
## [1] "Akurasi model Decision Trees: 0.96"

2.2.4 Visualisasi Model

Kita juga dapat memvisualisasikan model Decision Trees yang telah kita latih

# Load library untuk plotting
library(rpart.plot)

# Plot Decision Trees
rpart.plot(tree_model)

2.2.5 Interpretasi Hasil

Berdasarkan hasil evaluasi, kita dapat mengevaluasi seberapa baik model kita dalam memprediksi jenis spesies bunga Iris berdasarkan atribut-atribut yang ada dalam dataset. Selain itu, kita juga dapat menginterpretasi struktur pohon keputusan untuk memahami bagaimana model membuat keputusan

LS0tDQp0aXRsZTogIktsYXNpZmlrYXNpIg0Kc3VidGl0bGU6ICJEZWNpc2lvbiBUcmVlcyINCmF1dGhvcjogIk11aGFtbWFkIE5hdWZhbCBBcmRpYW5zeWFoIChEYXRhIFNjaWVudGlzdCkiDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclQiAlZCwgJVknKWAiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50OiANCiAgICBodG1sX2RvY3VtZW50OiBudWxsDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgdGhlbWU6IHNhbmRzdG9uZQ0KICAgIGNzczogc3R5bGUxLmNzcw0KICAgIGhpZ2hsaWdodDogbW9ub2Nocm9tZQ0KLS0tDQoNCg0KPGltZyBzdHlsZT0iZmxvYXQ6IHJpZ2h0OyBtYXJnaW46IDBweCAxMDBweCAwcHggMHB4OyB3aWR0aDoyNSUiIHNyYz0ibmF1ZmFsLmpwZWciLz4gDQoNCmBgYHtyIGxvZ28sIGVjaG89RkFMU0UsZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGggPSAnMzAlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJMYW1iYW5nLnBuZyIpDQpgYGANCg0KRW1haWwgJm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7Jm5ic3A7OiAgbmF1ZmFsMzQzM0BnbWFpbC5jb20gPGJyPg0KUlB1YnMgICZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyAmbmJzcDsgJm5ic3A7ICZuYnNwOzogaHR0cHM6Ly93d3cucnB1YnMuY29tL211aGFtbWFkX25hdWZhbC8gPGJyPg0KSnVydXNhbiAmbmJzcDsgJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7OiBbU3RhdGlzdGlrYSBCaXNuaXNdKGh0dHBzOi8vbWF0YW5hdW5pdmVyc2l0eS5hYy5pZC8/bHk9YWNhZGVtaWMmYz1zYikgPGJyPg0KQWRkcmVzcyAgJm5ic3A7ICZuYnNwOyAmbmJzcDsgJm5ic3A7IDogSmFsYW4gR3VudW5nIEdhbHVuZ2d1bmcgNSBCbG9rIEU5LCBOby4yMQ0KDQoqKioNCg0KIyBQZW5kYWh1bHVhbg0KDQpLbGFzaWZpa2FzaSBhZGFsYWggcHJvc2VzIHBlbmdlbG9tcG9rYW4gb2JqZWsgYXRhdSBkYXRhIGtlIGRhbGFtIGthdGVnb3JpIGF0YXUga2VsYXMgYmVyZGFzYXJrYW4gY2lyaS1jaXJpIGF0YXUgYXRyaWJ1dCB0ZXJ0ZW50dS4gTWV0b2RlIGtsYXNpZmlrYXNpIG1lcnVwYWthbiBhbGdvcml0bWEgYXRhdSB0ZWtuaWsgeWFuZyBkaWd1bmFrYW4gdW50dWsgbWVsYWt1a2FuIHByb3NlcyBrbGFzaWZpa2FzaSB0ZXJzZWJ1dC4gDQoNCg0KYGBge3IgZWNobz1GQUxTRX0NCmxpYnJhcnkoRGlhZ3JhbW1lUikNCmxpYnJhcnkoRGlhZ3JhbW1lUnN2ZykNCg0KIyBDcmVhdGUgYSBuZXcgRGlhZ3JhbW1lUnN2ZyBvYmplY3Qgd2l0aCBjdXN0b21pemVkIHN0eWxlDQptaW5kbWFwIDwtIGdyVml6KA0KICAiZGlncmFwaCB7DQogICAgZ3JhcGggW2xheW91dCA9IGRvdCwgZm9udHNpemUgPSAyNiwgc3BsaW5lcyA9IHRydWUsIG92ZXJsYXAgPSBmYWxzZSwgc2VwID0gMC4yLCBiZ2NvbG9yID0gdHJhbnNwYXJlbnQsIG1hcmdpbiA9IDAuMywgcmFua2RpciA9IFRCXQ0KICAgIG5vZGUgW3NoYXBlID0gcmVjdGFuZ2xlLCBzdHlsZSA9IGZpbGxlZCwgZmlsbGNvbG9yID0gJyNGRkNDNjYnLCBmb250c2l6ZSA9IDI2XQ0KICAgIGVkZ2UgW2NvbG9yID0gJyM3Nzc3NzcnXQ0KICAgIE1ldG9kZUtsYXNpZmlrYXNpIFtsYWJlbCA9ICdNZXRvZGUgS2xhc2lmaWthc2knLCBmb250c2l6ZSA9IDMwLCB3aWR0aCA9IDEsIGhlaWdodCA9IDEuMiwgc2hhcGUgPSBib3gsIGZpbGxjb2xvciA9ICcjOTlDQ0ZGJ10NCiAgICBLTk47IERlY2lzaW9uVHJlZXM7IFJhbmRvbUZvcmVzdDsgU1ZNOyBOYWl2ZUJheWVzOyBOZXVyYWxOZXR3b3JrczsgTG9naXN0aWNSZWdyZXNzaW9uOyBHQk07IEFkYUJvb3N0OyBFbnNlbWJsZUxlYXJuaW5nIFtmaWxsY29sb3IgPSAnIzY2Q0M5OSddDQoNCiAgICBNZXRvZGVLbGFzaWZpa2FzaSAtPiB7DQogICAgICBLTk47IERlY2lzaW9uVHJlZXM7IFJhbmRvbUZvcmVzdDsgU1ZNOyBOYWl2ZUJheWVzOyBOZXVyYWxOZXR3b3JrczsgTG9naXN0aWNSZWdyZXNzaW9uOyBHQk07IEFkYUJvb3N0OyBFbnNlbWJsZUxlYXJuaW5nDQogICAgfQ0KICB9IiwNCiAgaGVpZ2h0ID0gMjAwLCB3aWR0aCA9IDgwMCAgIyBNZW5lbnR1a2FuIHRpbmdnaSBkYW4gbGViYXIgZ2FtYmFyDQopDQoNCiMgRGlzcGxheSB0aGUgbWluZG1hcA0KbWluZG1hcA0KYGBgDQoNCktldGVyYW5nYW4gdW11bSB0ZXJrYWl0IG1ldG9kZSBLbGFzaWZpa2FzaSBhZGFsYWggc2ViYWdhaSBiZXJpa3V0Og0KDQoqICoqSy1OZWFyZXN0IE5laWdoYm9ycyAoSy1OTik6KiogTWV0b2RlIGluaSBtZW5na2xhc2lmaWthc2lrYW4gb2JqZWsgYmVyZGFzYXJrYW4gbWF5b3JpdGFzIGtlbGFzIHRldGFuZ2dhIHRlcmRla2F0bnlhLiBKaWthIHN1YXR1IG9iamVrIG1lbWlsaWtpIHNlYmFnaWFuIGJlc2FyIHRldGFuZ2dhIGRhcmkgc3VhdHUga2VsYXMgdGVydGVudHUsIG1ha2Egb2JqZWsgdGVyc2VidXQgZGlrbGFzaWZpa2FzaWthbiBrZSBkYWxhbSBrZWxhcyB0ZXJzZWJ1dC4NCiogKipEZWNpc2lvbiBUcmVlczoqKiBEZWNpc2lvbiB0cmVlcyBhZGFsYWggbW9kZWwgcHJlZGlrdGlmIHlhbmcgbWVuZ2d1bmFrYW4gc3RydWt0dXIgcG9ob24ga2VwdXR1c2FuIHVudHVrIG1lbGFrdWthbiBrbGFzaWZpa2FzaS4gUGFkYSBzZXRpYXAgc2ltcHVsIHBvaG9uLCBrZXB1dHVzYW4gZGlidWF0IGJlcmRhc2Fya2FuIG5pbGFpIGRhcmkgc3VhdHUgYXRyaWJ1dC4NCiogKipOYWl2ZSBCYXllczoqKiBNZXRvZGUga2xhc2lmaWthc2kgaW5pIGJlcmRhc2Fya2FuIHRlb3JlbWEgQmF5ZXMgZGVuZ2FuIGFzdW1zaSBpbmRlcGVuZGVuc2kgYW50YXJhIHNldGlhcCBwYXNhbmdhbiBhdHJpYnV0LiBNZXNraXB1biBzZWRlcmhhbmEsIE5haXZlIEJheWVzIHNlcmluZyBrYWxpIGVmZWt0aWYgZGFuIGNlcGF0LCB0ZXJ1dGFtYSB1bnR1ayBkYXRhc2V0IGRlbmdhbiBqdW1sYWggYXRyaWJ1dCB5YW5nIGJlc2FyLg0KKiAqKlN1cHBvcnQgVmVjdG9yIE1hY2hpbmVzIChTVk0pOioqIFNWTSBtZW5jYXJpIGh5cGVycGxhbmUgdGVyYmFpayB5YW5nIG1lbWlzYWhrYW4gZHVhIGtlbGFzIGRhbGFtIHJ1YW5nIGF0cmlidXQuIFR1anVhbiB1dGFtYW55YSBhZGFsYWggdW50dWsgbWVuY2FyaSBoeXBlcnBsYW5lIHlhbmcgbWVtaWxpa2kgbWFyZ2luIHRlcmJlc2FyIGFudGFyYSBkdWEga2VsYXMuDQoqICoqUmFuZG9tIEZvcmVzdDoqKiBSYW5kb20gRm9yZXN0IGFkYWxhaCB0ZWtuaWsgZW5zZW1ibGUgbGVhcm5pbmcgeWFuZyBtZW5nZ2FidW5na2FuIGJhbnlhayBkZWNpc2lvbiB0cmVlcyBrZSBkYWxhbSBzYXR1IG1vZGVsLiBTZXRpYXAgZGVjaXNpb24gdHJlZSBkaWJhbmd1biBzZWNhcmEgaW5kZXBlbmRlbiwgZGFuIGhhc2lsIGtsYXNpZmlrYXNpIGFraGlyIGRpcGVyb2xlaCBkZW5nYW4gbWVuZ2FtYmlsIG1heW9yaXRhcyBzdWFyYSBkYXJpIHNlbXVhIHBvaG9uLg0KKiAqKk5ldXJhbCBOZXR3b3JrczoqKiBKYXJpbmdhbiBzYXJhZiB0aXJ1YW4gKE5ldXJhbCBOZXR3b3JrcykgYWRhbGFoIG1vZGVsIGtvbXB1dGFzaSB5YW5nIHRlcmRpcmkgZGFyaSBuZXVyb24tbmV1cm9uIHlhbmcgc2FsaW5nIHRlcmh1YnVuZy4gRGFsYW0ga29udGVrcyBrbGFzaWZpa2FzaSwgbmV1cmFsIG5ldHdvcmtzIGRhcGF0IGRpZ3VuYWthbiBzZWJhZ2FpIG1ldG9kZSB5YW5nIHNhbmdhdCBrdWF0IHVudHVrIG1lbXBlbGFqYXJpIHBvbGEtcG9sYSB5YW5nIGtvbXBsZWtzIGRhcmkgZGF0YS4NCiogKipMb2dpc3RpYyBSZWdyZXNzaW9uOioqIExvZ2lzdGljIHJlZ3Jlc3Npb24gYWRhbGFoIG1ldG9kZSBzdGF0aXN0aWsgeWFuZyBkaWd1bmFrYW4gdW50dWsga2xhc2lmaWthc2kgYmluZXIsIGRpIG1hbmEgbW9kZWwgYmVydXNhaGEgbWVtcHJlZGlrc2kgcHJvYmFiaWxpdGFzIG1hc3VrIGtlIGRhbGFtIHNhbGFoIHNhdHUgZGFyaSBkdWEga2VsYXMuDQoqICoqR3JhZGllbnQgQm9vc3RpbmcgTWFjaGluZXMgKEdCTSk6KiogTWVuZ2dhYnVuZ2thbiBiZWJlcmFwYSBtb2RlbCBsZW1haCAobWlzYWxueWEsIGRlY2lzaW9uIHRyZWVzKSBzZWNhcmEgYmVydGFoYXAgdW50dWsgbWVuaW5na2F0a2FuIGtpbmVyamEuDQoqICoqQWRhQm9vc3Q6KiogTWVtYnVhdCBtb2RlbCB5YW5nIGJlcnVydXRhbiwgZGkgbWFuYSBzZXRpYXAgbW9kZWwgbWVuY29iYSB1bnR1ayBtZW1wZXJiYWlraSBrZXNhbGFoYW4geWFuZyBkaWxha3VrYW4gb2xlaCBtb2RlbCBzZWJlbHVtbnlhR3JhZGllbnQgQm9vc3RpbmcgTWFjaGluZXMgKEdCTSk6IE1lbmdnYWJ1bmdrYW4gYmViZXJhcGEgbW9kZWwgbGVtYWggKG1pc2FsbnlhLCBkZWNpc2lvbiB0cmVlcykgc2VjYXJhIGJlcnRhaGFwIHVudHVrIG1lbmluZ2thdGthbiBraW5lcmphLg0KKiAqKkVuc2VtYmxlIE1ldGhvZHM6KiogRW5zZW1ibGUgbWV0aG9kcyBtZW5nZ2FidW5na2FuIHByZWRpa3NpIGRhcmkgYmViZXJhcGEgbW9kZWwga2xhc2lmaWthc2kgdW50dWsgbWVuaW5na2F0a2FuIGtpbmVyamEgcHJlZGlrc2kuIENvbnRvaCBsYWluIGRhcmkgZW5zZW1ibGUgbWV0aG9kcyBhZGFsYWggQm9vc3RpbmcgZGFuIEJhZ2dpbmcuDQoNClNldGlhcCBtZXRvZGUga2xhc2lmaWthc2kgbWVtaWxpa2kga2VsZWJpaGFuIGRhbiBrZWxlbWFoYW4gdGVydGVudHUgdGVyZ2FudHVuZyBwYWRhIHNpZmF0IGRhdGEgeWFuZyBkaWhhZGFwaSBkYW4gdHVqdWFuIGRhcmkga2xhc2lmaWthc2kgdGVyc2VidXQuIFBlbWlsaWhhbiBtZXRvZGUga2xhc2lmaWthc2kgeWFuZyB0ZXBhdCBtZW1lcmx1a2FuIHBlbWFoYW1hbiB5YW5nIGJhaWsgdGVudGFuZyBkYXRhIHlhbmcgZGlndW5ha2FuIHNlcnRhIGVrc3BlcmltZW4gdW50dWsgbWVuZW50dWthbiBtZXRvZGUgeWFuZyBwYWxpbmcgY29jb2sgdW50dWsga2FzdXMgdGVydGVudHUuDQoNCiMgRGVjaXNpb24gVHJlZXMNCg0KRGVjaXNpb24gVHJlZXMgKFBvaG9uIEtlcHV0dXNhbikgYWRhbGFoIG1vZGVsIHBlbWJlbGFqYXJhbiBtZXNpbiB5YW5nIHNhbmdhdCBwb3B1bGVyIHVudHVrIHR1Z2FzIGtsYXNpZmlrYXNpIGRhbiByZWdyZXNpLiBNZXJla2EgbWVuZ2hhc2lsa2FuIG1vZGVsIHlhbmcgbXVkYWggZGlwYWhhbWkgZGFuIG11ZGFoIGRpaW50ZXJwcmV0YXNpa2FuLCBtaXJpcCBkZW5nYW4gbG9naWthIG1hbnVzaWEuDQoNCmBgYHtyIGRlY2lzaW9uX3RyZWUsIGVjaG89RkFMU0UsZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGggPSAnMTAwJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiRGVjaXNpb25fVHJlZS5naWYiKQ0KYGBgDQoNCiMjIFByb3NlcyBLZXJqYSAqRGVjaXNpb24gVHJlZXMqDQoNCkRlY2lzaW9uIFRyZWVzIChQb2hvbiBLZXB1dHVzYW4pIGFkYWxhaCBhbGdvcml0bWEgcGVtYmVsYWphcmFuIG1lc2luIHlhbmcgbWVuZ2d1bmFrYW4gc3RydWt0dXIgcG9ob24gYmVyaGllcmFya2kgdW50dWsgbWVsYWt1a2FuIHByZWRpa3NpLiBEaSBiYXdhaCBpbmkgYWRhbGFoIGxhbmdrYWgtbGFuZ2thaCB1bXVtIHRlbnRhbmcgY2FyYSBrZXJqYSBhbGdvcml0bWEgRGVjaXNpb24gVHJlZXM6DQoNCjEuIFBlbWlsaWhhbiBGaXR1cg0KQWxnb3JpdG1hIERlY2lzaW9uIFRyZWVzIG1lbWlsaWggZml0dXIgbWFuYSB5YW5nIGFrYW4gZGlndW5ha2FuIHVudHVrIG1lbWJhZ2kgZGF0YSBtZW5qYWRpIHN1YmdydXAgeWFuZyBsZWJpaCBrZWNpbC4gUGVtaWxpaGFuIGZpdHVyIGluaSBkaWxha3VrYW4gYmVyZGFzYXJrYW4ga3JpdGVyaWEgdGVydGVudHUgc2VwZXJ0aSBHaW5pIEltcHVyaXR5IGF0YXUgSW5mb3JtYXRpb24gR2Fpbi4NCg0KMi4gUGVtYmFnaWFuIERhdGENClNldGVsYWggZml0dXIgZGlwaWxpaCwgYWxnb3JpdG1hIG1lbWJhZ2kgZGF0YSBtZW5qYWRpIGR1YSBhdGF1IGxlYmloIHN1YmdydXAgYmVyZGFzYXJrYW4gbmlsYWkgZml0dXIgeWFuZyBkaXBpbGloLiBTZXRpYXAgc3ViZ3J1cCBha2FuIG1ld2FraWxpIGNhYmFuZy1jYWJhbmcgZGFyaSBwb2hvbiBrZXB1dHVzYW4uDQoNCjMuIFBlbmd1bGFuZ2FuDQpQcm9zZXMgcGVtYmFnaWFuIGRhdGEgZGkgYXRhcyBkaXVsYW5naSBwYWRhIHNldGlhcCBjYWJhbmcgcG9ob24gc2VjYXJhIHJla3Vyc2lmIGhpbmdnYSBzYXR1IGF0YXUgbGViaWgga29uZGlzaSBiZXJoZW50aSB0ZXJwZW51aGksIHNlcGVydGkgbWVuY2FwYWkganVtbGFoIGRhdGEgbWluaW11bSBkYWxhbSBzYXR1IGNhYmFuZyBhdGF1IGtlZGFsYW1hbiBtYWtzaW11bSBwb2hvbi4NCg0KNC4gUGVuZW50dWFuIExhYmVsDQpTZXRlbGFoIHBlbWJhZ2lhbiBkYXRhIHNlbGVzYWksIGFsZ29yaXRtYSBtZW5lbnR1a2FuIGxhYmVsIChrZWxhcyBhdGF1IG5pbGFpKSB1bnR1ayBzZXRpYXAgZGF1biBwb2hvbiBiZXJkYXNhcmthbiBtYXlvcml0YXMga2VsYXMgYXRhdSBuaWxhaSBkYWxhbSBzZXRpYXAgc3ViZ3J1cC4NCg0KNS4gUHJ1bmluZyAoUGVtYW5na2FzYW4pDQpCZWJlcmFwYSBhbGdvcml0bWEgRGVjaXNpb24gVHJlZXMgZGFwYXQgbWVsYWt1a2FuIHBydW5pbmcgc2V0ZWxhaCBwZW1iYW5ndW5hbiBwb2hvbiB1bnR1ayBtZW5jZWdhaCBvdmVyZml0dGluZywgeWFpdHUgZGVuZ2FuIG1lbmdoYXB1cyBjYWJhbmctY2FiYW5nIHlhbmcgdGlkYWsgc2lnbmlmaWthbi4NCg0KQmVyaWt1dCBhZGFsYWggYmViZXJhcGEga29uc2VwIHBlbnRpbmcgeWFuZyBkaWd1bmFrYW4gZGFsYW0gYWxnb3JpdG1hIERlY2lzaW9uIFRyZWVzOg0KDQotICoqR2luaSBJbXB1cml0eSoqOiBNZXRyaWsgeWFuZyBtZW5ndWt1ciBzZWJlcmFwYSBzZXJhZ2FtIHNlYnVhaCBoaW1wdW5hbiBzYW1wZWwgZGFyaSBrZWxhcyB0ZXJ0ZW50dS4NCi0gKipJbmZvcm1hdGlvbiBHYWluKio6IE1ldHJpayB5YW5nIG1lbmd1a3VyIHBlbnVydW5hbiBrZXRpZGFrcGFzdGlhbiBzZXRlbGFoIHBlbWlzYWhhbiBoaW1wdW5hbiBzYW1wZWwuDQotICoqRW50cm9weSoqOiBLb25zZXAgZGFyaSB0ZW9yaSBpbmZvcm1hc2kgeWFuZyBkaWd1bmFrYW4gdW50dWsgbWVuZ2hpdHVuZyBJbmZvcm1hdGlvbiBHYWluLg0KDQojIyBQZW5nZ3VuYWFuIERlY2lzaW9uIFRyZWVzDQoNCktpdGEgYWthbiBtZW5nZ3VuYWthbiBkYXRhc2V0ICJJcmlzIiB5YW5nIHRlcnNlZGlhIGRhbGFtIHBha2V0IGBkYXRhc2V0c2AgZGkgUi4gRGF0YXNldCBpbmkgYmVyaXNpIGluZm9ybWFzaSB0ZW50YW5nIGF0cmlidXQtYXRyaWJ1dCBidW5nYSBJcmlzIChwYW5qYW5nIGRhbiBsZWJhciBzZXBhbCBkYW4gcGV0YWwpIHNlcnRhIGxhYmVsIGtlbGFzIChqZW5pcyBzcGVzaWVzIGJ1bmdhIElyaXMpLg0KDQojIyMgUGVyc2lhcGFuIERhdGENCg0KUGVydGFtYS10YW1hLCBraXRhIHBlcmx1IG1lbXVhdCBkYXRhc2V0IGRhbiBtZW1wZXJzaWFwa2FuIGRhdGE6DQoNCmBgYHtyfQ0KIyBMb2FkIGRhdGFzZXQNCmRhdGEoaXJpcykNCg0KIyBMaWhhdCBzdHJ1a3R1ciBkYXRhc2V0DQpzdHIoaXJpcykNCmBgYA0KDQojIyMgUGVsYXRpaGFuIE1vZGVsDQoNClNlbGFuanV0bnlhLCBraXRhIG1lbGF0aWggbW9kZWwga2xhc2lmaWthc2kgbWVuZ2d1bmFrYW4gYWxnb3JpdG1hIERlY2lzaW9uIFRyZWVzOg0KDQpgYGB7cn0NCiMgUGlzYWhrYW4gZml0dXIgZGFuIHRhcmdldA0KWCA8LSBpcmlzWywgMTo0XQ0KeSA8LSBpcmlzWywgNV0NCg0KIyBQZWxhdGloYW4gbW9kZWwgRGVjaXNpb24gVHJlZXMNCmxpYnJhcnkocnBhcnQpDQp0cmVlX21vZGVsIDwtIHJwYXJ0KHkgfiAuLCBkYXRhID0gWCwgbWV0aG9kID0gImNsYXNzIikNCg0KYGBgDQoNCiMjIyBFdmFsdWFzaSBNb2RlbA0KDQpTZXRlbGFoIG1lbGF0aWggbW9kZWwsIGtpdGEgZGFwYXQgbWVuZ2V2YWx1YXNpIGtpbmVyamFueWEgZGVuZ2FuIG1lbmdndW5ha2FuIGRhdGFzZXQgeWFuZyBzYW1hOg0KDQpgYGB7cn0NCiMgUHJlZGlrc2kga2VsYXMNCnByZWRpa3NpIDwtIHByZWRpY3QodHJlZV9tb2RlbCwgWCwgdHlwZSA9ICJjbGFzcyIpDQoNCiMgSGl0dW5nIGFrdXJhc2kNCmFrdXJhc2kgPC0gc3VtKHByZWRpa3NpID09IHkpIC8gbGVuZ3RoKHkpDQpwcmludChwYXN0ZSgiQWt1cmFzaSBtb2RlbCBEZWNpc2lvbiBUcmVlczoiLCBha3VyYXNpKSkNCmBgYA0KDQojIyMgVmlzdWFsaXNhc2kgTW9kZWwNCg0KS2l0YSBqdWdhIGRhcGF0IG1lbXZpc3VhbGlzYXNpa2FuIG1vZGVsIERlY2lzaW9uIFRyZWVzIHlhbmcgdGVsYWgga2l0YSBsYXRpaA0KDQpgYGB7cn0NCiMgTG9hZCBsaWJyYXJ5IHVudHVrIHBsb3R0aW5nDQpsaWJyYXJ5KHJwYXJ0LnBsb3QpDQoNCiMgUGxvdCBEZWNpc2lvbiBUcmVlcw0KcnBhcnQucGxvdCh0cmVlX21vZGVsKQ0KYGBgDQoNCiMjIyBJbnRlcnByZXRhc2kgSGFzaWwNCg0KQmVyZGFzYXJrYW4gaGFzaWwgZXZhbHVhc2ksIGtpdGEgZGFwYXQgbWVuZ2V2YWx1YXNpIHNlYmVyYXBhIGJhaWsgbW9kZWwga2l0YSBkYWxhbSBtZW1wcmVkaWtzaSBqZW5pcyBzcGVzaWVzIGJ1bmdhIElyaXMgYmVyZGFzYXJrYW4gYXRyaWJ1dC1hdHJpYnV0IHlhbmcgYWRhIGRhbGFtIGRhdGFzZXQuIFNlbGFpbiBpdHUsIGtpdGEganVnYSBkYXBhdCBtZW5naW50ZXJwcmV0YXNpIHN0cnVrdHVyIHBvaG9uIGtlcHV0dXNhbiB1bnR1ayBtZW1haGFtaSBiYWdhaW1hbmEgbW9kZWwgbWVtYnVhdCBrZXB1dHVzYW4=