RSS

Apache Commons DecompositionSolvers

Apache Commons DecompositionSolvers

Jesus it’s been too long since I got back to this!

Anyway, right, the

DecompositionSolver

Intro / Why-I-Need-To-Worry-About-This

Linear algebra exists for a reason; namely, us. Suppose we’re attempting to find the coordinate values, which under a certain transform, become a specific value. Let’s keep it simple and call it:

 x + 2y + 3z = 1
2x + 4y + 3z = 2
4x           = 3

As I’m sure you can remember from grade school, you have the same number of equations as unknowns, so it is almost certainly solvable. We just subtract two of the first equation from the second, four of the first equation form the third, four of the second from the third, one of the second from the first, and a quarter of the third from the first. Then we maybe divide the third by eight and the second by three, and presto,

x = 3/4
y = 1/8
z = 0

Unfortunately, as programmers, we both know that this is much easier done in practice than in theory; and when you’re automating  a task, a working theory is the only thing that really counts.

So, those of you who have already taken linear algebra (quite possibly all of you) may be familiar with a much easier way of representing this problem:

┌1 2 3┐┌x┐   ┌1┐
│2 4 3││y│ = │2│
└4 0 0┘└z┘   └3┘

A decomposition basically solves this, through a sequence of steps on both sides that reduces the original matrix to an identity matrix, while having the right-hand matrix undergo the same operations. This is commonly written as an augmented matrix, like so:

┌1 2 3│1┐
│2 4 3│2│
└4 0 0│3┘

Matrix reduction is a heck of a lot more straightforward than the nonsense I spouted a few paragraphs back, though going into its details is a bit off topic here. Our final matrix, after the reduction, looks like this:

┌1 0 0│3/4┐
│0 1 0│1/8│
└0 0 1│ 0 ┘

How Do We Do This in Java?

Not just Java, actually; this is specifically about the Apache Commons Math3 decomposition solver interface.

One of the tricks with reduction is that there are a lot of different, equally effective, ways to go about it; and like any other algorithm, the efficiency depends, in large part, on the initial state of your matrix. My personal favorite is the LU Decomposition. (Or, if you prefer a link that isn’t a video, look here.)

First I recommend making a Maven project out of your Java project, presuming that it isn’t already fitting that form factor. Afterwards, open up pom.xml, and add this:

<dependencies>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-math3</artifactId>
        <version>3.5</version>
    </dependency>
</dependencies>

right after the close of the build tag. Your project is now pulling classes from across the internet, on Apache Commons Math3. Later on, you may want the version number to be a bit higher; for now I’m using version 3.5.

So, you’ll note that you have access to a host of new classes, all in some subpackage of org.apache.commons.math3. Import org.apache.commons.math3.linear.* into your class file.

We can solve the above problem by creating a RealMatrix of the initial matrix, potentially like so:

RealMatrix matrix = new Array2DRowRealMatrix(new double[][]{
    {1.0, 2.0, 3.0},
    {2.0, 4.0, 3.0},
    {4.0, 0.0, 0.0}
});

But don’t get me wrong, there are literally dozens of ways to create a RealMatrix.

Next, create a RealVector, describing the other side of the equation, perhaps like so:

RealVector vector = new ArrayRealVector(new double[]{
    1.0,
    2.0,
    3.0
});

We now have a matrix and vector representation of the two sides of our equation.

Working with RealMatrix and RealVector

If you’re an experienced programmer, you probably expect some kind of Command Pattern to show up next. It’s certainly what I would do, if I needed to duplicated the exact operations in the exact order on more than one piece of base data. Fortunately, something like it has already been implemented by Apache.

If you look up the Apache Commons Math3 javadocs, you’ll notice that while RealMatrix has a lot of handy operations, they generally just involve polling for data, not actually operating on it. Commons has made the wise move to encapsulate operations in their own classes, rather than just their own methods. There are many dozen other classes, such as MatrixUtils (remember that one!), which both generate and operate on RealMatrix and RealVector classes.

In this instance, turn to DecompositionSolver. It’s meant for tasks just like our own, and there are many subclasses. As I said, my preference is LUDecomposition, but that is only capable of handling square matrices. Since our matrix is square, that’s fine; in other cases when your matrix doesn’t fit the profile, look through EigenDecomposition, SingularValueDecomposition, or some other utility.

For LUDecomposition, we’ll want to do something like this:

DecompositionSolver solver = new LUDecomposition(matrix).getSolver();

The work has been done, as one initialization, LUDecomposition doesn’t just store the matrix as a property; it determines from it the exact sequence of operations necessary to turn it into an identity matrix.

Once you have your solver, you can get your final right-hand vector via:

solver.solve(vector);

which will provide you with:

┌3/4┐
│1/8│
└ 0 ┘

Final Source Code

Here’s a working example of how such a program might work.

 package oberlin.math3;

import java.io.*;
import java.util.*;

import org.apache.commons.math3.linear.*;

public class MatrixReducer {
    
    public static void main(String...args) {
        new MatrixReducer();
    }
    
    public MatrixReducer() {
        try(BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
                Scanner scanner = new Scanner(System.in)) {
            writer.write("\nEnter first row of three numbers: ");
            writer.flush();
            
            RealVector vector1 = new ArrayRealVector(new double[]{scanner.nextDouble(), scanner.nextDouble(), scanner.nextDouble()});
            
            writer.write("\nEnter second row of three numbers: ");
            writer.flush();
            
            RealVector vector2 = new ArrayRealVector(new double[]{scanner.nextDouble(), scanner.nextDouble(), scanner.nextDouble()});

            writer.write("\nEnter third row of three numbers: ");
            writer.flush();
            
            RealVector vector3 = new ArrayRealVector(new double[]{scanner.nextDouble(), scanner.nextDouble(), scanner.nextDouble()});
            
            
            //create matrix
            RealMatrix matrix = MatrixUtils.createRealIdentityMatrix(3);
            matrix.setRowVector(0, vector1);
            matrix.setRowVector(1, vector2);
            matrix.setRowVector(2, vector3);
            
            //get other side
            writer.write("\nEnter vector on right side (3 entries):");
            writer.flush();
            
            RealVector vector = new ArrayRealVector(new double[]{scanner.nextDouble(), scanner.nextDouble(), scanner.nextDouble()});
            
            
            writer.write("Solving...");
            writer.flush();
            
            DecompositionSolver solver = new LUDecomposition(matrix).getSolver();
            matrix = solver.solve(matrix);
            vector = solver.solve(vector);
            
            writer.write("Solution: \n");
            writer.flush();
            
            writer.write("┌" + matrix.getEntry(0, 0) + " " + matrix.getEntry(0, 1) + " "
                    + matrix.getEntry(0, 2) + "┐┌x┐   ┌" + Double.toString(vector.getEntry(0)) + "┐\n");
            writer.write("│" + matrix.getEntry(1, 0) + " " + matrix.getEntry(1, 1) + " "
                    + matrix.getEntry(1, 2) + "││y│ = │" + Double.toString(vector.getEntry(1)) + "│\n");
            writer.write("└" + matrix.getEntry(2, 0) + " " + matrix.getEntry(2, 1) + " "
                    + matrix.getEntry(2, 2) + "┘└z┘   └" + Double.toString(vector.getEntry(2)) + "┘\n");
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Advertisements
 
Leave a comment

Posted by on June 30, 2015 in Java, Programming

 

Tags: , , , , , , , , , ,

Famous Works of Art Improved by Cats

Flavorwire

If there’s any one thing that could improve a Botticelli painting, what would it be? Well, a big furry cat, of course! Okay, so obviously we’re not serious, but that doesn’t make this series of cat-augemnted artworks, which we first heard about over at It’s Nice That, any less hilarious. Over at Great Artists’ Mews, Zarathustra the cat wants to get the record straight — Mona Lisa was only smiling like that because she had a fat tabby squirming in her arms. The site comes with this very cat-like disclaimer: “We are real. All the artworks at this site are real. Nobody’s opinion about Us, Our art or this site will ever disturb Our suprematism.” Fair enough. Click through to see some of our favorites, and if you’re not all kittied out, head over to Great Artists’ Mews for even more cat-infiltrated art.

View original post 58 more words

 
Leave a comment

Posted by on April 5, 2015 in Uncategorized

 

Nothing’s Scarier than Imminent Success.

It’s been an interesting few weeks, but then, it’s also been an interesting few months. On the other hand, I could probably continue that line of thought, until the time span was so broad there was nothing left to hold it relative to.

The last few years have been very rough, but also fortuitous. I actually got my degree in Physics and Neuroscience, with the idea that I would someday work in neuroprosthetics. (Note to misguided Grammar Nazis: the subjects are capitalized as proper nouns when they are also unique department names. You’re welcome.) Unfortunately I also graduated in 2006, the beginning of a very dark time, and have yet to hold a physics job of any kind. The closest I’ve gotten to neuroscience was a brief stint as a substitute teacher for some elementary school special needs classes.

I basically jumped, for lack of any option, right back into programming when I got out. This isn’t to say that I haven’t had quite a few jobs that were once thought to be meant for teenagers along the way. At least five pharmacies, a hardware store, a few groceries. I am in the woeful state of having a mother who has a complete detachment from the workforce that I am confronted with; a father who really helps but has limited understanding of how one gets published today, and the limitations placed on the amount of money that I can actually make; and a brother who is nought but treacherous.

To give you an idea of what I mean by “treacherous”, I worked for him for eight months after he begged me for help on a cloud computing company that he wanted to put together, deferring applying to grad school. My sister and mother had already taken the hint and ceased contact with him, I naïvely thought that perhaps I could reunite my family through further contact and arbitration. He provided a long list of people who were supposedly behind him on it. In eight months, I could get direct contact with none of those people. Additionally, I discovered that his software patent was entirely fabricated. At the end of those eight months, he “terminated” me, I never saw a dime of the promised pay.

I quietly took note of the extent of his evil, hung up the phone, and disowned him. In the mean time, I took the GREs and got within the uncertainty limit of a perfect score on the math section. I applied to MIT, and had everything going for me, until I discovered that during that time, during my work for this play-house company, along with a not-yet-mentioned struggle with neuropathy from a medication I was on, my debt with my student loans reached a critical point. I had defaulted. My school would no longer provide transcripts. The days got even darker.

Every darkness does have its dawn, if you’re willing to work and wait long enough. I hooked up with the wonderful Sparo Vigil, here in New Mexico, and grabbed a part time job working for Home Depot. It wasn’t a high point of my life, but it made me enough to get along, and even pay back a small part of my student loans. I continued to program, working for myself, and established a sequence of frameworks to make the job easier. My cumulative experience in education and software led me to game development, and my training in the scientific method showed me a path to creating an ideal environment, and sequence of products built in that environment, with a legitimate positive change brought about in the world.

This framework is together; it works beautifully. Today, I’m going to use it for the first time, and create a finished (if not market-worthy) product. It will lift me out of the bog that I am in. I have to admit, that’s a little frightening.

If things had continued to be low, and dirty, and hard, then at least I would have a response for it. I would have a plan for how to move forward, to keep my head above the water. My ideals have been set much higher than that, though. I left the Home Depot job some time ago, maybe a year; I have Sparo to thank for keeping me afloat while I worked on the framework and my writing. Things are about to be much better, and I’m not sure how to take that.

It’s not that every little detail is finished, it’s that I’m at version 1.0. I have a system by which I can rapidly go from idea to product, possibly in an afternoon (though early on, I imagine the exception will be the rule). The rest is going to be an extensive amount of linear algebra and differential geometry, digital signal processing techniques and their implementation, modernizing of my design patterns, and writing a bridge to the Steamworks API. After that, publishing, and marketing. Later on, probably expansion of the framework interface into other languages, like Python, Ruby, and Scala. I’m looking forward to all of these things.

I’m looking forward.

I had almost forgotten how thrilling that can be.

 
Leave a comment

Posted by on March 30, 2015 in State of the Moment

 

Tags: , , ,

20 Python libraries you can’t live without

Python Tips

Hi there fellas. Today i am going to list 20 python libraries which have been a part of my toolbelt and should be a part of yours as well. So here they are

View original post 538 more words

 
Leave a comment

Posted by on March 21, 2015 in Uncategorized

 

The NIO.2 Watcher

So, I’ve been working on a side project involving the Builder tutorial. It roughly (not entirely, but roughly) works out as a machine-operated interpreter, that is, code altered by machine before being translated. After that it does something even more awesome, but it’s only capable of triggering the compilation, after alteration, through a utility that isn’t as well known as it should be.

The Watcher Utility

As of Java 7, we got the NIO.2 classes. These included Path (which most of you are probably familiar with), Files, FileSystem, asynchronous channels, and a host of other goodies. One of them was the Watch Service API.

What Watch ultimately amounts to is a device that can trigger an event any time an arbitrary subset of data is altered in some way. The easiest possible example is monitoring a directory for changes, but this is, gloriously, not exclusive. In classic Java nomenclature, one might think of it as a sort of PathEventListener, in a way; but it’s capable of a bit more than that particular name implies. It doesn’t have to be associated with Paths, and unlike most listeners, it’s less about monitoring for user-generated interrupts, and more about monitoring for system-wide circumstances, including secondary effects.

Using a Watcher

Watchers keep internal collections of keys, each one associated with a source object. This registration is typically located on the source object, at least directly. The best, and most correct, way to do this is through direct implementation of the Watchable interface. Many JDK classes, such as Path, already implement this. Once implemented, you would use the method:

Watchable.register(WatchService watchService, Kind<?>...events)

This method registers all events, of the specified types, on the provided WatchService object. Every time one of them occurs, the key is flagged as signaled, and in its own time the WatchService will retrieve the data from that key and operate.

Note that a Path can be many things. It could be a path to a directory on your machine, which is of program concern. It could be a path to a printer tray, or a server, or even a kitchen appliance (think polling the status of an automated espresso machine). In this example, I will be showing a manner in which a directory path can register to be watched for alterations.

WatchEvent.Kind interface

This can be thought of, for old school Java programmers, as the class type of a Watch event. Most of the frequently used keys are in java.nio.file.StandardWatchEventKinds, but as an interface, it is fully customizable. They only require two methods to be overridden, that is, WatchEvent.Kind.name(), which simply returns a String value representing the type of event; and WatchEvent.Kind.type(), which returns a Class that describes the location context of the event.

WatchEvent.Kind.type() may return null, and it won’t break anything; but after getting a feel for the results of StandardWatchEventKinds, you might consider implementing it. As an example, for ENTRY_CREATE, ENTRY_MODIFY, and ENTRY_DELETE, the context is a relative path between the Path being watched, and the item that has changed. (Knowing that a random item was deleted is of little if any use, without knowing which one.)

Implementing a WatchService

Most of the WatchServices you are likely to use are stock in the JDK. I’m going to start with one of them; in a later blog, I’ll probably create one from scratch, but it really is better to start simple.

For the common case of monitoring a directory, FileSystem.newWatchService() covers everything you need. It is important to get a watcher for the correct type of FileSystem, though; as many of you know, Java is capable, as of version 7, of taking advantage of the numerous file system-specific capabilities. The safest way to do it is through:

WatchService watcher = FileSystem.getDefault().newWatchService();

But there may be many points in which you intend to grab a watcher from a file system of a specific, or even custom, type. This is fine, but be aware of the extra layer of debugging.

Afterward, each path can be registered with the watch service through its Path.register(…) method. Be certain to include every variety of WatchEvent.Kind that you want to watch for. It may be tempting to simply register for every single standard type every time, but I encourage you, as a matter of practice, to consider whether you’re really concerned about each Kind before including it. They do, technically, cost a small amount of system resources; and while it may not be noticeable for small projects, when you’re dealing with massive file hierarchies it can become a concern.

When polling for changes, it is mildly more complicated than it is with Listeners. The watcher must be polled for WatchKey objects. WatchKeys are generated when a watched alteration occurs. They all have a state, which is continuously either ready, meaning the associated Watchable is valid but without events; signaled, meaning that at least one event has occurred and been registered with this WatchKey; and invalid, meaning that it is no longer sensible to consider the associated Watchable a candidate for events.

There’s more than one way to get the next signaled WatchKey, but one of the most efficient methods is WatchService.take(). This will always return a signaled WatchKey. It is a blocking method, so use it with that in mind; if no WatchKeys are yet signaled, it will wait until one is before returning.

Once you have a WatchKey, a secondary loop examines every sequential change that has occurred. (If you’re curious, if a WatchEvent occurs for a WatchKey that is already signaled, it is added to the stack and no other alterations are made; if it occurs while the WatchKey is ready, it initiates the stack and WatchKey is flipped to signaled). This is done via WatchKey.pollEvents(). For each event, you may examine the WatchEvent, and act on it accordingly.

After all is said and done, and the WatchKey has zero events left to parse, call WatchKey.reset(). This attempts to flip the WatchKey back to the ready state; if it fails (if the key is now invalid), the method returns false. This might signal, as an example, that the watched path no longer exists.

Example

Any WachService manager must be running continuously. The antipattern approach is to simply use a while-true block; but in general, it is less hazardous to make it its own thread.

import java.io.IOException;
import java.nio.*;
import java.nio.file.*;
import java.nio.file.WatchEvent.Kind;

public class DirectoryWatcher implements Runnable {
    
    private WatchService watcher;
    private volatile boolean isRunning = false;
    
    public DirectoryWatcher() throws IOException {
        watcher = FileSystems.getDefault().newWatchService();
    }
    
    /**
     * Begins watching provided path for changes.
     * 
     * @param path
     * @throws IOException 
     */
    public void register(Path path) throws IOException {
        //register the provided path with the watch service
        path.register(watcher,    StandardWatchEventKinds.ENTRY_CREATE,
                                StandardWatchEventKinds.ENTRY_MODIFY,
                                StandardWatchEventKinds.ENTRY_DELETE);
    }

    @Override
    public void run() {
        isRunning = true;
        
        while(isRunning) {
            //retrieve the next WatchKey
            try {
                WatchKey key = watcher.take();
                
                key.pollEvents().stream().forEach(event -> {
                    final Kind<?> kind = event.kind();
                    
                    if(kind != StandardWatchEventKinds.OVERFLOW) {
                        final Path path = ((WatchEvent<Path>)event).context();
                        System.out.println(kind + " event occurred on '" + path + "'");
                    }
                });
                
                if(!key.reset()) {
                    //the key should be valid now; but if it is not,
                    //then the directory was likely deleted.
                    break;
                }
                    
            } catch (InterruptedException e) {
                continue;
            }
            
            Thread.yield();
        }
    }
    
    public void stop() {
        this.isRunning = false;
    }
}

Simple enough, yes?

The register(…) method may be a little redundant; however, the run() method is where the meat is. WatchKeys are retrieved with WatchService.take(); afterward, in a parallel stream, each WatchEvent associated with that key is looped through. (When an event is of type OVERFLOW, it usually means that data on the event has been lost; not optimal, but the best course of action here is to continue to the next key.)

In this instance, the event is simply reported to the terminal, but this lambda expression is where you would take arbitrary actions according to the event. It is also possible to use an external iteration to do this, if you need to change values or perform another non-lambda-kosher action.

After all events have been iterated through, WatchKey.reset() is called, and checked. In the event that it returns false, something has happened to our directory, and the thread has become a potential resource leak; so it is shut down automatically. Otherwise, the thread then yields to other threads, and repeats itself.

Here’s a small Main class that I’ve built to use this. A single path parameter will be the directory to monitor; or it will simply watch for $HOME/watchtest.

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

public class Main {

    public static void main(String[] args) throws IOException {
        final String location = (args.length > 0) ? args[1] : 
            System.getProperty("user.home") + "/watchtest";
        
        final Path path = Paths.get(location);
        DirectoryWatcher watcher = new DirectoryWatcher();
        watcher.register(path);
        (new Thread(watcher)).start();
        
        //wait a set amount of time, then stop the program
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            //continue
        }
        watcher.stop();
    }

}

Try running it, and making a few changes to your select directory. See what it does.

And That’s It!

The next real question is how to create your own WatchService; which is totally doable. Generally, though, it isn’t necessary. The next time I come back to this subject, I’ll be going over that, possibly starting with WatchKey.Kinds. First, though, I need to get back to the project that I started this for, and I need to continue the Build Tool tutorial, so it might be a bit.

Good coding!

 
Leave a comment

Posted by on March 11, 2015 in Java, NIO.2, Programming

 

Tags: , , , , , , , , , , , , , , , , ,

So What the Hell Happened!?

Jesus Christ I need to get back to this blog.

Okay, long, in-depth story which will hopefully be funnier to read than it was to live through. Happy ending, I promise.

My wonderful lover has opted to buy us both new computers; starting with barebones kits. That’s not as a big a deal to a physicist, and possibly also witch apparently. I just upgraded from something that ran well because I oiled it and cleaned it every single day (metaphorically) to something that would probably run well if I poured orange juice on it. However, first there was its construction.

Usually, I deal with latent static charge by simply contacting the metal chassis and grounding myself. In this case, given the exposure time, it seemed wise to go ahead and get one of the anti-static grounding straps for my wrist.

As a man who has built several complete devices transistor by transistor, including my share of audio equipment, this didn’t feel like it would be a big deal. The only issue with building a computer is that you have to subject yourself to the whims of the hardware designers, and operating system designers, when those whims may have nothing to do with what you’re accustomed to and, occasionally, don’t even make any sense. It went more like this. I’ll be brief.

1. Find metal hex nuts for case, install them. Line up motherboard, attach screws. Notice that you didn’t line it up right, and it isn’t grounded. Remove screws. Remove and move hex nuts. Line up properly. Attach screws. Notice that you once again have it out of alignment, detach screws, board, and nuts. Line everything up, double check each of the available screw holes. Screw it in, one by one. Properly attach motherboard, except for the fact that you were supposed to do the backplate first. Ignore freaking backplate.

2. Line up the processor properly, check. Double check that you’ve lined up the processor properly, check. Ease processor into socket. Notice that it went in a lot easier than last time, and pray to the computer building gods (who would that be? Brigid?) that you didn’t just break anything. Seal processor down with lever. Struggle to attach cooling unit. Struggle more. Attach argumentative cooling unit.

2 ½. Look around, try and find the fan plug. Not find the fan plug. Find something that looks like it might do the job, even though it has an extra pin. Connect. Double check that that actually makes any sense. Does make sense, great. Pop in memory. Attach faceplate cables. Completely overlook the faceplate fan.

3. Attach power supply to case. Attach power cables to motherboard, one by one. Wrap a motherload of electrical tape around the non-modular power supply’s dangling cables. Keep graphics card on standby. Spend an hour trying to figure out where the SSD is even supposed to go in this tower case. Finally find out, on account of girlfriend’s keen eye, install it. Notice that you just installed it backwards. Slide it out, install it again. Pop SATA 3 cables on.

~4. Plug in keyboard, mouse, monitor, turn it on, get to BIOS. Pat self on back. Select “optimize”, because what harm could that do? (Hint: Quite a bit, as it turns out.) On a whim, select option to search for hidden processor cores. Save changes. Restart. Notice that nothing is happening, save for the blue LED lamp, and you can’t even get to BIOS.

4. Punch self in kidney.

Well, to be fair, I slid my Hitachi 2TB from my old computer in at that point too. I knew I could boot. This mistake was actually made after I went back into BIOS settings, just to ensure that everything was in order, without doing nearly enough research.

3 again. Take deep, deep breath. Count to ten. Look up BIOS, try and find reset jumper; fail. With girlfriend’s assistance, because you know they don’t make them to come out easy, remove all power cables and pop the CMOS battery out. Push power button for thirty full seconds, drain all capacitors completely. Pop battery back in. (This is what you do when you can’t even find the jumper; it’s just as effective. Just don’t do it without good cause.) Pray to Morrigan, Celtic goddess of battle and change, for wisdom. Turn computer on, notice that it’s nice and alive again.

4. Never, ever, ever do that again.

At this point I could boot to my 2 TB easily enough. Unfortunately, while Ubuntu immediately noticed all the awesome new hardware, thanked me for it in its own Unixy way, and went to town like a child at a ball pit; Windows did something quite different. Windows is keyed not to users, but to motherboards. When it noticed that it was on the wrong motherboard, it immediately assumed that it was pirated, and rather than presenting me with some eloquent message about how I’m a pirate asshole (which I am not) and refusing to run, it flashed a blue screen covered in gibberish UTF-8,  and restarted, before I ever got to the desktop.

As it turns out, this OEM software was licensed entirely to my last machine. I did not realize that, but I was thoroughly pissed off at the underhandedness of a deal like that. In any case, whilst there may be a way to confuse Windows into thinking it’s on the same machine; I am not a pirate, and I needed to get a non-preinstalled copy of Windows 7. That cost us about a third of what the machines did.

(For those who are curious, I did find the secondary fan socket and plug in the faceplate fan later.)

Once it arrived, I plugged it onto the 120 GB SATA 3 SSD. It took quite a while to install, I unplugged every other drive first just to be safe, and afterward, I could successfully boot to WIndows 7. (I refuse to buy Windows 8.) The problem was, now I couldn’t get back over to Linux, where all of my work was. GRUB would not load. It hadn’t changed, but the system wouldn’t see it.

Next up, I tried boot-repair, but it kept telling me, even when running on its own LiveUSB, that I was running a program like Synaptic in the background. That could not make less sense. So, I cut out an even slice at the end of the SSD, of about 17 GB, and popped a new root partition of Ubuntu on there. The install worked flawlessly; but the machine still couldn’t see it.

So, I spent quite a while bouncing from forum to forum, trying to figure out why my BIOS was not detecting GRUB. I reinstalled it on the HDD to be safe, and removed my SSD partition. (Ubuntu installs in maybe twenty minutes anyway.) Eventually, I discovered that the culprit might be this Infinity 2.2 TB feature, a feature that allows you to boot from drives that are larger than 2.2 TB. That’s a progressive feature, but I don’t actually own one of those and I’m not likely to pick a 4 TB up any time soon. When I disabled it, GRUB popped up.

However, GRUB couldn’t find Windows. Minor loss as an engineer, but I will ultimately need it for unit-testing and I have a lot of games written exclusively for Windows that I would like to play. I found myself at an impasse; GRUB didn’t see Windows, and Infinity only saw Windows. I would still like it if I could find a way to get GRUB to recognize Windows; but I messed with the partition flags a bit when I was trying to get SSD GRUB to boot and I imagine that the problem might be there.

So, at this point, on the occasion that I do want Windows, I simply hit F11 on boot, select 2.2 TB Infinity as my boot device, punch a key to select a disk, and pick the SSD. The funny thing is, even after that, and even with Windows on the SATA 3 SSD, Ubuntu still boots faster; off of a SATA 2, mind you.

So, I’m back in business. I haven’t forgotten about the builder tutorial at all, but I have been lightly sidetracked with another project involving easing the interface between Java and GLSL. (The builder so far has, in fact, been quite useful for that.) I’ve also noticed a number of chunks in my builder tutorial that could be optimized by migrating them fully to NIO/NIO-2; as there aren’t any old java.io packages holding me back. (NIO is blisteringly faster.)

Add constructing the other machine afterward and you can seen why I’ve been away. I have suspended nothing on this blog, and it’s good to be back to it. We’re just about to get to the fun part in the builder tutorial, and I’m looking forward to it. (Especially on this beast.)

 
Leave a comment

Posted by on February 23, 2015 in Programming, State of the Moment

 

Tags: , , , , , , , , ,

Bionics, Biological Self-Checks, and How I Just Lost my Right Nipple Ring.

Soooooooo.

Yeah, I didn’t literally lose it. It migrated to the surface over the course of more than a year. I was attempting to remove it, thinking that it needed to be re-set, and while attempting to remove the bead it just popped off.

Seriously, straight through the flesh. I didn’t feel a thing physically, so I’m presuming that there was nothing but a little cutaneous tissue holding it on. However, there was this profound moment of loss. I put up a blog post on piercing art before, and since have gotten six pieces; two in my right ear, two in my left (nonsymmetric), and two nipple rings.

I remember people fretting about male body art in the east, in my notoriously old-South family, but honestly I am much more concerned about losing it than I ever was about getting it. We think of these things as something permanent. We think of them as a lasting part of us. However, the truth is that tattoos bleach over time, scarification can (somewhat) fade over over an extended period, and believe me, the body is very good at differentiating between what does belong to it, and what does not, so every piercing you get, given enough time, will find its way out.

Some are better behaved than others.

I remember back in the day, when neuroprosthetics wasn’t a real thing, and we referred to it by the comic-book names of bionics and cybernetics, there was a lasting belief that the metal could simply be sealed to the body somehow. The thought was, incorrectly, that stopping the bleeding would convince the body that the wound was closed. Unfortunately, that isn’t the case; if you breach the skin, the immune system will know about it, and may complain vividly until the gap is closed.

This was eventually worked around by integrating the skin as part of the treatment. Modern artificial cochlea are actually two-piece components; one of them is subdermal (beneath the skin), the other superdermal. The superdermal part is the part that you can actually interact with; it requires a power source, it can be tuned and calibrated, and it can be removed. In operation, it communicates with the subdermal part via a focused magnetic field, which passes through the skin with little interference. The subdermal component is the one responsible for communicating this signal to the auditory nerves.

You know what happens when you try and merge the super- and sub- components into one? You get a nasty infection and potentially further damage.

For bionic limbs, the winning method (as of yet) is to receive signals sent to the stumps that correspond with attempted actions with the missing limb, interpret them with an on-board neural network, and feed the proper message to the twenty two or more motors in the limb. It is fantastically effective, and even allows for feedback to the brain. No breach necessary.

So how does the body know that the wound is open? Our dermis is a little more complicated than a paper bag. Describing the entire immune response requires more patience than I have as a writer, or you have as an off-brand reader who might have been expecting something more akin to modular human designs (which it is not). However, the breach of the skin releases compounds called cytokines, which act as messengers to the rest of the body and trigger a full-fledged assault. Unlike well-designed software, the body was formed on the crucible of natural selection, and often has many functional systems partially manifest in a single physical one.

So, the next obvious question. If hole-in-the-chassis bionics and cybernetics don’t work, and my right nipple ring was removed as a foreign invader, why hasn’t my left moved? There are more factors, I’m certain, than I specifically know of. However, deeper piercings, particularly those with a hole on both sides of the flesh, have slower rejection rates. (Note that I did not say “no rejection rate”; but slow enough to approximate to permanence.) Additional issues can include secondary local inflammation; which you may think of as the immune system going into five-alarm mode and accepting greater degrees of loss. This includes infections (which have their own problems, keep it clean!), irritation from over-cleaning (which also has its problems), and metal sensitivities. Using something biocompatible is generally a good idea, even if you have no known metal sensitivities. Last but not least is weight; heavier jewellery migrates on account of gravity alone.

Cytokines are one of the first-phases of what you may think of as an organic observer pattern. Think of the various immune-related tissues as observers; and compounds like cytokines, chemokins, and elastin proteins, are messages to them. “Ah,” you say, “now you’re speaking my language!” Sort of. Is it possible to prevent this by suppressing the messages? Sure, if you don’t mind developing oozing sores from a repressed immune system. As for me, I will simply be having Phil give it a thorough autoclaving and punch it back in there, perhaps further down.

 
Leave a comment

Posted by on January 30, 2015 in Body Art

 

Tags: , , , , , , , , ,