Task brief
When analysing a methylation data, it may be needed to simulate values from mixtures of beta distributions. In this assessment, you are requested to simulate values from a mixture of beta distributions using accept/reject sampling and importance sampling.
Define X a random variable describing the frequency of methylation. \(X_1, \ldots, X_n\) are i.i.d. distributed according to \(f(x)\). Define a mixture of three beta distributions as following:
\[f(x) = \frac{1}{3} Be(\alpha_1=1,\beta_1=5) + \frac{1}{3} Be(\alpha_2=3,\beta_2=5) + \frac{1}{3} Be(\alpha_3=10,\beta_3=5)\]
1. Plot the density \(f(x)\).

2. Implement an accept/reject algorithm, with \(Unif(0,1)\) proposal distribution.
We first set the seed at 1234 in order to allow reproducability
We then define the value of K, which is the maximum of the density. From looking at the graph above of the mixed beta distribution, we can see that the function has a maximum at x=0. Therefore to find the maximum value of \(f(x)\), we solve \(f(x=0)\) and find the associated theta value is 1.67. We can alternatively use an \(R\) function max() which returns the same value.
We then use runif() to simulate 10,000 values from a uniform distribution.
The acceptance probability is defined as \[ p = \frac{\pi(\theta|\mathbf{x})}{K*g(\theta)} \] where \(\pi(\theta|\mathbf{x})\) is our mixed beta function f(x), \(K\) is the maximum of that function, and \(g(\theta)\) is the uniform distribution in (0, 1), so it is equal to 1 for all values of theta.
Therefore we can define our acceptance probability as simply f(theta)/K.
We then run our acceptance algorithm. First we define another variable u with 10000 values from another \(Unif(0, 1)\) distribution. Then we make a filter ind that identifies only the values in u which are less than the acceptance probability.
Finally we apply the filter to our proposed thetas, and plot the accepted thetas on a histogram, with the target distribution added for comparison.

3. Compute the observed acceptance rate and compare it with the theoretical one.
The observed acceptance rate is the proportion of points in proposed theta that are accepted, ie length(theta[ind])/N >> [1] 0.5978.
The theoretical acceptance rate is \(1/K\), because \(K*1\) represents the entire area of proposed thetas, while 1 is the area under the pdf. In our case \(1/K = 0.6\).
The theoretical and observed acceptance rates are nearly the same.
[1] 0.5978
[1] 0.6
4. Implement an importance sampling algorithm.
We use the same variable theta with 10000 values from \(Unif(0,1)\) for the implementation of the accept/reject algorithm.
The weights are computed by \[ w^{(i)}\propto\frac{\pi(\theta^{(i)}|\mathbf{x})}{g(\theta^{(i)})} \] In our case \(g(\theta) == 1\) for all \(\theta\) because we are using the \(Unif(0,1)\) distribution. So we can omit \(g(\theta)\) from our calculations.
We then need to normalise the weights to \((0, 1)\).
Finally, we can derive the density of the importance sample directly with density(), setting weights=W to apply the weights to each value of proposed thetas.
5. Compare on the same plot the target density, the density of the accepted values for the accept/reject algorithm, and the density of the values weighted by importance sampling.

6. Which of the two algorithms seems to approximate the target distribution better? Which one you would use and why?
Both algorithms show a very similar density. Unfortunately both algorithms deviate from the target distribution towards x=0, for an unknown reason.
To compare further I checked the mean of the target distribution by weighting the averages of each component distribution by \(1/3\). I found the mean = 0.4028.
\[\mathbb{E}[\theta|\mathbf{x}] = \frac {1}{3} (\frac{1}{1+5}) + \frac {1}{3}(\frac{3}{3+5}) + \frac {1}{3}(\frac{10}{10+5}) = 0.4028\] The mean of the rejection sampling distribution can be checked with mean(theta[ind]).
\[\mathbb{E}_R[\theta|\mathbf{x}] = 0.4018\]
Finally, the mean of the importance sampling distribution can be checked with
\[\mathbb{E}_I[\theta|\mathbf{x}] \leftarrow \frac {1}{N} {\sum w^{(i)}\theta^{(i)}} = 0.4056\]
We can see that the mean of the rejection sampling algorithm comes closer to the true value than the importance sampling algorithm, though only slightly.
[1] 0.4017751
[1] 0.4055834
I would use the rejection sampling algorithm because the mean is closer to the target value, and I find it to be more intuitive and elegant. However it does depend on our being able to compute \(K\), which can easily be done in this case, but may sometimes be difficult. If we can’t compute \(K\), or if we can’t find a distribution \(g(\theta)\) such that \(K*g(\theta) \geqslant \theta \ , \forall \ \theta\), then we would need to use importance sampling.
LS0tDQp0aXRsZTogIk1vbnRlLUNhcmxvIGFsZ29yaXRobXMiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCiMjIyMgVGFzayBicmllZg0KV2hlbiBhbmFseXNpbmcgYSBtZXRoeWxhdGlvbiBkYXRhLCBpdCBtYXkgYmUgbmVlZGVkIHRvIHNpbXVsYXRlIHZhbHVlcyBmcm9tIG1peHR1cmVzIG9mIGJldGEgZGlzdHJpYnV0aW9ucy4gSW4gdGhpcyBhc3Nlc3NtZW50LCB5b3UgYXJlIHJlcXVlc3RlZCB0byBzaW11bGF0ZSB2YWx1ZXMgZnJvbSBhIG1peHR1cmUgb2YgYmV0YSBkaXN0cmlidXRpb25zIHVzaW5nIGFjY2VwdC9yZWplY3Qgc2FtcGxpbmcgYW5kIGltcG9ydGFuY2Ugc2FtcGxpbmcuIA0KDQpEZWZpbmUgWCBhIHJhbmRvbSB2YXJpYWJsZSBkZXNjcmliaW5nIHRoZSBmcmVxdWVuY3kgb2YgbWV0aHlsYXRpb24uICRYXzEsIFxsZG90cywgWF9uJCBhcmUgaS5pLmQuIGRpc3RyaWJ1dGVkIGFjY29yZGluZyB0byAkZih4KSQuIERlZmluZSBhIG1peHR1cmUgb2YgdGhyZWUgYmV0YSBkaXN0cmlidXRpb25zIGFzIGZvbGxvd2luZzoNCg0KJCRmKHgpID0gXGZyYWN7MX17M30gQmUoXGFscGhhXzE9MSxcYmV0YV8xPTUpICsgXGZyYWN7MX17M30gQmUoXGFscGhhXzI9MyxcYmV0YV8yPTUpICsgXGZyYWN7MX17M30gQmUoXGFscGhhXzM9MTAsXGJldGFfMz01KSQkDQoNCiMjIyMgMS4gUGxvdCB0aGUgZGVuc2l0eSAkZih4KSQuDQoNCg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCmYgPC0gZnVuY3Rpb24oeCkgew0KICBiZXRhMSA8LSBkYmV0YSh4LCAxLCA1KQ0KICBiZXRhMiA8LSBkYmV0YSh4LCAzLCA1KQ0KICBiZXRhMyA8LSBkYmV0YSh4LCAxMCwgNSkNCiAgcmV0dXJuIChiZXRhMS8zICsgYmV0YTIvMyArIGJldGEzLzMpDQp9DQoNCnggPC0gc2VxKDAsIDEsIGJ5ID0gMC4wMDEpDQoNCnBsb3QoeCwgZih4KSwgbWFpbiA9ICdNaXhlZCBCZXRhIERpc3RyaWJ1dGlvbicsIGNvbCA9ICdjeWFuJykNCmBgYA0KDQojIyMjIDIuIEltcGxlbWVudCBhbiBhY2NlcHQvcmVqZWN0IGFsZ29yaXRobSwgd2l0aCAkVW5pZigwLDEpJCBwcm9wb3NhbCBkaXN0cmlidXRpb24uDQoNCldlIGZpcnN0IHNldCB0aGUgc2VlZCBhdCAxMjM0IGluIG9yZGVyIHRvIGFsbG93IHJlcHJvZHVjYWJpbGl0eQ0KDQpXZSB0aGVuIGRlZmluZSB0aGUgdmFsdWUgb2YgSywgd2hpY2ggaXMgdGhlIG1heGltdW0gb2YgdGhlIGRlbnNpdHkuICBGcm9tIGxvb2tpbmcgYXQgdGhlIGdyYXBoIGFib3ZlIG9mIHRoZSBtaXhlZCBiZXRhIGRpc3RyaWJ1dGlvbiwgd2UgY2FuIHNlZSB0aGF0IHRoZSBmdW5jdGlvbiBoYXMgYSBtYXhpbXVtIGF0IHg9MC4gIFRoZXJlZm9yZSB0byBmaW5kIHRoZSBtYXhpbXVtIHZhbHVlIG9mICRmKHgpJCwgd2Ugc29sdmUgJGYoeD0wKSQgYW5kIGZpbmQgdGhlIGFzc29jaWF0ZWQgdGhldGEgdmFsdWUgaXMgMS42Ny4gIFdlIGNhbiBhbHRlcm5hdGl2ZWx5IHVzZSBhbiAkUiQgZnVuY3Rpb24gYG1heCgpYCB3aGljaCByZXR1cm5zIHRoZSBzYW1lIHZhbHVlLg0KDQpXZSB0aGVuIHVzZSBgcnVuaWYoKWAgdG8gc2ltdWxhdGUgMTAsMDAwIHZhbHVlcyBmcm9tIGEgdW5pZm9ybSBkaXN0cmlidXRpb24uICANCg0KVGhlIGFjY2VwdGFuY2UgcHJvYmFiaWxpdHkgaXMgZGVmaW5lZCBhcyANCiQkIHAgPSBcZnJhY3tccGkoXHRoZXRhfFxtYXRoYmZ7eH0pfXtLKmcoXHRoZXRhKX0gJCQNCndoZXJlICRccGkoXHRoZXRhfFxtYXRoYmZ7eH0pJCBpcyBvdXIgbWl4ZWQgYmV0YSBmdW5jdGlvbiBgZih4KWAsICRLJCBpcyB0aGUgbWF4aW11bSBvZiB0aGF0IGZ1bmN0aW9uLCBhbmQgJGcoXHRoZXRhKSQgaXMgdGhlIHVuaWZvcm0gZGlzdHJpYnV0aW9uIGluICgwLCAxKSwgc28gaXQgaXMgZXF1YWwgdG8gMSBmb3IgYWxsIHZhbHVlcyBvZiB0aGV0YS4NCg0KVGhlcmVmb3JlIHdlIGNhbiBkZWZpbmUgb3VyIGFjY2VwdGFuY2UgcHJvYmFiaWxpdHkgYXMgc2ltcGx5IGBmKHRoZXRhKS9LYC4NCg0KV2UgdGhlbiBydW4gb3VyIGFjY2VwdGFuY2UgYWxnb3JpdGhtLiAgRmlyc3Qgd2UgZGVmaW5lIGFub3RoZXIgdmFyaWFibGUgYHVgIHdpdGggMTAwMDAgdmFsdWVzIGZyb20gYW5vdGhlciAkVW5pZigwLCAxKSQgZGlzdHJpYnV0aW9uLiAgVGhlbiB3ZSBtYWtlIGEgZmlsdGVyIGBpbmRgIHRoYXQgaWRlbnRpZmllcyBvbmx5IHRoZSB2YWx1ZXMgaW4gYHVgIHdoaWNoIGFyZSBsZXNzIHRoYW4gdGhlIGFjY2VwdGFuY2UgcHJvYmFiaWxpdHkuDQoNCkZpbmFsbHkgd2UgYXBwbHkgdGhlIGZpbHRlciB0byBvdXIgcHJvcG9zZWQgdGhldGFzLCBhbmQgcGxvdCB0aGUgYWNjZXB0ZWQgdGhldGFzIG9uIGEgaGlzdG9ncmFtLCB3aXRoIHRoZSB0YXJnZXQgZGlzdHJpYnV0aW9uIGFkZGVkIGZvciBjb21wYXJpc29uLg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCiMgU2V0IHRoZSBzZWVkIGF0IDEyMzQuDQpzZXQuc2VlZCgxMjM0KQ0KDQojIFdlIHdhbnQgMTAwMDAgdmFsdWVzDQpOIDwtIDEwMDAwDQoNCiMgRGVmaW5lIHRoZSB2YWx1ZSBLDQpLIDwtIG1heChmKHgpKSAjID0xLjY3LCBhdCB4PTANCg0KIyBTaW11bGF0ZSAxMCwwMDAgdmFsdWVzIGZyb20gYSB1bmlmb3JtIGRpc3RyaWJ1dGlvbi4gDQp0aGV0YSA8LSBydW5pZihOKQ0KDQojIERlZmluZSB0aGUgYWNjZXB0YW5jZSBwcm9iYWJpbGl0eS4NCmFjY19wcm9iIDwtIGYodGhldGEpL0sNCg0KIyBBY2NlcHQgb3IgcmVqZWN0IHRoZSBzaW11bGF0ZWQgdmFsdWUgYWNjb3JkaW5nIHRvIHRoZSBhY2NlcHRhbmNlIHByb2JhYmlsaXR5Lg0KdSA8LSBydW5pZihOKQ0KaW5kIDwtICh1IDwgYWNjX3Byb2IpDQoNCnRoZXRhX2FjY2VwdGVkIDwtIHRoZXRhW2luZF0NCg0KaGlzdCh0aGV0YV9hY2NlcHRlZCwgcHJvYmFiaWxpdHkgPSBULCB4bGltPWMoMCwxKSx5bGltPWMoMCwyKSwgDQogICAgIG1haW4gPSAnSGlzdG9ncmFtIG9mIGFjY2VwdGVkIHRoZXRhcycsDQogICAgIHhsYWIgPSAnQWNjZXB0ZWQgdGhldGEgdmFsdWVzJykNCnRoIDwtIHNlcSgwLCAxLCBieT0wLjAxKQ0KbGluZXModGgsIGYodGgpLCBsd2Q9MiwgY29sPSdjeWFuJykgIyBhZGQgdGhlIHRhcmdldCBkaXN0cmlidXRpb24NCg0KZF9yIDwtIGRlbnNpdHkodGhldGFfYWNjZXB0ZWQpDQoNCmBgYA0KDQojIyMjIDMuIENvbXB1dGUgdGhlIG9ic2VydmVkIGFjY2VwdGFuY2UgcmF0ZSBhbmQgY29tcGFyZSBpdCB3aXRoIHRoZSB0aGVvcmV0aWNhbCBvbmUuIA0KIFRoZSBvYnNlcnZlZCBhY2NlcHRhbmNlIHJhdGUgaXMgdGhlIHByb3BvcnRpb24gb2YgcG9pbnRzIGluIHByb3Bvc2VkIHRoZXRhIHRoYXQgYXJlIGFjY2VwdGVkLCBpZSBgbGVuZ3RoKHRoZXRhW2luZF0pL04gPj4gWzFdIDAuNTk3OGAuDQogDQogVGhlIHRoZW9yZXRpY2FsIGFjY2VwdGFuY2UgcmF0ZSBpcyAkMS9LJCwgYmVjYXVzZSAkSyoxJCByZXByZXNlbnRzIHRoZSBlbnRpcmUgYXJlYSBvZiBwcm9wb3NlZCB0aGV0YXMsIHdoaWxlIDEgaXMgdGhlIGFyZWEgdW5kZXIgdGhlIHBkZi4gIEluIG91ciBjYXNlICQxL0sgPSAwLjYkLiAgDQogDQogVGhlIHRoZW9yZXRpY2FsIGFuZCBvYnNlcnZlZCBhY2NlcHRhbmNlIHJhdGVzIGFyZSBuZWFybHkgdGhlIHNhbWUuDQogDQpgYGB7ciAsIGVjaG89RkFMU0V9DQojIG9ic2VydmVkIGFjY2VwdGFuY2UgcmF0ZSANCmxlbmd0aCh0aGV0YVtpbmRdKS9OICMgMC41OTc4DQoNCiMgdGhlb3JldGljYWwgYWNjZXB0YW5jZSByYXRlDQoxL0sgIyAwLjYNCg0KDQpgYGANCg0KDQojIyMjIDQuIEltcGxlbWVudCBhbiBpbXBvcnRhbmNlIHNhbXBsaW5nIGFsZ29yaXRobS4gDQoNCldlIHVzZSB0aGUgc2FtZSB2YXJpYWJsZSBgdGhldGFgIHdpdGggMTAwMDAgdmFsdWVzIGZyb20gJFVuaWYoMCwxKSQgZm9yIHRoZSBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgYWNjZXB0L3JlamVjdCBhbGdvcml0aG0uIA0KDQpUaGUgd2VpZ2h0cyBhcmUgY29tcHV0ZWQgYnkgDQokJCAgd157KGkpfVxwcm9wdG9cZnJhY3tccGkoXHRoZXRhXnsoaSl9fFxtYXRoYmZ7eH0pfXtnKFx0aGV0YV57KGkpfSl9ICQkDQpJbiBvdXIgY2FzZSAkZyhcdGhldGEpID09IDEkIGZvciBhbGwgJFx0aGV0YSQgYmVjYXVzZSB3ZSBhcmUgdXNpbmcgdGhlICRVbmlmKDAsMSkkIGRpc3RyaWJ1dGlvbi4gU28gd2UgY2FuIG9taXQgJGcoXHRoZXRhKSQgZnJvbSBvdXIgY2FsY3VsYXRpb25zLg0KDQpXZSB0aGVuIG5lZWQgdG8gbm9ybWFsaXNlIHRoZSB3ZWlnaHRzIHRvICQoMCwgMSkkLg0KDQpGaW5hbGx5LCB3ZSBjYW4gZGVyaXZlIHRoZSBkZW5zaXR5IG9mIHRoZSBpbXBvcnRhbmNlIHNhbXBsZSBkaXJlY3RseSB3aXRoIGBkZW5zaXR5KClgLCBzZXR0aW5nIGB3ZWlnaHRzPVdgIHRvIGFwcGx5IHRoZSB3ZWlnaHRzIHRvIGVhY2ggdmFsdWUgb2YgcHJvcG9zZWQgdGhldGFzLg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCncgPC0gZih0aGV0YSkNClcgPC0gdy9zdW0odykgIyBpbXBvcnRhbmNlIHdlaWdodHMgYXJlIG5vcm1hbGlzZWQNCmRfaSA8LSBkZW5zaXR5KHRoZXRhLHdlaWdodHM9Vyxmcm9tPTAsdG89MSkgIyB0aGUgaW1wb3J0YW5jZSBzYW1wbGUgZGVuc2l0eQ0KDQpgYGANCg0KDQojIyMjIDUuIENvbXBhcmUgb24gdGhlIHNhbWUgcGxvdCB0aGUgdGFyZ2V0IGRlbnNpdHksIHRoZSBkZW5zaXR5IG9mIHRoZSBhY2NlcHRlZCB2YWx1ZXMgZm9yIHRoZSBhY2NlcHQvcmVqZWN0IGFsZ29yaXRobSwgYW5kIHRoZSBkZW5zaXR5IG9mIHRoZSB2YWx1ZXMgd2VpZ2h0ZWQgYnkgaW1wb3J0YW5jZSBzYW1wbGluZy4gDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KDQpwbG90KHgsIGYoeCksIG1haW4gPSAnVGFyZ2V0IERpc3RyaWJ1dGlvbiBhbmQgQXBwcm94aW1hdGlvbnMnLCBjb2wgPSAnY3lhbicpICMgdGFyZ2V0IGRlbnNpdHkNCmxpbmVzKGRfciwgY29sID0gInJlZCIsIGx3ZCA9IDIsIGx0eSA9IDIpICMgYWRkIHRoZSByZWplY3Rpb24gZGVuc2l0eQ0KbGluZXMoZF9pLGNvbD0iZGFya29yYW5nZTEiLGx3ZD0yLGx0eT0yKSAjIGFkZCB0aGUgaW1wb3J0YW5jZSBkZW5zaXR5DQpsZWdlbmQoMC4yLCAwLjgsIGxlZ2VuZD1jKCJUYXJnZXQgZGlzdHJpYnV0aW9uIiwgIlJlamVjdGlvbiIsICJJbXBvcnRhbmNlIiksDQogICAgICAgY29sPWMoImN5YW4iLCAicmVkIiwgImRhcmtvcmFuZ2UxIiksIGx0eT1jKDEsIDIsIDIpLCBjZXg9MC44KQ0KYGBgDQoNCg0KDQojIyMgNi4gV2hpY2ggb2YgdGhlIHR3byBhbGdvcml0aG1zIHNlZW1zIHRvIGFwcHJveGltYXRlIHRoZSB0YXJnZXQgZGlzdHJpYnV0aW9uIGJldHRlcj8gV2hpY2ggb25lIHlvdSB3b3VsZCB1c2UgYW5kIHdoeT8NCg0KDQpCb3RoIGFsZ29yaXRobXMgc2hvdyBhIHZlcnkgc2ltaWxhciBkZW5zaXR5LiAgVW5mb3J0dW5hdGVseSBib3RoIGFsZ29yaXRobXMgZGV2aWF0ZSBmcm9tIHRoZSB0YXJnZXQgZGlzdHJpYnV0aW9uIHRvd2FyZHMgeD0wLCBmb3IgYW4gdW5rbm93biByZWFzb24uDQoNClRvIGNvbXBhcmUgZnVydGhlciBJIGNoZWNrZWQgdGhlIG1lYW4gb2YgdGhlIHRhcmdldCBkaXN0cmlidXRpb24gYnkgd2VpZ2h0aW5nIHRoZSBhdmVyYWdlcyBvZiBlYWNoIGNvbXBvbmVudCBkaXN0cmlidXRpb24gYnkgJDEvMyQuICBJIGZvdW5kIHRoZSBtZWFuID0gMC40MDI4Lg0KDQokJFxtYXRoYmJ7RX1bXHRoZXRhfFxtYXRoYmZ7eH1dID0gXGZyYWMgezF9ezN9IChcZnJhY3sxfXsxKzV9KSArIFxmcmFjIHsxfXszfShcZnJhY3szfXszKzV9KSArIFxmcmFjIHsxfXszfShcZnJhY3sxMH17MTArNX0pID0gMC40MDI4JCQgDQpUaGUgbWVhbiBvZiB0aGUgcmVqZWN0aW9uIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBjYW4gYmUgY2hlY2tlZCB3aXRoIGBtZWFuKHRoZXRhW2luZF0pYC4NCg0KJCRcbWF0aGJie0V9X1JbXHRoZXRhfFxtYXRoYmZ7eH1dID0gMC40MDE4JCQgDQogDQpGaW5hbGx5LCB0aGUgbWVhbiBvZiB0aGUgaW1wb3J0YW5jZSBzYW1wbGluZyBkaXN0cmlidXRpb24gY2FuIGJlIGNoZWNrZWQgd2l0aA0KDQokJFxtYXRoYmJ7RX1fSVtcdGhldGF8XG1hdGhiZnt4fV0gXGxlZnRhcnJvdyBcZnJhYyB7MX17Tn0ge1xzdW0gd157KGkpfVx0aGV0YV57KGkpfX0gPSAwLjQwNTYkJCANCg0KV2UgY2FuIHNlZSB0aGF0IHRoZSBtZWFuIG9mIHRoZSByZWplY3Rpb24gc2FtcGxpbmcgYWxnb3JpdGhtIGNvbWVzIGNsb3NlciB0byB0aGUgdHJ1ZSB2YWx1ZSB0aGFuIHRoZSBpbXBvcnRhbmNlIHNhbXBsaW5nIGFsZ29yaXRobSwgdGhvdWdoIG9ubHkgc2xpZ2h0bHkuICANCg0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCiMgZXhwZWN0ZWQgdmFsdWUgb2YgdGhlIHJlamVjdGlvbiBzYW1wbGluZyBkaXN0cmlidXRpb24NCm1lYW4odGhldGFbaW5kXSkgIyBbMV0gMC40MDE3NzUxDQoNCiMgZXhwZWN0ZWQgdmFsdWUgb2YgdGhlIGltcG9ydGFuY2Ugc2FtcGxpbmcgZGlzdHJpYnV0aW9uDQpzdW0odyp0aGV0YSkvTiAjIFsxXSAwLjQwNTU4MzQNCmBgYA0KDQoNCg0KSSB3b3VsZCB1c2UgdGhlIHJlamVjdGlvbiBzYW1wbGluZyBhbGdvcml0aG0gYmVjYXVzZSB0aGUgbWVhbiBpcyBjbG9zZXIgdG8gdGhlIHRhcmdldCB2YWx1ZSwgYW5kIEkgZmluZCBpdCB0byBiZSBtb3JlIGludHVpdGl2ZSBhbmQgZWxlZ2FudC4gSG93ZXZlciBpdCBkb2VzIGRlcGVuZCBvbiBvdXIgYmVpbmcgYWJsZSB0byBjb21wdXRlICRLJCwgd2hpY2ggY2FuIGVhc2lseSBiZSBkb25lIGluIHRoaXMgY2FzZSwgYnV0IG1heSBzb21ldGltZXMgYmUgZGlmZmljdWx0LiAgSWYgd2UgY2FuJ3QgY29tcHV0ZSAkSyQsIG9yIGlmIHdlIGNhbid0IGZpbmQgYSBkaXN0cmlidXRpb24gJGcoXHRoZXRhKSQgc3VjaCB0aGF0ICRLKmcoXHRoZXRhKSBcZ2Vxc2xhbnQgXHRoZXRhIFwgLCBcZm9yYWxsIFwgXHRoZXRhJCwgdGhlbiB3ZSB3b3VsZCBuZWVkIHRvIHVzZSBpbXBvcnRhbmNlIHNhbXBsaW5nLg==