Graphviz breaks down on the md5 src program.

We can't really rely on Graphviz. It should be able to handle these graphs
as they only contain a couple of thousand vertices but it triggers some
kind of failure case.

As the class of graphs that need to be visualised is very restricted in
comparison to the Graphviz input I've started writing a domain specific
replacement. The first thing to do is to simplify the layout problem
using structural similiarity. A basic principle in graph layout is that
similarity in the graph should be reflected by symmetry in the result.

To manipulate induced subgraphs I've started working on a Region class that
indicates a marked subset of vertices (and any induced edges). This is
used to partition the graph in a bottom-up process that splits the
graph into partitions according to an equality relation that considers
local graph structure. It is computing an indirection representation of
isomorphisms amongst the sub-graphs (the indirect part is a numbering of
the vertices within the subgroup that preserves the relation).
Old changes sitting in working folder.
New version of the Region class.

Switched the sparse representation to a dense bitmap. Started to
implement set theoretic operations over the vertices.

This cuts the MD5 graph that Graphviz won't render into two pieces
that it can.
Cropped out the old Region class.
Implemented the executability relation on the RegionX.

After implementing this graph search algorithm for about the billionth
(and hopefully the last time) it occurs to me that it has never been
published. Really should write a tech report about how this generalises
the dominance relation over bi-graphs and its connection to reachability
and valid simulations of a dataflow program.
Cutting out dominated regions for each values in the MD5 graph.

Results looks a bit wonky. Need to work out what the crappy looking
values are, and why the dominated frontiers are so small.
Initial views of MD5

Fixed a couple of bugs: the horrific mess in RegionX::repr() was overflowing
and corrupting memory. Replaced it with something more stable. Typo in the
opcode enum meant that the extract and lor ops had the same value. Added some
more code for outputting the Regions / Blocks.

Now that GraphViz can render a partial view of MD5 the small size of the
dominated regions is obvious: there is a huge degree of diffusion in the
hash function which shows up as a single dependency chain with frequent
inputs from earlier values in the chain and the very wide extraction of
words from the input chunk.

The extraction process is essentially parallel so it produces a very wide
graph (everything has the same rank). The computation process is very
sequential (single chain). The edges from the wide single rank to almost
every rank in the chain are as randomly distributed as possible. Explains
why GraphViz chokes on the input...

Next step is returning to computing isomorphisms between subgraphs. Although
subgraph isomorphism is hard in general this graph has highly distinct local
structure so it is far from the worst case. Inside the chain the nodes with
high fan-out are easy to spot and should be isomorphic to one another.
Splitting collections into partition based on local equality.

New module contains the bin-building code generalised over a template.
The first use is splitting the Values in the Block into bins based on
an equality relation that takes into account the number of uses (out-degree)
and the type. The next step is looking at the uses as a vector of
Instructions and re-partitioning based on the local equivalency relation.
This currently checks that the opcodes match and each input/output operand
has the same type.

If the shape of the use-partition matches then the partition of the data-values
stands, otherwise it can be split into smaller bins where the using instructions
differ. The entry point in the isomorphism module should throw away
"uninteresting" bins (judged by size of graph regions in each element and the
number of elements in the bin) and scan each remaining bin to a higher
depth.

At some point the bins within each bin need to be resolved, which is very
expensive. Either all permutations need to be checked or some kind of
backtracking implemented. The distribution of graph regions to bins is
essentially an encoding of the constraints entailed by the regions matching
other elements in the same bin.
Second level bins.

The first goal is using these to split the first-level bins. This requires
an equality relation over something. These somethings are not quite Regions
yet, rather they are ways of mapping Regions onto a canonical representation.
Rough sketch of the somethings...

Each of the bins is now stored in a container called a CanonSet,
within which each Canon contains separated sets of graph vertices.
The Values referenced are assumed to be in a definite order. The
rationale for this is that we will hang each isomorphic region
from a root Value and the process of binding them together will
establish an (arbitrary but consistent) ordering for them. The
Instructions are split into definites and possibles. The definites
have unique enough traces from the root that we can distinguish
between them, and thus we know the ordering is preserved across
every Canon in a CanonSet. The possibles are a partition of the
remaining Instructions according to a local equivalence relation.
Equality is preserved over blocks of these partitions between
Canons in a CanonSet, but the exact ordering is unknown. If two
Canons refer to isomorphic regions then some unknown permutation
of these sets will produce the isomorphic mapping between them.

This generates the two-level binning as before, then splits the
bins according to the partition of the possibles partition. Bins
2 and 3 are currently split incorrectly when they should remain
merged. The reason is that the when we compare the partitions we
treat them as distributions of graph sructure and compare them
by shape - but the blocks within the partition have not been
ordered so the comparison is invalid. Any consistent ordering will
do for the blocks - opcode ordering for example.