File: u_ng_mst.t

package info (click to toggle)
libgraph-perl 1%3A0.96-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 1,316 kB
  • ctags: 938
  • sloc: perl: 6,094; sh: 8; makefile: 2
file content (150 lines) | stat: -rw-r--r-- 3,640 bytes parent folder | download | duplicates (6)
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;
}