Lab Analitik Bisnis CME Group Foundation

by Andrew Durrer

Source: https://www.rpubs.com/adurrer/bsadlab_08

1 Pendahuluan

Pada lab ini, kita akan fokus pada analisis sensitivitas dan simulasi Monte Carlo.

Analisis sensitivitas adalah studi mengenai bagaimana suatu ketidakpastian dalam suatu keluaran dari suatu model atau sistem matematika (numerik atau lainnya) dapat dibagi ke berbagai sumber ketidakpastian. Kita akan menggunakan package lpSolveAPI di R seperti yang kita lakukan di lab sebelumnya.

Simulasi Monte Carlo menggunakan pengambilan sampel acak berulang dari alam semesta atau populasi tertentu untuk mendapatkan hasil tertentu. Jenis simulasi ini dikenal sebagai simulasi probabilistik, bukan simulasi deterministik.

Contoh simulasi Monte Carlo adalah yang diterapkan untuk memperkirakan nilai pi. Simulasi ini didasarkan untuk menghasilkan titik-titik acak di dalam satuan persegi dan melihat berapa banyak titik yang berada dalam lingkaran yang dikelilingi oleh satuan persegi (yang ditandai dengan warna merah). Semakin tinggi jumlah titik sampel, semakin dekat hasilnya dengan hasil sebenarnya. Setelah memilih 30.000 titik secara acak, perkiraan untuk pi jauh lebih mendekati nilai sebenarnya dalam empat titik ketelitian desimal.

Di lab ini, kita akan mempelajari cara membuat sampel acak dengan berbagai simulasi dan yang dibahas sejauh ini adalah cara menjalankan analisis sensitivitas pada kasus penggunaan pemasaran.

2 Aturan

Ingatlah untuk selalu mengatur direktori kerja Anda ke lokasi sumber file Anda. Buka ‘Session’, geser ke bawah ke ‘Set Working Directory’, dan klik ‘To Source File Location’. Bacalah dengan teliti di bawah ini dan ikuti instruksi untuk menyelesaikan tugas dan menjawab pertanyaan apa pun. Kirimkan pekerjaan Anda ke RPubs seperti yang dijelaskan di catatan sebelumnya.

3 Catatan

Untuk tugas Anda, Anda mungkin menggunakan kumpulan data yang berbeda dari yang disertakan di sini. Selalu baca dengan seksama instruksi di Sakai. Tugas / pertanyaan yang harus diselesaikan / dijawab dan ditandai dengan huruf tebal yang lebih besar dan diberi nomor sesuai dengan penempatannya di bagian tugas.

4 Bagian A: Analisis Sensitivitas

Untuk melakukan analisis sensitivitas, kita perlu mengunduh lagi package lpSolveAPI kecuali Anda sudah menginstallnya di R Anda.

# Require will load the package only if not installed 
# Dependencies = TRUE makes sure that dependencies are install
if(!require("lpSolveAPI",quietly = TRUE))
  install.packages("lpSolveAPI",dependencies = TRUE, repos = "https://cloud.r-project.org")

Kita akan mengingat kembali dan menyelesaikan lagi kasus pemasaran yang dibahas di kelas (juga bagian dari lab sebelumnya).

library(lpSolveAPI)

# We start with `0` constraint and `2` decision variables. The object name `lpmark` is discretionary.
lpmark2 = make.lp(0, 2)

# Define type of optimization as maximum and dump the screen output into a `dummy` variable
dummy = lp.control(lpmark2, sense="max") 

# Set the objective function coefficients 
set.objfn(lpmark2, c(275.691, 48.341))

#Add all constraints to the model
add.constraint(lpmark2, c(1, 1), "<=", 350001)
add.constraint(lpmark2, c(1, 0), ">=", 15000)
add.constraint(lpmark2, c(0, 1), ">=", 75000)
add.constraint(lpmark2, c(2, -1), "=", 1)
add.constraint(lpmark2, c(1, 0), ">=", 0)
add.constraint(lpmark2, c(0, 1), ">=", 0)

#Show the problem setting in tabular/matrix form. It's useful to see if our contraints have been properly set.
lpmark2
## Model name: 
##                C1       C2            
## Maximize  275.691   48.341            
## R1              1        1  <=  350001
## R2              1        0  >=   15000
## R3              0        1  >=   75000
## R4              2       -1   =       1
## R5              1        0  >=       0
## R6              0        1  >=       0
## Kind          Std      Std            
## Type         Real     Real            
## Upper         Inf      Inf            
## Lower           0        0
#Solve the linear programming problem
solve(lpmark2)
## [1] 0
#The next two lines of codes will show the optimum results.
#Frist: Display the objective function optimum value i.e. the optimum sales value.
get.objective(lpmark2)
## [1] 43443717
#Second: Display the decision variables optimum values i.e. the optimum values for radio and tv ads.
get.variables(lpmark2) 
## [1] 116667.3 233333.7

Untuk bagian sensitivitas, kita akan menambahkan dua kode baru untuk mendapatkan hasil sensitivitas.

#Display sensitivity to the COEFFICIENTS of objective function. 
get.sensitivity.obj(lpmark2)
## $objfrom
## [1]  -96.6820 -137.8455
## 
## $objtill
## [1] 1e+30 1e+30

5 Tugas 1

Hasilnya memiliki dua bagian yaitu: data yg dihasilkan berlabel objfrom dimana data tersebut menunjukkan batas bawah koefisien sedangkan data yg dihasilkan berlabel objtill menunjukkan batas atasnya. Jelaskan secara bersamaan apa yang diwakili oleh hasil sensitivitas dengan mengacu pada model pemasaran.

5.1 Jawaban Tugas 1

Objek menunjukkan berapa jumlah terendah dari setiap variabel harus agar dari persamaan dapat dipenuhi tanpa perlu dioptimalkan dan keberatan adalah angka yang sangat besar

#Display sensitivity to the CONSTRAINTS (or the right hand side values). 
#There will be a total of m+n values where m is the number of contraints and n is the number of decision variables
get.sensitivity.rhs(lpmark2) 
## $duals
## [1] 124.12433   0.00000   0.00000  75.78333   0.00000   0.00000   0.00000
## [8]   0.00000
## 
## $dualsfrom
## [1]  1.125005e+05 -1.000000e+30 -1.000000e+30 -3.050010e+05 -1.000000e+30
## [6] -1.000000e+30 -1.000000e+30 -1.000000e+30
## 
## $dualstill
## [1] 1.00000e+30 1.00000e+30 1.00000e+30 4.75002e+05 1.00000e+30 1.00000e+30
## [7] 1.00000e+30 1.00000e+30

6 Tugas 2

Untuk latihan ini, kita hanya tertarik pada bagian pertama dari keluaran yang diberi label duals. Jelaskan secara bersamaan apa yang diwakili oleh dua hasil sensitivitas bukan nol. Dalam jawaban Anda, bedakan antara batasan yang mengikat dan tidak mengikat, dan sertakan penjelasan tentang kelebihan / kekurangan, dan mengenai nilai-nilai marjinal.

6.1 Jawaban Tugas 2

Hasil bukan nol mewakili kendala tidak mengikat yang berarti bahwa saat varibale meningkat, solusi optimal tidak terpengaruh. dengan kata lain memiliki kelonggaran untuk “bergerak” sementara batasan pengikatan terbatas dan akan mempengaruhi solusi optimal jika ditingkatkan. Ini juga berarti bahwa ada nilai marjinal jika diikat dan oleh karena itu dipengaruhi oleh perubahan.

Untuk memperoleh pemahaman yang lebih baik tentang hasil sensitivitas, dan untuk memastikan integritas kalkulasi, uji independen dapat dilakukan.

7 Tugas 3

Jalankan lagi pemecah program linier mulai dari awal, dengan menentukan objek model baru lpmark1. Semuanya sama, ubah batasan anggaran hanya dengan 1 dollar dan selesaikan. Secara spesifik, semua sama, ubah batasan pertama \(X1 + X2 <= 350000\) hanya dengan 1 dollar, sehingga batasan baru akan menjadi \(X1 + X2 <= 350001\). Catat nilai optimal untuk penjualan seperti yang diberikan oleh fungsi tujuan.

# Define a new model object called lpmark1
lpmark1 = make.lp(0, 2)
# Repeat rest of commands with the one constraint change for budget. Solve and display the objective function optimum value

8 Tugas 4

Hitung perubahan diferensial dalam penjualan. Bagikan pengamatan Anda.

8.1 Jawaban Tugas 4

Saya tidak melihat perubahan didalam penjualan.

9 Tugas 5

Menjalankan pemecah program linier lagi mulai dari awal, dengan menetapkan objek model baru lpmark2. Semua dianggap sama, ubah batasan keempat \(2X1 - X2 = 0\) dengan hanya 1 dollar dan selesaikan. Batasan baru akan menjadi \(2X1 - X2 = 1\). Catat nilai optimal untuk penjualan seperti yang diberikan oleh fungsi tujuan.

# Define a new model object called lpmark2
lpmark2 = make.lp(0, 2)
# Repeat rest of commands with the above constraint changed. Solve and display the objective function optimum value

10 Tugas 6

Hitung perubahan diferensial dalam penjualan. Bagikan pengamatan Anda.

10.1 Jawaban Tugas 6

Perbedaan meningkat antara lpmark1 dan ini berjalan.

11 BAGIAN B: SIMULASI MONTE CARLO

Untuk tugas ini, kita akan menjalankan simulasi Monte Carlo untuk menghitung probabilitas bahwa pengembalian harian dari S&P akan > 5%. Kita akan mengasumsikan bahwa laba harian S&P historis mengikuti distribusi normal dengan pengembalian harian rata-rata 0,03 (%) dan deviasi standar 0,97 (%).

Untuk permulaan, kita akan membuat 100 sampel acak dari suatu distribusi normal. Untuk sampel yang dibuat, kita akan menghitung rata-rata, standar deviasi, dan probabilitas kejadian dimana hasil simulasi lebih besar dari 5%.

Untuk menghasilkan sampel acak dari distribusi normal, kita akan menggunakan fungsi rnorm () di R. Pada dicontoh di bawah ini, kita menetapkan jumlah proses (atau sampel) menjadi 100.

# number of simulations/samples
runs2 = 10000
# random number generator per defined normal distribution with given mean and standard deviation
sims2 =  rnorm(runs2,mean=0.03,sd=0.97)
# Mean calculated from the random distribution of samples
average2 = mean(sims2)
average2
## [1] 0.03245042
# Mean calculated from the random distribution of samples
average2 = mean(sims2)
average2
## [1] 0.03245042
# probability of occurrence on any given day based on samples will be equal to count (or sum) where sample result is greater than 5% divided by total number of samples. 
prob2 = sum(sims2 >=0.05)/runs2
prob2
## [1] 0.4947

12 Tugas 7

Ulangi perhitungan di atas untuk kasus di mana jumlah simulasi / sampel sama dengan 1000. Catat mean, deviasi standar, dan probabilitas. Beri nama semua variabel yang diperlukan sebagai run1, sims1, average1, std1, dan prob1.

# Repeat calculations here
runs1=1000
average1=0.02195311
std1=0.9513167
prob1=0.505

13 Tugas 8

Ulangi kalkulasi di atas untuk kasus dimana jumlah simulasi / sampel sama dengan 10000. Catat mean, deviasi standar, dan probabilitas. Beri nama semua variabel yang diperlukan sebagai run2, sims2, average2, std2, dan prob2.

# Repeat calculations here
runs2=10000
average2=0.02928042
std2=0.9636561
prob2=0.4891

14 Tugas 9

Catat didalam bentuk tabel nilai mean, deviasi standar, dan probabilitas untuk ketiga kasus: simulasi 100, 1000, dan 10000.

15 Tugas 10

Jelaskan bagaimana nilai berubah / berperilaku saat jumlah simulasi bertambah. Apa taruhan terbaik Anda untuk kemungkinan terjadinya lebih besar dari 5% dan mengapa? Bagaimana ini mirip dengan kasus penggunaan gambar untuk menghitung pi yang disajikan di paragraf pengantar?

15.1 Jawaban Tugas 10

Secara umum, dengan semakin banyak simulasi, semakin akurat prediksinya sehingga standar deviasi menjadi lebih ketat dan probabilitasnya meningkat seiring berjalannya waktu. Sekitar separuh waktu pengembalian lebih besar dari 5%. Ini mirp dalam arti bahwa semakin banyak variasi yang ditambahkan, semakin akurat prediksinya dan semakin representatif angkanya di dunia nyata.

Latihan 2C yang terakhir adalah opsional bagi mereka yang tertarik untuk lebih meningkatkan pembelajaran materi pelajaran mereka, dan menyempurnakan keterampilan mereka dalam R. Pekerjaan Anda akan dinilai tetapi Anda tidak akan dinilai untuk latihan ini. Anda dapat mengikuti petunjuk yang disajikan dalam video contoh setara Excel di [https://www.youtube.com/watch?v=wKdmEXCvo9s].

Ulangi latihan untuk pengembalian harian S&P di mana semuanya sama kecuali kita sekarang tertarik pengembalian kumulatif mingguan dan probabilitas bahwa pengembalian kumulatif mingguan lebih besar dari 5%. Atur jumlah simulasi menjadi 10000.

LS0tDQp0aXRsZTogIk9wdGltaXphdGlvbi1MYWI5LUJ1c2luZXNzLUFuYWx5dGljcyINCmF1dGhvcjogIllvbmF0aGFuIEFuZ2dyYWl3YW4iDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclQiAlZCwgJVknKWAiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50OiANCiAgICBoaWdobGlnaHQ6IG1vbm9jaHJvbWUNCiAgICB0aGVtZTogc3BhY2VsYWINCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCi0tLQ0KDQpgYGB7ciBMb2dvLGVjaG89RkFMU0UsZmlnLmFsaWduPSdjZW50ZXInLCBvdXQud2lkdGggPSAnNDAlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJDOi9Vc2Vycy9Zb25hdGhhbi9Eb3dubG9hZHMvbG9nb21hdGFuYS5qcGciKQ0KYGBgDQoqTGFiIEFuYWxpdGlrIEJpc25pcyBDTUUgR3JvdXAgRm91bmRhdGlvbioNCg0KKmJ5IEFuZHJldyBEdXJyZXIqDQoNCipTb3VyY2U6IGh0dHBzOi8vd3d3LnJwdWJzLmNvbS9hZHVycmVyL2JzYWRsYWJfMDgqDQoNCiMgUGVuZGFodWx1YW4NCg0KUGFkYSBsYWIgaW5pLCBraXRhIGFrYW4gZm9rdXMgcGFkYSBhbmFsaXNpcyBzZW5zaXRpdml0YXMgZGFuIHNpbXVsYXNpIE1vbnRlIENhcmxvLg0KDQpBbmFsaXNpcyBzZW5zaXRpdml0YXMgYWRhbGFoIHN0dWRpIG1lbmdlbmFpIGJhZ2FpbWFuYSBzdWF0dSBrZXRpZGFrcGFzdGlhbiBkYWxhbSBzdWF0dSBrZWx1YXJhbiBkYXJpIHN1YXR1IG1vZGVsIGF0YXUgc2lzdGVtIG1hdGVtYXRpa2EgKG51bWVyaWsgYXRhdSBsYWlubnlhKSBkYXBhdCBkaWJhZ2kga2UgYmVyYmFnYWkgc3VtYmVyIGtldGlkYWtwYXN0aWFuLiBLaXRhIGFrYW4gbWVuZ2d1bmFrYW4gcGFja2FnZSBgbHBTb2x2ZUFQSWAgZGkgUiBzZXBlcnRpIHlhbmcga2l0YSBsYWt1a2FuIGRpIGxhYiBzZWJlbHVtbnlhLg0KDQpTaW11bGFzaSBNb250ZSBDYXJsbyBtZW5nZ3VuYWthbiBwZW5nYW1iaWxhbiBzYW1wZWwgYWNhayBiZXJ1bGFuZyBkYXJpIGFsYW0gc2VtZXN0YSBhdGF1IHBvcHVsYXNpIHRlcnRlbnR1IHVudHVrIG1lbmRhcGF0a2FuIGhhc2lsIHRlcnRlbnR1LiBKZW5pcyBzaW11bGFzaSBpbmkgZGlrZW5hbCBzZWJhZ2FpIHNpbXVsYXNpIHByb2JhYmlsaXN0aWssIGJ1a2FuIHNpbXVsYXNpIGRldGVybWluaXN0aWsuDQoNCkNvbnRvaCBzaW11bGFzaSBNb250ZSBDYXJsbyBhZGFsYWggeWFuZyBkaXRlcmFwa2FuIHVudHVrIG1lbXBlcmtpcmFrYW4gbmlsYWkgYHBpYC4gU2ltdWxhc2kgaW5pIGRpZGFzYXJrYW4gdW50dWsgbWVuZ2hhc2lsa2FuIHRpdGlrLXRpdGlrIGFjYWsgZGkgZGFsYW0gc2F0dWFuIHBlcnNlZ2kgZGFuIG1lbGloYXQgYmVyYXBhIGJhbnlhayB0aXRpayB5YW5nIGJlcmFkYSBkYWxhbSBsaW5na2FyYW4geWFuZyBkaWtlbGlsaW5naSBvbGVoIHNhdHVhbiBwZXJzZWdpICh5YW5nIGRpdGFuZGFpIGRlbmdhbiB3YXJuYSBtZXJhaCkuIFNlbWFraW4gdGluZ2dpIGp1bWxhaCB0aXRpayBzYW1wZWwsIHNlbWFraW4gZGVrYXQgaGFzaWxueWEgZGVuZ2FuIGhhc2lsIHNlYmVuYXJueWEuIFNldGVsYWggbWVtaWxpaCAzMC4wMDAgdGl0aWsgc2VjYXJhIGFjYWssIHBlcmtpcmFhbiB1bnR1ayBgcGlgIGphdWggbGViaWggbWVuZGVrYXRpIG5pbGFpIHNlYmVuYXJueWEgZGFsYW0gZW1wYXQgdGl0aWsga2V0ZWxpdGlhbiBkZXNpbWFsLg0KIA0KYGBge3IsIGVjaG89RkFMU0UsZmlnLmFsaWduPSdsZWZ0JyxmaWcuY2FwPSIiLCBvdXQud2lkdGggPSAnMjAlJ30NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJnYW1iYXIxLmdpZiIpDQpgYGANCg0KRGkgbGFiIGluaSwga2l0YSBha2FuIG1lbXBlbGFqYXJpIGNhcmEgbWVtYnVhdCBzYW1wZWwgYWNhayBkZW5nYW4gYmVyYmFnYWkgc2ltdWxhc2kgZGFuICB5YW5nIGRpYmFoYXMgc2VqYXVoIGluaSBhZGFsYWggY2FyYSBtZW5qYWxhbmthbiBhbmFsaXNpcyBzZW5zaXRpdml0YXMgcGFkYSBrYXN1cyBwZW5nZ3VuYWFuIHBlbWFzYXJhbi4NCg0KIyBBdHVyYW4NCg0KSW5nYXRsYWggdW50dWsgc2VsYWx1IG1lbmdhdHVyIGRpcmVrdG9yaSBrZXJqYSBBbmRhIGtlIGxva2FzaSBzdW1iZXIgZmlsZSBBbmRhLiBCdWthICdTZXNzaW9uJywgZ2VzZXIga2UgYmF3YWgga2UgJ1NldCBXb3JraW5nIERpcmVjdG9yeScsIGRhbiBrbGlrICdUbyBTb3VyY2UgRmlsZSBMb2NhdGlvbicuIEJhY2FsYWggZGVuZ2FuIHRlbGl0aSBkaSBiYXdhaCBpbmkgZGFuIGlrdXRpIGluc3RydWtzaSB1bnR1ayBtZW55ZWxlc2Fpa2FuIHR1Z2FzIGRhbiBtZW5qYXdhYiBwZXJ0YW55YWFuIGFwYSBwdW4uIEtpcmlta2FuIHBla2VyamFhbiBBbmRhIGtlIFJQdWJzIHNlcGVydGkgeWFuZyBkaWplbGFza2FuIGRpIGNhdGF0YW4gc2ViZWx1bW55YS4NCg0KIyBDYXRhdGFuDQoNClVudHVrIHR1Z2FzIEFuZGEsIEFuZGEgbXVuZ2tpbiBtZW5nZ3VuYWthbiBrdW1wdWxhbiBkYXRhIHlhbmcgYmVyYmVkYSBkYXJpIHlhbmcgZGlzZXJ0YWthbiBkaSBzaW5pLiBTZWxhbHUgYmFjYSBkZW5nYW4gc2Vrc2FtYSBpbnN0cnVrc2kgZGkgU2FrYWkuIFR1Z2FzIC8gcGVydGFueWFhbiB5YW5nIGhhcnVzIGRpc2VsZXNhaWthbiAvIGRpamF3YWIgZGFuIGRpdGFuZGFpIGRlbmdhbiBodXJ1ZiB0ZWJhbCB5YW5nIGxlYmloIGJlc2FyIGRhbiBkaWJlcmkgbm9tb3Igc2VzdWFpIGRlbmdhbiBwZW5lbXBhdGFubnlhIGRpIGJhZ2lhbiB0dWdhcy4NCg0KIyBCYWdpYW4gQTogQW5hbGlzaXMgU2Vuc2l0aXZpdGFzDQoNClVudHVrIG1lbGFrdWthbiBhbmFsaXNpcyBzZW5zaXRpdml0YXMsIGtpdGEgcGVybHUgbWVuZ3VuZHVoIGxhZ2kgcGFja2FnZSBgbHBTb2x2ZUFQSWAga2VjdWFsaSBBbmRhIHN1ZGFoIG1lbmdpbnN0YWxsbnlhIGRpIFIgQW5kYS4NCg0KYGBge3J9DQojIFJlcXVpcmUgd2lsbCBsb2FkIHRoZSBwYWNrYWdlIG9ubHkgaWYgbm90IGluc3RhbGxlZCANCiMgRGVwZW5kZW5jaWVzID0gVFJVRSBtYWtlcyBzdXJlIHRoYXQgZGVwZW5kZW5jaWVzIGFyZSBpbnN0YWxsDQppZighcmVxdWlyZSgibHBTb2x2ZUFQSSIscXVpZXRseSA9IFRSVUUpKQ0KICBpbnN0YWxsLnBhY2thZ2VzKCJscFNvbHZlQVBJIixkZXBlbmRlbmNpZXMgPSBUUlVFLCByZXBvcyA9ICJodHRwczovL2Nsb3VkLnItcHJvamVjdC5vcmciKQ0KYGBgDQoNCktpdGEgYWthbiBtZW5naW5nYXQga2VtYmFsaSBkYW4gbWVueWVsZXNhaWthbiBsYWdpIGthc3VzIHBlbWFzYXJhbiB5YW5nIGRpYmFoYXMgZGkga2VsYXMgKGp1Z2EgYmFnaWFuIGRhcmkgbGFiIHNlYmVsdW1ueWEpLg0KDQpgYGB7cn0NCmxpYnJhcnkobHBTb2x2ZUFQSSkNCg0KIyBXZSBzdGFydCB3aXRoIGAwYCBjb25zdHJhaW50IGFuZCBgMmAgZGVjaXNpb24gdmFyaWFibGVzLiBUaGUgb2JqZWN0IG5hbWUgYGxwbWFya2AgaXMgZGlzY3JldGlvbmFyeS4NCmxwbWFyazIgPSBtYWtlLmxwKDAsIDIpDQoNCiMgRGVmaW5lIHR5cGUgb2Ygb3B0aW1pemF0aW9uIGFzIG1heGltdW0gYW5kIGR1bXAgdGhlIHNjcmVlbiBvdXRwdXQgaW50byBhIGBkdW1teWAgdmFyaWFibGUNCmR1bW15ID0gbHAuY29udHJvbChscG1hcmsyLCBzZW5zZT0ibWF4IikgDQoNCiMgU2V0IHRoZSBvYmplY3RpdmUgZnVuY3Rpb24gY29lZmZpY2llbnRzIA0Kc2V0Lm9iamZuKGxwbWFyazIsIGMoMjc1LjY5MSwgNDguMzQxKSkNCg0KI0FkZCBhbGwgY29uc3RyYWludHMgdG8gdGhlIG1vZGVsDQphZGQuY29uc3RyYWludChscG1hcmsyLCBjKDEsIDEpLCAiPD0iLCAzNTAwMDEpDQphZGQuY29uc3RyYWludChscG1hcmsyLCBjKDEsIDApLCAiPj0iLCAxNTAwMCkNCmFkZC5jb25zdHJhaW50KGxwbWFyazIsIGMoMCwgMSksICI+PSIsIDc1MDAwKQ0KYWRkLmNvbnN0cmFpbnQobHBtYXJrMiwgYygyLCAtMSksICI9IiwgMSkNCmFkZC5jb25zdHJhaW50KGxwbWFyazIsIGMoMSwgMCksICI+PSIsIDApDQphZGQuY29uc3RyYWludChscG1hcmsyLCBjKDAsIDEpLCAiPj0iLCAwKQ0KDQojU2hvdyB0aGUgcHJvYmxlbSBzZXR0aW5nIGluIHRhYnVsYXIvbWF0cml4IGZvcm0uIEl0J3MgdXNlZnVsIHRvIHNlZSBpZiBvdXIgY29udHJhaW50cyBoYXZlIGJlZW4gcHJvcGVybHkgc2V0Lg0KbHBtYXJrMg0KYGBgDQoNCmBgYHtyfQ0KI1NvbHZlIHRoZSBsaW5lYXIgcHJvZ3JhbW1pbmcgcHJvYmxlbQ0Kc29sdmUobHBtYXJrMikNCmBgYA0KDQpgYGB7cn0NCiNUaGUgbmV4dCB0d28gbGluZXMgb2YgY29kZXMgd2lsbCBzaG93IHRoZSBvcHRpbXVtIHJlc3VsdHMuDQojRnJpc3Q6IERpc3BsYXkgdGhlIG9iamVjdGl2ZSBmdW5jdGlvbiBvcHRpbXVtIHZhbHVlIGkuZS4gdGhlIG9wdGltdW0gc2FsZXMgdmFsdWUuDQpnZXQub2JqZWN0aXZlKGxwbWFyazIpDQpgYGANCg0KYGBge3J9DQojU2Vjb25kOiBEaXNwbGF5IHRoZSBkZWNpc2lvbiB2YXJpYWJsZXMgb3B0aW11bSB2YWx1ZXMgaS5lLiB0aGUgb3B0aW11bSB2YWx1ZXMgZm9yIHJhZGlvIGFuZCB0diBhZHMuDQpnZXQudmFyaWFibGVzKGxwbWFyazIpIA0KYGBgDQpVbnR1ayBiYWdpYW4gc2Vuc2l0aXZpdGFzLCBraXRhIGFrYW4gbWVuYW1iYWhrYW4gZHVhIGtvZGUgYmFydSB1bnR1ayBtZW5kYXBhdGthbiBoYXNpbCBzZW5zaXRpdml0YXMuDQoNCmBgYHtyfQ0KI0Rpc3BsYXkgc2Vuc2l0aXZpdHkgdG8gdGhlIENPRUZGSUNJRU5UUyBvZiBvYmplY3RpdmUgZnVuY3Rpb24uIA0KZ2V0LnNlbnNpdGl2aXR5Lm9iaihscG1hcmsyKQ0KYGBgDQoNCiMgVHVnYXMgMQ0KSGFzaWxueWEgbWVtaWxpa2kgZHVhIGJhZ2lhbiB5YWl0dTogZGF0YSB5ZyBkaWhhc2lsa2FuIGJlcmxhYmVsIGBvYmpmcm9tYCBkaW1hbmEgZGF0YSB0ZXJzZWJ1dCBtZW51bmp1a2thbiBiYXRhcyBiYXdhaCBrb2VmaXNpZW4gc2VkYW5na2FuIGRhdGEgeWcgZGloYXNpbGthbiBiZXJsYWJlbCBgb2JqdGlsbGAgbWVudW5qdWtrYW4gYmF0YXMgYXRhc255YS4gSmVsYXNrYW4gc2VjYXJhIGJlcnNhbWFhbiBhcGEgeWFuZyBkaXdha2lsaSBvbGVoIGhhc2lsIHNlbnNpdGl2aXRhcyBkZW5nYW4gbWVuZ2FjdSBwYWRhIG1vZGVsIHBlbWFzYXJhbi4NCg0KIyMgSmF3YWJhbiBUdWdhcyAxDQpPYmplayBtZW51bmp1a2thbiBiZXJhcGEganVtbGFoIHRlcmVuZGFoIGRhcmkgc2V0aWFwIHZhcmlhYmVsIGhhcnVzIGFnYXIgZGFyaSBwZXJzYW1hYW4gZGFwYXQgZGlwZW51aGkgdGFucGEgcGVybHUgZGlvcHRpbWFsa2FuIGRhbiBrZWJlcmF0YW4gYWRhbGFoIGFuZ2thIHlhbmcgc2FuZ2F0IGJlc2FyDQogDQpgYGB7cn0NCiNEaXNwbGF5IHNlbnNpdGl2aXR5IHRvIHRoZSBDT05TVFJBSU5UUyAob3IgdGhlIHJpZ2h0IGhhbmQgc2lkZSB2YWx1ZXMpLiANCiNUaGVyZSB3aWxsIGJlIGEgdG90YWwgb2YgbStuIHZhbHVlcyB3aGVyZSBtIGlzIHRoZSBudW1iZXIgb2YgY29udHJhaW50cyBhbmQgbiBpcyB0aGUgbnVtYmVyIG9mIGRlY2lzaW9uIHZhcmlhYmxlcw0KZ2V0LnNlbnNpdGl2aXR5LnJocyhscG1hcmsyKSANCmBgYA0KIyBUdWdhcyAyDQpVbnR1ayBsYXRpaGFuIGluaSwga2l0YSBoYW55YSB0ZXJ0YXJpayBwYWRhIGJhZ2lhbiBwZXJ0YW1hIGRhcmkga2VsdWFyYW4geWFuZyBkaWJlcmkgbGFiZWwgYGR1YWxzYC4gSmVsYXNrYW4gc2VjYXJhIGJlcnNhbWFhbiBhcGEgeWFuZyBkaXdha2lsaSBvbGVoIGR1YSBoYXNpbCBzZW5zaXRpdml0YXMgYnVrYW4gbm9sLiBEYWxhbSBqYXdhYmFuIEFuZGEsIGJlZGFrYW4gYW50YXJhIGJhdGFzYW4geWFuZyBtZW5naWthdCBkYW4gdGlkYWsgbWVuZ2lrYXQsIGRhbiBzZXJ0YWthbiBwZW5qZWxhc2FuIHRlbnRhbmcga2VsZWJpaGFuIC8ga2VrdXJhbmdhbiwgZGFuIG1lbmdlbmFpIG5pbGFpLW5pbGFpIG1hcmppbmFsLg0KIA0KIyMgSmF3YWJhbiBUdWdhcyAyDQpIYXNpbCBidWthbiBub2wgbWV3YWtpbGkga2VuZGFsYSB0aWRhayBtZW5naWthdCB5YW5nIGJlcmFydGkgYmFod2Egc2FhdCB2YXJpYmFsZSBtZW5pbmdrYXQsIHNvbHVzaSBvcHRpbWFsIHRpZGFrIHRlcnBlbmdhcnVoLiBkZW5nYW4ga2F0YSBsYWluIG1lbWlsaWtpIGtlbG9uZ2dhcmFuIHVudHVrICJiZXJnZXJhayIgc2VtZW50YXJhIGJhdGFzYW4gcGVuZ2lrYXRhbiB0ZXJiYXRhcyBkYW4gYWthbiBtZW1wZW5nYXJ1aGkgc29sdXNpIG9wdGltYWwgamlrYSBkaXRpbmdrYXRrYW4uIEluaSBqdWdhIGJlcmFydGkgYmFod2EgYWRhIG5pbGFpIG1hcmppbmFsIGppa2EgZGlpa2F0IGRhbiBvbGVoIGthcmVuYSBpdHUgZGlwZW5nYXJ1aGkgb2xlaCBwZXJ1YmFoYW4uDQoNClVudHVrIG1lbXBlcm9sZWggcGVtYWhhbWFuIHlhbmcgbGViaWggYmFpayB0ZW50YW5nIGhhc2lsIHNlbnNpdGl2aXRhcywgZGFuIHVudHVrIG1lbWFzdGlrYW4gaW50ZWdyaXRhcyBrYWxrdWxhc2ksIHVqaSBpbmRlcGVuZGVuIGRhcGF0IGRpbGFrdWthbi4NCg0KIyBUdWdhcyAzIA0KSmFsYW5rYW4gbGFnaSBwZW1lY2FoIHByb2dyYW0gbGluaWVyIG11bGFpIGRhcmkgYXdhbCwgZGVuZ2FuIG1lbmVudHVrYW4gb2JqZWsgbW9kZWwgYmFydSBgbHBtYXJrMWAuIFNlbXVhbnlhIHNhbWEsIHViYWggYmF0YXNhbiBhbmdnYXJhbiBoYW55YSBkZW5nYW4gIDEgZG9sbGFyIGRhbiBzZWxlc2Fpa2FuLiBTZWNhcmEgc3Blc2lmaWssIHNlbXVhIHNhbWEsIHViYWggYmF0YXNhbiBwZXJ0YW1hICRYMSArIFgyIDw9IDM1MDAwMCQgaGFueWEgZGVuZ2FuIDEgZG9sbGFyLCBzZWhpbmdnYSBiYXRhc2FuIGJhcnUgYWthbiBtZW5qYWRpICRYMSArIFgyIDw9IDM1MDAwMSQuIENhdGF0IG5pbGFpIG9wdGltYWwgdW50dWsgcGVuanVhbGFuIHNlcGVydGkgeWFuZyBkaWJlcmlrYW4gb2xlaCBmdW5nc2kgdHVqdWFuLg0KDQpgYGB7cn0NCiMgRGVmaW5lIGEgbmV3IG1vZGVsIG9iamVjdCBjYWxsZWQgbHBtYXJrMQ0KbHBtYXJrMSA9IG1ha2UubHAoMCwgMikNCiMgUmVwZWF0IHJlc3Qgb2YgY29tbWFuZHMgd2l0aCB0aGUgb25lIGNvbnN0cmFpbnQgY2hhbmdlIGZvciBidWRnZXQuIFNvbHZlIGFuZCBkaXNwbGF5IHRoZSBvYmplY3RpdmUgZnVuY3Rpb24gb3B0aW11bSB2YWx1ZQ0KYGBgDQoNCiMgVHVnYXMgNA0KSGl0dW5nIHBlcnViYWhhbiBkaWZlcmVuc2lhbCBkYWxhbSBwZW5qdWFsYW4uIEJhZ2lrYW4gcGVuZ2FtYXRhbiBBbmRhLg0KDQojIyBKYXdhYmFuIFR1Z2FzIDQNClNheWEgdGlkYWsgbWVsaWhhdCBwZXJ1YmFoYW4gZGlkYWxhbSBwZW5qdWFsYW4uDQoNCiMgVHVnYXMgNQ0KTWVuamFsYW5rYW4gcGVtZWNhaCBwcm9ncmFtIGxpbmllciBsYWdpIG11bGFpIGRhcmkgYXdhbCwgZGVuZ2FuIG1lbmV0YXBrYW4gb2JqZWsgbW9kZWwgYmFydSBscG1hcmsyLiBTZW11YSBkaWFuZ2dhcCBzYW1hLCB1YmFoIGJhdGFzYW4ga2VlbXBhdCAkMlgxIC0gWDIgPSAwJCBkZW5nYW4gaGFueWEgMSBkb2xsYXIgZGFuIHNlbGVzYWlrYW4uIEJhdGFzYW4gYmFydSBha2FuIG1lbmphZGkgJDJYMSAtIFgyID0gMSQuIENhdGF0IG5pbGFpIG9wdGltYWwgdW50dWsgcGVuanVhbGFuIHNlcGVydGkgeWFuZyBkaWJlcmlrYW4gb2xlaCBmdW5nc2kgdHVqdWFuLg0KDQpgYGB7cn0NCiMgRGVmaW5lIGEgbmV3IG1vZGVsIG9iamVjdCBjYWxsZWQgbHBtYXJrMg0KbHBtYXJrMiA9IG1ha2UubHAoMCwgMikNCiMgUmVwZWF0IHJlc3Qgb2YgY29tbWFuZHMgd2l0aCB0aGUgYWJvdmUgY29uc3RyYWludCBjaGFuZ2VkLiBTb2x2ZSBhbmQgZGlzcGxheSB0aGUgb2JqZWN0aXZlIGZ1bmN0aW9uIG9wdGltdW0gdmFsdWUNCmBgYA0KDQojIFR1Z2FzIDYNCkhpdHVuZyBwZXJ1YmFoYW4gZGlmZXJlbnNpYWwgZGFsYW0gcGVuanVhbGFuLiBCYWdpa2FuIHBlbmdhbWF0YW4gQW5kYS4NCg0KIyMgSmF3YWJhbiBUdWdhcyA2DQpQZXJiZWRhYW4gbWVuaW5na2F0IGFudGFyYSBscG1hcmsxIGRhbiBpbmkgYmVyamFsYW4uDQoNCiMgQkFHSUFOIEI6IFNJTVVMQVNJIE1PTlRFIENBUkxPDQoNClVudHVrIHR1Z2FzIGluaSwga2l0YSBha2FuIG1lbmphbGFua2FuIHNpbXVsYXNpIE1vbnRlIENhcmxvIHVudHVrIG1lbmdoaXR1bmcgcHJvYmFiaWxpdGFzIGJhaHdhIHBlbmdlbWJhbGlhbiBoYXJpYW4gZGFyaSBTJlAgYWthbiA+IDUlLiBLaXRhIGFrYW4gbWVuZ2FzdW1zaWthbiBiYWh3YSBsYWJhIGhhcmlhbiBTJlAgaGlzdG9yaXMgbWVuZ2lrdXRpIGRpc3RyaWJ1c2kgbm9ybWFsIGRlbmdhbiBwZW5nZW1iYWxpYW4gaGFyaWFuIHJhdGEtcmF0YSAwLDAzICglKSBkYW4gZGV2aWFzaSBzdGFuZGFyIDAsOTcgKCUpLg0KDQpVbnR1ayBwZXJtdWxhYW4sIGtpdGEgYWthbiBtZW1idWF0IDEwMCBzYW1wZWwgYWNhayBkYXJpIHN1YXR1IGRpc3RyaWJ1c2kgbm9ybWFsLiBVbnR1ayBzYW1wZWwgeWFuZyBkaWJ1YXQsIGtpdGEgYWthbiBtZW5naGl0dW5nIHJhdGEtcmF0YSwgc3RhbmRhciBkZXZpYXNpLCBkYW4gcHJvYmFiaWxpdGFzIGtlamFkaWFuIGRpbWFuYSBoYXNpbCBzaW11bGFzaSBsZWJpaCBiZXNhciBkYXJpIDUlLg0KDQpVbnR1ayBtZW5naGFzaWxrYW4gc2FtcGVsIGFjYWsgZGFyaSBkaXN0cmlidXNpIG5vcm1hbCwga2l0YSBha2FuIG1lbmdndW5ha2FuIGZ1bmdzaSBgcm5vcm0gKClgIGRpIFIuIFBhZGEgZGljb250b2ggZGkgYmF3YWggaW5pLCBraXRhIG1lbmV0YXBrYW4ganVtbGFoIHByb3NlcyAoYXRhdSBzYW1wZWwpIG1lbmphZGkgMTAwLg0KIA0KYGBge3J9DQojIG51bWJlciBvZiBzaW11bGF0aW9ucy9zYW1wbGVzDQpydW5zMiA9IDEwMDAwDQojIHJhbmRvbSBudW1iZXIgZ2VuZXJhdG9yIHBlciBkZWZpbmVkIG5vcm1hbCBkaXN0cmlidXRpb24gd2l0aCBnaXZlbiBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24NCnNpbXMyID0gIHJub3JtKHJ1bnMyLG1lYW49MC4wMyxzZD0wLjk3KQ0KYGBgDQoNCmBgYHtyfQ0KIyBNZWFuIGNhbGN1bGF0ZWQgZnJvbSB0aGUgcmFuZG9tIGRpc3RyaWJ1dGlvbiBvZiBzYW1wbGVzDQphdmVyYWdlMiA9IG1lYW4oc2ltczIpDQphdmVyYWdlMg0KYGBgDQpgYGB7cn0NCiMgTWVhbiBjYWxjdWxhdGVkIGZyb20gdGhlIHJhbmRvbSBkaXN0cmlidXRpb24gb2Ygc2FtcGxlcw0KYXZlcmFnZTIgPSBtZWFuKHNpbXMyKQ0KYXZlcmFnZTINCmBgYA0KDQpgYGB7cn0NCiMgcHJvYmFiaWxpdHkgb2Ygb2NjdXJyZW5jZSBvbiBhbnkgZ2l2ZW4gZGF5IGJhc2VkIG9uIHNhbXBsZXMgd2lsbCBiZSBlcXVhbCB0byBjb3VudCAob3Igc3VtKSB3aGVyZSBzYW1wbGUgcmVzdWx0IGlzIGdyZWF0ZXIgdGhhbiA1JSBkaXZpZGVkIGJ5IHRvdGFsIG51bWJlciBvZiBzYW1wbGVzLiANCnByb2IyID0gc3VtKHNpbXMyID49MC4wNSkvcnVuczINCnByb2IyDQpgYGANCiMgVHVnYXMgNyANClVsYW5naSBwZXJoaXR1bmdhbiBkaSBhdGFzIHVudHVrIGthc3VzIGRpIG1hbmEganVtbGFoIHNpbXVsYXNpIC8gc2FtcGVsIHNhbWEgZGVuZ2FuIDEwMDAuIENhdGF0IG1lYW4sIGRldmlhc2kgc3RhbmRhciwgZGFuIHByb2JhYmlsaXRhcy4gQmVyaSBuYW1hIHNlbXVhIHZhcmlhYmVsIHlhbmcgZGlwZXJsdWthbiBzZWJhZ2FpIHJ1bjEsIHNpbXMxLCBhdmVyYWdlMSwgc3RkMSwgZGFuIHByb2IxLg0KDQpgYGB7cn0NCiMgUmVwZWF0IGNhbGN1bGF0aW9ucyBoZXJlDQpydW5zMT0xMDAwDQphdmVyYWdlMT0wLjAyMTk1MzExDQpzdGQxPTAuOTUxMzE2Nw0KcHJvYjE9MC41MDUNCmBgYA0KDQojIFR1Z2FzIDggDQpVbGFuZ2kga2Fsa3VsYXNpIGRpIGF0YXMgdW50dWsga2FzdXMgZGltYW5hIGp1bWxhaCBzaW11bGFzaSAvIHNhbXBlbCBzYW1hIGRlbmdhbiAxMDAwMC4gQ2F0YXQgbWVhbiwgZGV2aWFzaSBzdGFuZGFyLCBkYW4gcHJvYmFiaWxpdGFzLiBCZXJpIG5hbWEgc2VtdWEgdmFyaWFiZWwgeWFuZyBkaXBlcmx1a2FuIHNlYmFnYWkgcnVuMiwgc2ltczIsIGF2ZXJhZ2UyLCBzdGQyLCBkYW4gcHJvYjIuDQogDQpgYGB7cn0NCiMgUmVwZWF0IGNhbGN1bGF0aW9ucyBoZXJlDQpydW5zMj0xMDAwMA0KYXZlcmFnZTI9MC4wMjkyODA0Mg0Kc3RkMj0wLjk2MzY1NjENCnByb2IyPTAuNDg5MQ0KYGBgDQoNCiMgVHVnYXMgOSANCkNhdGF0IGRpZGFsYW0gYmVudHVrIHRhYmVsIG5pbGFpIG1lYW4sIGRldmlhc2kgc3RhbmRhciwgZGFuIHByb2JhYmlsaXRhcyB1bnR1ayBrZXRpZ2Ega2FzdXM6IHNpbXVsYXNpIDEwMCwgMTAwMCwgZGFuIDEwMDAwLg0KIA0KIyBUdWdhcyAxMA0KSmVsYXNrYW4gYmFnYWltYW5hIG5pbGFpIGJlcnViYWggLyBiZXJwZXJpbGFrdSBzYWF0IGp1bWxhaCBzaW11bGFzaSBiZXJ0YW1iYWguIEFwYSB0YXJ1aGFuIHRlcmJhaWsgQW5kYSB1bnR1ayBrZW11bmdraW5hbiB0ZXJqYWRpbnlhIGxlYmloIGJlc2FyIGRhcmkgNSUgZGFuIG1lbmdhcGE/IEJhZ2FpbWFuYSBpbmkgbWlyaXAgZGVuZ2FuIGthc3VzIHBlbmdndW5hYW4gZ2FtYmFyIHVudHVrIG1lbmdoaXR1bmcgYHBpYCB5YW5nIGRpc2FqaWthbiBkaSBwYXJhZ3JhZiBwZW5nYW50YXI/DQoNCiMjIEphd2FiYW4gVHVnYXMgMTANClNlY2FyYSB1bXVtLCBkZW5nYW4gc2VtYWtpbiBiYW55YWsgc2ltdWxhc2ksIHNlbWFraW4gYWt1cmF0IHByZWRpa3NpbnlhIHNlaGluZ2dhIHN0YW5kYXIgZGV2aWFzaSBtZW5qYWRpIGxlYmloIGtldGF0IGRhbiBwcm9iYWJpbGl0YXNueWEgbWVuaW5na2F0IHNlaXJpbmcgYmVyamFsYW5ueWEgd2FrdHUuIFNla2l0YXIgc2VwYXJ1aCB3YWt0dSBwZW5nZW1iYWxpYW4gbGViaWggYmVzYXIgZGFyaSA1JS4gSW5pIG1pcnAgZGFsYW0gYXJ0aSBiYWh3YSBzZW1ha2luIGJhbnlhayB2YXJpYXNpIHlhbmcgZGl0YW1iYWhrYW4sIHNlbWFraW4gYWt1cmF0IHByZWRpa3NpbnlhIGRhbiBzZW1ha2luIHJlcHJlc2VudGF0aWYgYW5na2FueWEgZGkgZHVuaWEgbnlhdGEuIA0KDQpMYXRpaGFuIDJDIHlhbmcgdGVyYWtoaXIgYWRhbGFoIG9wc2lvbmFsIGJhZ2kgbWVyZWthIHlhbmcgdGVydGFyaWsgdW50dWsgbGViaWggbWVuaW5na2F0a2FuIHBlbWJlbGFqYXJhbiBtYXRlcmkgcGVsYWphcmFuIG1lcmVrYSwgZGFuIG1lbnllbXB1cm5ha2FuIGtldGVyYW1waWxhbiBtZXJla2EgZGFsYW0gUi4gUGVrZXJqYWFuIEFuZGEgYWthbiBkaW5pbGFpIHRldGFwaSBBbmRhIHRpZGFrIGFrYW4gZGluaWxhaSB1bnR1ayBsYXRpaGFuIGluaS4gQW5kYSBkYXBhdCBtZW5naWt1dGkgcGV0dW5qdWsgeWFuZyBkaXNhamlrYW4gZGFsYW0gdmlkZW8gY29udG9oIHNldGFyYSBFeGNlbCBkaSBbaHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj13S2RtRVhDdm85c10uDQoNClVsYW5naSBsYXRpaGFuIHVudHVrIHBlbmdlbWJhbGlhbiBoYXJpYW4gUyZQIGRpIG1hbmEgc2VtdWFueWEgc2FtYSBrZWN1YWxpIGtpdGEgc2VrYXJhbmcgdGVydGFyaWsgcGVuZ2VtYmFsaWFuIGt1bXVsYXRpZiBtaW5nZ3VhbiBkYW4gcHJvYmFiaWxpdGFzIGJhaHdhIHBlbmdlbWJhbGlhbiBrdW11bGF0aWYgbWluZ2d1YW4gbGViaWggYmVzYXIgZGFyaSA1JS4gQXR1ciBqdW1sYWggc2ltdWxhc2kgbWVuamFkaSAxMDAwMC4NCiANCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg==