Introduction:


A Rubik’s cube is a popular toy first created in 1974 by Ernő Rubik, a Hungarian sculptor and architect. It is a small cube made up of an n x n x n array of small cube blocks, called “cubies.” Each cubie face on the outside of the puzzle has a colored sticker. The goal is to rotate the cubies in slices of n x n x 1 in order to make all sides a solid color. We will be focusing on the traditional 3 x 3 x 3 Rubik’s cube, which has 6 center cubes, 12 edge cubes, and 8 corners.

A valid configuration of a Rubik’s cube is one that can be obtained by a series of slice rotations. In mathematical terms, the following three criteria must be met: (1) permutations of edge pieces and permutations of corner pieces have same parity, (2) the sum of corner twists is zero, and (3) the sum of edge twists is zero. Some examples of invalid configurations are two edges or two corner pieces being swapped, an edge being flipped, or a corner being twisted. There are 43,252,003,274,489,856,000 possible valid configurations. Interestingly, if you took apart a Rubik’s cube and randomly reassembled it, you would only have a 1/12 chance that your scrambled configuration is valid. All valid configurations are at most 20 moves away from the solution, but since people follow patterns and strategies to solve the puzzle, it usually takes more.

Our question is: What is the time complexity of optimally solving a 3x3x3 Rubik’s Cube? Our answer is: A 3x3x3 Rubik’s Cube is NP complete.


Description of the Result:


The Rubik’s Cube Problem is in NP

We can convert the Rubik’s cube problem into a decision problem - Can a particular cube be solved in exactly n moves? This decision problem is an NP problem because you can check if an n-move sequence solves the cube, and hence prove that it can be solved in n moves in polynomial time.


Hamiltonian Path is NP-complete

Q: What is the Hamiltonian Path problem?

Ans: So for a given graph, the Hamiltonian path problem requires you to find a hamiltonian path, where a hamiltonian path is a simple open path through a graph that goes through every vertex exactly once.

We can write the Hamiltonian Path problem in the following form: * HAMILTONIAN-PATH/ HP = { (G) | G is a graph that contains a Hamiltonian path }

To show that HP is in NP we could use a graph G with V vertices and E edges as our witness. We would nondeterministically choose edges from graph G that are to be included in the Hamilton path and then traverse/trace the path. The verifier would first confirm whether the path includes the same no. of vertices as the total no. of vertices in graph G. It would then confirm whether the path goes through each vertex exactly once. This entire process can be conducted within polynomial time, hence proving the HP is in NP.

Next we will reduce the Hamilton Cycle problem, which is a known NP-complete problem, to the Hamilton Path problem. So a Hamilton cycle is a closed loop/ graph cycle goes through the each vertex of the graph exactly once. The Hamiltonian Cycle problem can be expressed as follows:

  • HAMILTONIAN-CYCLE/ HC = { (G) | G is graph that contains a Hamiltonian cycle }.

To prove that HP is NP-hard we will polynomially reduce HC to HP by transforming an instance of HC to an instance of HP and vice versa.

Proof:

Construct graph G’ such that G contains a Hamiltonian cycle if and only if G’ contains a Hamiltonian path. To do this:

  • Choose an arbitrary vertex u in G and add a copy, u’, of it together with all its edges.

  • Add vertices v and v’ to the graph and connect v with u and v’ with u’

Suppose first that G contains a Hamiltonian cycle. Then we get a Hamiltonian path in G’ if we start in v, follow the cycle that we got from G back to u’ instead of u and finally end in v’. For instance, in the following figure, G contains the Hamiltonian cycle 2,5,1,3,4,2. In G’ this corresponds to v,2,5,1,3,4,2’,v’:

Conversely, suppose G’ contains a Hamiltonian path. In that case, the path must necessarily have endpoints in v and v’. This path can be transformed to a cycle in G. Namely, if we disregard v and v’, the path must have endpoints in u and u’ and if we remove u’ we get a cycle in G if we close the path back to u instead of u’.

Hence, we have shown that G contains a Hamiltonian cycle if and only if G’ contains a Hamiltonian path, which concludes the proof that HAMILTONIAN-PATH is NP-complete.


Hamiltonian Path reduces to Cayley Graph

A Cayley Graph is used to represent groups in an abstract way. A group is a set of elements with an identity element, an operation, an inverse of the operation, and some generating set. An example from the presentation was the group of all integers, generated by adding the numbers 2 and 3 together some number of times. The identity element is 0, the operation is addition, and the inverse is subtraction. To represent this group as a Cayley graph, draw a vertex for each member of the group, meaning every integer. Two vertices are connected by an edge if an instance of the group operation (adding 2 or 3) can transform one group member into another. The edges are directed to indicate the direction of the operation, and colored to indicate which generating element was used in the transformation. For example, a red arrow pointed from 1 to 3 to indicate that adding 2 to 1 gets 3.

A vertex-transitive graph is a graph in which all vertices are similar. There is an isomorphic transformation that relates the graph to itself. For any pair of vertices in a vertex-transitive graph, each vertex is similar to the other, so there is an automorphism that maps any vertex to any other vertex in the graph. All vertex-transitive graphs are regular, meaning all vertices on the graph have the same degree. Every Cayley graph is vertex-transitive, but not every vertex-transitive graph is a Cayley graph.

By the Lovász Conjecture, every finite connected vertex-transitive graph contains a Hamiltonian path. There are 5 known counterexamples, but none of them are Cayley graphs. So every finite connected Cayley graph contains a Hamiltonian path.

The Hamiltonian path problem can be constructed as follows, where G is a graph: On input G: Run CAYLEY-GRAPH on G and DWID.


Cayley Graph reduces to Rubik’s Cube

A Cayley Graph is a directed graph that has some finite set of generators, which are edges of the graph, that lead to a certain node of the graph. We can take the format of the Cayley Graph to represent a Rubik’s Cube graphically.

Each configuration of the Rubik’s Cube is represented as a node of the graph. Each movement of the Rubik’s Cube is represented by an edge of the graph. These movements can be any rotation of 90°, 180°, or 270° degrees for any row or column of the Rubik’s Cube.

If this Cayley Graph existed, it would be very large, but it is possible to exist. Each node would have directed edges that pointed to each possible configuration based on each possible movement of the Rubik’s Cube.

From the video lecture “Visual Group Theory, Lecture 1.2: Cayley graphs”, the Cayley Graph for a Rubik’s Cube is imagined as a “Big Book”. A sample entry for this book is shown below:

In this entry, it focuses on one configuration of the Rubik’s Cube as pictured in the image, which would be equivalent to one node of the Cayley Graph. It also shows each possible movement (although only for 90° rotations), which are equivalent to edges or generators of the Cayley Graph.

Since it is possible for every configuration and every movement of the Rubik’s Cube to be represented by a Cayley Graph, the Cayley Graph reduces to Rubik’s Cube. Therefore, the Rubik’s Cube is NP-Hard. Since we earlier proved that the Rubik’s Cube is in NP, the Rubik’s Cube Problem is NP-Complete.


Discussion:


We were initially planning to focus on proving that the n x n x n Rubik’s cube is NP complete, which was proved in paper by Erik Demaine, Sarah Eisenstat, and Mikhail Rudoy. While this proof was a huge deal to mathematicians and computer scientists and we were just as excited about presenting it, we realized that this proof is beyond what we can comprehend at this point with our knowledge of graphs and computation. While we were researching on alternate papers to understand this proof, we came across “god’s number”, which is 20 for a 3 x 3 x 3 Rubik’s cube. This is the maximum number of moves needed to solve any configuration. This intrigued us and we decided to narrow down our topic to a 3 x 3 x 3 rubik’s cube. However, we were not able to find a singular paper with all the reductions we needed and hence compiled our entire proof from different sources.

While this process was intimidating, it allowed us to understand the proof with a depth that would have probably not been possible otherwise. The Hamiltonian Path is the reduction that is used to prove that the n x n x n Rubik’s cube is NP complete, even though we are using it solely for the n = 3 case. From the original paper, we knew that the Hamiltonian Path is NP complete and so looked for proofs for the Hamiltonian path being NP complete. This is how we started our reduction. We found that the 3 x 3 x 3 rubik’s cube can be represented as a Cayley graph, which is how “god’s number” was found. We then looked for connections between Cayley graphs and Hamiltonian paths and found that every Cayley graph has a Hamiltonian path. We compiled everything we learned for our reduction: HAMILTONIAN-PATH ≤P CAYLEY-GRAPH ≤P RUBIK’S−CUBE.

Although we found a few short articles on this proof, since we did not follow a concrete, singular paper, we are unsure about our reduction. Mainly we are concerned if we are reducing in the right direction.

Optimal algorithms for the Rubik’s cube have been a point of discussion for generations and our original motivation behind choosing this topic was to learn the optimal algorithm that solves it. We learnt there is no such handed-down solution since it is a difficult problem and is in fact NP complete. The rubik’s cube problem is interesting because it is related to very important subjects in mathematics and computer science such as combinatorics, computational complexity, and group theory, to name just three. The Rubik’s cube is an instance of what’s called a configuration problem, the best-known example of which involves finding the most efficient way to re-organize boxes stacked in a warehouse. If an optimal solution to this problem was found, it would take algorithms to a whole new level.


Contributions:


For this project, we divided the material into five sections. Each team member was responsible for creating the slides and writing the blog material for their section. However, we all worked together to understand the proof and make decisions about the presentation, and we all met regularly to discuss the material and any issues. Joce worked on the “Introduction”, Nashshaba worked on the “Hamiltonian Path is NP-complete”, Charlotte worked on the “Hamiltonian Path reduces to Cayley Graph”, Ariana worked on the “Cayley Graph reduces to Rubik’s Cube”, and Asmita worked on the “Rubik’s Cube Problem is in NP” and the “Discussion”. Additionally, Asmita created the original draft for the presentation, and Joce compiled the R Markdown file for the blog post.


References:


  1. Erik D. Demaine, Sarah Eisenstat, Mikhail Rudoy. “Solving the Rubik’s Cube Optimally Is NP-Complete.”
  2. “Visual Group Theory, Lecture 1.2: Cayley Graphs.” YouTube, YouTube, 24 Feb. 2016, www.youtube.com/watch?v=vzEObOzsSKY.
  3. Algorithms And Complexity. Exercise Session 6, and Np-Problems. “In Mobile Telephony, You Need to Solve the Frequency Allocation Problem.” In Mobile Telephony, You Need to Solve the Frequency Allocation Problem.
  4. “Lovász Conjecture.” Wikipedia, Wikimedia Foundation, 14 Mar. 2018, en.wikipedia.org/wiki/Lov%C3%A1sz_conjecture.
  5. “Unsolveable Rubik’s Cube - Invalid Scramble.” Ruwix, ruwix.com/the-rubiks-cube/unsolvable-rubiks-cube-invalid-scramble/.
  6. Bartlett, Padraic. “Cayley Graphs.” Wolfram Demonstrations Project, 2007
  7. “Rubik’s Cube Notes – Cayley Graphs and God’s Algorithm.” Yet Another Mathblog, 18 Aug. 2016, yetanothermathblog.com/permutation-puzzles/lecture-notes-on-the-rubiks-cube/rubiks-cube-notes-cayley-graphs-and-gods-algorithm/.
  8. “Rubik’s Cube.” Wikipedia, Wikimedia Foundation, 2 May 2018, en.wikipedia.org/wiki/Rubik%27s_Cube.
  9. “Lovász Conjecture and Devil’s Algorithm.” Complex Projective 4-Space, 7 July 2013, cp4space.wordpress.com/2013/07/07/lovasz-conjecture-and-devils-algorithm/.
LS0tCnRpdGxlOiAiQ29tcHV0YXRpb24gaW4gUnViaWsncyBDdWJlIgphdXRob3I6ICJBc21pdGEgR2F1dGFtLCBKb2NlIEtvZmtlLCBBcmlhbmEgTWVyZWRpdGgsIE5hc2hzaGFiYSBOYXdheiwgQ2hhcmxvdHRlIENyYW5kYWxsIgpkYXRlOiAiTWF5IDMsIDIwMTgiCm91dHB1dDogb2lsYWJzOjpsYWJfcmVwb3J0Ci0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKbGlicmFyeShkcGx5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KG9pbGFicykKYGBgCgoqICogKgoKIyMjIEludHJvZHVjdGlvbjogCgotLS0KCiFbXShydWJpay5qcGcpCgpBIFJ1Ymlr4oCZcyBjdWJlIGlzIGEgcG9wdWxhciB0b3kgZmlyc3QgY3JlYXRlZCBpbiAxOTc0IGJ5IEVybsWRIFJ1YmlrLCBhIEh1bmdhcmlhbiBzY3VscHRvciBhbmQgYXJjaGl0ZWN0LiBJdCBpcyBhIHNtYWxsIGN1YmUgbWFkZSB1cCBvZiBhbiBuIHggbiB4IG4gYXJyYXkgb2Ygc21hbGwgY3ViZSBibG9ja3MsIGNhbGxlZCDigJxjdWJpZXMu4oCdIEVhY2ggY3ViaWUgZmFjZSBvbiB0aGUgb3V0c2lkZSBvZiB0aGUgcHV6emxlIGhhcyBhIGNvbG9yZWQgc3RpY2tlci4gVGhlIGdvYWwgaXMgdG8gcm90YXRlIHRoZSBjdWJpZXMgaW4gc2xpY2VzIG9mIG4geCBuIHggMSBpbiBvcmRlciB0byBtYWtlIGFsbCBzaWRlcyBhIHNvbGlkIGNvbG9yLiBXZSB3aWxsIGJlIGZvY3VzaW5nIG9uIHRoZSB0cmFkaXRpb25hbCAzIHggMyB4IDMgUnViaWvigJlzIGN1YmUsIHdoaWNoIGhhcyA2IGNlbnRlciBjdWJlcywgMTIgZWRnZSBjdWJlcywgYW5kIDggY29ybmVycy4KCkEgdmFsaWQgY29uZmlndXJhdGlvbiBvZiBhIFJ1Ymlr4oCZcyBjdWJlIGlzIG9uZSB0aGF0IGNhbiBiZSBvYnRhaW5lZCBieSBhIHNlcmllcyBvZiBzbGljZSByb3RhdGlvbnMuIEluIG1hdGhlbWF0aWNhbCB0ZXJtcywgdGhlIGZvbGxvd2luZyB0aHJlZSBjcml0ZXJpYSBtdXN0IGJlIG1ldDogKDEpIHBlcm11dGF0aW9ucyBvZiBlZGdlIHBpZWNlcyBhbmQgcGVybXV0YXRpb25zIG9mIGNvcm5lciBwaWVjZXMgaGF2ZSBzYW1lIHBhcml0eSwgKDIpIHRoZSBzdW0gb2YgY29ybmVyIHR3aXN0cyBpcyB6ZXJvLCBhbmQgKDMpIHRoZSBzdW0gb2YgZWRnZSB0d2lzdHMgaXMgemVyby4gU29tZSBleGFtcGxlcyBvZiBpbnZhbGlkIGNvbmZpZ3VyYXRpb25zIGFyZSB0d28gZWRnZXMgb3IgdHdvIGNvcm5lciBwaWVjZXMgYmVpbmcgc3dhcHBlZCwgYW4gZWRnZSBiZWluZyBmbGlwcGVkLCBvciBhIGNvcm5lciBiZWluZyB0d2lzdGVkLiBUaGVyZSBhcmUgNDMsMjUyLDAwMywyNzQsNDg5LDg1NiwwMDAgcG9zc2libGUgdmFsaWQgY29uZmlndXJhdGlvbnMuIEludGVyZXN0aW5nbHksIGlmIHlvdSB0b29rIGFwYXJ0IGEgUnViaWvigJlzIGN1YmUgYW5kIHJhbmRvbWx5IHJlYXNzZW1ibGVkIGl0LCB5b3Ugd291bGQgb25seSBoYXZlIGEgMS8xMiBjaGFuY2UgdGhhdCB5b3VyIHNjcmFtYmxlZCBjb25maWd1cmF0aW9uIGlzIHZhbGlkLiBBbGwgdmFsaWQgY29uZmlndXJhdGlvbnMgYXJlIGF0IG1vc3QgMjAgbW92ZXMgYXdheSBmcm9tIHRoZSBzb2x1dGlvbiwgYnV0IHNpbmNlIHBlb3BsZSBmb2xsb3cgcGF0dGVybnMgYW5kIHN0cmF0ZWdpZXMgdG8gc29sdmUgdGhlIHB1enpsZSwgaXQgdXN1YWxseSB0YWtlcyBtb3JlLgoKT3VyIHF1ZXN0aW9uIGlzOiBXaGF0IGlzIHRoZSB0aW1lIGNvbXBsZXhpdHkgb2Ygb3B0aW1hbGx5IHNvbHZpbmcgYSAzeDN4MyBSdWJpa+KAmXMgQ3ViZT8KT3VyIGFuc3dlciBpczogQSAzeDN4MyBSdWJpa+KAmXMgQ3ViZSBpcyBOUCBjb21wbGV0ZS4KCiogKiAqCgojIyMgRGVzY3JpcHRpb24gb2YgdGhlIFJlc3VsdDoKCi0tLSAKCiMjIyMgKipUaGUgUnViaWvigJlzIEN1YmUgUHJvYmxlbSBpcyBpbiBOUCoqCgpXZSBjYW4gY29udmVydCB0aGUgUnViaWvigJlzIGN1YmUgcHJvYmxlbSBpbnRvIGEgZGVjaXNpb24gcHJvYmxlbSAtIENhbiBhIHBhcnRpY3VsYXIgY3ViZSBiZSBzb2x2ZWQgaW4gZXhhY3RseSBuIG1vdmVzPyBUaGlzIGRlY2lzaW9uIHByb2JsZW0gaXMgYW4gTlAgcHJvYmxlbSBiZWNhdXNlIHlvdSBjYW4gY2hlY2sgaWYgYW4gbi1tb3ZlIHNlcXVlbmNlIHNvbHZlcyB0aGUgY3ViZSwgYW5kIGhlbmNlIHByb3ZlIHRoYXQgaXQgY2FuIGJlIHNvbHZlZCBpbiBuIG1vdmVzIGluIHBvbHlub21pYWwgdGltZS4KCi0tLQoKIyMjIyAqKkhhbWlsdG9uaWFuIFBhdGggaXMgTlAtY29tcGxldGUqKgoKKlE6KiBXaGF0IGlzIHRoZSBIYW1pbHRvbmlhbiBQYXRoIHByb2JsZW0/CgoqQW5zOiogU28gZm9yIGEgZ2l2ZW4gZ3JhcGgsIHRoZSBIYW1pbHRvbmlhbiBwYXRoIHByb2JsZW0gcmVxdWlyZXMgeW91IHRvIGZpbmQgYSBoYW1pbHRvbmlhbiBwYXRoLCB3aGVyZSBhIGhhbWlsdG9uaWFuIHBhdGggaXMgYSBzaW1wbGUgb3BlbiBwYXRoIHRocm91Z2ggYSBncmFwaCB0aGF0IGdvZXMgdGhyb3VnaCBldmVyeSB2ZXJ0ZXggZXhhY3RseSBvbmNlLgoKV2UgY2FuIHdyaXRlIHRoZSBIYW1pbHRvbmlhbiBQYXRoIHByb2JsZW0gaW4gdGhlIGZvbGxvd2luZyBmb3JtOgoqIEhBTUlMVE9OSUFO77yNUEFUSC8gSFAgPSB7IChHKSB8IEcgaXMgYSBncmFwaCB0aGF0IGNvbnRhaW5zIGEgSGFtaWx0b25pYW4gcGF0aCB9CgpUbyBzaG93IHRoYXQgSFAgaXMgaW4gTlAgd2UgY291bGQgdXNlIGEgZ3JhcGggRyB3aXRoIFYgdmVydGljZXMgYW5kIEUgZWRnZXMgYXMgb3VyIHdpdG5lc3MuIFdlIHdvdWxkIG5vbmRldGVybWluaXN0aWNhbGx5IGNob29zZSBlZGdlcyBmcm9tIGdyYXBoIEcgdGhhdCBhcmUgdG8gYmUgaW5jbHVkZWQgaW4gdGhlIEhhbWlsdG9uIHBhdGggYW5kIHRoZW4gdHJhdmVyc2UvdHJhY2UgdGhlIHBhdGguIFRoZSB2ZXJpZmllciB3b3VsZCBmaXJzdCBjb25maXJtIHdoZXRoZXIgdGhlIHBhdGggaW5jbHVkZXMgdGhlIHNhbWUgbm8uIG9mIHZlcnRpY2VzIGFzIHRoZSB0b3RhbCBuby4gb2YgdmVydGljZXMgaW4gZ3JhcGggRy4gSXQgd291bGQgdGhlbiBjb25maXJtIHdoZXRoZXIgdGhlIHBhdGggZ29lcyB0aHJvdWdoIGVhY2ggdmVydGV4IGV4YWN0bHkgb25jZS4gVGhpcyBlbnRpcmUgcHJvY2VzcyBjYW4gYmUgY29uZHVjdGVkIHdpdGhpbiBwb2x5bm9taWFsIHRpbWUsIGhlbmNlIHByb3ZpbmcgdGhlIEhQIGlzIGluIE5QLgoKTmV4dCB3ZSB3aWxsIHJlZHVjZSB0aGUgSGFtaWx0b24gQ3ljbGUgcHJvYmxlbSwgd2hpY2ggaXMgYSBrbm93biBOUC1jb21wbGV0ZSBwcm9ibGVtLCB0byAgICB0aGUgSGFtaWx0b24gUGF0aCBwcm9ibGVtLiBTbyBhIEhhbWlsdG9uIGN5Y2xlIGlzIGEgY2xvc2VkIGxvb3AvIGdyYXBoIGN5Y2xlIGdvZXMgdGhyb3VnaCB0aGUgZWFjaCB2ZXJ0ZXggb2YgdGhlIGdyYXBoIGV4YWN0bHkgb25jZS4gVGhlIEhhbWlsdG9uaWFuIEN5Y2xlIHByb2JsZW0gY2FuIGJlIGV4cHJlc3NlZCBhcyBmb2xsb3dzOiAKCiogSEFNSUxUT05JQU4tQ1lDTEUvIEhDID0geyAoRykgfCBHIGlzIGdyYXBoIHRoYXQgY29udGFpbnMgYSBIYW1pbHRvbmlhbiBjeWNsZSB9LgoKVG8gcHJvdmUgdGhhdCBIUCBpcyBOUC1oYXJkIHdlIHdpbGwgcG9seW5vbWlhbGx5IHJlZHVjZSBIQyB0byBIUCBieSB0cmFuc2Zvcm1pbmcgYW4gaW5zdGFuY2Ugb2YgSEMgdG8gYW4gaW5zdGFuY2Ugb2YgSFAgYW5kIHZpY2UgdmVyc2EuCgoqUHJvb2Y6KgoKQ29uc3RydWN0IGdyYXBoIEfigJkgc3VjaCB0aGF0IEcgY29udGFpbnMgYSBIYW1pbHRvbmlhbiBjeWNsZSBpZiBhbmQgb25seSBpZiBH4oCZIGNvbnRhaW5zIGEgSGFtaWx0b25pYW4gcGF0aC4gVG8gZG8gdGhpczogCiAKICogQ2hvb3NlIGFuIGFyYml0cmFyeSB2ZXJ0ZXggdSBpbiBHIGFuZCBhZGQgYSBjb3B5LCB14oCZLCBvZiBpdCB0b2dldGhlciB3aXRoIGFsbCBpdHMgZWRnZXMuCiAKICogQWRkIHZlcnRpY2VzIHYgYW5kIHbigJkgdG8gdGhlIGdyYXBoIGFuZCBjb25uZWN0IHYgd2l0aCB1IGFuZCB24oCZIHdpdGggdeKAmQogClN1cHBvc2UgZmlyc3QgdGhhdCBHIGNvbnRhaW5zIGEgSGFtaWx0b25pYW4gY3ljbGUuIFRoZW4gd2UgZ2V0IGEgSGFtaWx0b25pYW4gcGF0aCBpbiBH4oCZIGlmIHdlIHN0YXJ0IGluIHYsIGZvbGxvdyB0aGUgY3ljbGUgdGhhdCB3ZSBnb3QgZnJvbSBHIGJhY2sgdG8gdeKAmSBpbnN0ZWFkIG9mIHUgYW5kIGZpbmFsbHkgZW5kIGluIHbigJkuIEZvciBpbnN0YW5jZSwgaW4gdGhlIGZvbGxvd2luZyBmaWd1cmUsIEcgY29udGFpbnMgdGhlIEhhbWlsdG9uaWFuIGN5Y2xlIDIsNSwxLDMsNCwyLiBJbiBH4oCZIHRoaXMgY29ycmVzcG9uZHMgdG8gdiwyLDUsMSwzLDQsMuKAmSx24oCZOgoKIVtdKGhhbWlsdG9uaWFuLmpwZykKCkNvbnZlcnNlbHksIHN1cHBvc2UgR+KAmSBjb250YWlucyBhIEhhbWlsdG9uaWFuIHBhdGguIEluIHRoYXQgY2FzZSwgdGhlIHBhdGggbXVzdCBuZWNlc3NhcmlseSBoYXZlIGVuZHBvaW50cyBpbiB2IGFuZCB24oCZLiBUaGlzIHBhdGggY2FuIGJlIHRyYW5zZm9ybWVkIHRvIGEgY3ljbGUgaW4gRy4gTmFtZWx5LCBpZiB3ZSBkaXNyZWdhcmQgdiBhbmQgduKAmSwgdGhlIHBhdGggbXVzdCBoYXZlIGVuZHBvaW50cyBpbiB1IGFuZCB14oCZIGFuZCBpZiB3ZSByZW1vdmUgdeKAmSB3ZSBnZXQgYSBjeWNsZSBpbiBHIGlmIHdlIGNsb3NlIHRoZSBwYXRoIGJhY2sgdG8gdSBpbnN0ZWFkIG9mIHXigJkuCgpIZW5jZSwgd2UgaGF2ZSBzaG93biB0aGF0IEcgY29udGFpbnMgYSBIYW1pbHRvbmlhbiBjeWNsZSBpZiBhbmQgb25seSBpZiBH4oCZIGNvbnRhaW5zIGEgSGFtaWx0b25pYW4gcGF0aCwgd2hpY2ggY29uY2x1ZGVzIHRoZSBwcm9vZiB0aGF0IEhBTUlMVE9OSUFOLVBBVEggaXMgTlAtY29tcGxldGUuCgotLS0gCgojIyMjICoqSGFtaWx0b25pYW4gUGF0aCByZWR1Y2VzIHRvIENheWxleSBHcmFwaCoqCgpBIENheWxleSBHcmFwaCBpcyB1c2VkIHRvIHJlcHJlc2VudCBncm91cHMgaW4gYW4gYWJzdHJhY3Qgd2F5LiBBIGdyb3VwIGlzIGEgc2V0IG9mIGVsZW1lbnRzIHdpdGggYW4gaWRlbnRpdHkgZWxlbWVudCwgYW4gb3BlcmF0aW9uLCBhbiBpbnZlcnNlIG9mIHRoZSBvcGVyYXRpb24sIGFuZCBzb21lIGdlbmVyYXRpbmcgc2V0LiBBbiBleGFtcGxlIGZyb20gdGhlIHByZXNlbnRhdGlvbiB3YXMgdGhlIGdyb3VwIG9mIGFsbCBpbnRlZ2VycywgZ2VuZXJhdGVkIGJ5IGFkZGluZyB0aGUgbnVtYmVycyAyIGFuZCAzIHRvZ2V0aGVyIHNvbWUgbnVtYmVyIG9mIHRpbWVzLiBUaGUgaWRlbnRpdHkgZWxlbWVudCBpcyAwLCB0aGUgb3BlcmF0aW9uIGlzIGFkZGl0aW9uLCBhbmQgdGhlIGludmVyc2UgaXMgc3VidHJhY3Rpb24uIFRvIHJlcHJlc2VudCB0aGlzIGdyb3VwIGFzIGEgQ2F5bGV5IGdyYXBoLCBkcmF3IGEgdmVydGV4IGZvciBlYWNoIG1lbWJlciBvZiB0aGUgZ3JvdXAsIG1lYW5pbmcgZXZlcnkgaW50ZWdlci4gVHdvIHZlcnRpY2VzIGFyZSBjb25uZWN0ZWQgYnkgYW4gZWRnZSBpZiBhbiBpbnN0YW5jZSBvZiB0aGUgZ3JvdXAgb3BlcmF0aW9uIChhZGRpbmcgMiBvciAzKSBjYW4gdHJhbnNmb3JtIG9uZSBncm91cCBtZW1iZXIgaW50byBhbm90aGVyLiBUaGUgZWRnZXMgYXJlIGRpcmVjdGVkIHRvIGluZGljYXRlIHRoZSBkaXJlY3Rpb24gb2YgdGhlIG9wZXJhdGlvbiwgYW5kIGNvbG9yZWQgdG8gaW5kaWNhdGUgd2hpY2ggZ2VuZXJhdGluZyBlbGVtZW50IHdhcyB1c2VkIGluIHRoZSB0cmFuc2Zvcm1hdGlvbi4gRm9yIGV4YW1wbGUsIGEgcmVkIGFycm93IHBvaW50ZWQgZnJvbSAxIHRvIDMgdG8gaW5kaWNhdGUgdGhhdCBhZGRpbmcgMiB0byAxIGdldHMgMy4KCiFbXShjYXlsZXkuanBnKQpBIHZlcnRleC10cmFuc2l0aXZlIGdyYXBoIGlzIGEgZ3JhcGggaW4gd2hpY2ggYWxsIHZlcnRpY2VzIGFyZSBzaW1pbGFyLiBUaGVyZSBpcyBhbiBpc29tb3JwaGljIHRyYW5zZm9ybWF0aW9uIHRoYXQgcmVsYXRlcyB0aGUgZ3JhcGggdG8gaXRzZWxmLiBGb3IgYW55IHBhaXIgb2YgdmVydGljZXMgaW4gYSB2ZXJ0ZXgtdHJhbnNpdGl2ZSBncmFwaCwgZWFjaCB2ZXJ0ZXggaXMgc2ltaWxhciB0byB0aGUgb3RoZXIsIHNvIHRoZXJlIGlzIGFuIGF1dG9tb3JwaGlzbSB0aGF0IG1hcHMgYW55IHZlcnRleCB0byBhbnkgb3RoZXIgdmVydGV4IGluIHRoZSBncmFwaC4gQWxsIHZlcnRleC10cmFuc2l0aXZlIGdyYXBocyBhcmUgcmVndWxhciwgbWVhbmluZyBhbGwgdmVydGljZXMgb24gdGhlIGdyYXBoIGhhdmUgdGhlIHNhbWUgZGVncmVlLiBFdmVyeSBDYXlsZXkgZ3JhcGggaXMgdmVydGV4LXRyYW5zaXRpdmUsIGJ1dCBub3QgZXZlcnkgdmVydGV4LXRyYW5zaXRpdmUgZ3JhcGggaXMgYSBDYXlsZXkgZ3JhcGguCgpCeSB0aGUgTG92w6FzeiBDb25qZWN0dXJlLCBldmVyeSBmaW5pdGUgY29ubmVjdGVkIHZlcnRleC10cmFuc2l0aXZlIGdyYXBoIGNvbnRhaW5zIGEgSGFtaWx0b25pYW4gcGF0aC4gVGhlcmUgYXJlIDUga25vd24gY291bnRlcmV4YW1wbGVzLCBidXQgbm9uZSBvZiB0aGVtIGFyZSBDYXlsZXkgZ3JhcGhzLiBTbyBldmVyeSBmaW5pdGUgY29ubmVjdGVkIENheWxleSBncmFwaCBjb250YWlucyBhIEhhbWlsdG9uaWFuIHBhdGguCgpUaGUgSGFtaWx0b25pYW4gcGF0aCBwcm9ibGVtIGNhbiBiZSBjb25zdHJ1Y3RlZCBhcyBmb2xsb3dzLCB3aGVyZSBHIGlzIGEgZ3JhcGg6Ck9uIGlucHV0IEc6ClJ1biBDQVlMRVktR1JBUEggb24gRyBhbmQgRFdJRC4KCi0tLSAKCiMjIyMgKipDYXlsZXkgR3JhcGggcmVkdWNlcyB0byBSdWJpa+KAmXMgQ3ViZSoqCgpBIENheWxleSBHcmFwaCBpcyBhIGRpcmVjdGVkIGdyYXBoIHRoYXQgaGFzIHNvbWUgZmluaXRlIHNldCBvZiBnZW5lcmF0b3JzLCB3aGljaCBhcmUgZWRnZXMgb2YgdGhlIGdyYXBoLCB0aGF0IGxlYWQgdG8gYSBjZXJ0YWluIG5vZGUgb2YgdGhlIGdyYXBoLiBXZSBjYW4gdGFrZSB0aGUgZm9ybWF0IG9mIHRoZSBDYXlsZXkgR3JhcGggdG8gcmVwcmVzZW50IGEgUnViaWvigJlzIEN1YmUgZ3JhcGhpY2FsbHkuIAoKRWFjaCBjb25maWd1cmF0aW9uIG9mIHRoZSBSdWJpa+KAmXMgQ3ViZSBpcyByZXByZXNlbnRlZCBhcyBhIG5vZGUgb2YgdGhlIGdyYXBoLiBFYWNoIG1vdmVtZW50IG9mIHRoZSBSdWJpa+KAmXMgQ3ViZSBpcyByZXByZXNlbnRlZCBieSBhbiBlZGdlIG9mIHRoZSBncmFwaC4gVGhlc2UgbW92ZW1lbnRzIGNhbiBiZSBhbnkgcm90YXRpb24gb2YgOTDCsCwgMTgwwrAsIG9yIDI3MMKwIGRlZ3JlZXMgZm9yIGFueSByb3cgb3IgY29sdW1uIG9mIHRoZSBSdWJpa+KAmXMgQ3ViZS4gCgpJZiB0aGlzIENheWxleSBHcmFwaCBleGlzdGVkLCBpdCB3b3VsZCBiZSB2ZXJ5IGxhcmdlLCBidXQgaXQgaXMgcG9zc2libGUgdG8gZXhpc3QuIEVhY2ggbm9kZSB3b3VsZCBoYXZlIGRpcmVjdGVkIGVkZ2VzIHRoYXQgcG9pbnRlZCB0byBlYWNoIHBvc3NpYmxlIGNvbmZpZ3VyYXRpb24gYmFzZWQgb24gZWFjaCBwb3NzaWJsZSBtb3ZlbWVudCBvZiB0aGUgUnViaWvigJlzIEN1YmUuIAoKRnJvbSB0aGUgdmlkZW8gbGVjdHVyZSDigJxWaXN1YWwgR3JvdXAgVGhlb3J5LCBMZWN0dXJlIDEuMjogQ2F5bGV5IGdyYXBoc+KAnSwgdGhlIENheWxleSBHcmFwaCBmb3IgYSBSdWJpa+KAmXMgQ3ViZSBpcyBpbWFnaW5lZCBhcyBhIOKAnEJpZyBCb29r4oCdLiBBIHNhbXBsZSBlbnRyeSBmb3IgdGhpcyBib29rIGlzIHNob3duIGJlbG93OiAKCiFbXShiaWdib29rLmpwZykKCkluIHRoaXMgZW50cnksIGl0IGZvY3VzZXMgb24gb25lIGNvbmZpZ3VyYXRpb24gb2YgdGhlIFJ1Ymlr4oCZcyBDdWJlIGFzIHBpY3R1cmVkIGluIHRoZSBpbWFnZSwgd2hpY2ggd291bGQgYmUgZXF1aXZhbGVudCB0byBvbmUgbm9kZSBvZiB0aGUgQ2F5bGV5IEdyYXBoLiBJdCBhbHNvIHNob3dzIGVhY2ggcG9zc2libGUgbW92ZW1lbnQgKGFsdGhvdWdoIG9ubHkgZm9yIDkwwrAgcm90YXRpb25zKSwgd2hpY2ggYXJlIGVxdWl2YWxlbnQgdG8gZWRnZXMgb3IgZ2VuZXJhdG9ycyBvZiB0aGUgQ2F5bGV5IEdyYXBoLiAKClNpbmNlIGl0IGlzIHBvc3NpYmxlIGZvciBldmVyeSBjb25maWd1cmF0aW9uIGFuZCBldmVyeSBtb3ZlbWVudCBvZiB0aGUgUnViaWvigJlzIEN1YmUgdG8gYmUgcmVwcmVzZW50ZWQgYnkgYSBDYXlsZXkgR3JhcGgsIHRoZSBDYXlsZXkgR3JhcGggcmVkdWNlcyB0byBSdWJpa+KAmXMgQ3ViZS4gVGhlcmVmb3JlLCB0aGUgUnViaWvigJlzIEN1YmUgaXMgTlAtSGFyZC4gU2luY2Ugd2UgZWFybGllciBwcm92ZWQgdGhhdCB0aGUgUnViaWvigJlzIEN1YmUgaXMgaW4gTlAsIHRoZSBSdWJpa+KAmXMgQ3ViZSBQcm9ibGVtIGlzIE5QLUNvbXBsZXRlLgoKKiAqICoKCiMjIyBEaXNjdXNzaW9uOgoKLS0tCgpXZSB3ZXJlIGluaXRpYWxseSBwbGFubmluZyB0byBmb2N1cyBvbiBwcm92aW5nIHRoYXQgdGhlIG4geCBuIHggbiBSdWJpa+KAmXMgY3ViZSBpcyBOUCBjb21wbGV0ZSwgd2hpY2ggd2FzIHByb3ZlZCBpbiBwYXBlciBieSBFcmlrIERlbWFpbmUsIFNhcmFoIEVpc2Vuc3RhdCwgYW5kIE1pa2hhaWwgUnVkb3kuIFdoaWxlIHRoaXMgcHJvb2Ygd2FzIGEgaHVnZSBkZWFsIHRvIG1hdGhlbWF0aWNpYW5zIGFuZCBjb21wdXRlciBzY2llbnRpc3RzIGFuZCB3ZSB3ZXJlIGp1c3QgYXMgZXhjaXRlZCBhYm91dCBwcmVzZW50aW5nIGl0LCB3ZSByZWFsaXplZCB0aGF0IHRoaXMgcHJvb2YgaXMgYmV5b25kIHdoYXQgd2UgY2FuIGNvbXByZWhlbmQgYXQgdGhpcyBwb2ludCB3aXRoIG91ciBrbm93bGVkZ2Ugb2YgZ3JhcGhzIGFuZCBjb21wdXRhdGlvbi4gV2hpbGUgd2Ugd2VyZSByZXNlYXJjaGluZyBvbiBhbHRlcm5hdGUgcGFwZXJzIHRvIHVuZGVyc3RhbmQgdGhpcyBwcm9vZiwgd2UgY2FtZSBhY3Jvc3Mg4oCcZ29k4oCZcyBudW1iZXLigJ0sIHdoaWNoIGlzIDIwIGZvciBhIDMgeCAzIHggMyBSdWJpa+KAmXMgY3ViZS4gVGhpcyBpcyB0aGUgbWF4aW11bSBudW1iZXIgb2YgbW92ZXMgbmVlZGVkIHRvIHNvbHZlIGFueSBjb25maWd1cmF0aW9uLiBUaGlzIGludHJpZ3VlZCB1cyBhbmQgd2UgZGVjaWRlZCB0byBuYXJyb3cgZG93biBvdXIgdG9waWMgdG8gYSAzIHggMyB4IDMgcnViaWvigJlzIGN1YmUuIEhvd2V2ZXIsIHdlIHdlcmUgbm90IGFibGUgdG8gZmluZCBhIHNpbmd1bGFyIHBhcGVyIHdpdGggYWxsIHRoZSByZWR1Y3Rpb25zIHdlIG5lZWRlZCBhbmQgaGVuY2UgY29tcGlsZWQgb3VyIGVudGlyZSBwcm9vZiBmcm9tIGRpZmZlcmVudCBzb3VyY2VzLiAKCldoaWxlIHRoaXMgcHJvY2VzcyB3YXMgaW50aW1pZGF0aW5nLCBpdCBhbGxvd2VkIHVzIHRvIHVuZGVyc3RhbmQgdGhlIHByb29mIHdpdGggYSBkZXB0aCB0aGF0IHdvdWxkIGhhdmUgcHJvYmFibHkgbm90IGJlZW4gcG9zc2libGUgb3RoZXJ3aXNlLiBUaGUgSGFtaWx0b25pYW4gUGF0aCBpcyB0aGUgcmVkdWN0aW9uIHRoYXQgaXMgdXNlZCB0byBwcm92ZSB0aGF0IHRoZSBuIHggbiB4IG4gUnViaWvigJlzIGN1YmUgaXMgTlAgY29tcGxldGUsIGV2ZW4gdGhvdWdoIHdlIGFyZSB1c2luZyBpdCBzb2xlbHkgZm9yIHRoZSBuID0gMyBjYXNlLiBGcm9tIHRoZSBvcmlnaW5hbCBwYXBlciwgd2Uga25ldyB0aGF0IHRoZSBIYW1pbHRvbmlhbiBQYXRoIGlzIE5QIGNvbXBsZXRlIGFuZCBzbyBsb29rZWQgZm9yIHByb29mcyBmb3IgdGhlIEhhbWlsdG9uaWFuIHBhdGggYmVpbmcgTlAgY29tcGxldGUuIFRoaXMgaXMgaG93IHdlIHN0YXJ0ZWQgb3VyIHJlZHVjdGlvbi4gV2UgZm91bmQgdGhhdCB0aGUgMyB4IDMgeCAzIHJ1Ymlr4oCZcyBjdWJlIGNhbiBiZSByZXByZXNlbnRlZCBhcyBhIENheWxleSBncmFwaCwgd2hpY2ggaXMgaG93IOKAnGdvZOKAmXMgbnVtYmVy4oCdIHdhcyBmb3VuZC4gV2UgdGhlbiBsb29rZWQgZm9yIGNvbm5lY3Rpb25zIGJldHdlZW4gQ2F5bGV5IGdyYXBocyBhbmQgSGFtaWx0b25pYW4gcGF0aHMgYW5kIGZvdW5kIHRoYXQgZXZlcnkgQ2F5bGV5IGdyYXBoIGhhcyBhIEhhbWlsdG9uaWFuIHBhdGguIFdlIGNvbXBpbGVkIGV2ZXJ5dGhpbmcgd2UgbGVhcm5lZCBmb3Igb3VyIHJlZHVjdGlvbjogSEFNSUxUT05JQU4tUEFUSCDiiaRQIENBWUxFWS1HUkFQSCDiiaRQIFJVQklL4oCZU+KIkkNVQkUuIAoKQWx0aG91Z2ggd2UgZm91bmQgYSBmZXcgc2hvcnQgYXJ0aWNsZXMgb24gdGhpcyBwcm9vZiwgc2luY2Ugd2UgZGlkIG5vdCBmb2xsb3cgYSBjb25jcmV0ZSwgc2luZ3VsYXIgcGFwZXIsIHdlIGFyZSB1bnN1cmUgYWJvdXQgb3VyIHJlZHVjdGlvbi4gTWFpbmx5IHdlIGFyZSBjb25jZXJuZWQgaWYgd2UgYXJlIHJlZHVjaW5nIGluIHRoZSByaWdodCBkaXJlY3Rpb24uCgpPcHRpbWFsIGFsZ29yaXRobXMgZm9yIHRoZSBSdWJpa+KAmXMgY3ViZSBoYXZlIGJlZW4gYSBwb2ludCBvZiBkaXNjdXNzaW9uIGZvciBnZW5lcmF0aW9ucyBhbmQgb3VyIG9yaWdpbmFsIG1vdGl2YXRpb24gYmVoaW5kIGNob29zaW5nIHRoaXMgdG9waWMgd2FzIHRvIGxlYXJuIHRoZSBvcHRpbWFsIGFsZ29yaXRobSB0aGF0IHNvbHZlcyBpdC4gV2UgbGVhcm50IHRoZXJlIGlzIG5vIHN1Y2ggaGFuZGVkLWRvd24gc29sdXRpb24gc2luY2UgaXQgaXMgYSBkaWZmaWN1bHQgcHJvYmxlbSBhbmQgaXMgaW4gZmFjdCBOUCBjb21wbGV0ZS4gVGhlIHJ1Ymlr4oCZcyBjdWJlIHByb2JsZW0gaXMgaW50ZXJlc3RpbmcgYmVjYXVzZSBpdCBpcyByZWxhdGVkIHRvIHZlcnkgaW1wb3J0YW50IHN1YmplY3RzIGluIG1hdGhlbWF0aWNzIGFuZCBjb21wdXRlciBzY2llbmNlIHN1Y2ggYXMgY29tYmluYXRvcmljcywgY29tcHV0YXRpb25hbCBjb21wbGV4aXR5LCBhbmQgZ3JvdXAgdGhlb3J5LCB0byBuYW1lIGp1c3QgdGhyZWUuIFRoZSBSdWJpa+KAmXMgY3ViZSBpcyBhbiBpbnN0YW5jZSBvZiB3aGF04oCZcyBjYWxsZWQgYSBjb25maWd1cmF0aW9uIHByb2JsZW0sIHRoZSBiZXN0LWtub3duIGV4YW1wbGUgb2Ygd2hpY2ggaW52b2x2ZXMgZmluZGluZyB0aGUgbW9zdCBlZmZpY2llbnQgd2F5IHRvIHJlLW9yZ2FuaXplIGJveGVzIHN0YWNrZWQgaW4gYSB3YXJlaG91c2UuIElmIGFuIG9wdGltYWwgc29sdXRpb24gdG8gdGhpcyBwcm9ibGVtIHdhcyBmb3VuZCwgaXQgd291bGQgdGFrZSBhbGdvcml0aG1zIHRvIGEgd2hvbGUgbmV3IGxldmVsLgoKKiAqICoKCiMjIyBDb250cmlidXRpb25zOgoKLS0tCgpGb3IgdGhpcyBwcm9qZWN0LCB3ZSBkaXZpZGVkIHRoZSBtYXRlcmlhbCBpbnRvIGZpdmUgc2VjdGlvbnMuIEVhY2ggdGVhbSBtZW1iZXIgd2FzIHJlc3BvbnNpYmxlIGZvciBjcmVhdGluZyB0aGUgc2xpZGVzIGFuZCB3cml0aW5nIHRoZSBibG9nIG1hdGVyaWFsIGZvciB0aGVpciBzZWN0aW9uLiBIb3dldmVyLCB3ZSBhbGwgd29ya2VkIHRvZ2V0aGVyIHRvIHVuZGVyc3RhbmQgdGhlIHByb29mIGFuZCBtYWtlIGRlY2lzaW9ucyBhYm91dCB0aGUgcHJlc2VudGF0aW9uLCBhbmQgd2UgYWxsIG1ldCByZWd1bGFybHkgdG8gZGlzY3VzcyB0aGUgbWF0ZXJpYWwgYW5kIGFueSBpc3N1ZXMuIEpvY2Ugd29ya2VkIG9uIHRoZSDigJxJbnRyb2R1Y3Rpb27igJ0sIE5hc2hzaGFiYSB3b3JrZWQgb24gdGhlIOKAnEhhbWlsdG9uaWFuIFBhdGggaXMgTlAtY29tcGxldGXigJ0sIENoYXJsb3R0ZSB3b3JrZWQgb24gdGhlIOKAnEhhbWlsdG9uaWFuIFBhdGggcmVkdWNlcyB0byBDYXlsZXkgR3JhcGjigJ0sIEFyaWFuYSB3b3JrZWQgb24gdGhlIOKAnENheWxleSBHcmFwaCByZWR1Y2VzIHRvIFJ1Ymlr4oCZcyBDdWJl4oCdLCBhbmQgQXNtaXRhIHdvcmtlZCBvbiB0aGUg4oCcUnViaWvigJlzIEN1YmUgUHJvYmxlbSBpcyBpbiBOUOKAnSBhbmQgdGhlIOKAnERpc2N1c3Npb27igJ0uIEFkZGl0aW9uYWxseSwgQXNtaXRhIGNyZWF0ZWQgdGhlIG9yaWdpbmFsIGRyYWZ0IGZvciB0aGUgcHJlc2VudGF0aW9uLCBhbmQgSm9jZSBjb21waWxlZCB0aGUgUiBNYXJrZG93biBmaWxlIGZvciB0aGUgYmxvZyBwb3N0LiAKCiogKiAqIAoKIyMjIFJlZmVyZW5jZXM6CgotLS0KCjEuIEVyaWsgRC4gRGVtYWluZSwgU2FyYWggRWlzZW5zdGF0LCBNaWtoYWlsIFJ1ZG95LiDigJxTb2x2aW5nIHRoZSBSdWJpa+KAmXMgQ3ViZSBPcHRpbWFsbHkgSXMgTlAtQ29tcGxldGUu4oCdCjIuIOKAnFZpc3VhbCBHcm91cCBUaGVvcnksIExlY3R1cmUgMS4yOiBDYXlsZXkgR3JhcGhzLuKAnSBZb3VUdWJlLCBZb3VUdWJlLCAyNCBGZWIuIDIwMTYsIHd3dy55b3V0dWJlLmNvbS93YXRjaD92PXZ6RU9iT3pzU0tZLgozLiBBbGdvcml0aG1zIEFuZCBDb21wbGV4aXR5LiBFeGVyY2lzZSBTZXNzaW9uIDYsIGFuZCBOcC1Qcm9ibGVtcy4g4oCcSW4gTW9iaWxlIFRlbGVwaG9ueSwgWW91IE5lZWQgdG8gU29sdmUgdGhlIEZyZXF1ZW5jeSBBbGxvY2F0aW9uIFByb2JsZW0u4oCdIEluIE1vYmlsZSBUZWxlcGhvbnksIFlvdSBOZWVkIHRvIFNvbHZlIHRoZSBGcmVxdWVuY3kgQWxsb2NhdGlvbiBQcm9ibGVtLgo0LiDigJxMb3bDoXN6IENvbmplY3R1cmUu4oCdIFdpa2lwZWRpYSwgV2lraW1lZGlhIEZvdW5kYXRpb24sIDE0IE1hci4gMjAxOCwgZW4ud2lraXBlZGlhLm9yZy93aWtpL0xvdiVDMyVBMXN6X2NvbmplY3R1cmUuCjUuIOKAnFVuc29sdmVhYmxlIFJ1YmlrJ3MgQ3ViZSAtIEludmFsaWQgU2NyYW1ibGUu4oCdIFJ1d2l4LCBydXdpeC5jb20vdGhlLXJ1Ymlrcy1jdWJlL3Vuc29sdmFibGUtcnViaWtzLWN1YmUtaW52YWxpZC1zY3JhbWJsZS8uIAo2LiBCYXJ0bGV0dCwgUGFkcmFpYy4g4oCcQ2F5bGV5IEdyYXBocy7igJ0gV29sZnJhbSBEZW1vbnN0cmF0aW9ucyBQcm9qZWN0LCAyMDA3CjcuIOKAnFJ1YmlrJ3MgQ3ViZSBOb3RlcyDigJMgQ2F5bGV5IEdyYXBocyBhbmQgR29kJ3MgQWxnb3JpdGhtLuKAnSBZZXQgQW5vdGhlciBNYXRoYmxvZywgMTggQXVnLiAyMDE2LCB5ZXRhbm90aGVybWF0aGJsb2cuY29tL3Blcm11dGF0aW9uLXB1enpsZXMvbGVjdHVyZS1ub3Rlcy1vbi10aGUtcnViaWtzLWN1YmUvcnViaWtzLWN1YmUtbm90ZXMtY2F5bGV5LWdyYXBocy1hbmQtZ29kcy1hbGdvcml0aG0vLgo4LiDigJxSdWJpaydzIEN1YmUu4oCdIFdpa2lwZWRpYSwgV2lraW1lZGlhIEZvdW5kYXRpb24sIDIgTWF5IDIwMTgsIGVuLndpa2lwZWRpYS5vcmcvd2lraS9SdWJpayUyN3NfQ3ViZS4gCjkuIOKAnExvdsOhc3ogQ29uamVjdHVyZSBhbmQgRGV2aWwncyBBbGdvcml0aG0u4oCdIENvbXBsZXggUHJvamVjdGl2ZSA0LVNwYWNlLCA3IEp1bHkgMjAxMywgY3A0c3BhY2Uud29yZHByZXNzLmNvbS8yMDEzLzA3LzA3L2xvdmFzei1jb25qZWN0dXJlLWFuZC1kZXZpbHMtYWxnb3JpdGhtLy4KCg==