Thursday, March 13, 2014

Exporting Literate Haskell With HSColour and Pandoc

In yesterday's post I said I would detail the workflow from literate Haskell + markdown to postable html, so here we go:

Requirements: You need to have Haskell installed somehow. I generally recommend the Haskell Platform installed through your OS's package manager (pacman, apt-get, homebrew...). At a minimum, you need ghc and cabal-install Next, you need hscolour and pandoc installed. If you already have them, great! If not, run these commands:

cabal install hscolour
cabal install pandoc

Once you have those installed, it's relatively simple - just run this script:

There you go! Now you've highlighted the code bits, and left the rest to be formatted as markdown!

Isomorphism, Equality, PQ, and Other Ways of Saying the Same Thing

Note: this whole document is literate code generated by a workflow I'll talk a bit more about tomorrow.  It's a short shell script that's quite useful.  You can find the program as a gist on github.

So we’ll first take as an axiom that math is based on axioms. So far so good? Well, an important thing to note with this is that it’s really easy for axioms to have different significance - it all comes down to what metaphor you use in your brain to describe the axiomset
For example, MIU seems wholly abstract, but it turned out to be isomorphic to some operations on the integers modulo 3. And that isomorphism allowed some things to be made clear about it that weren’t otherwise.
In Chapter 2, Hofstadter defines some axioms that he calls the “PQ system”. These axioms are:
  1. The only valid characters are -, P, and Q
  2. -P-Q-- is a theorem
  3. x. xP -Q -x is a theorem
  4. xyz. if xP yQ z is a theorem, then xP -yQ -z is a theorem
First lets define our types Hyphen strings are essentially equivalent to natural numbers, so we’ll make that explicit

> data Nat = Zero | S Nat deriving (Show, Read)
> data Str = PQ Nat Nat Nat deriving (Show, Read)

Next we’ll define a few numbers for convenience

> one = S Zero
> two = S one

And this is all we really need Now let’s define the basic axiomset

> a1 = PQ one one two
> a2 (PQ a1 a2 s) = PQ (S a1) a2 (S s)
> a3 (PQ a1 a2 s) = PQ a1 (S a2) (S s)

Now we generate a list of all the theorems by iterating a2 starting from a1, and then mapping and iterating a3 over that list. Isn't it wonderful what you can do with lazy evaluation?

> theorems = map (iterate a3) $ iterate a2 a1

Now this is great if we just want the list of all axioms, but not really that useful if we want to check if something’s in there. You know, given the infinite axiom space and all. So right now checking for theoremhood is actually really computationally difficult - you have to produce all axioms and just check if something’s in there. Now, there are some strings where it’s obvious that it’s not a theorem - P-Q-PPP is malformed, like 3$&*(! So, how would we go about making a deterministic test that finishes in finite time?
This is your cue to try and solve the problem yourself before spoilers.
So, to review:
  • We’ve got an infinite list of theorems, generated by some recursive rules
  • Our job is to somehow figure out if any given (valid) string is going to be somewhere in that list
  • There are two recursive rules doing the generating, so we can’t even do a linear scan through the infinite set
  • And, most algorithms to do diagonal scans are annoyingly complicated for what should be a simple test
  • Neither of those “full scan” approaches can ever give us certainty that something is a nontheorem - just that we haven’t found it yet
Well, the simplest way is to exploit an isomorphism between PQ and arithmetic. You can see this if you interpret xP yQ z as "\(x + y = z\)". Hofstadter tried to make it clear with the suggestive names P and Q. I tried to make the hint stronger, by defining PQ in terms of natural numbers. But, to do a good theoremhood check, we first need to actually write out the code for natural number arithmetic
Just for kicks, lets actually implement the Peano Axioms, or at least the ones we need.
First, let’s define equality

> instance Eq Nat where

First, m = n iff S(m) = S(n) (Peano Axiom 8) An equivalent to the above is that S(m) = S(n) iff m = n

>     (S n1) == (S n2) = n1 == n2

Equality is reflexive (Peano Axiom 1)

>     Zero == Zero     = True

Now that we’ve defined both our truth patterns, we can rest assured that every other case will turn out false

>     _ == _           = False

Next we’ll define all the arithmetic required by the Num typeclass

> instance Num Nat where

Zero is the additive identity, and this definition of addition actually looks about the same as Peano Addition If we’re adding Zero, then we can just return the other number And, S(n) + a = S(n + a). The pattern match to S(n1) + S(n2) is just a way of increasing the speed at which the recursion terminates

>   (S n1) + (S n2) = S . S $ n1 + n2
>   n + Zero = n
>   Zero + n = n

Next we’ve got multiplication, if only because it’s required by the typeclass. It’s just repeated addition, so this is pretty simple. The first rule is that anything multiplied by Zero is Zero.  The second rule is that for any n1*S(n2) = n1 + n1*n2.

>   n1 * (S n2) = n1 + n1 * n2
>   Zero * _ = Zero
>   _ * Zero = Zero

More num class fillers

>   negate = undefined
>   abs = id
>   signum _ = one
>   fromInteger 0 = Zero
>   fromInteger n = S $ fromInteger $ n - 1

So now we’ve got the tools to create a function that would test axiomhood, but it’d be horribly inefficient. It’d look something like this:
isTheorem (PQ a1 a2 s) = a1 + a2 == s
Now, that’s all well and good, but it first has to do the O(n) addition of a1 and a2, then the O(n) equality of a1 + a2 and s. Surely we can make this into one n, instead of two? Well, the way to do so is actually really easy - we just exploit the isomorphism between addition and subtraction.
First, we define our recursive rule

>   (S n1) - (S n2) = n1 - n2

Next, our base cases. Subtracting Zero from anything is just a null op, and we don’t have a clear definition in PQ of negative numbers - you can’t have -5 hyphens

>   n - Zero = n
>   Zero - _ = undefined

So from there our work is really easy - we can just recurse down once The algorithm below will take exactly (a1 + a2) iterations to check for theoremhood

> isTheorem (PQ a1 a2 s) = s - a1 - a2 == Zero

And with that we’re done - we’ve defined the PQ system, written out something to list all the theorems, discovered some novel properties of it, and leveraged those to write a quick theoremhood tester.  Not bad, eh?

Wednesday, March 12, 2014

An Important Note About LaTeX In The Browser

I'm going to be doing more and more mathy posts, and I want to be able to use LaTeX in them
If you use Chrome, you're in luck - Tex Renderer is an extension that will do exactly what you need it to.
Another solution is Tex The World

On Firefox, on the other hand, there's a Greasemonkey script that works about as well as Tex Renderer

If you don't know what LaTeX is, that's a whole different article - but a quick search brought up this

Some samples to test with:
$\forall$
$\frac{a}{b}$
$\sqrt{2\pi}$
$\int_1^{\infty} \frac{1}{x}$

Thursday, March 6, 2014

MIU Haskellized

Note: crosspost from here, I originally planned to keep that blog separate but on thinking more about it I realized that's stupid.

One of the first formal systems that Hofstadter introduces in the book is the so-called MIU system. It consists of four rules that can be used to transform a string of M's, I's, and U's:
Add a U to the end of any string ending in I. For example: MI to MIU.
Double the string after the M (that is, change Mx, to Mxx). For example: MIU to MIUIU.
Replace any III with a U. For example: MUIIIU to MUUU.
Remove any UU. For example: MUUU to MU.
  1. MU contains no I's
  2. MU contains no I's
  3. Lemma: You can only eliminate all I's from a string if the number of I's is a multiple of three
    • the only way to remove I's is to convert them to U's
    • I's can only be converted to U's in groups of 3
    • ∴ You can only eliminate all I's if the number of I's ≡ 0 (mod 3)
  4. Lemma: There is no string of multiplications by 2 and subtractions of 3
    • ∀ x. x - 3 ≡ x (mod 3)
    • 0 * 2 ≡ 0 (mod 3)
    • 1 * 2 ≡ 2 (mod 3)
    • 2 * 2 ≡ 1 (mod 3)
    • ∴ by exhaustion, there is no string of multiplications by 2 and subtractions of 3 that will generate a multiple of 3
  5. ∴ There is no combination of rule applications that will eliminate all I's from a string
  6. ∴ MU is underivable in the MIU system
Anyway, here's my code for manipulating MIU strings. Have fun!

A Comparison Of The Three Browsers Most Of You Use

So by now I've gotten a few hundred page views, and I've noticed something:
10% of you are using IE
Which has me realizing that a post talking about the advantages of different browsers was probably worth writing.  So here's a comparison of the three browsers at least 10% of you use:


Mozilla's Firefox, built from the ashes of Netscape, could not-all-that-inaccurately be called the Emacs of web browsers.  It's free, open source, and it's been called an OS.  Of course, for me that's not the killer feature; that role is filled by the amazing tab handling.  It's not that it does anything exceptionally well (except for tab groups - those are awesome) but that everyone else does something horribly wrong.
That being said, if you don't suffer from tab overload, it will be slower than Chrome, so you're probably better off moving on.  That being said, there are a few extensions for Firefox that no one's done a good Chrome port of yet

Pros:
Cons:
  • Bad at clearing memory during continued use
  • Only third best html5 support
  • Slow startup

 
Google's browser, you've probably already heard of it.  44% of you, actually, use Chrome.  It doesn't really need much introduction, so there won't be.  If you're using it, I'd recommend taking a look at this post.  I'd recommend using it unless you're super concerned about ethical software, privacy, or you simply have too many tabs.

Pros:
Cons:
  • Proprietary
  • Weak tab handling without extensions
  • Overall heavier memory usage by making each tab (and each extension!) its own process 

Don't use it.  Please switch.  It's slow, has bad html5 support, and relatively insecure.  While recent versions have definitely improved this situation, exploits are being created for it faster than any other browser just because most of the least tech savvy users are using it.  It's also proprietary, completely closed source (Chrome at least has Chromium behind it), and it's not customizable.  So yeah.  Switch, save yourself the headache.  If you can't bring yourself to switch, at least update to IE 11.  There are still people out there using IE6.  That one's been completely broken since it was first made in 2001.  Don't be one of those people.