Linear equation solver

Previously I wrote something about solvers here, so I felt like I should do something more. Making some test calculations myself, I have seen that solving linear equations on a computer can be so fast, that it practically happens in real time, even with systems that have large numbers of unknown variables. This has inspired me to create a small interface to show how this works. Unfortunately, it requires a special library, which is missing in most hosting plans. This means that showing a demo is practically impossible, but at least I can show a couple of screenshots here.

A system of linear equations has a number of unknown variables. In its simplest form it has two equations, both of the form ax + by = c, with x and y being the unknowns and a, b and c being any positive or negative numbers. To find x and y, we have learned in school that we can take x from the first equation (as a function of y) and substitute this value where x appears in the second equation. But doing this manually can be slow and error-prone.

Here we signal that we want to know the number of unknown variables, before we attempt to solve any equations. This is important, because we need to ensure that the number of equations is equal to them. Whenever this value is changed, we have to update all equations so that they still remain solvable. This means that any previously entered numbers would be meaningless in the new context, so they are removed as well. If we have just two equations, we need to fill a, b and c for each of them, which means that we need to show six input fields to the user (hence n(n+1)). Here we don’t present anything more than the user would need. Seen from a UI perspective, having the wrong number of equations is worse than having no equations at all. This blank screen highlights the idea that we can “progressively enhance” the interface as we become more informed of the user’s requirements. The screen area will be filled vertically as the user moves through the steps in the system. This allows new content additions to appear instantly without recalculating the layout.

Not good. Any characters, floating point numbers and numbers less or equal zero should be rejected here. By drawing a sudden line we say to the user: “You either play by the rules, or you may not continue.” The screen will stay blank and we minimize the number of possible places for interaction in the presence of an error. Because there aren’t many choices in this case, the interface itself starts to become suggesting. But as it is limiting too, this won’t be appropriate for sites that have to present important content.

Here is what happens when we type 1, 2 and 3 in succession:

Each time the system of linear equations changes and more unknown variables appear. The number of lower-case letters can be exceeded quite soon if we are uncautios and enter a very large number. Problematic is that the number of input fields grows fast and at a certain point filling all of them will become a serious usability problem. But we may not always need to fill all availble factors as the data about them will be hard to obtain. From an observation that most unknown variables may not participate in every equation, we can assume that as long as the user doesn’t enter a value, it is zero. Filling only the factors we have instead of all possible ones can ease a bit of the usability problems we have. The problem is that all fields need to be presented, because we don’t know in advance which ones the user may choose to fill.

Once we enter some values and press the arrow key to proceed, we can see that there is no solution available. Both equations are the same; they are not truly independent and substracting the first from the second would cancel it.

Math is fun has an example of a linear system of equations with three unknown variables and a result, which is said to be a = 5, b = 3, c = -2 (there they are x, y and z respectively). We can try the factor values as seen in their matrix and see if we get the same solution.

This seems correct and marks the last “step” in our calculation. If we press the arrow below the equations again, the result is just replaced with the same one. (When I think about it now, an improvement would be to not calculate it at all if no factors were changed.) If we change a single value and press the button again, we get a different result while most of our numbers are still preserved. This is nice if we want to test/try out some slight modifications. Again, we update only the screen area in green.

If we go back and enter a new number of unknowns both the existing system and its result are deleted. A new system appears with new factors to enter.

Each step in our result generation was immediate as JavaScript was injecting new content behind the scenes at lightning speed. But if we think that our prototype should work without JS too, we would need to find a way to extract all values that were dynamically entered by the user. This may not be possible, but we can at least make sure that the equations can still be updated.

If we increase the number of unknowns (in this case 16), we can fill an entire screen with data. This step is still instantaneous. Up to having around 80 unknowns, the generation of the inputs fields is remarkably fast even on a slow, single-core CPU. (I have also tested with 150, but this starts to take something like 4 seconds.) That number of unknown variables makes our lettering scheme obsolete. The question is, from a design perspective, why do we need to show all variables on the screen when they add so much noise? I would say for the reasons of context. If we remove all characters and arithmetic signs, it is no longer obvious what we are trying to do or that we are solving equations at all. I have seen all input fields presented in a table, but then it’s hard to know which factor exactly you are entering, since they all look the same. Closely relating the factors to their respective unknown variables, at the place where the user is currently looking allows us to eliminate many of the questions that may arise during use. The eye now doesn’t need to move constantly up and down to see to which of the unknown variables a factor of interest relates.

How can we test then if a system with so many variables works as expected? Our initial thought might be to write a script that automatically fills all available input fields with random numbers. Unfortunately, I wasn’t able to do this in plain JavaScript and some people wrote that this isn’t possible for security reasons. (Imagine how easy it would be for spammers to populate the contact forms on your website, for example.) I haven’t tried to do this with specialized tools (Selenium maybe?). What I tried is to fill some of the input fields and see whether this will output any result. This is much faster than trying to learn another library.

It works and again this appears almost immediately after the button is pressed. (Note that there are many zero values behind the scenes that are sent too.) Here I have rounded the numbers to five places after the comma, which is a tradeoff between accuracy (taking the soul out of the number) and the ability to present many results in a limited screen area.

Again, the library that does the actual calculation isn’t my own, this overly simplistic “interface” (or the conscious lack of it) merely communicates with it, extracts the data and presents it. I just felt that a complex interface wouldn’t coexist well with large amounts of data. I hope that this example has inspired you to think about the use of math in new ways.