{"id":329,"date":"2017-08-27T17:45:00","date_gmt":"2017-08-27T17:45:00","guid":{"rendered":"http:\/\/konrad.burnik.org\/wordpress\/?p=329"},"modified":"2018-11-05T17:39:07","modified_gmt":"2018-11-05T17:39:07","slug":"hyperbolic-numbers-and-fractals","status":"publish","type":"post","link":"https:\/\/konrad.burnik.org\/wordpress\/hyperbolic-numbers-and-fractals\/","title":{"rendered":"Hyperbolic numbers and fractals"},"content":{"rendered":"<p>What happens when we change the identity defining the imaginary unit for the complex numbers <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/konrad.burnik.org\/wordpress\/wp-content\/ql-cache\/quicklatex.com-872e71dae1d339c9852ae4ec4a5a1ddd_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#105;&#94;&#50;&#61;&#45;&#49;\" title=\"Rendered by QuickLaTeX.com\" height=\"15\" width=\"59\" style=\"vertical-align: 0px;\"\/> to <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/konrad.burnik.org\/wordpress\/wp-content\/ql-cache\/quicklatex.com-02340a84aaf0803d9aaeab80047a8240_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#105;&#94;&#50;&#61;&#49;\" title=\"Rendered by QuickLaTeX.com\" height=\"15\" width=\"45\" style=\"vertical-align: 0px;\"\/> and enforcing <em>i\u00a0<\/em>different from 1?\u00a0 We get the somewhat less known numbers called\u00a0<a href=\"https:\/\/en.wikipedia.org\/wiki\/Split-complex_number\"><em>hyperbolic<\/em>\u00a0or <em>split-complex numbers<\/em><\/a>. The most common thing about complex numbers that comes to mind are the nice pictures of fractals and there are plenty of tools already out there to generate them. However, for the hyperbolic numbers there aren't as much fractal generators out there, so let us now make a simple tool in Python to generate these fractals as well.<\/p>\n<p>First, we need to implement the basic arithmetic with hyperbolic numbers. This will enable us to write simple arithmetic expressions like <em>z**2 + c <\/em>directly\u00a0instead of writing out the expressions in component form using real and imaginary parts. I made a simple Python implementation of class\u00a0<em>HyperbolicNumber<\/em>\u00a0in module\u00a0<em>hyperbolic\u00a0<\/em>doing exactly this.\u00a0Using this module, we can now write a function for counting the number of iterations of <em>f(z)=z**2+c<\/em> before \"escaping to infinity\" in a straightforward way. In fact the formula is identical to the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Mandelbrot_set#Escape_time_algorithm\">escape-time algorithm<\/a>\u00a0for fractals over complex numbers.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-linenumbers=\"false\">from hyperbolic import HyperbolicNumber\r\n\r\ndef f(z):\r\n    w = z\r\n    total = 0\r\n    while mag(w) &lt; 2.0 and total &lt; 300:\r\n        w = w**2 + z\r\n        total += 1\r\n    return total<\/pre>\n<p>Basically, the above function is all we need to start generating images of fractals. Here of course, we focus only on the famous map family {\u00a0<em>f_c(z) = z**2+c} <\/em>\u00a0indexed by <em>c,<\/em> but any other could be used as well. We add an additional parameter to\u00a0<em>f(z)<\/em>\u00a0 to become <em>f(z,c)<\/em> and encapsulate it in the\u00a0<em>HyperbolicFractal<\/em> class. This class will be our abstraction for a fractal calculation, which basically just calculates a 2**-k approximation of the Julia set of <em>f_c<\/em> over some given rectangular region in the hyperbolic number plane. For all the points <em>z<\/em> of a given rectangular range [<em>centerx-rangex, centerx+rangex]x[centery-rangey, centery+rangey]<\/em> we perform the call to<em> f(z, c)<\/em>. To avoid recalculation every time of the same region, or part of a region, points which have already been calculated are stored in an internal cache so any subsequent calls to <em>f(z, c)<\/em>\u00a0are just looked up instead of being recalculated. Here's the code.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-linenumbers=\"false\">import numpy\r\nimport matplotlib.cm as cm\r\nimport matplotlib.pylab as plt\r\nfrom hyperbolic import HyperbolicNumber\r\n\r\nclass HyperbolicFractal:\r\n    def __init__(self):\r\n        self.hits = 0\r\n        self.cache = {}\r\n        \r\n    def f(self, z, c):\r\n        if (z, c) in self.cache:\r\n            self.hits += 1\r\n            return self.cache[(z, c)]\r\n        w = z\r\n        total = 0\r\n        while mag(w) &lt; 2.0 and total &lt; 300:\r\n            w = w**2 + c\r\n            total += 1\r\n        self.cache[(z, c)] = total\r\n        return self.cache[(z, c)]\r\n\r\n    def show(self, scale, centerx, centery, rangex, rangey, c):\r\n        \"\"\"Draw a 2**(-scale) approximation of a hyperbolic fractal \r\n        over a given rectangular range.\"\"\"\r\n        self.hits = 0\r\n        totals = (centerx+rangex - (centerx-rangex))\\\r\n        * (centery+rangey - (centery-rangey))\r\n        t = [[self.f((1.0\/(2**scale)) * HyperbolicNumber(x,y), c)\\\r\n        for x in range(centerx-rangex, centerx+rangex)]\\\r\n        for y in range(centery-rangey, centery+rangey)]\r\n        matrix = numpy.matrix(t)\r\n        fig = plt.figure()\r\n        plt.imshow(matrix, interpolation='bilinear', cmap=cm.RdYlGn, origin='center')\r\n        print (\"Total: {} Cache hits: {} Cache hit ratio: {}\".format(totals, self.hits, (1.0 * self.hits)\/totals))\r\n        plt.show()<\/pre>\n<p>Let's try it out.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-linenumbers=\"false\">H = HyperbolicFractal()\r\nH.show(7, 0, 0, 200, 200, HyperbolicNumber(-20\/2**3, 0))\r\n\r\n<\/pre>\n<p><a href=\"http:\/\/konrad.burnik.org\/wordpress\/wp-content\/uploads\/2017\/08\/hyp_fractal_1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-347\" src=\"http:\/\/konrad.burnik.org\/wordpress\/wp-content\/uploads\/2017\/08\/hyp_fractal_1.png\" alt=\"\" width=\"267\" height=\"253\" \/><\/a><\/p>\n<p>And there you have it! We now have a tool to look into the hyperbolic number world.<\/p>\n<p>The full code for this implementation can be found on\u00a0<a href=\"https:\/\/github.com\/konradburnik\/HyperbolicNumbers\">Github<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<p>Copyright \u00a9 2017, Konrad Burnik<\/p>\n<div class='watch-action'><div class='watch-position align-left'><div class='action-like'><a class='lbg-style3 like-329 jlk' href='javascript:void(0)' data-task='like' data-post_id='329' data-nonce='b932f7ab63' rel='nofollow'><img class='wti-pixel' src='https:\/\/konrad.burnik.org\/wordpress\/wp-content\/plugins\/wti-like-post\/images\/pixel.gif' title='Like' \/><span class='lc-329 lc'>0<\/span><\/a><\/div><div class='action-unlike'><a class='unlbg-style3 unlike-329 jlk' href='javascript:void(0)' data-task='unlike' data-post_id='329' data-nonce='b932f7ab63' rel='nofollow'><img class='wti-pixel' src='https:\/\/konrad.burnik.org\/wordpress\/wp-content\/plugins\/wti-like-post\/images\/pixel.gif' title='Unlike' \/><span class='unlc-329 unlc'>0<\/span><\/a><\/div> <\/div> <div class='status-329 status align-left'><\/div><\/div><div class='wti-clear'><\/div>","protected":false},"excerpt":{"rendered":"<p>What happens when we change the identity defining the imaginary unit for the complex numbers to and enforcing i\u00a0different from 1?\u00a0 We get the somewhat less known numbers called\u00a0hyperbolic\u00a0or split-complex numbers. The most common thing about complex numbers that comes to mind are the nice pictures of fractals and there are plenty of tools already [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_mi_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"_s2mail":"yes","footnotes":""},"categories":[3],"tags":[],"class_list":["post-329","post","type-post","status-publish","format-standard","hentry","category-fractals"],"_links":{"self":[{"href":"https:\/\/konrad.burnik.org\/wordpress\/wp-json\/wp\/v2\/posts\/329","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/konrad.burnik.org\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/konrad.burnik.org\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/konrad.burnik.org\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/konrad.burnik.org\/wordpress\/wp-json\/wp\/v2\/comments?post=329"}],"version-history":[{"count":91,"href":"https:\/\/konrad.burnik.org\/wordpress\/wp-json\/wp\/v2\/posts\/329\/revisions"}],"predecessor-version":[{"id":725,"href":"https:\/\/konrad.burnik.org\/wordpress\/wp-json\/wp\/v2\/posts\/329\/revisions\/725"}],"wp:attachment":[{"href":"https:\/\/konrad.burnik.org\/wordpress\/wp-json\/wp\/v2\/media?parent=329"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/konrad.burnik.org\/wordpress\/wp-json\/wp\/v2\/categories?post=329"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/konrad.burnik.org\/wordpress\/wp-json\/wp\/v2\/tags?post=329"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}