1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
use Test::More qw/no_plan/;
=head1 NAME
Test program for Graph.
=head2 SYNOPSIS
perl u_ng_mst.t [ A [ D [ N ] ] ]
=head2 DESCRIPTION
This program constructs various trees, embeds them in general graphs,
and tests various minimum spanning tree methods: MST_Kruskal,
MST_Prim, MST_Dijkstra.
A is arity and it defaults to 4.
D is depth and it defaults to 3.
N is chain/star size and it defaults to 40. (The minimum is 10.)
(To use a default, specify '-'.)
=head1 AUTHOR
Nathan Goodman
=cut
my ($A, $D, $N) = @ARGV;
$A = 3 if ($A || 0) < 1;
$D = 4 if ($D || 0) < 1;
$N = 40 if ($N || 0) < 1;
use strict;
use Graph;
use Graph::Directed;
use Graph::Undirected;
for my $arity (1..$A) {
for my $depth (1..$D) {
print "# depth=$depth, arity=$arity\n";
# $g=construct(new Graph::Directed,$depth,$arity);
my $h=construct(new Graph::Undirected,$depth,$arity);
my $t=regular_tree(new Graph::Undirected,$depth,$arity);
my $mst1=$h->MST_Kruskal;
is($mst1,$t,"Kruskal");
my $mst2=$h->MST_Prim;
is($mst2,$t,"Prim");
my $mst3=$h->MST_Dijkstra;
is($mst3,$t,"Dijkstra");
# ok(1,"end of tests for depth=$depth, arity=$arity");
}
}
# do some long chains
my $arity=1;
for(my $depth=10;$depth<=$N;$depth+=10) {
print "# depth=$depth, arity=$arity\n";
# $g=construct(new Graph::Directed,$depth,$arity);
my $h=construct(new Graph::Undirected,$depth,$arity);
my $t=regular_tree(new Graph::Undirected,$depth,$arity);
my $mst1=$h->MST_Kruskal;
is($mst1,$t,"Kruskal");
my $mst2=$h->MST_Prim;
is($mst2,$t,"Prim");
my $mst3=$h->MST_Dijkstra;
is($mst3,$t,"Dijkstra");
# ok(1,"end of tests for depth=$depth, arity=$arity");
}
# do some wide stars
my $depth=1;
for(my $arity=10;$arity<=$N;$arity+=10) {
print "# depth=$depth, arity=$arity\n";
# $g=construct(new Graph::Directed,$depth,$arity);
my $h=construct(new Graph::Undirected,$depth,$arity);
my $t=regular_tree(new Graph::Undirected,$depth,$arity);
my $mst1=$h->MST_Kruskal;
is($mst1,$t,"Kruskal");
my $mst2=$h->MST_Prim;
is($mst2,$t,"Prim");
my $mst3=$h->MST_Dijkstra;
is($mst3,$t,"Dijkstra");
# ok(1,"end of tests for depth=$depth, arity=$arity");
}
exit;
sub construct {
my($g, $depth, $arity, $density)=@_;
$density or $density=3;
# make a tree with edge weights of1
$g=regular_tree($g,$depth,$arity);
# add heavier edges
my @nodes=$g->vertices;
my $new_edges=int $density*@nodes;
for (1..$new_edges) {
my $i=int rand $#nodes;
my $j=int rand $#nodes;
next if $g->has_edge($nodes[$i],$nodes[$j]);
$g->add_weighted_edge($nodes[$i],$nodes[$j],2);
}
print "# V = ", scalar $g->vertices, ", E = ", scalar $g->edges, "\n";
return $g;
}
sub regular_tree {
my($tree,$depth,$arity,$root)=@_;
defined $root or do {
$root=0;
$tree->add_vertex($root);
};
if ($depth>0) {
for (my $i=0; $i<$arity; $i++) {
my $child="$root/$i";
$tree->add_vertex($child);
$tree->add_weighted_edge($root,$child,1);
regular_tree($tree,$depth-1,$arity,$child);
}
}
$tree;
}
sub is_quiet {
my($a,$b,$tag)=@_;
return if $a eq $b;
is($a,$b,$tag);
}
sub ok_quiet {
my($bool,$tag)=@_;
return if $bool;
ok($bool,$tag);
}
sub min {
if ($#_==0) {@_=@{$_[0]} if 'ARRAY' eq ref $_[0];}
return undef unless @_;
if ($#_==1) {my($x,$y)=@_; return ($x<=$y?$x:$y);}
my $min=shift @_;
map {$min=$_ if $_<$min} @_;
$min;
}
sub max {
if ($#_==0) {@_=@{$_[0]} if 'ARRAY' eq ref $_[0];}
return undef unless @_;
if ($#_==1) {my($x,$y)=@_; return ($x>=$y?$x:$y);}
my $max=shift @_;
map {$max=$_ if $_>$max} @_;
$max;
}
|