1 Praktek 12: Ekspektasi Maksimalisasi

Dalam kelas ini kita akan menggunakan algoritma Ekspektasi Maksimalisasi untuk mengestimasi parameter Campuran Gaussian. Metode ini menyediakan pengklasifikasi yang tidak terjaga dan sangat berguna ketika distribusi Gaussian diasumsikan.

Misalkan kita ingin memodelkan parameter populasi yang diasumsikan menjadi salah satu dari dua populasi normal gaussian dengan probabilitas pencampuran \(\pi\). Artinya, \(x_i\sim N(\mu_1, \Sigma_1)\) dengan probabilitas \(\pi\), \(x_i\sim N(\mu_2, \Sigma_2)\) dengan probabilitas \((1-\pi)\). Dinotasikan \(\theta_1= (\mu_1, \Sigma_1)\) dan \(\theta_2= (\mu_2, \Sigma_2)\) parameter untuk tiap populasi dan \(\pi\) sebagai parameter pencampuran, \(\phi_1\) dan \(\phi_2\) untuk densitas tiap distribusi. Algoritma Ekspektasi Maksimalisasi dapat disimpulkan di langkah berikut.

  1. Ambil tebakan awal untuk parameter \(\hat{\mu}_1, \hat{\mu}_2, \hat{\Sigma}_1, \hat{\Sigma}_2, \hat{\pi}\)

  2. Langkah ekspektasi: Menghitung \[\hat{\gamma}_i=\dfrac{\hat{\pi}\phi_1(y_i)}{\hat{\pi}\phi_1(y_i)+(1-\hat{\pi})\phi_2(y_i)}\]

  3. Langkah memaksimumkan: Menghitung Mean dan Varians \[\begin{align*} \hat{\mu_1} &= \dfrac{\sum_{i=1}^n\hat{\gamma}_ix_i}{\sum_{i=1}^n\hat{\gamma}_i} & \hat{\Sigma_1} = \dfrac{1}{n}\dfrac{\sum_{i=1}^n\hat{\gamma}_i(x_i-\mu_1)(x_i-\mu_1)^T}{\sum_{i=1}^n\hat{\gamma}_i}\\ \hat{\mu_2}& = \dfrac{\sum_{i=1}^n(1-\hat{\gamma}_i)x_i}{\sum_{i=1}^n(1-\hat{\gamma}_i)} & \hat{\Sigma_2} = \dfrac{1}{n}\dfrac{\sum_{i=1}^n\hat{\gamma}_i(x_i-\mu_2)(x_i-\mu_2)^T}{\sum_{i=1}^n(1-\hat{\gamma}_i)} \end{align*}\] dan probabilitas campuran \(\hat{\pi} = \dfrac{1}{n}\sum_{i=1}^n\hat{\gamma}_i\).

  4. Iterasikan langkah 2 dan 3 hingga konvergen.

1.1 Latihan 1:

Simulasikan 300 sample dari Gaussian Mixture dengan probabilitas pencampuran setara dengan \(1/3\) sebagai berikut: \[\begin{equation*} Y_1 \sim N\bigg(\begin{bmatrix}1\\1\end{bmatrix},\begin{bmatrix}2&1\\1&1\end{bmatrix} \bigg) \qquad Y_2 \sim N\bigg(\begin{bmatrix}7\\7\end{bmatrix},\begin{bmatrix}2&2\\2&5\end{bmatrix} \bigg) \end{equation*}\]

  1. Visualisasikan distribusinya dengan menggunakan scatter plot dan gunakan skala kontinu untuk memisahkan warna berdasarkan populasinya.

  1. Mengimplementasikan algoritma EM untuk memperkirakan parameternya.

Bantuan: Buat tebakan untuk \(\mu_1\) dan \(\mu_2\) hanya dengan dua dari \(y_i\) dengan acak. Mulai \(\Sigma_1\) dan \(\Sigma_2\) sebagai sample matriks kovarians dan \(\pi\) dengan nilai \(0.5\). Kriteria berhenti dimana perbedaan antara dua nilai berturut-turut dari log ekspektasi lengkap kurang dari toleransi yang diinginkan \(|l_k-l_{k-1}|<\text{tol}\).

  1. Visualisasikan nilai yang diperoleh untuk probabilitas tiap poin iterasi terawal ke-8.
## Warning: package 'reshape' was built under R version 4.0.2

1.2 Latihan 2

Mari gunakan Algoritma EM untuk mengsegmentasikan sebuah gambar. Dalam kasus ini kita akan gunakan gambar melanoma.

## Warning: package 'OpenImageR' was built under R version 4.0.2

Algoritme segmentasi gambar biasa mengubah larik tiga dimensi yaitu gambar menjadi matriks 3 kolom dengan jumlah baris sebanyak jumlah piksel.

## [1] 737280      3

Dalam kasus ini kita akan mencari proyeksi 1 dimensi dari matriks agar algoritma EM dapat digunakan untuk mengestimasi parameter distribusi yang menghasilkan proyeksi.

  1. Implentasikan sebuah fungsi yang dapat memperkirakan parameter dari Gaussian dalam kasus 1 dimensi.
  1. Diketahui dalam literatur bahwa pola melanoma biasanya diekspresikan dalam warna biru. Jalankan algoritma EM menggunakan informasi tersebut dan tampilkan hasil akhirnya.

  1. Gunakan proyeksi yang mempertahankan variabilitas data sebanyak mungkin (komponen pertama di PCA) dan terapkan EM. Visualisasikan hasilnya.

  1. Gunakan proyeksi Pencahayaan \(L = (0.229, 0.588. 0.114)\) dan tampilkan hasil menerapkan algoritma EM.

  1. Pada akhirnya, kita akan gunakan varian dari algoritma Independent Histogram Pursuit. Algoritma ini menemukan proyeksi yang memaksimumkan amplitudo bimodal. sekali proyeksi ditemukan, kita lanjut ke contoh latihan sebelumnya.
LS0tDQp0aXRsZTogJ0xhYjY6IEV4cGVjdGVkIE1heGltaXphdGlvbicNCmF1dGhvcjogIldpZGkgeWFudGloIg0KZGF0ZTogImByIGZvcm1hdChTeXMuRGF0ZSgpLCAnJUIgJWQsICVZJylgIg0Kb3V0cHV0OiANCiAgaHRtbF9kb2N1bWVudDogDQogICAgaGlnaGxpZ2h0OiBtb25vY2hyb21lDQogICAgdGhlbWU6IHNwYWNlbGFiDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDogeWVzDQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQotLS0NCg0KYGBge3IgTG9nbywgZWNobz1GQUxTRSxmaWcuYWxpZ249J2NlbnRlcicsIG91dC53aWR0aCA9ICc0MCUnfQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vZ2l0aHViLmNvbS9CYWt0aS1TaXJlZ2FyL2ltYWdlcy9ibG9iL21hc3Rlci9sb2dvLnBuZz9yYXc9dHJ1ZSIpDQpgYGANCg0KIyBQcmFrdGVrIDEyOiBFa3NwZWt0YXNpIE1ha3NpbWFsaXNhc2kNCg0KRGFsYW0ga2VsYXMgaW5pIGtpdGEgYWthbiBtZW5nZ3VuYWthbiBhbGdvcml0bWEgRWtzcGVrdGFzaSBNYWtzaW1hbGlzYXNpIHVudHVrIG1lbmdlc3RpbWFzaSBwYXJhbWV0ZXIgQ2FtcHVyYW4gR2F1c3NpYW4uIE1ldG9kZSBpbmkgbWVueWVkaWFrYW4gcGVuZ2tsYXNpZmlrYXNpIHlhbmcgdGlkYWsgdGVyamFnYSBkYW4gc2FuZ2F0IGJlcmd1bmEga2V0aWthIGRpc3RyaWJ1c2kgR2F1c3NpYW4gZGlhc3Vtc2lrYW4uDQoNCk1pc2Fsa2FuIGtpdGEgaW5naW4gbWVtb2RlbGthbiBwYXJhbWV0ZXIgcG9wdWxhc2kgeWFuZyBkaWFzdW1zaWthbiBtZW5qYWRpIHNhbGFoIHNhdHUgZGFyaSBkdWEgcG9wdWxhc2kgbm9ybWFsIGdhdXNzaWFuIGRlbmdhbiBwcm9iYWJpbGl0YXMgcGVuY2FtcHVyYW4gJFxwaSQuIEFydGlueWEsICR4X2lcc2ltIE4oXG11XzEsIFxTaWdtYV8xKSQgZGVuZ2FuIHByb2JhYmlsaXRhcyAkXHBpJCwgJHhfaVxzaW0gTihcbXVfMiwgXFNpZ21hXzIpJCBkZW5nYW4gcHJvYmFiaWxpdGFzICQoMS1ccGkpJC4gRGlub3Rhc2lrYW4gJFx0aGV0YV8xPSAoXG11XzEsIFxTaWdtYV8xKSQgZGFuICRcdGhldGFfMj0gKFxtdV8yLCBcU2lnbWFfMikkIHBhcmFtZXRlciB1bnR1ayB0aWFwIHBvcHVsYXNpIGRhbiAkXHBpJCBzZWJhZ2FpIHBhcmFtZXRlciBwZW5jYW1wdXJhbiwgJFxwaGlfMSQgZGFuICRccGhpXzIkIHVudHVrIGRlbnNpdGFzIHRpYXAgZGlzdHJpYnVzaS4gQWxnb3JpdG1hIEVrc3Bla3Rhc2kgTWFrc2ltYWxpc2FzaSBkYXBhdCBkaXNpbXB1bGthbiBkaSBsYW5na2FoIGJlcmlrdXQuDQoNCjEuIEFtYmlsIHRlYmFrYW4gYXdhbCB1bnR1ayBwYXJhbWV0ZXIgJFxoYXR7XG11fV8xLCBcaGF0e1xtdX1fMiwgXGhhdHtcU2lnbWF9XzEsIFxoYXR7XFNpZ21hfV8yLCBcaGF0e1xwaX0kDQoNCjIuIExhbmdrYWggZWtzcGVrdGFzaTogTWVuZ2hpdHVuZw0KJCRcaGF0e1xnYW1tYX1faT1cZGZyYWN7XGhhdHtccGl9XHBoaV8xKHlfaSl9e1xoYXR7XHBpfVxwaGlfMSh5X2kpKygxLVxoYXR7XHBpfSlccGhpXzIoeV9pKX0kJA0KDQozLiBMYW5na2FoIG1lbWFrc2ltdW1rYW46IE1lbmdoaXR1bmcgTWVhbiBkYW4gVmFyaWFucw0KJCRcYmVnaW57YWxpZ24qfQ0KIFxoYXR7XG11XzF9ICY9IFxkZnJhY3tcc3VtX3tpPTF9Xm5caGF0e1xnYW1tYX1faXhfaX17XHN1bV97aT0xfV5uXGhhdHtcZ2FtbWF9X2l9ICYgXGhhdHtcU2lnbWFfMX0gPSBcZGZyYWN7MX17bn1cZGZyYWN7XHN1bV97aT0xfV5uXGhhdHtcZ2FtbWF9X2koeF9pLVxtdV8xKSh4X2ktXG11XzEpXlR9e1xzdW1fe2k9MX1eblxoYXR7XGdhbW1hfV9pfVxcDQogXGhhdHtcbXVfMn0mID0gXGRmcmFje1xzdW1fe2k9MX1ebigxLVxoYXR7XGdhbW1hfV9pKXhfaX17XHN1bV97aT0xfV5uKDEtXGhhdHtcZ2FtbWF9X2kpfSAmICBcaGF0e1xTaWdtYV8yfSA9IFxkZnJhY3sxfXtufVxkZnJhY3tcc3VtX3tpPTF9Xm5caGF0e1xnYW1tYX1faSh4X2ktXG11XzIpKHhfaS1cbXVfMileVH17XHN1bV97aT0xfV5uKDEtXGhhdHtcZ2FtbWF9X2kpfQ0KXGVuZHthbGlnbip9JCQNCmRhbiBwcm9iYWJpbGl0YXMgY2FtcHVyYW4gJFxoYXR7XHBpfSA9IFxkZnJhY3sxfXtufVxzdW1fe2k9MX1eblxoYXR7XGdhbW1hfV9pJC4NCg0KNC4gSXRlcmFzaWthbiBsYW5na2FoIDIgZGFuIDMgaGluZ2dhIGtvbnZlcmdlbi4NCg0KDQojIyBMYXRpaGFuIDE6DQpTaW11bGFzaWthbiAzMDAgc2FtcGxlIGRhcmkgR2F1c3NpYW4gTWl4dHVyZSBkZW5nYW4gcHJvYmFiaWxpdGFzIHBlbmNhbXB1cmFuIHNldGFyYSBkZW5nYW4gJDEvMyQgc2ViYWdhaSBiZXJpa3V0Og0KJCRcYmVnaW57ZXF1YXRpb24qfQ0KWV8xIFxzaW0gTlxiaWdnKFxiZWdpbntibWF0cml4fTFcXDFcZW5ke2JtYXRyaXh9LFxiZWdpbntibWF0cml4fTImMVxcMSYxXGVuZHtibWF0cml4fSBcYmlnZykgXHFxdWFkIFlfMiBcc2ltIE5cYmlnZyhcYmVnaW57Ym1hdHJpeH03XFw3XGVuZHtibWF0cml4fSxcYmVnaW57Ym1hdHJpeH0yJjJcXDImNVxlbmR7Ym1hdHJpeH0gXGJpZ2cpIA0KXGVuZHtlcXVhdGlvbip9JCQNCg0KYS4gVmlzdWFsaXNhc2lrYW4gZGlzdHJpYnVzaW55YSBkZW5nYW4gbWVuZ2d1bmFrYW4gc2NhdHRlciBwbG90IGRhbiBndW5ha2FuIHNrYWxhIGtvbnRpbnUgdW50dWsgbWVtaXNhaGthbiB3YXJuYSBiZXJkYXNhcmthbiBwb3B1bGFzaW55YS4NCg0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KG12dG5vcm0pDQoNCk11MSA9IGMoMSwxKQ0KTXUyID0gYyg3LDcpDQpTaWdtYTEgPSBtYXRyaXgoYygyLCAxLCAxLCAxKSwgMiwyKQ0KU2lnbWEyID0gbWF0cml4KGMoMiwgMiwgMiwgNSksIDIsMikNCg0KcGkgPSAxLzMNCm4gPSAzMDANCg0Kc2V0LnNlZWQoMikNCmRhdGEgPSBtYXRyaXgoMCwgbiwgMikNCnogPSByZXAoMCxuKQ0KZm9yIChpIGluIDE6bil7DQogIHpbaV0gPSByYmlub20oMSwxLHBpKQ0KICBpZiAoeltpXSA9PTEpew0KICAgIGRhdGFbaSxdID0gcm12bm9ybSgxLCBNdTEsU2lnbWExKQ0KICB9ZWxzZXsNCiAgICBkYXRhW2ksXSA9IHJtdm5vcm0oMSwgTXUyLFNpZ21hMikNCiAgfQ0KfQ0KDQp0by5wbG90ID0gZGF0YS5mcmFtZSh4ID0gZGF0YVssMV0sIA0KICAgICAgICAgICAgICAgICAgeSA9IGRhdGFbLDJdLCANCiAgICAgICAgICAgICAgICAgIGNsYXNzID0gIHopDQpnZ3Bsb3QodG8ucGxvdCkrIGFlcyh4LCB5LCBjb2xvciA9IGNsYXNzKSsNCiAgZ2VvbV9wb2ludCgpK2dlb21fZGVuc2l0eV8yZCgpDQpgYGANCg0KYi4gTWVuZ2ltcGxlbWVudGFzaWthbiBhbGdvcml0bWEgRU0gdW50dWsgbWVtcGVya2lyYWthbiBwYXJhbWV0ZXJueWEuDQoNCipCYW50dWFuKjogQnVhdCB0ZWJha2FuIHVudHVrICRcbXVfMSQgZGFuICRcbXVfMiQgaGFueWEgZGVuZ2FuIGR1YSBkYXJpICR5X2kkIGRlbmdhbiBhY2FrLiBNdWxhaSAkXFNpZ21hXzEkIGRhbiAkXFNpZ21hXzIkIHNlYmFnYWkgc2FtcGxlIG1hdHJpa3Mga292YXJpYW5zICBkYW4gJFxwaSQgZGVuZ2FuIG5pbGFpICQwLjUkLiBLcml0ZXJpYSBiZXJoZW50aSBkaW1hbmEgcGVyYmVkYWFuIGFudGFyYSBkdWEgbmlsYWkgYmVydHVydXQtdHVydXQgZGFyaSBsb2cgZWtzcGVrdGFzaSBsZW5na2FwIGt1cmFuZyBkYXJpIHRvbGVyYW5zaSB5YW5nIGRpaW5naW5rYW4gJHxsX2stbF97ay0xfXw8XHRleHR7dG9sfSQuDQoNCmBgYHtyfQ0KI2luaXRpYWwgdmFsdWVzDQpwaSA9IDAuNQ0KbXUxID0gZGF0YVsxLF0NCm11MiA9IGRhdGFbMTUwLF0NCnNpZ21hMSA9IGNvdihkYXRhKQ0Kc2lnbWEyID0gY292KGRhdGEpDQpgYGANCg0KYGBge3J9DQpsaWJyYXJ5KFNETVRvb2xzKQ0KDQojIEVNIGFsZ29yaXRobQ0KQWxwaGEgPSBOVUxMDQp0b2wgPSAxMF4tMg0KaXRlciA9IDANClEgPSAwDQpwaGkxID0gZG12bm9ybShkYXRhLCBtdTEsIHNpZ21hMSkNCnBoaTIgPSBkbXZub3JtKGRhdGEsIG11Miwgc2lnbWEyKQ0KUV8gPSBzdW0obG9nKHBpKStsb2cocGhpMSkpICsNCiAgc3VtKGxvZyhwaSkrbG9nKHBoaTIpKQ0KDQp3aGlsZSAoYWJzKFEtUV8pPj10b2wpIHsNCg0KICBpdGVyID0gaXRlcisxDQogIFEgPSBRXw0KDQogICMgRXhwZWN0YXRpb24gc3RlcA0KICBhbHBoYSA9IHBpKnBoaTEvKHBpKnBoaTErKDEtcGkpKnBoaTIpDQogIEFscGhhID0gY2JpbmQoQWxwaGEsIGFscGhhKQ0KDQogICMgTWF4aW1pemF0aW9uIHN0ZXANCiAgbXUxID0gYXBwbHkoZGF0YSwgMiwgZnVuY3Rpb24oY29sKSB3dC5tZWFuKGNvbCwgYWxwaGEpKQ0KICBtdTIgPSBhcHBseShkYXRhLCAyLCBmdW5jdGlvbihjb2wpIHd0Lm1lYW4oY29sLCAxLWFscGhhKSkNCiAgc2lnbWExID0gY292Lnd0KGRhdGEsIHd0ID0gYWxwaGEsIG1ldGhvZCA9ICJNTCIpJGNvdg0KICBzaWdtYTIgPSBjb3Yud3QoZGF0YSwgd3QgPSAxLWFscGhhLCBtZXRob2QgPSAiTUwiKSRjb3YNCiAgcGkgPSBtZWFuKGFscGhhKQ0KDQogIHBoaTEgPSBkbXZub3JtKGRhdGEsIG11MSwgc2lnbWExKQ0KICBwaGkyID0gZG12bm9ybShkYXRhLCBtdTIsIHNpZ21hMikNCiAgUV8gPSBzdW0obG9nKHBpKStsb2cocGhpMSkpICsNCiAgICBzdW0obG9nKHBpKStsb2cocGhpMikpDQp9DQpgYGANCg0KYy4gVmlzdWFsaXNhc2lrYW4gbmlsYWkgeWFuZyBkaXBlcm9sZWggdW50dWsgcHJvYmFiaWxpdGFzIHRpYXAgcG9pbiBpdGVyYXNpIHRlcmF3YWwga2UtOC4NCmBgYHtyfQ0KbGlicmFyeShyZXNoYXBlKQ0KDQp0by5wbG90ID0gZGF0YS5mcmFtZSh4ID0gZGF0YVssMV0sDQogICAgICAgICAgICAgICAgICAgICB5ID0gZGF0YVssMl0sDQogICAgICAgICAgICAgICAgICAgICBpdGVyID0gQWxwaGFbLDE6OF0pDQp0by5wbG90ID0gbWVsdCh0by5wbG90LCBpZC52YXJzID0gYygieCIsICJ5IikpDQoNCmdncGxvdCh0by5wbG90KSthZXMoeCx5LCBjb2xvciA9IHZhbHVlKSsNCiAgZ2VvbV9wb2ludCgpK2ZhY2V0X3dyYXAofnZhcmlhYmxlLCBucm93ID0gMikNCmBgYA0KDQojIyBMYXRpaGFuIDINCk1hcmkgZ3VuYWthbiBBbGdvcml0bWEgRU0gdW50dWsgbWVuZ3NlZ21lbnRhc2lrYW4gc2VidWFoIGdhbWJhci4gRGFsYW0ga2FzdXMgaW5pIGtpdGEgYWthbiBndW5ha2FuIGdhbWJhciAqbWVsYW5vbWEqLg0KDQpgYGB7cn0NCmxpYnJhcnkoT3BlbkltYWdlUikNCmltZyA9IHJlYWRJbWFnZSgiTWVsYW5vbWEucG5nIikNCmltYWdlU2hvdyhpbWcpDQpgYGANCg0KQWxnb3JpdG1lIHNlZ21lbnRhc2kgZ2FtYmFyIGJpYXNhIG1lbmd1YmFoIGxhcmlrIHRpZ2EgZGltZW5zaSB5YWl0dSBnYW1iYXIgbWVuamFkaSBtYXRyaWtzIDMga29sb20gZGVuZ2FuIGp1bWxhaCBiYXJpcyBzZWJhbnlhayBqdW1sYWggcGlrc2VsLg0KYGBge3J9DQppbWcudmVjdCA9IGFwcGx5KGltZywgMywgYXMudmVjdG9yICkNCmRpbShpbWcudmVjdCkNCmBgYA0KDQpEYWxhbSBrYXN1cyBpbmkga2l0YSBha2FuIG1lbmNhcmkgcHJveWVrc2kgMSBkaW1lbnNpIGRhcmkgbWF0cmlrcyBhZ2FyIGFsZ29yaXRtYSBFTSBkYXBhdCBkaWd1bmFrYW4gdW50dWsgbWVuZ2VzdGltYXNpIHBhcmFtZXRlciBkaXN0cmlidXNpIHlhbmcgbWVuZ2hhc2lsa2FuIHByb3lla3NpLg0KDQphLiBJbXBsZW50YXNpa2FuIHNlYnVhaCBmdW5nc2kgeWFuZyBkYXBhdCBtZW1wZXJraXJha2FuIHBhcmFtZXRlciBkYXJpIEdhdXNzaWFuIGRhbGFtIGthc3VzIDEgZGltZW5zaS4NCg0KYGBge3J9DQpFTSA9IGZ1bmN0aW9uKGRhdGEpew0KICANCiAgc2V0LnNlZWQoMSkNCiAgcGkgPSAwLjUNCiAgbXUxID0gc2FtcGxlKGRhdGEsMSkNCiAgbXUyID0gc2FtcGxlKGRhdGEsMSkNCiAgc2QxID0gc2QoZGF0YSkNCiAgc2QyID0gc2QxDQogIA0KICB0b2wgPSAxMF4tMg0KICBpdGVyID0gMA0KICBRID0gMA0KICBwaGkxID0gZG5vcm0oZGF0YSwgbXUxLCBzZDEpDQogIHBoaTIgPSBkbm9ybShkYXRhLCBtdTIsIHNkMikNCiAgUV8gPSBzdW0obG9nKHBpKStsb2cocGhpMSkpICsNCiAgICBzdW0obG9nKHBpKStsb2cocGhpMikpDQogIA0KICB3aGlsZSAoYWJzKFEtUV8pPj10b2wpIHsNCiAgICANCiAgICBpdGVyID0gaXRlcisxDQogICAgUSA9IFFfDQogICAgDQogICAgIyBFeHBlY3RhdGlvbiBzdGVwIA0KICAgIGFscGhhID0gcGkqcGhpMS8ocGkqcGhpMSsoMS1waSkqcGhpMikNCiAgICANCiAgICAjIE1heGltaXphdGlvbiBzdGVwDQogICAgbXUxID0gd3QubWVhbihkYXRhLCBhbHBoYSkNCiAgICBtdTIgPSB3dC5tZWFuKGRhdGEsIDEtYWxwaGEpDQogICAgc2QxID0gd3Quc2QoZGF0YSwgd3QgPSBhbHBoYSkNCiAgICBzZDIgPSB3dC5zZChkYXRhLCB3dCA9IDEtYWxwaGEpDQogICAgcGkgPSBtZWFuKGFscGhhKQ0KICAgIA0KICAgIHBoaTEgPSBkbm9ybShkYXRhLCBtdTEsIHNkMSkNCiAgICBwaGkyID0gZG5vcm0oZGF0YSwgbXUyLCBzZDIpDQogICAgUV8gPSBzdW0obG9nKHBpKStsb2cocGhpMSkpICsNCiAgICAgIHN1bShsb2cocGkpK2xvZyhwaGkyKSkNCiAgfQ0KICAgIHJldHVybihhbHBoYSkNCiB9DQpgYGANCg0KYi4gRGlrZXRhaHVpIGRhbGFtIGxpdGVyYXR1ciBiYWh3YSBwb2xhICptZWxhbm9tYSogYmlhc2FueWEgZGlla3NwcmVzaWthbiBkYWxhbSB3YXJuYSBiaXJ1LiBKYWxhbmthbiBhbGdvcml0bWEgRU0gbWVuZ2d1bmFrYW4gaW5mb3JtYXNpIHRlcnNlYnV0IGRhbiB0YW1waWxrYW4gaGFzaWwgYWtoaXJueWEuDQoNCmBgYHtyfQ0KIyBCbHVlIGFycmF5ICsgRU0NCmJsdWUgPSBpbWcudmVjdFssM10NCnByb2IgPSBFTShibHVlKQ0KY2xhc3NpZmljYXRpb24gPSAocHJvYj4wLjUpKzANCnNlZ21lbnRlZC5pbWFnZSA9IHJlcGxpY2F0ZSgzLGNsYXNzaWZpY2F0aW9uLCBzaW1wbGlmeSA9IFQpDQpkaW0oc2VnbWVudGVkLmltYWdlKSA9IGRpbShpbWcpICANCmltYWdlU2hvdyhzZWdtZW50ZWQuaW1hZ2UpDQpgYGANCg0KYy4gR3VuYWthbiBwcm95ZWtzaSB5YW5nIG1lbXBlcnRhaGFua2FuIHZhcmlhYmlsaXRhcyBkYXRhIHNlYmFueWFrIG11bmdraW4gKGtvbXBvbmVuIHBlcnRhbWEgZGkgUENBKSBkYW4gdGVyYXBrYW4gRU0uIFZpc3VhbGlzYXNpa2FuIGhhc2lsbnlhLg0KDQpgYGB7cn0NCiMgUENBICsgRU0NCnMuaW1nLnZlY3QgPSBzY2FsZShpbWcudmVjdCkNCnNpZ21hID0gY292KGltZy52ZWN0KQ0KZWlnID0gZWlnZW4oc2lnbWEpDQplaWdlbnZlY3RvcnMgPSBlaWckdmVjdG9yc1ssMV0NCnByb2plY3Rpb24gPSBzLmltZy52ZWN0JSolIGVpZ2VudmVjdG9ycw0KDQpwcm9iID0gRU0ocHJvamVjdGlvbikNCmNsYXNzaWZpY2F0aW9uID0gKHByb2I+MC41KSswDQpzZWdtZW50ZWQuaW1hZ2UgPSByZXBsaWNhdGUoMyxjbGFzc2lmaWNhdGlvbiwgc2ltcGxpZnkgPSBUKQ0KZGltKHNlZ21lbnRlZC5pbWFnZSkgPSBkaW0oaW1nKSAgDQppbWFnZVNob3coc2VnbWVudGVkLmltYWdlKQ0KYGBgDQoNCmQuIEd1bmFrYW4gcHJveWVrc2kgUGVuY2FoYXlhYW4gJEwgPSAoMC4yMjksIDAuNTg4LiAwLjExNCkkIGRhbiB0YW1waWxrYW4gaGFzaWwgbWVuZXJhcGthbiBhbGdvcml0bWEgRU0uDQoNCmBgYHtyfQ0KIyBMdW1pbmFuY2UgKyBFTQ0KbHVtaW5hbmNlID0gYygwLjI5OSwgMC41ODcsIDAuMTE0KQ0KDQpwcm9qZWN0aW9uID0gaW1nLnZlY3QlKiVsdW1pbmFuY2UNCg0KcHJvYiA9IEVNKHByb2plY3Rpb24pDQpjbGFzc2lmaWNhdGlvbiA9IChwcm9iPjAuNSkrMA0Kc2VnbWVudGVkLmltYWdlID0gcmVwbGljYXRlKDMsY2xhc3NpZmljYXRpb24sIHNpbXBsaWZ5ID0gVCkNCmRpbShzZWdtZW50ZWQuaW1hZ2UpID0gZGltKGltZykgIA0KaW1hZ2VTaG93KHNlZ21lbnRlZC5pbWFnZSkNCmBgYA0KDQplLiBQYWRhIGFraGlybnlhLCBraXRhIGFrYW4gZ3VuYWthbiB2YXJpYW4gZGFyaSBhbGdvcml0bWEgSW5kZXBlbmRlbnQgSGlzdG9ncmFtIFB1cnN1aXQuIEFsZ29yaXRtYSBpbmkgbWVuZW11a2FuIHByb3lla3NpIHlhbmcgbWVtYWtzaW11bWthbiBhbXBsaXR1ZG8gYmltb2RhbC4gc2VrYWxpIHByb3lla3NpIGRpdGVtdWthbiwga2l0YSBsYW5qdXQga2UgY29udG9oIGxhdGloYW4gc2ViZWx1bW55YS4NCg0KYGBge3J9DQojIGxpYnJhcnkobW9kZXMpICMgQ291bGQgbm90IGZpbmQgYW5vdGhlciBwYWNrYWdlIHRvIHJlcGxhY2UgaXQNCiMgDQojICMgSW5kZXBlbmRlbnQgSGlzdG9ncmFtIFB1cnN1aXQNCiMgdGhldGEgPSBleHBhbmQuZ3JpZChzZXEoMSwzNjAsbGVuZ3RoLm91dCA9IDUwKSwgDQojICAgICAgICAgICAgICAgICAgICAgc2VxKDEsMzYwLGxlbmd0aC5vdXQgPSA1MCkpDQojIA0KIyB3ID0gbWF0cml4KDAsbnJvdyh0aGV0YSksMykNCiMgYW1wbGl0dWRlID0gcmVwKDAsIG5yb3codGhldGEpKQ0KIyBmb3IgKGkgaW4gMTpucm93KHRoZXRhKSl7DQojICAgd1tpLF0gPSBjKHNpbih0aGV0YVtpLDFdKSpjb3ModGhldGFbaSwyXSksDQojICAgICAgICAgICAgIHNpbih0aGV0YVtpLDFdKSpzaW4odGhldGFbaSwyXSksDQojICAgICAgICAgICAgIGNvcyh0aGV0YVtpLDFdKSkNCiMgICBhbXBsaXR1ZGVbaV0gPSBiaW1vZGFsaXR5X2FtcGxpdHVkZShpbWcudmVjdCUqJXdbaSxdLCBmaWcgPSBGKQ0KIyB9DQojIA0KIyBpbmQgPSB3aGljaC5tYXgoYW1wbGl0dWRlKQ0KIyB3Lm9wdCA9IHdbaW5kLF0NCiMgcHJvamVjdGlvbiA9IGltZy52ZWN0JSoldy5vcHQNCiMgDQojIHByb2IgPSBFTShwcm9qZWN0aW9uKQ0KIyBjbGFzc2lmaWNhdGlvbiA9IChwcm9iPjAuNSkrMA0KIyBzZWdtZW50ZWQuaW1hZ2UgPSByZXBsaWNhdGUoMyxjbGFzc2lmaWNhdGlvbiwgc2ltcGxpZnkgPSBUKQ0KIyBkaW0oc2VnbWVudGVkLmltYWdlKSA9IGRpbShpbWcpICANCiMgaW1hZ2VTaG93KHNlZ21lbnRlZC5pbWFnZSkNCmBgYA0KDQoNCg0KDQoNCg0KDQo=