# ETOOBUSY ðŸš€ minimal blogging for the impatient

# Generic Graph Representation

**TL;DR**

Where we discuss about a generic model for the graph.

I find it very instructive to study #algorithms, and also to try to code them in the most generic way possible. Iâ€™m not sure why, actually: most of the times the implementation can be easily tailored to the problem I have, and sometimes this means just re-implementing the whole thingâ€¦ but thatâ€™s life.

Iâ€™ll gloss over a lot of pre-conditions here, assuming that you knowâ€¦ what
a graph (in the *graph theory* sense) means.

# Representing the Graph - Generically

To remain general, we should aim for a representation that assumes nothing about how the algorithm will be used. Will it be objects? Simple hashes? Arrays? Anything else?

We will just do the following assumptions:

- a
*node*is represented by a Perl scalar (this was easy); - the
*nodes*that can be reached from a*node*`X`

are in a list that can be retrieved through a function.

This should give us a model that is generic enough to use, while still being simple enough to implement independently of the real graph representation.

# An example?

Letâ€™s make an example: suppose that the graph is represented like this:

*nodes*are strings, representing places;*edges*are represented implicitly with a hash of arrays.

Something like this:

```
my %graph = (
airport => [qw< work >],
home => [qw< work school >],
park => [qw< school >],
school => [qw< park home >],
work => [qw< home airport >],
);
```

This tells us that we can reach `work`

from the `airport`

, or that we can
reach both `park`

and `home`

from `school`

. This representation is good for
a very generic graph, including directed graphs.

Our *nodes* in this case are the strings `airport`

, `home`

, `park`

,
`school`

, and `work`

. The list associated to each node allows representing
the edges.

In our representation, the following function would allow us to represent these adjacencies through a function:

```
sub graph_dependencies_sub {
my %graph = @_;
return sub {
my ($node) = @_;
return @{$graph{$node}};
}
}
my $graph_adjacencies = graph_adjacencies_sub(%graph);
```

Now `$graph_adjacencies`

encapsulates our representation of the graph: when
provided a *node*, it gives out the list of *nodes* that can be reached from
it:

```
my @nodes_from_home = $graph_adjacencies->('home');
```

# Another example?

We might, of course, start from a different representation for the graph, e.g. based on objects:

*nodes*are objects;*edges*are represented as a list of adjacent nodes that each node holds.

```
package Graph;
sub new {
my ($package, $name) = @_;
return bless {name => $name, neighbors => {}}, $package;
};
sub name {
my $self = shift;
return $self->{name};
}
sub neighbors {
my $self = shift;
return @{$self->{neighbors}};
}
sub add_neighbors {
my $self = shift;
$self->{neighbors}{$_->name} = $_ for @_;
return $self;
}
package main;
my ($airport, $home, $park, $school, $work) =
map { Graph->new($_) } qw< airport home park school work >;
$airport->add_neighbors($work);
$home->add_neighbors($work, $school);
$park->add_neighbors($school);
$school->add_neighbors($park, $home);
$work->add_neighbors($home, $airport);
```

Itâ€™s basically the same graph as before, only represented differently.
Again, itâ€™s easy to adapt to the generic representation, itâ€™s basically just
`Graph::neighbors`

:

```
my $graph_adjacencies = \&Graph::neighbors;
```

Of course if you intend to inherit from `Graph`

this will break, so the more
robust thing to do is to use a wrapper:

```
sub graph_dependencies_sub {
return sub {
my ($node) = @_;
return $node->neighbors;
};
}
my $graph_adjacencies = graph_adjacencies_sub();
```

# Edge lists anyone?

This representation is sub-optimal when edges are represented as stand-alone elements, e.g.:

*nodes*are strings;*edges*are represented as pairs of nodes in anonymous arrays`[$from, $to]`

.

Something like this (for the same graph):

```
my @edges = (
[ 'airport', 'work' ],
[ 'home', 'work' ],
[ 'home', 'school' ],
[ 'park', 'school' ],
[ 'school', 'park' ],
[ 'school', 'home' ],
[ 'work', 'home' ],
[ 'work', 'airport' ],
);
```

The adaptation in this case is a bitâ€¦ *clunky*:

```
my $graph_adjacencies = sub {
my ($node) = @_;
map { $_->[1] } grep { $_->[0] eq $node } @edges;
}
```

Every timeâ€¦ we are iterating through the whole of `@edges`

. Of course we
can do some pre-computing:

```
sub graph_adjacencies_sub {
my %graph;
for my $edge (@_) {
my ($from, $to) = @$edge;
$graph{$from} = $to;
}
return sub {
my ($node) = @_;
return @{$graph{$node}};
};
}
my $graph_adjacencies = graph_adjacencies_sub(@edges);
```

â€¦ at the expense of requiring some more space.

But hey! I promised that the representation would be generic and easy to adapt to, not that it would solve every problem in the world!

# Summing Up

The representation that we introduced basically requires us to decide on
what we mean by *node* and provide a function that computes the list of
other *nodes* that can be reached from it. It allows us to represent
whatever graph, and itâ€™s fairly easy to adapt toâ€¦ which we will leverage
in the future discussing a few #algorithms about graphs.

Cheers!

*Comments? Octodon, , GitHub, Reddit, or drop me a line!*