Thoroughly Modern Perl


An overview of:


Finding shortest time or distance with Graph::Undirected


The [Graph]( module on CPAN is mostly well documented. One place it falls short is explaining that not only can you create weighted edges, you can also use various edge attributes to calculate different minimum spanning trees (via Dijkstra's algorithm) based on any given attribute.

Here we create a small network of railway lines between cities, from the example on page 9 in John Armstrong's "Track Planning for Realistic Operation" (Kalmbach Books, 1986):

* There are two routes from A to D: A-B-D, and A-C-D.

* Here we assume that the route via B is longer but faster, and via
  C shorter but slower.

* The line continues from D through E and G to H.

* There is a branch line from E to F.

We calculate the shortest route by distance, and then by time.

Note the undocumented attribute parameter to SPT_Dijkstra().

#!/usr/bin/env perl
use strict;
use warnings;

use Graph::Undirected;

my $station_graph = Graph::Undirected->new();

# Add a few cities

$station_graph->add_path(qw(A B D E G H)); # first route via B
$station_graph->add_path(qw(A C D));       # second via C
$station_graph->add_path(qw(E F));         # branch route

# Define characteristics of the alternate routes

# Longer but faster
$station_graph->set_edge_attribute(qw(A B distance), 150);
$station_graph->set_edge_attribute(qw(A B time), 3.1);

# Shorter yet slower
$station_graph->set_edge_attribute(qw(A C distance), 120);
$station_graph->set_edge_attribute(qw(A C time), 3.3);

# Find spanning tree in distance
my $sptg1 = $station_graph->SPT_Dijkstra(attribute => 'distance');

print "Shortest Distance: ". join('|',$sptg1->SP_Dijkstra('A','H'));
print "\n";

# Clear cache (required for recalculation)

# Find spanning tree in time
my $sptg2 = $station_graph->SPT_Dijkstra(attribute => 'time');

print "Shortest Time:     ". join('|',$sptg2->SP_Dijkstra('A','H'));
print "\n";


When run, this shows as follows:

$ perl 
Shortest Distance: A|C|D|E|G|H
Shortest Time:     A|B|D|E|G|H

If you want to use a directed graph, create the graph by replacing that line with:

my $station_graph = Graph::Directed->new();

and be sure to specify the starting node for the spanning trees:

my $sptg1 = $station_graph->SPT_Dijkstra(attribute => 'distance', first_root => 'A');
my $sptg2 = $station_graph->SPT_Dijkstra(attribute => 'time', first_root => 'A');

Printing Perl documentation


Why? There's still nothing like printed documentation when you're learning a new subject. Or perhaps you'd like a PDF document to view on your tablet.

Here's the quickest way to create a PDF from any Perl documentation on your system. For example, let's do the CPAN module SQL::Abstract:

pod2pdf --pagesize=letter `perldoc -l SQL::Abstract`       > /tmp/SQL_Abstract.pdf`

Now you can view or print that. I find print 2-up pages, double-sided (4 total pages per sheet) is a handy and space-saving yet still readable. You might find it useful to reduce the PDF margins and let evince or okular manage the actual 2-up physical margins later:

pod2pdf --margins 18 --pagesize=letter       `perldoc -l SQL::Abstract` > /tmp/SQL_Abstract.pdf

The margins parameter is in printer's points (1/72 inch) and 18pt = ¼inch (0.635cm). You can also specify --left-margin as well as right, top, and bottom margins individually.

When printing several PDFs together, you may want to suppress blank pages. This is important when using double-sided or 2-up printing. To join several PDFs together for printing, you can use:

pdfunite a-in.pdf b-in.pdf output.pdf

If you are having difficulty printing documentation that contains Unicode,

 cpanm App::pod2pdf Paper::Specs

Excellent Moose introductions and tutorials


Modern Perl (see also the Modern Perl book) is based on, among other things, Moose as an object system, built on Perl 5's innate but spare O-O abilities.

This introduction [] explains not only Moose itself but quickly, and fairly painlessly, brings you into modern object orientation.

Also, Moose Is Perl − A Guide to the New Revolution [] − an over 400-page guide from the introductory to the detailed.

CPAN tricks


What modules are installed on my system?

# <span style="text-decoration: underline;">cpan -l</span>

From the cpan prompt, how can I tell whether a module is already installed, and what version?

cpan> <span style="text-decoration: underline;">i <em>module_name</em></span>

And how can I tell which modules are out-of-date or have updated versions?

cpan> <span style="text-decoration: underline;">r</span>

…which gives a result like:

Package namespace installed latest in CPAN file
Archive::Extract       0.70   0.72 BINGOS/Archive-…0.72.tar.gz
Attribute::Handlers    0.94   0.96 SMUELLER/Attribute…0.96.tar.gz
AutoLoader             5.73   5.74 SMUELLER/AutoLoader-5.74.tar.gz
B::Debug               1.18   1.19 RURBAN/B-Debug-1.19.tar.gz
Carp                   1.29 1.3301 ZEFRAM/Carp-1.3301.tar.gz
Clone                  0.36   0.37 GARU/Clone-0.37.tar.gz
Compress::Bzip2        2.16   2.17 RURBAN/Compress-….tar.gz
DB_File               1.827  1.831 PMQS/DB_File-1.831.tar.gz
Data::Dumper          2.145  2.151 SMUELLER/Data…151.tar.gz