Below is the hands-on exercises on the advanced methods. This will cover the heuristic search and how to perform Bayesian model averaging.

Note: in the following text: Bayesian network, structure and DAG are synonyms.

MCMC over the structures

Usually, the output of a Bayesian network analysis of a dataset ends-up with a single well adjusted DAG. From the researcher point of view this could be frustrating. Indeed, the model is the one that is best supported by the data but the uncertainty quantification is missing. Classically in epidemiology, researchers are used to express point estimate with an uncertainty measure. An arc in a Bayesian network is a point estimate, we will see how to perform model averaging. The link strength measure is designed to account for that. An more natural alternative is to perform MCMC over structures (Friedman & Koller, 2003).

We use the mcmcabn() function on the cache of pre-computed networks scores. One needs to define the type of score used (here is the marginal likelihood mlik). The maximum of number of parents per node (same as the one used in buildscorecache()). The MCMC learning scheme, defined as: number of MCMC samples, number of thinned sampled (to avoid autocorrelation) and the length of the burn-in phase. Possibly a starting DAG and a structural prior. We also need to select the relative probability of performing radical moves (shuffling). Indeed, a naive MCMC approach is known to get very easily stuck in local maximum (for more details see: (Grzegorczyk & Husmeier, 2008; Su & Borsuk, 2016)).

mcmc.out <- mcmcabn(score.cache = mycache,
                  score = "mlik",
                  data.dists = dist,
                  max.parents = 4,
                  mcmc.scheme = c(1000,9,500),
                  seed = 321,
                  verbose = FALSE,
                  start.dag = "random",
                  prob.rev = 0.07,
                  prob.mbr = 0.07,
                  prior.choice = 1)

This is again computationally complex!

Her is a plot of the MCMC samples. One can see the scores of the structures on the y-axis in function of the index steps. The dots are the radical moves. One the right side a histogram shows the number of structures with a given score. As one can see the histogram is very peaked on the maximum possible score.

One can also display the cumulative maximum score (used for network score optimization).

But the major advantage of this method is the possibility of querying the MCMC sample using a formula statement.

# average individual arc support
query(mcmcabn = mcmc.out)
                  AR     pneumS     female     livdam       eggs  wormCount
AR        0.00000000 0.01069893 0.01139886 0.01159884 0.07599240 0.00349965
pneumS    0.00589941 0.00000000 0.01539846 0.00829917 0.10398960 0.00429957
female    0.00579942 0.01879812 0.00000000 0.01769823 0.00659934 0.00249975
livdam    0.00689931 0.00999900 0.01119888 0.00000000 0.44275572 0.00439956
eggs      0.14908509 0.09239076 0.01019898 0.29377062 0.00000000 0.02959704
wormCount 0.76062394 0.08119188 0.03349665 0.07039296 0.91700830 0.00000000
age       0.13568643 0.07349265 0.15768423 0.11338866 0.09739026 0.01399860
adg       0.03019698 0.01589841 0.08359164 0.00959904 0.17288271 0.00349965
                 age        adg
AR        0.77212279 0.08649135
pneumS    0.19238076 0.03989601
female    0.29857014 0.12168783
livdam    0.06649335 0.01169883
eggs      0.25057494 0.36466353
wormCount 0.88481152 0.31056894
age       0.00000000 0.47095290
adg       0.52864714 0.00000000
# probability that worm count being linked to age but not to female directly
query(mcmcabn = mcmc.out,formula = ~wormCount|age-wormCount|female)
[1] 0.01889811
# probability that worm count being directly linked to age and adg and that adg is link to age (undirected)
query(mcmcabn = mcmc.out,formula = ~wormCount|age + wormCount|adg + age|adg)+
  query(mcmcabn = mcmc.out,formula = ~wormCount|age + wormCount|adg + adg|age)
[1] 0.2451755

References

Friedman, N., & Koller, D. (2003). Being bayesian about network structure. A bayesian approach to structure discovery in bayesian networks. Machine Learning, 50(1-2), 95–125.
Grzegorczyk, M., & Husmeier, D. (2008). Improving the structure MCMC sampler for bayesian networks by introducing a new edge reversal move. Machine Learning, 71(2-3), 265.
Koivisto, M., & Sood, K. (2004). Exact bayesian structure discovery in bayesian networks. Journal of Machine Learning Research, 5(May), 549–573.
Korb, K. B., & Nicholson, A. E. (2010). Bayesian artificial intelligence. CRC press.
Su, C., & Borsuk, M. E. (2016). Improving structure mcmc for bayesian networks through markov blanket resampling. The Journal of Machine Learning Research, 17(1), 4042–4061.
LS0tCnRpdGxlOiAiSGFuZHMtb24gZXhlcmNpc2U6IGFkdmFuY2VkIGZlYXR1cmVzIG9mIEFCTiBhbmFseXNpcyAtIFVzZVIhIENvbmZlcmVuY2UiCmZvbnRzaXplOiAxM3B0Cm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDIKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKYmlibGlvZ3JhcGh5OiBiaWJfYWR2YW5jZWQuYmliCmNzbDogYXBhLmNzbAotLS0KCiZuYnNwOwoKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IEZBTFNFLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBjb2xsYXBzZT1GQUxTRSwKICAgICAgICAgICAgICAgICAgICAgIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLmhlaWdodD00LCBmaWcud2lkdGg9MTAsIGNvbW1lbnQgPSBOQSkKCm9wdGlvbnMoc2NpcGVuPTk5OSkKCnF1aWV0IDwtIGZ1bmN0aW9uKHgpIHsgCiAgc2luayh0ZW1wZmlsZSgpKSAKICBvbi5leGl0KHNpbmsoKSkgCiAgaW52aXNpYmxlKGZvcmNlKHgpKSAKfSAKCiMjIGxpYnJhcnkKbGlicmFyeShrbml0cikKbGlicmFyeShrYWJsZUV4dHJhKQpsaWJyYXJ5KGFibikKbGlicmFyeShtY21jYWJuKQoKIyMgbG9hZCBkYXRhCgpkYXRhKCJhZGciLCBwYWNrYWdlID0gImFibiIpCgphZGcgPC0gYWRnICU+JSBhcy5kYXRhLmZyYW1lKCkKCmRyb3AgPC0gd2hpY2goY29sbmFtZXMoZHQpJWluJSBjKCJwbmV1bSIsICJlcGc1IiwgIndvcm1zIiwgImZhcm0iKSkKCmBgYAoKQmVsb3cgaXMgdGhlIGhhbmRzLW9uIGV4ZXJjaXNlcyBvbiB0aGUgYWR2YW5jZWQgbWV0aG9kcy4gVGhpcyB3aWxsIGNvdmVyIHRoZSAqKmhldXJpc3RpYyBzZWFyY2gqKiBhbmQgaG93IHRvIHBlcmZvcm0gKipCYXllc2lhbiBtb2RlbCBhdmVyYWdpbmcqKi4KCipOb3RlOiBpbiB0aGUgZm9sbG93aW5nIHRleHQ6IEJheWVzaWFuIG5ldHdvcmssIHN0cnVjdHVyZSBhbmQgREFHIGFyZSBzeW5vbnltcy4qCgoKIyBIZXVyaXN0aWMgc2VhcmNoCgpUaGUgYG1vc3RQcm9iYWJsZSgpYCBmdW5jdGlvbiBpcyBsaW1pdGVkIHRvIDIwIHRvIDI1IG5vZGVzIChpZiBjb21wdXRlZCBvbiBhIGNvbXB1dGluZyBjbHVzdGVyIGV2ZW4gd2l0aCBhIGxpbWl0ZWQgbnVtYmVyIG9mIHBhcmVudCkuIFRoZW4gZm9yIGxhcmdlciBwcm9ibGVtIHRoaXMgYXBwcm9hY2ggYmVjb21lcyBpbnRyYWN0YWJsZSBmb3JtIGEgY29tcHV0YXRpb25hbCBwb2ludCBvZiB2aWV3LiBUaGUgbWFpbiBhZHZhbnRhZ2VzIG9mIHRoZSBgbW9zdFByb2JhYmxlKClgIGZ1bmN0aW9uIGlzIHRoYXQgdGhlIHJldHVybmVkIHN0cnVjdHVyZSBpcyB0aGUgb25lIHRoYXQgaGFzIHRoZSBtYXhpbWFsIHBvc3NpYmxlIHNjb3JlLCB0aHVzIGl0IGlzIGNhbGxlZCAqKmV4YWN0KiogaW4gdGhhdCBzZW5zZSBbQGtvaXZpc3RvMjAwNGV4YWN0XS4gSXQgY29tcGFyZXMgYWxsIHBvc3NpYmxlIHN0cnVjdHVyZSB0byBzZWxlY3QgdGhlIG9wdGltYWwgb25lLiAKClRoZSBoZXVyaXN0aWMgc2VhcmNoZXMgYXJlIHRlY2huaXF1ZXMgdGhhdCB0ZW5kcyB0byBwZXJmb3JtIGEgZ3JlZWR5IG9wdGltaXphdGlvbi4gVGhlbiB0aGVyZSBpcyBubyBndWFyYW50ZWVzIHRvIHJlYWNoIHRoZSBtYXhpbXVtIHNjb3JlLiBJbiB0aGlzIGNvbnRleHQgZ3JlZWR5IG1lYW5zOiBwZXJmb3JtIGxvY2FsIG9wdGltaXphdGlvbiBhbmQgaG9waW5nIHRvIGdldCB0aGUgb3ZlcmFsbCBtYXhpbXVtLgoKV2Ugd2lsbCB1c2UgYSBIaWxsLUNsaW1iZXIgW0Brb3JiMjAxMGJheWVzaWFuXS4gV2UgbmVlZCB0byBzZXQgdXAgdGhlIG51bWJlciBvZiBzZWFyY2hlcyBhbmQgdGhlIG51bWJlciBvZiBzdGVwcyBwZXIgc2VhcmNoZXMuIFRoZSBzdGFydGluZyBwb2ludCAoaGVyZSB3ZSBjaG9vc2UgYSByYW5kb20gRGlyZWN0ZWQgQWN5Y2xpYyBHcmFwaCAoREFHKSkuIFRoZSByZXN0IG9mIHBhcmFtZXRlcnMgaXMgZXF1aXZhbGVudCB0byB0aGUgb25lcyB1c2VkIGluIGBidWlsZHNjb3JlY2FjaGUoKWAgZnVuY3Rpb24uCgpgYGB7ciBoZXVyaXN0aWMxLCBlY2hvPVRSVUUsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD00fQoKYWJuZGF0YSA8LSBhZGcgJT4lCiAgZHBseXI6OnNlbGVjdCgtZmFybSkgJT4lCiAgYXMuZGF0YS5mcmFtZSgpCgphYm5kYXRhWywxOjVdIDwtIGFzLmRhdGEuZnJhbWUobGFwcGx5KGFibmRhdGFbLDE6NV0sIGZhY3RvcikpCmRpc3QgPC0gbGlzdChBUiA9ICJiaW5vbWlhbCIsIHBuZXVtUyA9ICJiaW5vbWlhbCIsIGZlbWFsZT0iYmlub21pYWwiLCAKICAgICAgICAgICAgIGxpdmRhbT0gImJpbm9taWFsIiwgZWdncyA9ICJiaW5vbWlhbCIsd29ybUNvdW50ID0gInBvaXNzb24iLAogICAgICAgICAgICAgYWdlPSAiZ2F1c3NpYW4iLCBhZGcgPSAiZ2F1c3NpYW4iKQoKI3NldCBtYXhpbXVtIG51bWJlciBvZiBwb3NzaWJsZSBwYXJlbnQgcGVyIG5vZGUKbWF4LnBhciA8LSA0CgojIGNvbXB1dGUgYSBjYWNoZSBvZiBzY29yZXMKbXljYWNoZSA8LSBidWlsZFNjb3JlQ2FjaGUoZGF0YS5kZiA9IChhYm5kYXRhKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEuZGlzdHMgPSBkaXN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LnBhcmVudHMgPSBtYXgucGFyKQoKIyBzZXQgbnVtYmVyIG9mIHNlYXJjaGVzIGFuZCBudW1iZXIgb2Ygc3RlcHMKbnVtLnNlYXJjaGVzIDwtIDIwMAptYXguc3RlcHMgPC0gMTUwCgojIEhpbGwtY2xpbWJlcgpoZXVyLnJlcyA8LSBxdWlldChzZWFyY2hIZXVyaXN0aWMoc2NvcmUuY2FjaGUgPSBteWNhY2hlLAogICAgICAgICAgICAgICAgICAgICAgICAgICBzY29yZSA9ICJtbGlrIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5kaXN0cyA9IGRpc3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5wYXJlbnRzID0gNCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnQuZGFnID0gInJhbmRvbSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bS5zZWFyY2hlcyA9IG51bS5zZWFyY2hlcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4LnN0ZXBzID0gbWF4LnN0ZXBzLAogICAgICAgICAgICAgICAgICAgICAgICAgICBzZWVkID0gMzIxMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZSA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGFsZ28gPSAiaGMiKSkKCiMgZm9yIGNvbXBhcmlzb24gbGV0IHVzIGNvbXB1dGUgdGhlIG1heGltdW0gZXhhY3Qgc2NvcmUKbXlkYWcgPC0gKG1vc3RQcm9iYWJsZShzY29yZS5jYWNoZSA9IG15Y2FjaGUpKQojIGFsdGVybmF0aXZlbHkgeW91IGNvdWxkIHVzZSB0aGUgcHJlY29tcHV0ZWQgIm15ZGFnIiB1c2luZzoKIyMgbG9hZChteWRhZy5SZGF0YSkgCgpmYWJuIDwtIGZpdEFibihvYmplY3QgPSBteWRhZykKCiMgcGxvdCBIaWxsLUNsaW1iZXIgc2NvcmVzCmRmLmhldXIgPC0gdW5saXN0KGhldXIucmVzJHNjb3JlcykKcGxvdChOVUxMLGx0eT0xLCB4bGFiPSJJbmRleCBvZiBoZXVyaXN0aWMgc2VhcmNoIix5bGFiPSJCTiBzY29yZSIsIHlsaW0gPSBjKG1pbih1bmxpc3QoZGYuaGV1cikpLG1heCh1bmxpc3QoZGYuaGV1cikpKSwgeGxpbSA9IGMoMCxudW0uc2VhcmNoZXMpKQpmb3IoaSBpbiAxOm51bS5zZWFyY2hlcyl7CiAgaWYoc3VtKGk9PW9yZGVyKGRmLmhldXIsZGVjcmVhc2luZyA9IFRSVUUpWzE6MTBdKSl7CiAgICBwb2ludHMoeD1pLHk9ZGYuaGV1cltpXSx0eXBlPSJwIixwY2g9MTksIGNvbD1yZ2IoMCwwLDEsIDAuOCksbHdkID0gMikKICAgIH1lbHNlewogICAgcG9pbnRzKHg9aSx5PWRmLmhldXJbaV0sdHlwZT0icCIscGNoPTE5LCBjb2w9cmdiKDAsMCwwLCAwLjMpKQogIH0KfQpwb2ludHMoeCA9IG1heCh1bmxpc3QoZGYuaGV1cikpLHkgPSBtYXgodW5saXN0KGRmLmhldXIpKSxjb2w9InJlZCIscGNoPTE5KQphYmxpbmUoaCA9IGZhYm4kbWxpaywgY29sPSJyZWQiLGx0eSA9IDMpCgpgYGAKCkFib3ZlIHdlIHBsb3QgdGhlIG1heGltdW0gc2NvcmVzIGFmdGVyIDE1MCBzdGVwcyBvdXQgb2YgMjAwIGRpZmZlcmVudCBzZWFyY2hlcyBvZiBhIEhpbGwtQ2xpbWJlci4gVGhlIGJsdWVzIGRvdGVzIGFyZSB0aGUgMTAgYmVzdCBzZWFyY2hlcy4gVGhlIHJlZCBkYXNoZWQgbGluZSBpcyB0aGUgbWF4aW11bSBwb3NzaWJsZSBzY29yZS4gCgpgYGB7ciBoZXVyaXN0aWMyLCBlY2hvPVRSVUUsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD00fQojIGxldCB1cyBwbG90IHRoZSBldm9sdXRpb24gb2Ygc2NvcmVzIGR1cmluZyBvcHRpbWl6YXRpb24KTG9uZyA8LSAoaGV1ci5yZXMkZGV0YWlsZWQuc2NvcmUpCkxvbmcuYXJyIDwtIGFycmF5KHVubGlzdChMb25nKSwgZGltID0gYyhucm93KExvbmdbWzFdXSksIG5jb2woTG9uZ1tbMV1dKSwgbGVuZ3RoKExvbmcpKSkKcGxvdChOVUxMLGx0eT0xLCB4bGFiPSJOdW1iZXIgb2YgU3RlcHMiLHlsYWI9IkJOIHNjb3JlIiwgeWxpbSA9IGMobWluKHVubGlzdChkZi5oZXVyKSksbWF4KHVubGlzdChkZi5oZXVyKSkpLCB4bGltID0gYygwLG1heC5zdGVwcykpCmZvcihpIGluIDE6bnVtLnNlYXJjaGVzKXsKICBpZihzdW0oaT09b3JkZXIodW5saXN0KGhldXIucmVzJHNjb3JlcyksZGVjcmVhc2luZyA9IFRSVUUpWzE6MTBdKSl7CiAgICBwb2ludHMoeD0xOihtYXguc3RlcHMtMSkseT1Mb25nLmFyclsxLCxpXSx0eXBlPSJsIixsdHk9MSwgY29sPXJnYigwLDAsMSwgMC44KSxsd2QgPSAyKQogICAgfWVsc2V7CiAgICBwb2ludHMoeD0xOihtYXguc3RlcHMtMSkseT1Mb25nLmFyclsxLCxpXSx0eXBlPSJsIixsdHk9MSwgY29sPXJnYigwLDAsMCwgMC4yNSkpCiAgfQp9CmxpbmVzKHg9MToobWF4LnN0ZXBzLTEpLHk9TG9uZy5hcnJbMSwsd2hpY2gubWF4KHVubGlzdChoZXVyLnJlcyRzY29yZXMpKV0sdHlwZT0ibCIsY29sPSJyZWQiLGx3ZD0zKQphYmxpbmUoaCA9IGZhYm4kbWxpaywgY29sPSJyZWQiLGx0eSA9IDMpCgpgYGAKQWJvdmUgd2UgcGxvdCB0aGUgc2NvcmVzIGluIGZ1bmN0aW9uIG9mIHRoZSBzdGVwcyBmb3IgdGhlIDIwMCBzZWFyY2hlcy4gVGhlIGJsdWUgbGluZXMgYXJlIHRoZSAxMCBiZXN0IGFuZCB0aGUgcmVkIG9uZSBpcyAqKnRoZSoqIG9uZSB0aGF0IGhhcyB0aGUgaGlnaGVzdCBzY29yZS4gQXMgb25lIGNhbiBzZWUsIGluIHNlYXJjaGVzIHRoYXQgd29yayB3ZWxsIHRoZSBvcHRpbWl6YXRpb24gaXMgYWxyZWFkeSBnb29kIGFmdGVyIDYwIHN0ZXBzLiBUaGlzIHBsb3QgaXMgYSBkaWFnbm9zdGljIHBsb3QgdXNlZCB0byBzZXQgdXAgdGhlIG51bWJlciBvZiByZXF1aXJlZCBzdGVwcy4gCgojIE1DTUMgb3ZlciB0aGUgc3RydWN0dXJlcwoKVXN1YWxseSwgdGhlIG91dHB1dCBvZiBhIEJheWVzaWFuIG5ldHdvcmsgYW5hbHlzaXMgb2YgYSBkYXRhc2V0IGVuZHMtdXAgd2l0aCBhIHNpbmdsZSB3ZWxsIGFkanVzdGVkIERBRy4gRnJvbSB0aGUgcmVzZWFyY2hlciBwb2ludCBvZiB2aWV3IHRoaXMgY291bGQgYmUgZnJ1c3RyYXRpbmcuIEluZGVlZCwgdGhlIG1vZGVsIGlzIHRoZSBvbmUgdGhhdCBpcyBiZXN0IHN1cHBvcnRlZCBieSB0aGUgZGF0YSBidXQgdGhlIHVuY2VydGFpbnR5IHF1YW50aWZpY2F0aW9uIGlzIG1pc3NpbmcuIENsYXNzaWNhbGx5IGluIGVwaWRlbWlvbG9neSwgcmVzZWFyY2hlcnMgYXJlIHVzZWQgdG8gZXhwcmVzcyBwb2ludCBlc3RpbWF0ZSB3aXRoIGFuIHVuY2VydGFpbnR5IG1lYXN1cmUuIEFuIGFyYyBpbiBhIEJheWVzaWFuIG5ldHdvcmsgaXMgYSBwb2ludCBlc3RpbWF0ZSwgd2Ugd2lsbCBzZWUgaG93IHRvIHBlcmZvcm0gbW9kZWwgYXZlcmFnaW5nLiBUaGUgKmxpbmsgc3RyZW5ndGgqIG1lYXN1cmUgaXMgZGVzaWduZWQgdG8gYWNjb3VudCBmb3IgdGhhdC4gQW4gbW9yZSBuYXR1cmFsIGFsdGVybmF0aXZlIGlzIHRvIHBlcmZvcm0gTUNNQyBvdmVyIHN0cnVjdHVyZXMgW0BmcmllZG1hbjIwMDNiZWluZ10uIAoKV2UgdXNlIHRoZSBgbWNtY2FibigpYCBmdW5jdGlvbiBvbiB0aGUgY2FjaGUgb2YgcHJlLWNvbXB1dGVkIG5ldHdvcmtzIHNjb3Jlcy4gT25lIG5lZWRzIHRvIGRlZmluZSB0aGUgdHlwZSBvZiBzY29yZSB1c2VkIChoZXJlIGlzIHRoZSBtYXJnaW5hbCBsaWtlbGlob29kIGBtbGlrYCkuIFRoZSBtYXhpbXVtIG9mIG51bWJlciBvZiBwYXJlbnRzIHBlciBub2RlIChzYW1lIGFzIHRoZSBvbmUgdXNlZCBpbiBgYnVpbGRzY29yZWNhY2hlKClgKS4gVGhlIE1DTUMgbGVhcm5pbmcgc2NoZW1lLCBkZWZpbmVkIGFzOiBudW1iZXIgb2YgTUNNQyBzYW1wbGVzLCBudW1iZXIgb2YgdGhpbm5lZCBzYW1wbGVkICh0byBhdm9pZCBhdXRvY29ycmVsYXRpb24pIGFuZCB0aGUgbGVuZ3RoIG9mIHRoZSBidXJuLWluIHBoYXNlLiBQb3NzaWJseSBhIHN0YXJ0aW5nIERBRyBhbmQgYSBzdHJ1Y3R1cmFsIHByaW9yLiBXZSBhbHNvIG5lZWQgdG8gc2VsZWN0IHRoZSByZWxhdGl2ZSBwcm9iYWJpbGl0eSBvZiBwZXJmb3JtaW5nIHJhZGljYWwgbW92ZXMgKHNodWZmbGluZykuIEluZGVlZCwgYSBuYWl2ZSBNQ01DIGFwcHJvYWNoIGlzIGtub3duIHRvIGdldCB2ZXJ5IGVhc2lseSBzdHVjayBpbiBsb2NhbCBtYXhpbXVtIChmb3IgbW9yZSBkZXRhaWxzIHNlZTogW0BncnplZ29yY3p5azIwMDhpbXByb3Zpbmc7QHN1MjAxNmltcHJvdmluZ10pLiAKCmBgYHtyLGV2YWw9RkFMU0UsIGVjaG89VFJVRX0KbWNtYy5vdXQgPC0gbWNtY2FibihzY29yZS5jYWNoZSA9IG15Y2FjaGUsCiAgICAgICAgICAgICAgICAgIHNjb3JlID0gIm1saWsiLAogICAgICAgICAgICAgICAgICBkYXRhLmRpc3RzID0gZGlzdCwKICAgICAgICAgICAgICAgICAgbWF4LnBhcmVudHMgPSA0LAogICAgICAgICAgICAgICAgICBtY21jLnNjaGVtZSA9IGMoMTAwMCw5LDUwMCksCiAgICAgICAgICAgICAgICAgIHNlZWQgPSAzMjEsCiAgICAgICAgICAgICAgICAgIHZlcmJvc2UgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgc3RhcnQuZGFnID0gInJhbmRvbSIsCiAgICAgICAgICAgICAgICAgIHByb2IucmV2ID0gMC4wNywKICAgICAgICAgICAgICAgICAgcHJvYi5tYnIgPSAwLjA3LAogICAgICAgICAgICAgICAgICBwcmlvci5jaG9pY2UgPSAxKQpgYGAKClRoaXMgaXMgYWdhaW4gY29tcHV0YXRpb25hbGx5IGNvbXBsZXghCgpIZXIgaXMgYSBwbG90IG9mIHRoZSBNQ01DIHNhbXBsZXMuIE9uZSBjYW4gc2VlIHRoZSBzY29yZXMgb2YgdGhlIHN0cnVjdHVyZXMgb24gdGhlIHktYXhpcyBpbiBmdW5jdGlvbiBvZiB0aGUgaW5kZXggc3RlcHMuIFRoZSBkb3RzIGFyZSB0aGUgcmFkaWNhbCBtb3Zlcy4gT25lIHRoZSByaWdodCBzaWRlIGEgaGlzdG9ncmFtIHNob3dzIHRoZSBudW1iZXIgb2Ygc3RydWN0dXJlcyB3aXRoIGEgZ2l2ZW4gc2NvcmUuIEFzIG9uZSBjYW4gc2VlIHRoZSBoaXN0b2dyYW0gaXMgdmVyeSBwZWFrZWQgb24gdGhlIG1heGltdW0gcG9zc2libGUgc2NvcmUuIAoKYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD00fQpsb2FkKCJtY21jLlJkYXRhIikKcGxvdChtY21jLm91dCkKYGBgCgpPbmUgY2FuIGFsc28gZGlzcGxheSB0aGUgY3VtdWxhdGl2ZSBtYXhpbXVtIHNjb3JlICh1c2VkIGZvciBuZXR3b3JrIHNjb3JlIG9wdGltaXphdGlvbikuCgpgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTR9CnBsb3QobWNtYy5vdXQsbWF4LnNjb3JlPVRSVUUpCmBgYAoKQnV0IHRoZSBtYWpvciBhZHZhbnRhZ2Ugb2YgdGhpcyBtZXRob2QgaXMgdGhlIHBvc3NpYmlsaXR5IG9mIHF1ZXJ5aW5nIHRoZSBNQ01DIHNhbXBsZSB1c2luZyBhIGZvcm11bGEgc3RhdGVtZW50LgoKYGBge3IsIGVjaG89VFJVRSwgZXZhbD1UUlVFfQojIGF2ZXJhZ2UgaW5kaXZpZHVhbCBhcmMgc3VwcG9ydApxdWVyeShtY21jYWJuID0gbWNtYy5vdXQpCgojIHByb2JhYmlsaXR5IHRoYXQgd29ybSBjb3VudCBiZWluZyBsaW5rZWQgdG8gYWdlIGJ1dCBub3QgdG8gZmVtYWxlIGRpcmVjdGx5CnF1ZXJ5KG1jbWNhYm4gPSBtY21jLm91dCxmb3JtdWxhID0gfndvcm1Db3VudHxhZ2Utd29ybUNvdW50fGZlbWFsZSkKCiMgcHJvYmFiaWxpdHkgdGhhdCB3b3JtIGNvdW50IGJlaW5nIGRpcmVjdGx5IGxpbmtlZCB0byBhZ2UgYW5kIGFkZyBhbmQgdGhhdCBhZGcgaXMgbGluayB0byBhZ2UgKHVuZGlyZWN0ZWQpCnF1ZXJ5KG1jbWNhYm4gPSBtY21jLm91dCxmb3JtdWxhID0gfndvcm1Db3VudHxhZ2UgKyB3b3JtQ291bnR8YWRnICsgYWdlfGFkZykrCiAgcXVlcnkobWNtY2FibiA9IG1jbWMub3V0LGZvcm11bGEgPSB+d29ybUNvdW50fGFnZSArIHdvcm1Db3VudHxhZGcgKyBhZGd8YWdlKQpgYGAKCgojIFJlZmVyZW5jZXMKCg==