Jekyll2017-11-14T09:49:10-08:00/Art is Never Finished...Only Abandoned. – Leonardo da VinciThe Reinforced Pentakis Dodecahedron Dome2017-11-05T00:00:00-07:002017-11-05T00:00:00-07:00/blog/pentakis-dodecahedron-dome<p>For your amusement, I would like to present a reinforced version of a geodesic dome that is many times stronger than conventional geodesic domes. It is essentially two concentric domes, one nested inside the other, connected entirely by tetrahedra in a way that both strengthens the dome and provides space for insulation. Compared to single-layer geodesic structures, this new structure uses about 2-3x more materials, but it is so much stronger that it is startling.</p>
<p>The internal structure is very regular, as a paper model shows:</p>
<p class="center"><img src="pentakis_dome_bottom.jpg" alt="pentakis_dome_bottom" title="A paper reinforced Pentakis Dodecahedron dome mockup, viewed from the bottom to show the internal structure. " /></p>
<p>The outside shape is the top 3/4ths of a 60-sided pentakis dodecahedron:</p>
<p class="center"><img src="pentakis_dome_top.jpg" alt="pentakis_dome_top" title="An external view of a paper mockup of the Reinforced Pentakis Dodecahedron Dome" /></p>
<p>This dome is constructed from the surfaces the <a href="http://en.wikipedia.org/wiki/icosahedron">Icosahedron</a>, the <a href="http://en.wikipedia.org/wiki/Triakis_icosahedron">Triakis Icosahedron</a> and a <a href="http://en.wikipedia.org/wiki/Pentakis_dodecahedron">Pentakis Dodecahedron</a>. Those terms sounds like a mouthful, but their meanings are fairly simple:</p>
<table>
<tbody>
<tr>
<td><img src="triakis-subdivision.png" alt="triakis subdivision" title="Triakis subdivision" /></td>
<td><strong>Triakis</strong>: For each original triangular face of the polyhedra, add a new midpoint on the triangle and form three new triangular faces. (In 3D, this midpoint should have same radius as the other vertices.)</td>
</tr>
<tr>
<td><img src="icosahedron-dice.jpg" alt="icosahedron dice" title="Icosahedron" /></td>
<td><strong>Icosahedron</strong>: The 20-sided platonic solid formed by connecting 5 equilateral triangles at every vertex.</td>
</tr>
<tr>
<td><img src="pentakis-subdivision.png" alt="pentakis subdivision" title="Pentakis subdivision" /></td>
<td><strong>Pentakis</strong>: The same as “tri-akis”, but for pentagonal faces, thus making five new triangles.</td>
</tr>
<tr>
<td><img src="dodecahedron-dice.jpg" alt="dodecahedron dice" title="Dodecahedron" /></td>
<td><strong>Dodecahedron</strong>: The 12-sided platonic solid formed by connecting 3 regular pentagons at every vertex.</td>
</tr>
</tbody>
</table>
<p>There are a few advantages to constructing a dome of this type:</p>
<ol>
<li>It is fairly simple: there are only three different triangle shapes that need to be cut out.</li>
<li>Every edge is part of at least one tetrahedron, making it incredibly strong and rigid.</li>
<li>The tetrahedra form trapped spaces between an ‘inner’ dome surface and an ‘outer’ dome surface. This space may be useful as a type of crawlspace for insulation, wiring, or ventilation.</li>
<li>Even if the dome is not connected to the ground, it is rigid and self-supporting. This is unlike most other geodesic domes, which require strong connections between foundations and the rest of the structure or they fold or collapse.</li>
<li>As with other domes, the edges can be made first as a skeleton and then the faces attached later, or the faces can be flat and connected with a suitable edge-connection method. In the latter case, a larger structure could be made entirely out of plywood, stamped metal, glass, or perhaps ceramic tile.</li>
</ol>
<p>In the rest of this article, I will next briefly review <a href="#geodesic_construction">how other geodesic domes are made</a>, discuss <a href="#geodesic_advantages">their advantages</a>, then talk about <a href="#geodesic_disadvantages">the problems I encountered in them while making paper models</a>, and then <a href="#pentakis_construction">how to make this new dome structure</a>.</p>
<p><a name="geodesic_construction"></a></p>
<h2 id="background-geodesic-dome-construction">Background: Geodesic Dome Construction</h2>
<p>What <strong>is</strong> a geodesic dome, anyway? How do you decide the sizes of all those little triangles? Although they initially may appear very mysterious, geodesic structures are actually formed from very simple patterns.</p>
<p>Most domes are created from regular platonic polyhedra. What are those? Well, if you have ever played <a href="http://dnd.wizards.com">games</a> with 4-, 6-, 8-, 12-, and 20-sided die)-sided dice, you have seen all the platonic polyhedra. If you have not, it may be a fun exercise to cut out paper triangles, squares, and pentagons, and try to rediscover the shapes yourself. The five platonic solids are the only polyhedra with these two properties:</p>
<ol>
<li>Every edge has the same length</li>
<li>Every face is the same polygon</li>
</ol>
<p>Typically, people making geodesic domes choose a tetrahedron (4-sides), octahedron (8-sides), or icosahedron (20-sides), because these polehedra may be formed using, respectively, 3, 4, or 5 equilateral triangles connected together at each vertex.</p>
<p>For geodesic domes, the icosahedron is by far the most popular choice of a starting shape because it is already closer to a sphere than the other platonic solids.</p>
<p class="center"><img src="icosahedron.png" alt="icosahedron" title="An icosahedron. " /></p>
<p>The next step is to divide the edges of each triangle into <script type="math/tex">v</script> smaller pieces, and then form smaller triangles connecting the new midpoints. In general, the <script type="math/tex">v</script>th level subdivision is made by breaking each edge of the triangle into <script type="math/tex">n</script> pieces:</p>
<p class="center"><img src="subdivisions.png" alt="subdivided triangles" title="Subdivided triangles" /></p>
<p>For the rest of this example, we will use the 2<script type="math/tex">v</script> subdivision. So let’s draw a 2<script type="math/tex">v</script> subdivided icosahedron:</p>
<p class="center"><img src="icosahedron-subdivided-2v.png" alt="subdivided triangles" title="An icosahedron with its edges divided in 2, thus producing 4 new triangles." /></p>
<p>The last step is “push out” the newly created vertices so that they also lie on the surface of the sphere defined by the original polyhedron. As the points are pushed out, their angular coordinates (i.e. latitude and longitude) on the surface of the sphere must not change.</p>
<p class="center"><img src="icosahedral-2v-sphere.png" alt="geodesic 1v, 2v, 3v" title="A sphere formed by pushing the new vertices out to the same radius as the other vertices." /></p>
<p>Mathematically, this last operation is simply the constraint that every vertex <script type="math/tex">(x_i, y_i, z_i)</script> be the same distance <script type="math/tex">d</script> from the center of the polyhedron:</p>
<script type="math/tex; mode=display">d = \sqrt{x_i^2 + y_i^2 + z_i^2}</script>
<p>Working out the analytic solutions for the lengths of the triangles in the <script type="math/tex">v</script>th subdivision of various polyhedra is within the abilities of many high school students, and perhaps even a few gifted middle school students, but it does take some patience and persistence. Thankfully, there are <a href="http://www.dirkbertels.net/computing/pentaDome_files/pentaDome_070206.pdf">many</a>… <a href="http://www.geometer.org/mathcircles/geodesic.pdf">good</a>… <a href="http://www.salsburg.com/geod/geodesicmath.pdf">examples</a> to start from if you are curious about calculating the coordinates.</p>
<p><a name="geodesic_advantages"></a></p>
<h2 id="advantages-of-domes">Advantages of Domes</h2>
<p>Geodesic domes are attractive structures in part because they are so simple – there are only 2 different triangle shapes needed for the 2v and 3v designs. When I helped organize the <a href="http://portland.sciencehackday.org">2017 Portland Science Hack Day</a>, one of our kid zone activities was to assemble a geodesic dome out of cardboard. We used a 40W laser cutter to quickly cut the cardboard (25 of the 18x18x24” boxes from HomeDepot is plenty, costing $36.50 in total), and stuck it together the edges with tape remarkably quickly:</p>
<p class="center"><img src="shd-dome.jpg" alt="Science Hack Day Dome" title="The Portland 2017 Science Hack Day kid zone 2v geodesic dome." /></p>
<p>Some people even build entire homes this way. Advocates of geodesic dome homes tout the design as being one of the strongest, most material-efficient types of structure possible, and most engineers who look at one will immediately be able to give several reasons why this is true:</p>
<ol>
<li>Of all possible shapes, a sphere has the highest ratio of volume to surface area. All other things being equal, this means that there will be fewer materials used to construct a home with a certain volume. There will also be relatively less energy lost through the surface, so it will be cheaper to heat or cool.</li>
<li>Spheres are <a href="https://en.wikipedia.org/wiki/Gridshell">doubly-curved surfaces</a>, which are generally more rigid than <a href="https://en.wikipedia.org/wiki/Developable_surface">singly curved surfaces</a> like cylinders that can crush or kink. You may have noticed how the rounded bottom of an aluminum can is much stronger than the sides, even though the metal is the same thickness.</li>
<li>Geodesic domes are constructed from many small triangles. Triangles cannot pivot or bend at the joints, unlike squares or other polygons, and are thus one of the strongest shapes in engineering. One glance at the <a href="http://en.wikipedia.org/wiki/truss">truss structures</a> used in cranes, planes, and spacecraft are all based on the concept of “triangularizing” a structure to make it as rigid and strong as possible.</li>
</ol>
<p><a name="geodesic_disadvantages"></a></p>
<h2 id="weakpoints-of-geodesic-domes">Weakpoints of Geodesic Domes</h2>
<p>One big surprise that the paper geodesic dome models revealed to me was how the strength of the geodesic dome absolutely depends on it being connected at the base where the geodesic dome touches the ground. Although a completed sphere is quite strong, a dome has very little strength unless its edges are securely anchored to the ground!</p>
<p>It’s hard to show in photos, but the paper geodesic dome I made appears to support itself when sitting on the table, but it quite floppy and easily curls up into strange shapes if the base edge is not taped down.</p>
<table class="center">
<tbody>
<tr>
<td><img src="geodesic_dome.jpg" alt="geodesic_dome.jpg" title="A geodesic dome unconnected to the ground..." /></td>
<td><img src="geodesic_squashed.jpg" alt="geodesic_squashed" title="...is quite floppy!" /></td>
</tr>
</tbody>
</table>
<p>Although a dome constructed with thick members like wood or metal might appear self-supporting, this is not mathematically true, and failure to connect the foundation of the dome will result in only a fraction of the true strength being developed.</p>
<p><a name="pentakis_construction"></a></p>
<h2 id="constructing-the-pentakis-dodecahedron">Constructing the Pentakis Dodecahedron</h2>
<p>One of the fastest ways for me to develop intuition for structures that are too complicated to visualize is to build small mock-ups. I have always liked arts and crafts, so I printed out some templates of various shapes on thick card stock paper, and taped the edges together with scotch tape. If you have an hour to spare, I encourage you to unleash your inner elementary school student, grab your scissors (and maybe a drink and a podcast too!), and try making one of these yourself.</p>
<p>Here’s how to make it:</p>
<p>First, print out six copies of the <a href="reinforced-pentakis-dodecahedron.pdf">PDF of this design</a>.</p>
<p>Next, cut out the triangular tetrahedra. Optionally, you may also use a knife to cut out the insides of the triangles, if you want to be able to see the internal structure.</p>
<p>Then, fold the sides up and tape them together to form tetrahedra:</p>
<table class="center">
<tbody>
<tr>
<td><img src="pentakis_construction_step0.jpg" alt="pentakis-step-1" title="Step 0." /></td>
<td><img src="pentakis_construction_step1.jpg" alt="pentakis-step-1" title="Step 1." /></td>
</tr>
</tbody>
</table>
<p>When you have five tetrahedra, tape them together along their edges. This creates one quarter of a triakis icosahedron.</p>
<table class="center">
<tbody>
<tr>
<td><img src="pentakis_construction_step2.jpg" alt="pentakis-step-1" title="Step 2." /></td>
<td><img src="pentakis_construction_step3.jpg" alt="pentakis-step-1" title="Step 3." /></td>
</tr>
</tbody>
</table>
<p>Finally, cover the surface with the smaller pentakis triangles.</p>
<table class="center">
<tbody>
<tr>
<td><img src="pentakis_construction_step4.jpg" alt="pentakis-step-1" title="Step 4." /></td>
<td><img src="pentakis_construction_step5.jpg" alt="pentakis-step-1" title="Step 5." /></td>
</tr>
</tbody>
</table>
<p>Repeat this process to the edges of the small dome you just created, adding more tetrahedra and skin surfaces in this way until you have 3/4ths of a complete sphere.</p>
<p>While you are cutting out paper, you may also want to compare the relative strength of this with other common shapes:</p>
<ul>
<li><a href="http://www.korthalsaltes.com/model.php?name_en=icosahedron">Paper template for an icosahedron</a></li>
<li><a href="http://www.korthalsaltes.com/model.php?name_en=dodecahedron">Paper template for a dodecahedron</a></li>
<li><a href="https://www.discovere.org/sites/default/files/Dome%20Home_0.pdf">Paper template for a 2v geodesic dome</a></li>
<li><a href="http://mathworld.wolfram.com/pdf/PentakisDodecahedron.pdf">Paper template for a pentakis dodecahedron</a></li>
</ul>
<p>If you want to make new triangles and create your own reinforced pentakis dodecahedron of arbitrary size, the magic numbers for a dome of radius <script type="math/tex">r</script> are:</p>
<ul>
<li>The icosahedron’s equilateral triangles have three edges of length <script type="math/tex">l_1 = 1.0514622 r</script></li>
<li>The triakis icosahedron’s icoceles triangles have one edge of length <script type="math/tex">l_1</script> and two edges of length <script type="math/tex">l_2 = 0.66500310 r</script></li>
<li>The pentakis dodecahedron’s icoceles triangles have one edge of length <script type="math/tex">l_2</script> and two edges of length <script type="math/tex">l_3 = 1.12732203 l_2</script></li>
</ul>
<p>If you would like to estimate the amount of flat material that you will need, you will find <a href="https://en.wikipedia.org/wiki/Heron%27s_formula">Heron’s Formula</a> useful:</p>
<script type="math/tex; mode=display">A = \sqrt{s(s-a)(s-b)(s-c)}</script>
<p>where <script type="math/tex">A</script> is the area of a triangle, <script type="math/tex">s=\frac{1}{2}(a+b+c)</script> is half of the perimeter of the triangle, and <script type="math/tex">a,b,c</script> are the lengths of the sides of the triangle.</p>
<h2 id="a-note-on-duality">A note on Duality</h2>
<p>It’s fun to look at the mathematics of these polyhedra as well. Basically, this dome is constructed by starting with an icosahedron, adding tetrahedra to the outside, and then add pentagons to the new points defined by this, and then scaling all the radii carefully. Here is an early model whose vertices’ radii are not all equal:</p>
<table class="center">
<tbody>
<tr>
<td><img src="icosahedron.jpg" alt="icosahedron" title="A paper Icosahedron" /></td>
<td><img src="icosahedron_stellated.jpg" alt="icosahedron_stellated" title="A paper great stellated icosahedron" /></td>
</tr>
</tbody>
</table>
<p>The above tetrahedra that I taped to the outside of the icosahedron are very big, creating a <a href="http://en.wikipedia.org/wiki/Great_stellated_dodecahedron">great stellated icosahedron</a> instead of a triakis icosahedron. If you were to connect the tips of these tetrahedra, they would define 12 new pentagonal surfaces, because the “dual” of the icosahedron is the dodecahedron.</p>
<p>Duality expresses a mathematical symmetry that appears in many different disciplines, and while a full post on duality is out of scope of this article, the core thing to realize is that in this example of duality, the number of sides and vertices switch:</p>
<ul>
<li>Icosahedron: 12 vertices, 20 (triangular) sides</li>
<li>Dodecahedron: 12 (pentagonal) sides, 20 vertices</li>
</ul>
<p>And also the number of faces and the sides of each face switch:</p>
<ul>
<li>Icosahedron: 3-sided faces, 5 faces connecting at each vertex</li>
<li>Dodecahedron: 5-sided faces, 3 faces connecting at each vertex</li>
</ul>
<p>If we reduce the radius of the tips of the great stellated icosahedron, the shape becomes a “triakis icosahedron”, in which all vertices have equal radii. By happy coincidence, the convex hull of those vertices defines a pentakis dodecahedron. It is pretty neat that all of the vertices are still at a constant radius.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Most of us would rather live in a beautiful home than one with efficient geometry, so perhaps it is not a surprise that geodesic designs are not very popular and take a backseat to traditional construction techniques. Personally, I find domes to be so ugly that they are actually kind of cute, but I understand that they might not pass muster with the local homeowners association.</p>
<p>Aesthetics aside, dome construction is probably best reserved for extremely harsh environments: cold-weather shelters, underground structures, or perhaps spacecraft. If the spaces between the icosahedron and pentakis dodecahedron were sealed airtight, they could also act as insulation, floatation chambers, or – for extraterrestrial homes – as airlocks that protect the inner chamber.</p>
<p>It is a big world out there, and because it is unlikely that I am the first person to think along these lines before, please <a href="mailto:drrobot-at-gmail.com">let me know</a> of other examples of this structure and other more developed implementations. I would be really curious to see pictures of real structures implementing this shape.</p>
<h2 id="future-directions">Future Directions</h2>
<p>As with any thought experiment, this little game raised more questions than it answered:</p>
<ul>
<li>Are there other shapes that may also be connected such that every edge is part of a tetrahedron? Is this possible with every triangularized shape and its dual?</li>
<li>How does one further subdivide the triangles of this structure to make it more spherical, as was done with the 2v, 3v, and higher-order geodesic domes, while keeping every edge part of at least one tetrahedron?</li>
</ul>
<p>There are fun engineering topics that would also be worth figuring out for this structure:</p>
<ul>
<li>If this were made of fabric instead of rigid materials, could this be made a self-inflating structure by filling the tetrahedral cells with compressed air or expanding foam?</li>
<li>Could this be made entirely out of ceramic tile or glass, connected at the edges in a manner that avoids stress concentrations? Where are the stresses in each trianglular member?</li>
<li>Would this be strong enough to be buried underground as an earth-sheltered home? On earth…or mars?</li>
<li>How could the corners and edges of this structure be safely and cheaply sealed against water intrusion? How could condensation be removed from the inside?</li>
</ul>For your amusement, I would like to present a reinforced version of a geodesic dome that is many times stronger than conventional geodesic domes. It is essentially two concentric domes, one nested inside the other, connected entirely by tetrahedra in a way that both strengthens the dome and provides space for insulation. Compared to single-layer geodesic structures, this new structure uses about 2-3x more materials, but it is so much stronger that it is startling.Introduction to Geometric Algebra, Part 12017-07-12T00:00:00-07:002017-07-12T00:00:00-07:00/blog/intro-to-geometric-algebra-1<p>Geometric Algebra (GA) is one of those things that we should have all learned in high school because it would have made physics and mathematics in college so much easier.</p>
<p>The fact that we did not learn it in high school is probably because GA appears to only have been known by mathematicians studying <a href="https://www.wikipedia.org/wiki/clifford_algebra">Clifford Algebras</a>. Mathematicians may be 100 years ahead of everybody else in so many ways, but they are not always the best at communicating their subject to non-mathematicians. The physics community, at least, seems to have figured out that GA is useful, and since physicists are 20 years ahead of the rest of the sciences in the adoption of good tools and methods, it seems safe to predict that in the future engineers will start seeing GA in school in a couple of decades, or <a href="http://link-to-paper">even sooner</a>!</p>
<p>Geometric Algebra could be taught in high school immediately after basic algebra. Not only is GA not particularly difficult to learn, it provides a unified perspective for several areas:</p>
<ul>
<li>GA lets you <strong>easily perform 2D and 3D vector transformations</strong>. It is simpler to perform spatial rotations than using matrices, sines, and inverse trigonometric operations, and it generalizes to more dimensions in a straightforward way.</li>
<li>GA gives a <strong>clear geometric meaning to the imaginary number</strong> – or all 3 imaginary numbers, in the case of quaternions.</li>
<li>GA <strong>replaces div, grad, curl, with a single vector derivative</strong>. To an electrical engineer like myself, it is frankly <em>amazing</em> to see the four Maxwell Equations reduced into a single equation!</li>
<li>GA is <strong>coordinate-free</strong> and can let you make analytic conclusions without first choosing a basis</li>
<li>GA is a framework <strong>applicable to dozens of different fields</strong> of physics and engineering, including classical and quantum mechanics.</li>
</ul>
<p>While I am far from being an expert in Geometric Algebra, I wanted to write an accessible, bare-bones introduction to the subject so that people can follow my use of it in a future post on hyperbolic geometry. For this reason, this post will just focus on 2D operations, and perhaps in a later post I can talk about rotations in 3D space or 4D spacetime, differential equations, Maxwell’s Equations, and other applications.</p>
<h1 id="preparation-basic-concepts">Preparation: Basic Concepts</h1>
<p>Before introducing Geometric Algebra, I’m going to briefly review coordinate systems, basis vectors, and the inner and outer products. As an engineer and not a mathematician, I will focus on examples and developing intuition rather than rigor, entirely symbolic notation, or the capacity to generalize expressions. Checking correctness with a proof must follow the intuition that there is something there to prove!</p>
<h2 id="concept-properties-of-algebras">Concept: Properties of Algebras</h2>
<p>Most people have a vague idea what algebra is: it is a set of rules to add and multiply objects of different quantities, often represented in school using the variables <script type="math/tex">x</script> and <script type="math/tex">y</script>. The operations you perform usually satisfy the properties of being</p>
<ul>
<li><strong>associative</strong>, meaning that you can reorder operations <script type="math/tex">(qr)s=q(rs)</script>; and</li>
<li><strong>distributive</strong>, meaning that you can expand like <script type="math/tex">q(r+s)=qr+qs</script>.</li>
</ul>
<p>The algebra you learned in school had one other property:</p>
<ul>
<li><strong>commutative</strong> multiplication, meaning that you can reorder terms <script type="math/tex">qr = rq</script>.</li>
</ul>
<p>This is <strong>not so</strong> in Geometric Algebra and matrix algebras, in which the <em>ordering</em> of terms being multiplied matters and generally speaking <script type="math/tex">qr \ne rq</script>.</p>
<p>If you are wondering why some operations are not commutative, consider where you would end up navigating if you start in a given orientation and:</p>
<ul>
<li>Walk forward 100 paces (<script type="math/tex">q</script>) and then turn right (<script type="math/tex">r</script>); or</li>
<li>Turn right (<script type="math/tex">r</script>) and then walk forward 100 paces (<script type="math/tex">q</script>).</li>
</ul>
<p>Another example is to consider the commutivity of addition and subtraction: <script type="math/tex">4+3=3+4</script>, but does <script type="math/tex">4-3=3-4</script>?</p>
<h2 id="concept-coordinate-system-and-references">Concept: Coordinate System and References</h2>
<p>To introduce GA we need to define a coordinate system with two things:</p>
<ol>
<li>A way to measure distance (hopefully evenly!)</li>
<li>Reference directions (hopefully independent!)</li>
</ol>
<p>Let us consider our options first. If we are drawing on a sheet of paper, we could measure distances using the number of marks passed on a grid. This grid could be:</p>
<table>
<tbody>
<tr>
<td><img src="coord-arb.png" alt="coord-arb" title="Curvilinear coordinates." /></td>
<td><strong>Arbitrary or Curvilinear coordinates</strong>. We <em>could</em> draw any bunch of curved lines unevenly over the page in a wavy grid as long as the lines parallel to each other did not intersect. This sounds crazy, but sometimes you need to account for some distortion in a space and this type of coordinate system can be very useful as a transformation. In most cases, however, it would be a poor choice for most problems because one unit of distance is not exactly “equal” to another unit elsewhere on the page.</td>
</tr>
<tr>
<td><img src="coord-polar.png" alt="coord-polar" title="Polar Coordinates." /></td>
<td><strong>Polar</strong>. We <em>could</em> use we could use an angle (from a reference direction) and a distance or angle from an origin to define where a point is, as is often done on spherical surfaces like the surface of the Earth. While useful in certain circumstances, but again suffer from the problem that distances at different areas on the page are not easily compared.</td>
</tr>
<tr>
<td><img src="coord-rectangular.png" alt="coord-rect" title="Rectangular Coordinates." /></td>
<td><strong>Rectangular Coordinates</strong>. Known as the familiar “XY” coordinate system for most people, we could (and will!) use a grid of straight, parallel lines to find the coordinates of a point. Most problems that are not on highly distorted surfaces are most simply considered in this way – and even on curved surfaces, if you “zoom in” far enough, most surfaces begin to look “locally flat” and begin to resemble straight lines.</td>
</tr>
</tbody>
</table>
<p>Now that we are measuring distances evenly with a Cartesian grid, we need to choose a <strong>basis</strong>, which are essentially the directions that we reference. The choice of the directions is partly arbitrary, and partly not. For example, we can rotate the grid to be in any orientation and still get the same results. What other options do we have?</p>
<table>
<tbody>
<tr>
<td><img src="coord-skew.png" alt="coord-skewed" title="Non-orthogonal-basis" /></td>
<td><strong>Non-orthogonal basis</strong>. We <em>could</em> choose any two directions to draw our parallel lines in, which would probably our grid skewed, but we would soon notice that moving along <script type="math/tex">x</script> also moves you along <script type="math/tex">y</script> in some important sense. This seems like a problem, so we must add another constraint!</td>
</tr>
<tr>
<td><img src="coord-rectangular.png" alt="coord-rectangular" title="Cartesian Coordinates" /></td>
<td><strong>Orthogonal</strong>. If we make the two vectors orthogonal (i.e. 90 degrees to each other) we can now move independently in each direction. But what if we accidentally spaced our parallel lines different distances apart along each axis? If we do not add a constraint that both reference directions be of the same magnitude, we might accidentally measure distances along X in units of meters and distances along Y in distances of feet.</td>
</tr>
<tr>
<td><img src="coord-cartesian.png" alt="coord-cartesian" title="Cartesian Coordinates" /></td>
<td><strong>Orthonormal</strong>. If your basis is orthogonal and are equal in magnitude (i.e. distances on each are measured in the same way), we call the basis “orthonormal”.</td>
</tr>
</tbody>
</table>
<p>One of the advantages of GA is that the exact choice of basis often does not matter – it could be rotated to any number of crazy angles or different scales – and that you can find relationships without choosing a basis at all.</p>
<h2 id="concept-vectors">Concept: Vectors</h2>
<p>Using our new coordinate space, let us now draw two example <strong>vectors</strong> <script type="math/tex">a</script> and <script type="math/tex">b</script>, which are mixtures of the basis directions <script type="math/tex">e_1</script> and <script type="math/tex">e_2</script>. We will use these same two vectors over and over again to keep the number of symbols low.</p>
<p>Rather than than using matrices or vector notation, which would do more harm than good because they would obfuscate important quantities, we will instead use simple algebraic forms to express vectors. Let us define</p>
<script type="math/tex; mode=display">% <![CDATA[
\begin{eqnarray*}
a & = & 2e_1 + 1e_2\\
b & = & 3e_1 + 4e_2 \end{eqnarray*} %]]></script>
<p class="center"><img src="example-vectors.png" alt="example-vectors" title="Sample vectors a and b" /></p>
<p>In plain english, the vector <script type="math/tex">a</script> means a direction that, for each three units you move along <script type="math/tex">e_1</script>, you must also move one unit along <script type="math/tex">e_2</script>. Note that we cannot “add” apples <script type="math/tex">e_1</script> and oranges <script type="math/tex">e_2</script>; the <script type="math/tex">+</script> symbol here means something like the word “and” for the terms with different basis vectors. We <em>can</em> reduce expressions with <script type="math/tex">e_1</script>, but not combine them with <script type="math/tex">e_2</script> in a way that is further reduced than this notation.</p>
<h4 id="example-vector-addition">Example: Vector Addition</h4>
<p>What is <script type="math/tex">a + b</script>?</p>
<script type="math/tex; mode=display">% <![CDATA[
\begin{eqnarray*}
a + b & = & (2e_1 + 1e_2) + (3e_1 + 4e_2) \\
& = & 2e_1 + 3e_1 + 1e_2 + 4e_2 \\
& = & (2+3)e_1 + (1+4)e_2 \\
& = & 5e_1 + 5e_2 \end{eqnarray*} %]]></script>
<h2 id="concept-vector-magnitude">Concept: Vector Magnitude</h2>
<p>Since trigonometry is familiar to most people, we will define the <strong>magnitude</strong> of a vector <script type="math/tex">a=\alpha_1 e_1 + \alpha_2 e_2</script> in the same way as was used the Pythagorean Theorem.</p>
<script type="math/tex; mode=display">\|a\| = \sqrt{\alpha_1^2 + \alpha_2^2}</script>
<h4 id="example-vector-magnitudes">Example: Vector Magnitudes</h4>
<p>What are the magnitudes of <script type="math/tex">a</script> and <script type="math/tex">b</script>?</p>
<p class="center"><img src="vector-magnitude.png" alt="vector-magnitude" title="Euclidean magnitude." /></p>
<script type="math/tex; mode=display">% <![CDATA[
\begin{eqnarray*}
\|a\| & = & \sqrt{2^2 + 1^2} = \sqrt{5}\\
\|b\| & = & \sqrt{3^2 + 4^2} = \sqrt{25} = 5\end{eqnarray*} %]]></script>
<h2 id="concept-projections-and-the-inner-product">Concept: Projections and the Inner Product</h2>
<p>Let us ask a very simple question about these vectors:</p>
<blockquote>
<p>If you move along <script type="math/tex">a</script>, how much do you also move along <script type="math/tex">b</script>?</p>
</blockquote>
<p>The answer to this question is given by the <strong>inner product</strong> (a.k.a. <strong>dot product</strong>). It is called the “inner” product because the answer is “inside” or “along” the vector to which you are projecting.</p>
<p>Most people remember trigonometry pretty well, in which case the single most important thing to remember about the inner product is:</p>
<script type="math/tex; mode=display">a\cdot b=\|a\|\|b\|\cos\theta</script>
<p class="center"><img src="inner-product-and-magnitude.png" alt="inner-product-and-magnitude" title="The inner product is related to magnitude." /></p>
<p>What can we discover about the consequences of this equation?</p>
<ul>
<li>The inner product <em>must</em> be commutative (<script type="math/tex">a\cdot b = b \cdot a</script>), because the cosine function is <strong>symmetric</strong> (a.k.a “even”), which is the property that <script type="math/tex">\cos(\theta)=\cos(-\theta)</script>. All this means is that the value of <script type="math/tex">\cos(...)</script> will be the same whether we measure from <script type="math/tex">a</script> to <script type="math/tex">b</script>, which is <script type="math/tex">\cos(\theta)</script>, or from <script type="math/tex">b</script> to <script type="math/tex">a</script>, which is <script type="math/tex">\cos(-\theta)</script>.</li>
</ul>
<p class="center"><img src="cosine-fn.png" alt="cosine-fn" title="The cosine function is symmetric." /></p>
<ul>
<li>
<p>If <script type="math/tex">\|a\|=1</script>, then <script type="math/tex">a \cdot a = 1</script> because there is zero angle between <script type="math/tex">a</script> and itself, and <script type="math/tex">\cos(0)=1</script>. We will use this property for basis vectors extensively, specifically that <script type="math/tex">e_1 \cdot e_1 = 1</script> and <script type="math/tex">e_2 \cdot e_2 = 1</script>.</p>
</li>
<li>
<p>Orthogonal things <em>must</em> have an inner product of zero, because if <script type="math/tex">\theta=\pm 90^\circ</script>, <script type="math/tex">\cos(\pm 90^\circ)=0</script>, and thus <script type="math/tex">a\cdot b=0</script>. This definitely applies to our basis vectors, where we see that <script type="math/tex">e_1 \cdot e_2 = e_2 \cdot e_1 = 0</script>.</p>
</li>
<li>
<p>The inner product <em>must</em> be related closely to magnitudes. It is easy to prove that <script type="math/tex">\|a\| = \sqrt{a \cdot a}</script>; can you see why? Geometrically, we could think of this definition of magnitude as being akin to “What do we get if we move in the direction of <script type="math/tex">a</script> by a number of units equal to the length of <script type="math/tex">a</script>? The magnitude of <script type="math/tex">a</script>.”</p>
</li>
</ul>
<p>It will also help to think the types of objects that enter and exit a “black box functional specification” of the inner product operation. The two “inputs” were vectors and the “output” was a scalar that measures the how much you move along one if you move along the other.</p>
<h4 id="example-inner-product">Example: Inner Product</h4>
<p>What is <script type="math/tex">a \cdot b</script> using the above values of <script type="math/tex">a</script> and <script type="math/tex">b</script>?</p>
<script type="math/tex; mode=display">% <![CDATA[
\begin{eqnarray*}
a \cdot b & = & (2e_1 + 1e_2) \cdot (3e_1 + 4e_2) \\
& = & 2e_1\cdot 3e_1 + 2e_1\cdot 4e_2 + 1e_2\cdot 3e_1 + 1e_2 \cdot 4e_2 \\
& = & 6e_1\cdot e_1 + 8e_1\cdot e_2 + 3e_2\cdot e_1 + 4e_2 \cdot e_2 \\
& = & 6 (1) + 8 (0) + 3 (0) + 4 (1) \\
& = & 10 \end{eqnarray*} %]]></script>
<h1 id="concept-rotations-and-the-outer-product">Concept: Rotations and the Outer Product</h1>
<p>Let us ask another very simple question about these vectors:</p>
<blockquote>
<p>If you start pointed in the direction of <script type="math/tex">a</script>, how much do you need to rotate to point in the direction of <script type="math/tex">b</script>?</p>
</blockquote>
<p>The <strong>outer product</strong> (a.k.a. <strong>wedge product</strong>) is what gives us the answer to this question.</p>
<p>As before, the easiest way to understand this is via trigonometry, in which case the most important fact is:</p>
<script type="math/tex; mode=display">a\wedge b=\|a\|\|b\|\sin\theta</script>
<p class="center"><img src="outer-product-and-sine2.png" alt="outer-product-and-sine2" title="The outer product is related to the sine. " /></p>
<p>This equation has several important consequences:</p>
<ul>
<li>The outer product is <em>not</em> commutative. In fact, the outer product is a kind of multiplication that is called <strong>anti-symmetric</strong>, which means that commuting the inputs flips the sign (<script type="math/tex">a\wedge b = - b \wedge a)</script>. This is fundamentally because <script type="math/tex">\sin()</script> is an odd function and <script type="math/tex">\sin(\theta)=-\sin(-\theta)</script>. There are also geometric reasons for rotations to not be commutative: if we start at <script type="math/tex">a</script>, we need to rotate counterclockwise to get to <script type="math/tex">b</script>, but we start at <script type="math/tex">b</script>, we need to rotate clockwise to get to <script type="math/tex">a</script>. The choice of which reference direction you measure from matters to the sign of the answer.</li>
</ul>
<p class="center"><img src="sine-fn.png" alt="sine-fn" title="The sine function is antisymmetric." /></p>
<ul>
<li>The outer product is closely related to <strong>rotation</strong> by 90 degrees, because that is the point at which <script type="math/tex">\sin(\theta)</script> is maximized and minimized. This is <em>so important</em> that we will right now assign the symbol <script type="math/tex">R</script> to a 90 degree counterclockwise rotation. We can think of smaller or larger rotations as being <script type="math/tex">R</script> multiplied by some scalar to adjust “how big” the rotation is. Under this idea, a 45 degree counterclockwise rotation would be <script type="math/tex">0.5R</script>, and a 90 degree clockwise rotation would be <script type="math/tex">-R</script>.</li>
</ul>
<p class="center"><img src="bivectors.png" alt="bivectors" title="A bivector is often drawn as an arc." /> <img src="outer-product-half-rotation.png" alt="outer-product-half-rotation" title="Half a rotation." /></p>
<ul>
<li>The outer product of two orthonormal vectors <em>must</em> be either <script type="math/tex">1R</script> or <script type="math/tex">-1R</script>. Why? Because if <script type="math/tex">\theta=\pm 90^\circ</script>, then <script type="math/tex">\sin(\pm 90^\circ)=\pm 1</script>. For the basis vectors, this means that <script type="math/tex">R = e_1 \wedge e_2</script> is a 90 degree counterclockwise rotation, and <script type="math/tex">-R = e_2 \wedge e_1</script> is a 90 degree clockwise rotation.</li>
</ul>
<p>Once again, it will help to consider the black box specification of the outer product operation. The two “inputs” were vectors and the “output” is a scaled amount of a 90 degree rotation <script type="math/tex">R</script>, which is neither a vector nor a scalar. What, exactly, is the type of this output object? After defining the geometric product, we will give it a better name.</p>
<h4 id="example-outer-product">Example: Outer Product</h4>
<p>What is <script type="math/tex">a \cdot b</script> using the above values of <script type="math/tex">a</script> and <script type="math/tex">b</script>?</p>
<script type="math/tex; mode=display">% <![CDATA[
\begin{eqnarray*}
a \wedge b & = & (2e_1 + 1e_2) \wedge (3e_1 + 4e_2) \\
& = & 2e_1\wedge 3e_1 + 2e_1\wedge 4e_2 + 1e_2\wedge 3e_1 + 1e_2 \wedge 4e_2 \\
& = & 6e_1\wedge e_1 + 8e_1\wedge e_2 + 3e_2\wedge e_1 + 4e_2 \wedge e_2 \\
& = & 6 (0) + 8 (+R) + 3 (-R) + 4 (0) \\
& = & 5R \end{eqnarray*} %]]></script>
<h1 id="geometric-algebra">Geometric Algebra</h1>
<p>With the preliminaries out of the way, we can now define the geometric product and actually start doing geometric algebra!</p>
<h2 id="the-geometric-product">The Geometric Product</h2>
<p>In the same way that we introduced the inner and outer products by asking a question, we will introduce the <strong>geometric product</strong> by asking a very general question:</p>
<blockquote>
<p>How do you transform <script type="math/tex">a</script> into <script type="math/tex">b</script>?</p>
</blockquote>
<p>Or equivilently, in terms of what we already know,</p>
<blockquote>
<p>How much do you need to rescale and rotate <script type="math/tex">a</script> so that it is equal to <script type="math/tex">b</script>?</p>
</blockquote>
<p>The intuition that we need both a rotation <em>and</em> a rescaling is key to understanding the geometric product. We will write the geometric product of <script type="math/tex">a</script> and <script type="math/tex">b</script> as <script type="math/tex">ab</script>, as we would write scalar multiplication of two variables in high school algebra. We can define the geometric product as:</p>
<script type="math/tex; mode=display">ab = a \cdot b + a \wedge b</script>
<p>But in some ways, this definition puts the cart before the horse! We can <em>discover</em> this equation if just try to multiply <script type="math/tex">a</script> and <script type="math/tex">b</script> together and be very careful about how we do so. Let us explore what happens when we try to compute <script type="math/tex">ab</script> using high school rules of algebra (sans commutative multiplication of nonscalars).</p>
<script type="math/tex; mode=display">% <![CDATA[
\begin{eqnarray*}
ab & = & (2e_1 + 1e_2) (3e_1 + 4e_2)\\
& = & (2e_1)(3e_1) + (2e_1)(4e_2) + (1e_2)(3e_1) + (1e_2)(4e_2)\\
& = & 6 e_1 e_1 + 8 e_1 e_2 + 3 e_2 e_1 + 4 e_2 e_2\\
\end{eqnarray*} %]]></script>
<p>Hmm. What should we do with the products of the unit vectors <script type="math/tex">e_1 e_1, e_1 e_2, e_2 e_1, e_2 e_2</script>? We can reason it out:</p>
<ul>
<li>
<p><script type="math/tex">e_1 e_1</script> asks, “How do I transform <script type="math/tex">e_1</script> into <script type="math/tex">e_1</script>?”. The answer, of course, is that nothing needs to be done! We can express this by scaling by one, the identity object, and write that <script type="math/tex">e_1 e_1 = 1</script>. If we recall the properties of dot and wedge products for unit length vectors, <script type="math/tex">e_1\cdot e_1=1</script> and <script type="math/tex">e_1\wedge e_1=0</script>, then this assumption also agrees with our definition of the geometric product, <script type="math/tex">e_1e_1=e_1\cdot e_1 + e_1 \wedge e_1 = 1 + 0R = 1</script>. No rotation was needed.</p>
</li>
<li>
<p><script type="math/tex">e_2 e_2</script> must also equal 1, for the same reasons.</p>
</li>
<li>
<p><script type="math/tex">e_1 e_2</script> is asking how do I transform <script type="math/tex">e_1</script> into <script type="math/tex">e_2</script>? We know that our basis vectors are orthonormal, so this must equal a 90 degree clockwise rotation <script type="math/tex">R</script>. <script type="math/tex">e_1e_2=e_1\cdot e_2 + e_1 \wedge e_2 = 0 + 1R = R</script>, and no rescaling is needed.</p>
</li>
<li>
<p><script type="math/tex">e_2 e_1</script> must thus equal <script type="math/tex">-R</script>, using similar reasoning.</p>
</li>
</ul>
<p>We can now finish the simplification process.</p>
<script type="math/tex; mode=display">% <![CDATA[
\begin{eqnarray*}
ab & = & 6 e_1 e_1 + 8 e_1 e_2 + 3 e_2 e_1 + 4 e_2 e_2\\
& = & 6 (1) + 8(R) + 3 (-R) + 4 (1)\\
& = & 10 + 5R\\
\end{eqnarray*} %]]></script>
<p>If you compare this results to what we found earlier (<script type="math/tex">a\cdot b=10</script> and <script type="math/tex">a\wedge b=5R</script>), we can indeed see that in this case <script type="math/tex">ab=a\cdot b + a\wedge b</script>. Now that you have the intuition, it would be a good time to prove this to yourself more generally for all <script type="math/tex">a,b</script>.</p>
<p>Speaking of intuition, what does the result <script type="math/tex">ab=10+5R</script> really mean? Does it mean that we should scale vector <script type="math/tex">a</script> by 10 times and go 5 quarter turns counterclockwise to end up at <script type="math/tex">b</script>? That seems obviously incorrect! So our interpretation has led us slightly astray.</p>
<p>We will correct this intuition of this just a moment, but now is a good time to introduce some simplying notation that will carry us beyond just two dimensions.</p>
<h2 id="simplifying-geometric-products-of-basis-vectors">Simplifying Geometric Products of Basis Vectors</h2>
<p>For brevity, if you have fewer than 10 dimensions, it is often convenient to combine the subscripts of basis vectors. That is, with this notational convention, <script type="math/tex">e_1 e_2 = e_{12}</script>, or <script type="math/tex">e_1 e_2 e_3 = e_{123}</script>.</p>
<p>As for simplifying more complex geometric product expressions with orthonormal vectors, we have already learned the only two rules that we need to know:</p>
<ol>
<li><script type="math/tex">e_i e_i = e_{ii} = 1</script>.</li>
<li><script type="math/tex">e_i e_j = e_{ij} = - e_{ji}</script>.</li>
</ol>
<p>That’s it! Let’s try an example to make sure this is completely obvious.</p>
<h4 id="example-simplifying-geometric-products">Example: Simplifying Geometric Products</h4>
<p>Simplify the quantity <script type="math/tex">e_2 e_3 e_2 e_1 e_3 e_2 e_2</script>.</p>
<script type="math/tex; mode=display">% <![CDATA[
\begin{eqnarray*}
e_2 e_3 e_2 e_1 e_3 e_2 e_2 & = & e_2 e_3 e_2 e_1 e_3 e_2 e_2\\
& = & e_2 e_3 e_2 e_1 e_3 (1) \\
& = & e_2 (-e_2 e_3) e_1 e_3\\
& = & -(1) e_3 e_2 e_1 e_3 \\
& = & -(1) e_3 e_2 e_1 e_3 \\
& = & - (- e_2 e_3) e_1 e_3 \\
& = & e_2 (- e_1 e_3) e_3 \\
& = & - e_2 e_1 (1) \\
& = & e_1 e_2 \\
& = & e_{12} \end{eqnarray*} %]]></script>
<h2 id="blades-grades-and-bivectors">Blades, Grades and Bivectors</h2>
<p>Let us make a table of the different types of objects we have seen up to this point, and add a new column called <strong>grade</strong> that more or less describes the dimensionality of the object.</p>
<table class="table">
<thead>
<tr>
<th>Object (a.k.a. Blade )</th>
<th>Examples</th>
<th>Basis</th>
<th>Grade</th>
<th>Relates to</th>
</tr>
</thead>
<tbody>
<tr>
<td>Scalar</td>
<td>1,2,3,4,5…</td>
<td>1</td>
<td>0</td>
<td>Magnitude</td>
</tr>
<tr>
<td>Vector</td>
<td><script type="math/tex">a,b</script></td>
<td><script type="math/tex">e_1, e_2</script></td>
<td>1</td>
<td>Direction</td>
</tr>
<tr>
<td>Bivector / Rotation</td>
<td><script type="math/tex">5R</script></td>
<td><script type="math/tex">e_{12}</script></td>
<td>2</td>
<td>Rotation</td>
</tr>
</tbody>
</table>
<p>Common parlance is to call <script type="math/tex">e_{12}</script> a bivector, and when we get to 3D, <script type="math/tex">e_{123}</script> is the trivector.</p>
<h2 id="the-meaning-of-geometric-products">The meaning of Geometric Products</h2>
<p>Let us look one more time at the vectors <script type="math/tex">a</script> and <script type="math/tex">b</script>, but this time let us include all four of the basis vectors we have seen thus far: <script type="math/tex">1, e_1, e_2, e_{12}</script>.</p>
<script type="math/tex; mode=display">% <![CDATA[
\begin{eqnarray*}
a & = & 0(1) + 2e_1 + 1e_2 + 0e_{12}\\
b & = & 0(1) + 3e_1 + 4e_2 + 0e_{12}\end{eqnarray*} %]]></script>
<p>In general, we will call this new compound object a “Multivector”. Multivector <script type="math/tex">a</script> has four components:</p>
<ul>
<li>An amount of “0” of a scalar quantity</li>
<li>An amount of “2” in direction <script type="math/tex">e_1</script></li>
<li>An amount of “1” in direction <script type="math/tex">e_2</script></li>
<li>An amount of “0” is the bivector (90 degree rotation) direction</li>
</ul>
<p>As we know by now, we cannot simplify this expression any further, because we cannot “add” apples and oranges and pears and bananas. All four objects are independent, different measurement units: the scalar values, the two basis values, and the bivector (<script type="math/tex">e_{12}</script>) value.</p>
<p>The only thing left to do in this post is to explore a few examples.</p>
<h4 id="example-on-the-order-of-multiplication-ab-vs-ba">Example: On the Order of Multiplication (<script type="math/tex">ab</script> vs <script type="math/tex">ba</script>)?</h4>
<p>What is the relationship between <script type="math/tex">ab</script> and <script type="math/tex">ba</script>?</p>
<script type="math/tex; mode=display">% <![CDATA[
\begin{eqnarray*}
ba & = & (3e_{1}+4e_{2})(2e_{1}+1e_{2})\\
& = & 6e_{11}+3e_{12}+8e_{21}+4e_{22}\\
& = & 6+3e_{12}-8e_{12}+4\\
& = & 10-5e_{12}\\
& = & (ab)^{\dagger}
\end{eqnarray*} %]]></script>
<p>where <script type="math/tex">^{\dagger}</script> means the complex conjugate. In physical terms, this means rotating clockwise instead of counterclockwise, which is consistent with our understanding thus far.</p>
<h4 id="example-how-do-we-move-from-a-to-b">Example: How do we move from <script type="math/tex">a</script> to <script type="math/tex">b</script>?</h4>
<p>If <script type="math/tex">ab</script> represents a transformation from <script type="math/tex">a</script> to <script type="math/tex">b</script>, how do we show it? Keeping in mind that geometric product operations are not commutative, should we pre- or post- multiply <script type="math/tex">a</script> with <script type="math/tex">ab</script> to transform it into <script type="math/tex">b</script>?</p>
<p>If we pre-multiply,</p>
<script type="math/tex; mode=display">% <![CDATA[
\begin{eqnarray*}
aba & = & (ab)a\\
& = & (10+5e_{12})(2e_{1}+1e_{2})\\
& = & 20e_{1}+10e_{2}+10e_{121}+5e_{122}\\
& = & 20e_{1}+10e_{2}-10e_{2}+5e_{1}\\
& = & 25e_{1}
\end{eqnarray*} %]]></script>
<p>Which is not equal to <script type="math/tex">b</script>. Perhaps we should try post-multiplying?</p>
<script type="math/tex; mode=display">% <![CDATA[
\begin{eqnarray*}
aab & = & a(ab)\\
& = & (2e_{1}+1e_{2})(10+5e_{12})\\
& = & 20e_{1}+10e_{112}+10e_{2}+5e_{212}\\
& = & 20e_{1}+10e_{2}+10e_{2}-5e_{1}\\
& = & 15e_{1}+20e_{2}\\
& = & 5(3e_{1}+4e_{2})\\
& = & 5b
\end{eqnarray*} %]]></script>
<p>Aha! That is just <script type="math/tex">b</script> multiplied by a factor of 5. Where did that factor of 5 come from? Well, If we normalized <script type="math/tex">a</script> and <script type="math/tex">b</script> to have unit length (i.e. <script type="math/tex">\frac{a}{\|a\|}</script> and <script type="math/tex">\frac{b}{\|b\|}</script>), then the factor of 5 disappears. Now is a good time to grab a sheet of paper and a pen and prove that <script type="math/tex">aab=b</script> for unit length vectors, and then read on:</p>
<script type="math/tex; mode=display">% <![CDATA[
\begin{eqnarray*}
r&=&\frac{a}{\|a\|}\frac{b}{\|b\|}\\
&=&...\end{eqnarray*} %]]></script>
<script type="math/tex; mode=display">\|r\|=1</script>
<p>If you can see that <script type="math/tex">r</script> represents a pure rotation (a.k.a. a <strong>rotor</strong>), then the transform from <script type="math/tex">a</script> to <script type="math/tex">b</script> could be described as: “normalize <script type="math/tex">a</script>, rotate by <script type="math/tex">r</script>, and then scale by <script type="math/tex">\|b\|</script> to reach <script type="math/tex">b</script>. In math, this is quite simply several products written from left to right:</p>
<script type="math/tex; mode=display">% <![CDATA[
\begin{eqnarray*}
a\frac{1}{\|a\|}r\|b\| & = & a\frac{1}{\|a\|}\frac{ab}{\|a\|\|b\|}\|b\|\\
& = & \frac{aab}{\|a\|^{2}}\\
& = & b
\end{eqnarray*} %]]></script>
<p>And we can see that the factor of 5 we saw earlier came from the fact that <script type="math/tex">\|a\|^2=5</script>. The true way to go from <script type="math/tex">a</script> to <script type="math/tex">b</script> is thus to multiply <script type="math/tex">a</script> by <script type="math/tex">\frac{ab}{\|a\|^2}</script>.</p>
<h1 id="conclusion">Conclusion</h1>
<p>For those with prior experience in engineering and physics, you have probably noticed by now that the bivector <script type="math/tex">e_{12}</script> is playing the role of the imaginary number <script type="math/tex">i=\sqrt{-1}</script>, and that this is all just complex mathematics in another form. However, you may agree after seeing the results in higher dimensions that it is perhaps more valid to say that complex mathematics is just a special case of geometric algebra!</p>
<h1 id="references">References</h1>
<p>I found the following papers useful while learning about Geometric Algebra. Ordering from easiest to hardest,</p>
<ul>
<li><em>Geometric Algebra Primer</em>, by Jaap Suter.</li>
<li><em>Imaginary Numbers are not Real – the Geometric Algebra of Spacetime</em>, by Stephen Gull, Anthony Lasenby, and Chris Doran.</li>
<li><em>A Survey of Geometric Algebra and Geometric Calculus</em>, by Alan Macdonald.</li>
<li><em>Oersted Medal Lecture 2002: Reforming the Mathematical Language of Physics</em> by David Hestenes.</li>
<li><em>An Introduction to Geometric Algebra and Calculus</em>, by Alan Bromborsky.</li>
<li><em>Geometric Algebra</em>, by Eric Chisolm.</li>
<li><em>Spacetime Physics with Geometric Algebra 1</em>, by David Hestenes.</li>
</ul>Geometric Algebra (GA) is one of those things that we should have all learned in high school because it would have made physics and mathematics in college so much easier.Hyperbolic Geometry & Special Relativity2017-06-02T00:00:00-07:002017-06-02T00:00:00-07:00/blog/hyperbolic-geometry-and-special-relativity<p>While studying <a href="https://arxiv.org/abs/0810.3328">An Introduction to Particle Physics</a> on a recent flight to Japan – studying math that is way above my head is a nerdy hobby of mine – I came across a simple viewpoint on special relativity that really stunned me:</p>
<blockquote>
<p>Consider a spatial rotation around, say, the z-axis (or, equivalently, mixing the x and y coordinates). Such a transformation is called an <strong>Euler Transformation</strong>, and takes the form</p>
</blockquote>
<script type="math/tex; mode=display">% <![CDATA[
\begin{eqnarray*}
t^{\prime} & = & t\\
x^{\prime} & = & x\cos\theta+y\sin\theta\\
y^{\prime} & = & -x\cos\theta+y\sin\theta\\
z^{\prime} & = & z \end{eqnarray*} %]]></script>
<blockquote>
<p>where \(\theta\) is the angle of rotation, called the <strong>Euler Angle</strong>. We can simultaneously express a Lorentz transformation as a sort of “rotation” that mixes a spatial dimension and a time dimension, as follows</p>
</blockquote>
<script type="math/tex; mode=display">% <![CDATA[
\begin{eqnarray*}
t^{\prime} & = & t\cosh\theta-x\sinh\theta\\
x^{\prime} & = & -t\sinh\theta+x\cosh\theta\\
y^{\prime} & = & y\\
z^{\prime} & = & z\end{eqnarray*} %]]></script>
<blockquote>
<p>where \(\theta \) is defined by the relationship \(\beta = \tan(\theta) \).</p>
</blockquote>
<p>After staring at that for a while, I was struck by the analogy between the “mixing” between coordinates when we rotate something, and the relativistic “mixing” between time and space when something accelerates. Although this is just an analogy and perhaps squeezing and stretching is a better metaphor than rotation in this case, is very tempting to search for the geometry of what is happening rather than just the algebra.</p>
<p>Whether it was the in flight wine or just the jet lag, I found myself lost in thought about the connection between hyperbolic geometry and special relativity – after all, what does it <em>mean</em> to say that our space is curved in a way consistent with hyperbolic geometry? We all study flat, Euclidean spaces in school, and as a roboticist who worked a lot with rigid body dynamics I became pretty comfortable with the concepts surrounding rotation matrices, quaternions, and SO(3) groups, I but I don’t ever recall using the hyperbolic cosine even once in my life. This was surprising to me, as I use math on a fairly regular basis.</p>
<p>To try to clear the matter in my mind, I made a little table of some of the definitions of sine, cosine, and their hyperbolic equivalents:</p>
<script type="math/tex; mode=display">% <![CDATA[
\begin{eqnarray}
\sin(x) & = & \frac{1}{2}(e^{ix}-e^{-ix}) & = & \sum_{k=0}^{\infty}\frac{(-1)^{k}x^{2k+1}}{(2k+1)!} \\
\cos(x) & = & \frac{1}{2}(e^{ix}+e^{-ix}) & = & \sum_{k=0}^{\infty}\frac{(-1)^{k}x^{2k}}{(2k)!} \\
\sinh(x) & = & \frac{1}{2}(e^{x}-e^{-x}) & = & \sum_{k=0}^{\infty}\frac{x^{2k+1}}{(2k+1)!} \\
\cosh(x) & = & \frac{1}{2}(e^{x}+e^{-x}) & = & \sum_{k=0}^{\infty}\frac{x^{2k}}{(2k)!} \end{eqnarray} %]]></script>
<p>Look at how the hyperbolic trig functions have no need of the imaginary number \(i=\sqrt{-1}\) or the alternating -1’s in the infinite series. One of the most frustrating things about \(i\) is that it is so incredibly useful algebraically, but it also makes things more cumbersome because expressions in general become more – pardon the pun – complex. The geometric meaning of the imaginary number is often associated with rotations, but I wonder if there are more geometric ways of understanding the same operation that have no need for the imaginary number per se. I would prefer to see mathematical expressions that are as simple as possible, but no simpler.</p>
<p>Even now, as I stare at the infinite series for hyperbolic sine and cosine, and their definitions in terms of the all-important exponential function, I wonder if in fact that “things with the imaginary number are wrong” in the same way that <a href="http://tauday.com/">“pi is wrong”</a>. It is not that sines are incorrect in an algebraic or mathematical sense, because they are clearly not. Rather, I am wondering whether, due to the way mathematics developed historically, perhaps we are using algebra that is more cumbersome than necessary to describe two legs of the same geometric elephant.</p>
<p>I would welcome good book recommendations connecting the essential geometry of hyperbolas to special relativity!</p>While studying An Introduction to Particle Physics on a recent flight to Japan – studying math that is way above my head is a nerdy hobby of mine – I came across a simple viewpoint on special relativity that really stunned me:Reviving the Dead…Content2017-05-30T00:00:00-07:002017-05-30T00:00:00-07:00/blog/reviving-the-dead<p>From 2003 until 2016, I had a personal website at <a href="https://roboloco.net/">roboloco.net</a>. It lasted until last year, when I finally grew tired of upgrading applications, keeping comments free of spam, and the servers secure from hackers and the occasional website defacement. Thank you, GitHub, for providing this terrible sysadmin a free place to store this content, and one that requires no regular maintanance!</p>
<p>Now! To slowly revive some of the content that has been offline for the past year…does GitHub have a tool for poking me to do that as well?</p>
<p>I’ll start with the <a href="/about">about page</a> as this is supposed to be a github.io page, after all.</p>From 2003 until 2016, I had a personal website at roboloco.net. It lasted until last year, when I finally grew tired of upgrading applications, keeping comments free of spam, and the servers secure from hackers and the occasional website defacement. Thank you, GitHub, for providing this terrible sysadmin a free place to store this content, and one that requires no regular maintanance!Project Euler Problem 892010-11-16T09:28:30-08:002010-11-16T09:28:30-08:00/project-euler/problem-89<p><a href="http://projecteuler.net/index.php?section=problems&id=89">Problem 89</a> was kind of fun: we needed to convert some sloppily written roman-numerals into their more efficient, minimal representations.</p>
<p>There are two tricks to doing this easily:</p>
<ol>
<li>When converting from roman numerals to decimal digits, it is simplest to process the roman numeral from right to left.</li>
<li>Since I can only be placed before V and X, X before L and C, and C before D and M, the symmetry of these results as you move up by powers of ten suggests that we use a few simple <code class="highlighter-rouge">cond</code> statements to handle numbers from 1 to 10, and recurse to handle the increasingly higher powers of ten.</li>
</ol>
<p>The code to implement these rules wasn’t particularly long. As usual, zipmap is very concise at creating mappings from characters to digits.</p>
<pre><code>(<span style="color: #729fcf;">use</span> '[clojure.contrib.duck-streams <span style="color: #729fcf;">:only</span> (read-lines)])
(<span style="color: #8ae234;">def</span> <span style="color: #edd400; font-weight: bold;">r2n</span> (zipmap <span style="color: #Fd7f98;">"IVXLCDM"</span> [1 5 10 50 100 500 1000]))
(<span style="color: #8ae234;">def</span> <span style="color: #edd400; font-weight: bold;">n2r</span> (zipmap (<span style="color: #729fcf;">vals</span> r2n) (<span style="color: #729fcf;">keys</span> r2n)))
<span style="color: #A8AaA5;">;; </span><span style="color: #A8AaA5;">Do things in reverse and it's so much easier to solve!
</span>(<span style="color: #8ae234;">defn</span> <span style="color: #edd400; font-weight: bold;">de-romanize</span>
<span style="color: #888a85;">"Returns the decimal representation of a roman numeral string s. "</span>
([s] (de-romanize (<span style="color: #729fcf;">reverse</span> (<span style="color: #729fcf;">map</span> r2n s)) 0 0))
([s total mx] (<span style="color: #8ae234;">if-let</span> [c (<span style="color: #729fcf;">first</span> s)]
(<span style="color: #8ae234;">if</span> (<span style="color: #729fcf;">>=</span> c mx)
(<span style="color: #8ae234;">recur</span> (<span style="color: #729fcf;">rest</span> s) (<span style="color: #729fcf;">+</span> total c) (<span style="color: #729fcf;">max</span> c mx))
(<span style="color: #8ae234;">recur</span> (<span style="color: #729fcf;">rest</span> s) (<span style="color: #729fcf;">-</span> total c) mx))
total)))
(<span style="color: #8ae234;">defn</span> <span style="color: #edd400; font-weight: bold;">romanize</span>
<span style="color: #888a85;">"Returns the minimal roman numeral representation of n"</span>
([n]
{<span style="color: #729fcf;">:pre</span> [(<span style="color: #729fcf;"><=</span> n 10000 )]}
(romanize (<span style="color: #729fcf;">quot</span> n 10) (<span style="color: #729fcf;">rem</span> n 10) 1))
([q r x]
(<span style="color: #8ae234;">if</span> (<span style="color: #729fcf;">></span> x 100)
(<span style="color: #729fcf;">repeat</span> (<span style="color: #729fcf;">+</span> q r) (n2r x))
(<span style="color: #8ae234;">->></span> (<span style="color: #729fcf;">concat</span>
(romanize (<span style="color: #729fcf;">quot</span> q 10) (<span style="color: #729fcf;">rem</span> q 10) (<span style="color: #729fcf;">*</span> x 10))
(<span style="color: #8ae234;">cond</span>
(<span style="color: #729fcf;"><</span> r 4) (<span style="color: #729fcf;">repeat</span> r (n2r x))
(<span style="color: #729fcf;">=</span> r 4) [(n2r x) (n2r (<span style="color: #729fcf;">*</span> 5 x))]
(<span style="color: #729fcf;"><</span> r 9) (<span style="color: #729fcf;">concat</span> [(n2r (<span style="color: #729fcf;">*</span> 5 x))] (<span style="color: #729fcf;">repeat</span> (<span style="color: #729fcf;">-</span> r 5) (n2r x)))
(<span style="color: #729fcf;">=</span> r 9) [(n2r x) (n2r (<span style="color: #729fcf;">*</span> 10 x))]
<span style="color: #729fcf;">:else</span> <span style="color: #Fd7f98;">""</span>))
(<span style="color: #729fcf;">apply</span> str )))))
(<span style="color: #8ae234;">defn</span> <span style="color: #edd400; font-weight: bold;">euler-89</span> [file]
(<span style="color: #729fcf;">reduce</span>
+
(<span style="color: #8ae234;">for</span> [l (read-lines file)]
(<span style="color: #729fcf;">-</span> (<span style="color: #729fcf;">count</span> l)
(<span style="color: #729fcf;">count</span> (romanize (de-romanize l)))))))
(euler-89 <span style="color: #Fd7f98;">"roman.txt"</span>)</code></pre>
<p>You may notice that I used preconditions to indicate the <code class="highlighter-rouge">romanize</code> function only works for numbers less than 10000.</p>Problem 89 was kind of fun: we needed to convert some sloppily written roman-numerals into their more efficient, minimal representations.Project Euler Problem 872010-10-20T08:27:12-07:002010-10-20T08:27:12-07:00/project-euler/problem-87<p><a href="http://projecteuler.net/index.php?section=problems&id=87">Problem 87</a> asks us to find how many numbers below 50 million that can be expressed as the sum of a prime square, cube, and fourth power.</p>
<p>By now we are old hands at this type of problem. By caching the exponents of prime numbers and using a set to filter out duplicates, we can find the solution in roughly 4 seconds:</p>
<pre><code>(<span style="color: #8ae234;">defn</span> <span style="color: #edd400; font-weight: bold;">euler-87</span> [top]
(<span style="color: #729fcf;">count</span>
(<span style="color: #729fcf;">into</span>
#{}
(<span style="color: #8ae234;">let</span> [squares (<span style="color: #729fcf;">map</span> #(expt % 2) primes)
cubes (<span style="color: #729fcf;">map</span> #(expt % 3) primes)
quads (<span style="color: #729fcf;">map</span> #(expt % 4) primes)]
(<span style="color: #8ae234;">for</span> [i (<span style="color: #729fcf;">take-while</span> #(<span style="color: #729fcf;"><</span> % top) squares)
j (<span style="color: #729fcf;">take-while</span> #(<span style="color: #729fcf;"><</span> % (<span style="color: #729fcf;">-</span> top i)) cubes)
k (<span style="color: #729fcf;">take-while</span> #(<span style="color: #729fcf;"><</span> % (<span style="color: #729fcf;">-</span> top i j)) quads)
s [(<span style="color: #729fcf;">+</span> i j k)]
<span style="color: #729fcf;">:when</span> (<span style="color: #729fcf;"><</span> s top)]
s)))))
(<span style="color: #729fcf;">time</span> (euler-87 50000000)) <span style="color: #A8AaA5;">;; </span><span style="color: #A8AaA5;">"Elapsed time: 3954.751452 msecs"
</span></code></pre>Problem 87 asks us to find how many numbers below 50 million that can be expressed as the sum of a prime square, cube, and fourth power.Project Euler Problem 862010-10-20T07:56:03-07:002010-10-20T07:56:03-07:00/project-euler/problem-86<p>Despite it’s relative simplicity, I wasted hours on <a href="http://projecteuler.net/index.php?section=problems&id=86">problem 86</a>. One important thing that I learned is:</p>
<p><strong>Sometimes you absolutely must formulate the problem in an incremental form!</strong></p>
<p>My long and complex first attempt at this problem began by generating Pythagorean triples (as we did in <a href="?tag=pythagorean-triplets">previous problems</a>), and computing cuboids whose geodesics were the same as those triples. Unfortunately, although this worked well, I did not formulate it in an incremental manner, so at best it would have O(n^2) performance for this kind of incremental search problem, as I realized in the final step.</p>
<p>On the other hand, if you formulate the problem in an incremental form, it is remarkably simple to solve:</p>
<pre><code>(<span style="color: #8ae234;">defn</span> <span style="color: #edd400; font-weight: bold;">square?</span> [x] (<span style="color: #729fcf;">=</span> x (expt (<span style="color: #729fcf;">int</span> (sqrt x)) 2)))
(<span style="color: #8ae234;">defn</span> <span style="color: #edd400; font-weight: bold;">cuboids</span> [m]
(<span style="color: #729fcf;">reduce</span>
+
(<span style="color: #8ae234;">for</span> [a (<span style="color: #729fcf;">filter</span> #(square? (<span style="color: #729fcf;">+</span> (<span style="color: #729fcf;">*</span> % %) (<span style="color: #729fcf;">*</span> m m)))
(<span style="color: #729fcf;">range</span> 1 (<span style="color: #729fcf;">inc</span> (<span style="color: #729fcf;">*</span> 2 m))))]
(<span style="color: #8ae234;">if</span> (<span style="color: #729fcf;">></span> a m)
(<span style="color: #729fcf;">-</span> (<span style="color: #729fcf;">quot</span> a 2) (<span style="color: #729fcf;">-</span> a m 1))
(<span style="color: #729fcf;">quot</span> a 2)))))
(<span style="color: #8ae234;">defn</span> <span style="color: #edd400; font-weight: bold;">euler-86</span> [L]
(<span style="color: #729fcf;">count</span> (<span style="color: #729fcf;">take-while</span> #(<span style="color: #729fcf;">></span> L %) (reductions + (<span style="color: #729fcf;">map</span> cuboids (<span style="color: #729fcf;">range</span>))))))
(<span style="color: #729fcf;">time</span> (euler-86 1000000)) <span style="color: #A8AaA5;">;; </span><span style="color: #A8AaA5;">"Elapsed time: 3872.220781 msecs"
</span></code></pre>Despite it’s relative simplicity, I wasted hours on problem 86. One important thing that I learned is:Project Euler Problem 852010-10-19T05:47:08-07:002010-10-19T05:47:08-07:00/project-euler/problem-85<p><a href="http://projecteuler.net/index.php?section=problems&id=85">Problem 85</a> asks us to find the number of rectangles that can be drawn in a grid of size m by n.</p>
<p>It may help to work out the answer to a few of the grids until you see the pattern: the number of rectangles is equal to the product of two summations.</p>
<pre><code>(<span style="color: #8ae234;">def</span> <span style="color: #edd400; font-weight: bold;">sums</span> (reductions + (<span style="color: #729fcf;">range</span>)))
(<span style="color: #8ae234;">defn</span> <span style="color: #edd400; font-weight: bold;">num-rects</span> [m n] (<span style="color: #729fcf;">*</span> (<span style="color: #729fcf;">nth</span> sums m) (<span style="color: #729fcf;">nth</span> sums n)))
(<span style="color: #8ae234;">defn</span> <span style="color: #edd400; font-weight: bold;">smallest-second</span> [coll]
(<span style="color: #729fcf;">reduce</span> #(<span style="color: #8ae234;">if</span> (<span style="color: #729fcf;"><</span> (<span style="color: #729fcf;">second</span> %1) (<span style="color: #729fcf;">second</span> %2)) %1 %2) coll))
(<span style="color: #8ae234;">defn</span> <span style="color: #edd400; font-weight: bold;">euler-85</span> [goal]
(<span style="color: #729fcf;">first</span>
(smallest-second
(<span style="color: #8ae234;">for</span> [i (<span style="color: #729fcf;">take-while</span> #(<span style="color: #729fcf;"><</span> (num-rects % 1) goal) (<span style="color: #729fcf;">rest</span> (<span style="color: #729fcf;">range</span>)))
j (<span style="color: #729fcf;">take-while</span> #(<span style="color: #729fcf;"><</span> 0 (<span style="color: #729fcf;">-</span> goal (num-rects i %))) (<span style="color: #729fcf;">rest</span> (<span style="color: #729fcf;">range</span>)))]
[(<span style="color: #729fcf;">*</span> i j) (<span style="color: #729fcf;">-</span> goal (num-rects i j))]))))
(<span style="color: #729fcf;">time</span> (euler-85 2000000)) <span style="color: #A8AaA5;">;; </span><span style="color: #A8AaA5;">"Elapsed time: 1607.372755 msecs"
</span></code></pre>
<p>Of course the above is straightforward, but we might as well remember the <a href="http://en.wikipedia.org/wiki/Carl_Friedrich_Gauss#Early_years_.281777.E2.80.931798.29"> story of Gauss as a young boy</a> and use an analytic solution for <code class="highlighter-rouge">num-rects</code>:</p>
<pre><code>(<span style="color: #8ae234;">defn</span> <span style="color: #edd400; font-weight: bold;">num-rects</span> [m n]
(<span style="color: #729fcf;">*</span> (<span style="color: #729fcf;">/</span> (<span style="color: #729fcf;">+</span> (<span style="color: #729fcf;">*</span> m m) m) 2)
(<span style="color: #729fcf;">/</span> (<span style="color: #729fcf;">+</span> (<span style="color: #729fcf;">*</span> n n) n) 2)))
(<span style="color: #729fcf;">time</span> (euler-85 2000000)) <span style="color: #A8AaA5;">;; </span><span style="color: #A8AaA5;">"Elapsed time: 45.927094 msecs"
</span></code></pre>
<p>I’m somewhat surprised that is so much faster – I would have thought that caching the values in the lazy list would have been only slightly slower, but it seems that my intuition was incorrect. The evils of premature optimization appears again.</p>Problem 85 asks us to find the number of rectangles that can be drawn in a grid of size m by n.Project Euler Problem 842010-10-19T05:29:12-07:002010-10-19T05:29:12-07:00/project-euler/problem-84<p><a href="http://projecteuler.net/index.php?section=problems&id=84">Problem 84</a> asks us to implement the classic game <a href="http://en.wikipedia.org/wiki/Monopoly_%28game%29">Monopoly</a> and find the most-visited spaces on the board…if we used two 4-sided dice instead of 6-sided ones.</p>
<p>Although it would probably be straightforward to compute probabilities directly using fractions, or indirectly approximate them with Hidden Markov Models, for now let’s just brute force it and use Clojure’s ability to run things in parallel.</p>
<pre><code>(<span style="color: #8ae234;">def</span> <span style="color: #edd400; font-weight: bold;">board</span> [<span style="color: #729fcf;">:GO</span> <span style="color: #729fcf;">:A1</span> <span style="color: #729fcf;">:CC1</span> <span style="color: #729fcf;">:A2</span> <span style="color: #729fcf;">:T1</span> <span style="color: #729fcf;">:R1</span> <span style="color: #729fcf;">:B1</span> <span style="color: #729fcf;">:CH1</span> <span style="color: #729fcf;">:B2</span> <span style="color: #729fcf;">:B3</span>
<span style="color: #729fcf;">:JAIL</span> <span style="color: #729fcf;">:C1</span> <span style="color: #729fcf;">:U1</span> <span style="color: #729fcf;">:C2</span> <span style="color: #729fcf;">:C3</span> <span style="color: #729fcf;">:R2</span> <span style="color: #729fcf;">:D1</span> <span style="color: #729fcf;">:CC2</span> <span style="color: #729fcf;">:D2</span> <span style="color: #729fcf;">:D3</span>
<span style="color: #729fcf;">:FP</span> <span style="color: #729fcf;">:E1</span> <span style="color: #729fcf;">:CH2</span> <span style="color: #729fcf;">:E2</span> <span style="color: #729fcf;">:E3</span> <span style="color: #729fcf;">:R3</span> <span style="color: #729fcf;">:F1</span> <span style="color: #729fcf;">:F2</span> <span style="color: #729fcf;">:U2</span> <span style="color: #729fcf;">:F3</span>
<span style="color: #729fcf;">:G2J</span> <span style="color: #729fcf;">:G1</span> <span style="color: #729fcf;">:G2</span> <span style="color: #729fcf;">:CC3</span> <span style="color: #729fcf;">:G3</span> <span style="color: #729fcf;">:R4</span> <span style="color: #729fcf;">:CH3</span> <span style="color: #729fcf;">:H1</span> <span style="color: #729fcf;">:T2</span> <span style="color: #729fcf;">:H2</span>])
(<span style="color: #8ae234;">def</span> <span style="color: #edd400; font-weight: bold;">b2i</span> (zipmap board (<span style="color: #729fcf;">range</span>))) <span style="color: #A8AaA5;">;; </span><span style="color: #A8AaA5;">Board symbols to integers
</span>
(<span style="color: #8ae234;">def</span> <span style="color: #edd400; font-weight: bold;">i2b</span> (zipmap (<span style="color: #729fcf;">range</span>) board)) <span style="color: #A8AaA5;">;; </span><span style="color: #A8AaA5;">Integers to board symbols
</span>
(<span style="color: #8ae234;">defn</span> <span style="color: #edd400; font-weight: bold;">card-CC</span>
<span style="color: #888a85;">"Community Chest. Returns the number of the square to move to."</span>
[n]
(<span style="color: #8ae234;">let</span> [options (<span style="color: #729fcf;">concat</span> [(b2i <span style="color: #729fcf;">:GO</span>) (b2i <span style="color: #729fcf;">:JAIL</span>)] (<span style="color: #729fcf;">repeat</span> 14 n))]
(rand-nth options)))
(<span style="color: #8ae234;">defn</span> <span style="color: #edd400; font-weight: bold;">card-CH</span>
<span style="color: #888a85;">"Chance card. Returns the number of the square to move to."</span>
[n]
(<span style="color: #8ae234;">let</span> [options [<span style="color: #729fcf;">:X</span> <span style="color: #729fcf;">:X</span> <span style="color: #729fcf;">:X</span> <span style="color: #729fcf;">:X</span> <span style="color: #729fcf;">:X</span> <span style="color: #729fcf;">:X</span>
<span style="color: #729fcf;">:GO</span> <span style="color: #729fcf;">:JAIL</span> <span style="color: #729fcf;">:C1</span> <span style="color: #729fcf;">:E3</span> <span style="color: #729fcf;">:H2</span> <span style="color: #729fcf;">:R1</span> <span style="color: #729fcf;">:NextR</span> <span style="color: #729fcf;">:NextR</span> <span style="color: #729fcf;">:NextU</span> <span style="color: #729fcf;">:Back3</span>]
event (rand-nth options)]
(<span style="color: #8ae234;">condp</span> = event
<span style="color: #729fcf;">:X</span> n <span style="color: #A8AaA5;">;; </span><span style="color: #A8AaA5;">Do nothing
</span> <span style="color: #729fcf;">:NextR</span> (<span style="color: #729fcf;">nth</span> (<span style="color: #729fcf;">map</span> b2i [<span style="color: #729fcf;">:R1</span> <span style="color: #729fcf;">:R2</span> <span style="color: #729fcf;">:R3</span> <span style="color: #729fcf;">:R4</span>]) <span style="color: #A8AaA5;">;; </span><span style="color: #A8AaA5;">Next railroad
</span> (<span style="color: #729fcf;">rem</span> (<span style="color: #729fcf;">quot</span> (<span style="color: #729fcf;">+</span> 5 n) 10) 4))
<span style="color: #729fcf;">:NextU</span> (<span style="color: #8ae234;">if</span> (<span style="color: #8ae234;">and</span> (<span style="color: #729fcf;">></span> n (b2i <span style="color: #729fcf;">:U1</span>)) <span style="color: #A8AaA5;">;; </span><span style="color: #A8AaA5;">Next Utility
</span> (<span style="color: #729fcf;"><</span> n (b2i <span style="color: #729fcf;">:U2</span>)))
(b2i <span style="color: #729fcf;">:U2</span>)
(b2i <span style="color: #729fcf;">:U1</span>))
<span style="color: #729fcf;">:Back3</span> (<span style="color: #8ae234;">if</span> (<span style="color: #729fcf;">=</span> (<span style="color: #729fcf;">-</span> n 3) (b2i <span style="color: #729fcf;">:CC3</span>))
(card-CC (<span style="color: #729fcf;">-</span> n 3)) <span style="color: #A8AaA5;">;; </span><span style="color: #A8AaA5;">Sometimes you land on another CC
</span> (<span style="color: #729fcf;">-</span> n 3)) <span style="color: #A8AaA5;">;; </span><span style="color: #A8AaA5;">But mostly you don't
</span> (b2i event))))
(<span style="color: #8ae234;">defn</span> <span style="color: #edd400; font-weight: bold;">dice-4</span> [] (<span style="color: #729fcf;">inc</span> (<span style="color: #729fcf;">rand-int</span> 4)))
(<span style="color: #8ae234;">defn</span> <span style="color: #edd400; font-weight: bold;">move</span> [[n doubles]]
(<span style="color: #8ae234;">let</span> [d1 (dice-4)
d2 (dice-4)
m (<span style="color: #8ae234;">if</span> (<span style="color: #8ae234;">and</span> (<span style="color: #729fcf;">=</span> d1 d2) (<span style="color: #729fcf;">=</span> 2 doubles))
(b2i <span style="color: #729fcf;">:JAIL</span>)
(<span style="color: #729fcf;">rem</span> (<span style="color: #729fcf;">+</span> n d1 d2) 40))]
[(<span style="color: #8ae234;">condp</span> = m
(b2i <span style="color: #729fcf;">:G2J</span>) (b2i <span style="color: #729fcf;">:JAIL</span>)
(b2i <span style="color: #729fcf;">:CC1</span>) (card-CC m)
(b2i <span style="color: #729fcf;">:CC2</span>) (card-CC m)
(b2i <span style="color: #729fcf;">:CC2</span>) (card-CC m)
(b2i <span style="color: #729fcf;">:CH1</span>) (card-CH m)
(b2i <span style="color: #729fcf;">:CH2</span>) (card-CH m)
(b2i <span style="color: #729fcf;">:CH3</span>) (card-CH m)
m)
(<span style="color: #8ae234;">if</span> (<span style="color: #729fcf;">=</span> d1 d2)
(<span style="color: #8ae234;">if</span> (<span style="color: #729fcf;">not</span> (<span style="color: #729fcf;">=</span> 2 doubles)) <span style="color: #A8AaA5;">;; </span><span style="color: #A8AaA5;">reset if 3rd double in a row
</span> (<span style="color: #729fcf;">inc</span> doubles)
0)
0)]))
(<span style="color: #8ae234;">defn</span> <span style="color: #edd400; font-weight: bold;">compute-monopoly-freqs</span> []
(<span style="color: #8ae234;">let</span> [trials 1000000
games 10
sim (<span style="color: #729fcf;">fn</span> [trials]
(frequencies (<span style="color: #729fcf;">take</span> trials (<span style="color: #729fcf;">map</span> first (<span style="color: #729fcf;">iterate</span> move [0 0])))))
freqs (<span style="color: #729fcf;">apply</span> merge-with + (<span style="color: #729fcf;">pmap</span> sim (<span style="color: #729fcf;">repeat</span> games trials)))
ps (<span style="color: #729fcf;">map</span> (<span style="color: #729fcf;">fn</span> [[c v]]
[(i2b c) (<span style="color: #729fcf;">double</span> (<span style="color: #729fcf;">*</span> 100 (<span style="color: #729fcf;">/</span> v trials games)))])
(<span style="color: #729fcf;">sort</span> freqs))]
(<span style="color: #729fcf;">map</span> #(b2i (<span style="color: #729fcf;">first</span> %)) (<span style="color: #729fcf;">take</span> 3 (<span style="color: #729fcf;">reverse</span> (<span style="color: #729fcf;">sort-by</span> second ps))))))
(<span style="color: #729fcf;">time</span> (compute-monopoly-freqs)) <span style="color: #A8AaA5;">;; </span><span style="color: #A8AaA5;">"Elapsed time: 10217.921373 msecs"
</span></code></pre>
<p>With the work of 10,000,000 trials divided evenly across 10 threads and evaluated in parallel in roughly 10 seconds, this gives the correct answer on my machine. However, the probabilities that I compute for the 6-sided dice are slightly different from the ones given on the Project Euler website, so this implementation is probably slightly incorrect. Can you find the mistake?</p>Problem 84 asks us to implement the classic game Monopoly and find the most-visited spaces on the board…if we used two 4-sided dice instead of 6-sided ones.Project Euler Problem 832010-10-18T09:23:14-07:002010-10-18T09:23:14-07:00/project-euler/problem-83<p><a href="http://projecteuler.net/index.php?section=problems&id=83">Problem 83</a> can be solved with A* exactly like the we did in <a href="?p=660">problem 81</a>. The only code that needs to be changed is the neighbors function <code class="highlighter-rouge">neigh</code> and the estimated cost-to-goal function <code class="highlighter-rouge">est</code>. Everything else can be reused from problem 81.</p>
<pre><code>(<span style="color: #8ae234;">defn</span> <span style="color: #edd400; font-weight: bold;">euler-83</span> []
(<span style="color: #8ae234;">let</span> [mat (load-matrix <span style="color: #Fd7f98;">"/zzz/work/matrix.txt"</span>)
m (<span style="color: #729fcf;">count</span> mat)
n (<span style="color: #729fcf;">count</span> (<span style="color: #729fcf;">first</span> mat))
cost (<span style="color: #729fcf;">fn</span> [[i j]] (<span style="color: #729fcf;">nth</span> (<span style="color: #729fcf;">nth</span> mat (<span style="color: #729fcf;">dec</span> i)) (<span style="color: #729fcf;">dec</span> j)))
start [1 1]
goal [m n]
goal? (<span style="color: #729fcf;">fn</span> [e] (<span style="color: #729fcf;">=</span> e goal))
est (<span style="color: #729fcf;">fn</span> [[i j]] 0)
neigh (<span style="color: #729fcf;">fn</span> [[i j]]
(<span style="color: #729fcf;">merge</span>
(<span style="color: #8ae234;">when</span> (<span style="color: #729fcf;"><</span> i m) {[(<span style="color: #729fcf;">inc</span> i) j] (cost [(<span style="color: #729fcf;">inc</span> i) j])})
(<span style="color: #8ae234;">when</span> (<span style="color: #729fcf;"><</span> j n) {[i (<span style="color: #729fcf;">inc</span> j)] (cost [i (<span style="color: #729fcf;">inc</span> j)])})
(<span style="color: #8ae234;">when</span> (<span style="color: #729fcf;"><</span> 1 i) {[(<span style="color: #729fcf;">dec</span> i) j] (cost [(<span style="color: #729fcf;">dec</span> i) j])})
(<span style="color: #8ae234;">when</span> (<span style="color: #729fcf;"><</span> 1 j) {[i (<span style="color: #729fcf;">dec</span> j)] (cost [i (<span style="color: #729fcf;">dec</span> j)])})))
path (a*-search est neigh start goal?)]
(<span style="color: #729fcf;">reduce</span> + (<span style="color: #729fcf;">map</span> cost path))))
(<span style="color: #729fcf;">time</span> (euler-83))</code></pre>
<p>With <code class="highlighter-rouge">est</code> set to always return zero, the A* search becomes effectively a memory-hungry version of <a href="http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm">Dijkstra’s Algorithm</a>.</p>Problem 83 can be solved with A* exactly like the we did in problem 81. The only code that needs to be changed is the neighbors function neigh and the estimated cost-to-goal function est. Everything else can be reused from problem 81.
(defn euler-83 []
(let [mat (load-matrix "/zzz/work/matrix.txt")
m (count mat)
n (count (first mat))
cost (fn [[i j]] (nth (nth mat (dec i)) (dec j)))
start [1 1]
goal [m n]
goal? (fn [e] (= e goal))
est (fn [[i j]] 0)
neigh (fn [[i j]]
(merge
(when (< i m) {[(inc i) j] (cost [(inc i) j])})
(when (< j n) {[i (inc j)] (cost [i (inc j)])})
(when (< 1 i) {[(dec i) j] (cost [(dec i) j])})
(when (< 1 j) {[i (dec j)] (cost [i (dec j)])})))
path (a*-search est neigh start goal?)]
(reduce + (map cost path))))