Tag: Technology

  • Playing With The Mandelbrot Set

    Playing With The Mandelbrot Set

    Prologue

    I have been fascinated with fractals ever since I was little. My first experience with them was at the Renaissance Fair where a vendor was selling prints of his artist renditions of fractals.

    I have been thinking that I kind of want one of those prints now, but since I am extra I wanted to do it myself. After all a little math isn’t that scary.

    The Math

    Iteration

    The first thing to understand is iteration. Imagine you have a sequence of numbers, where each number depends on the number that came before it, that’s the idea.

    Lets imagine our function takes two inputs, n which describes the “nth” place and a constant c. Our function would return it’s previous state squared plus the constant.

    f(n+1) = n^2 + c

    For a c of 1 you would get: 0, 1, 2, 5, 26… a sequence that continues to infinity.
    For a c of -1 you would get: 0, −1, 0, −1, 0… a sequence that does not continue to infinity.

    Exit Conditions

    I won’t pretend to know the math behind it, but we know that if a sequence ever reaches the absolute value of 2 then it will continue to infinity forever.

    Lets use this criteria to define a new function. This new function will take a constant c and return the length of the sequence of numbers that stays below 2. Since this could repeat forever, lets define a maximum number of iterations.

    The Code

    There are many iterations (heh) of the code. But lets start with what we have covered so far:

    // Define a sequence given a starting constant
    function sequence($constant)
    {
        $next = $constant;
        while (true) {
            yield $next;
            $next = $next**2 + $constant;
        }
    }
    
    // Count the iterations in a given sequence
    function iterations()
    {
        foreach (sequence() as $nth => $value) {
            if ($nth > MAX_ITERATIONS) {
                break;
            }
            if ($value >= 2) {
                return $nth;
            }
        }
    
        return 0;
    }

    It’s Never That Easy

    We are not working with your regular numbers here. We are working with complex numbers. A complex number is a number that has both a real and an imaginary component. For example, 1+2i is a complex number.

    So let’s rewrite our function to take complex numbers instead. To accomplish this I am using the markbaker/complex-functions library.

    function sequenceWithComplexNumbers($real, $imaginary) {
        $next = $test = new Complex\Complex($real, $imaginary);
        while (true) {
            yield $next;
            $next = $next->pow(2)->add($test);
        }
    }
    
    function countIterationsOfSequence($sequence) {
        foreach ($sequence as $nth => $value) {
            if ($nth >= MAX_ITERATIONS) {
                break;
            }
            if ($value->getReal() >= 2 || $value->getImaginary() >= 2) {
                return $nth;
            }
        }
    
        return 0;
    }

    Let’s Use OOP

    We are starting to work with enough code that encapsulating it into a class is starting to make sense. Let’s create a class that takes an input real and imaginary number, as well as a maximum number of iterations for the sequence. This class should represent both the sequence of numbers and the iteration count of the sequence. This isn’t the whole code but describes the interface:

    interface Mandelbrot
    {
        public function __construct(
            private float $real,
            private float $imaginary,
            private int $maxIterations,
        ) {}
    
        public function iterations(): int;
    
        public function sequence(): Generator;
    }

    Generating The Image

    Since we are working with complex numbers we can fill in the complex number plane. We can say that the X axis is the real component, and the Y axis is the imaginary component. For each X and Y, we:

    1. Create a Mandelbrot class instance for the given coordinate.
    2. Generate the sequence given our positions complex c constant.
    3. Count the iterations in the sequence.
    4. Color the pixel in depending on the number of iterations.

    For point #4 there, that’s the only real challenging part. I am using 256 iterations, or counting up to 0xff in hex. We can convert the number to grayscale by converting the iteration count from decimal to hexadecimal, then concatenating itself three times. This gives us 0x000000 to 0xffffff to work with, which is the entire gray color spectrum.

    There may be a follow-up blog post about adding color, but for now lets stick with gray. Oh, and I am using the intervention/image library for generating images.

    $width = $input->getArgument('width');
    $height = $input->getArgument('height');
    $realStart = -2;
    $realEnd = 1;
    $imaginaryStart = -1;
    $imaginaryEnd = 1;
    $filename = $input->getArgument('filename');
    
    $canvas = ImageManagerStatic::canvas($width, $height, '#ffffff');
    
    foreach (range(0, $width) as $x) {
        foreach (range(0, $height) as $y) {
            $mandelbrot = new Mandelbrot(
                $realStart + ($x / $width) * ($realEnd - $realStart),
                $imaginaryStart + ($y / $height) * ($imaginaryEnd - $imaginaryStart),
                MAX_ITERATIONS,
            );
            $iterations = $mandelbrot->iterations();
            $color = $iterations > 0 ? dechex(MAX_ITERATIONS - $iterations) : "00";
            $colorCode = "#$color$color$color";
            $canvas->pixel($colorCode, $x, $y);
        }
    }
    
    $canvas->save($filename, 100, 'png');

    Wrapping Things Up

    The code presented here is just one iteration that got me to the end result. The actual code uses the symfony/console component to handle inputs and outputs for generating a customizable image. This isn’t my finest work yet, I may publish the full code someday.

    The featured image on this post is a 4k-resolution image of the set, generated by this code. It took an hour or two to generate. My real goal for the project was a print-quality poster version, which unfortunately is a little too large for distribution on a blog, but that took a few days to generate.

  • Refurbishing Old Switch

    Authors Note

    This post was abandoned in a pending state for a bit over a year. To be honest, since I was not successful I was a little disheartened from posting it. I changed my mind though, the post is worth publishing anyways, despite the failure. So here it is-

    You might have read in the datacenter diary that a switch was failing, it had a bad fan. Clearly the device had to go, but I had hopes of refurbishing it. If anything, its a test-run of doing more of this.

    Just out of curiosity I popped the lid open. The fans look like pretty standard 40mm fans. I can feel there is a ton of dust and gunk jamming one of the fans, so it’s definitely dead.

    Honestly its a lot smaller than I expected
    Looking at the fans model numbers

    It looks like these are readily available on AliExpress and eBay, so for $12 I grabbed a pair. They ship from mainland China so it took a week or five but it eventually arrived.

    Unfortunately, after powering the device back on there was a snap and a pop and a wisp of blue smoke. No activity on the fans and the console port won’t light up.

    It looks like this device is destined for the dumpster. They cant all be winners.

  • A Failing Switch

    Datacenter Diary #1

    Im starting off a new category on my blog, “Datacenter Diary.” It basically just chronicles my adventures in the “Server Canyon” (or other) realm.

    In this post I recount dealing with our first major hardware failure. Hardware failure happens all the time, but this was a single-point-of-failure device. Our main backbone switch.

    Network switch with a fan warning
    Fan light lit up but temp seems fine

    I’ll admit I might have been ignoring an ever-louder growing rattle for a few weeks, but when the warning light lit up it was time for action.

    I picked up a new (previously enjoyed and lovingly revitalized) switch from Unix Surplus. I have no special relationship with them, just a happy customer. I ended up with a fancy Dell/Force-10 S60-44T-AC-R. I picked this device because the Server Canyon network sees large bursts of traffic and this device has a pretty large packet buffer. Plus, it has two 10-gigabit ports that I will definitely take advantage of later.

    Force-10 glamor shot

    The first thing to do was copy the config from the old PowerConnect to the new Force10 switch. This turned out to be a little more difficult than expected since they were different product lines, but a switch is a switch and I got it sorted.

    Luckily, nearly every piece of server infrastructure has redundant uplinks. This means that I just needed to trunk the switches and start moving servers over. The management and client networks were only disrupted as long as it took to move the plugs over, but the storage network utilizes redundant links so no real downtime occured.

    Here you can see an in-progress picture of the migration:

    The process ended without much fuss, I only managed to miss tagging one VLAN.

    Next, a post-mortem on the old switch. That is a problem for another blog post though!