| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Graph::Undirected::Hamiltonicity::Spoof; |
|
2
|
|
|
|
|
|
|
|
|
3
|
5
|
|
|
5
|
|
33505
|
use Modern::Perl; |
|
|
5
|
|
|
|
|
25
|
|
|
|
5
|
|
|
|
|
85
|
|
|
4
|
5
|
|
|
5
|
|
604
|
use Carp; |
|
|
5
|
|
|
|
|
10
|
|
|
|
5
|
|
|
|
|
229
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
5
|
|
|
5
|
|
1172
|
use Graph::Undirected; |
|
|
5
|
|
|
|
|
97713
|
|
|
|
5
|
|
|
|
|
133
|
|
|
7
|
5
|
|
|
5
|
|
1797
|
use Graph::Undirected::Hamiltonicity::Transforms qw(&add_random_edges &get_random_isomorph); |
|
|
5
|
|
|
|
|
10
|
|
|
|
5
|
|
|
|
|
559
|
|
|
8
|
|
|
|
|
|
|
|
|
9
|
5
|
|
|
5
|
|
34
|
use Exporter qw(import); |
|
|
5
|
|
|
|
|
9
|
|
|
|
5
|
|
|
|
|
3610
|
|
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
our @EXPORT_OK = qw( |
|
12
|
|
|
|
|
|
|
&spoof_canonical_hamiltonian_graph |
|
13
|
|
|
|
|
|
|
&spoof_known_hamiltonian_graph |
|
14
|
|
|
|
|
|
|
&spoof_random_graph |
|
15
|
|
|
|
|
|
|
&spoof_randomish_graph |
|
16
|
|
|
|
|
|
|
); |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
our %EXPORT_TAGS = ( all => \@EXPORT_OK, ); |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
############################################################################## |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
sub spoof_canonical_hamiltonian_graph { |
|
23
|
32
|
|
|
32
|
1
|
9062
|
my ($v) = @_; |
|
24
|
|
|
|
|
|
|
|
|
25
|
32
|
|
|
|
|
77
|
my $last_vertex = $v - 1; |
|
26
|
32
|
|
|
|
|
131
|
my @vertices = ( 0 .. $last_vertex ); |
|
27
|
|
|
|
|
|
|
|
|
28
|
32
|
|
|
|
|
151
|
my $g = Graph::Undirected->new( vertices => \@vertices ); |
|
29
|
32
|
|
|
|
|
14260
|
$g->add_edge( 0, $last_vertex ); |
|
30
|
|
|
|
|
|
|
|
|
31
|
32
|
|
|
|
|
17775
|
for ( my $i = 0; $i < $last_vertex; $i++ ) { |
|
32
|
276
|
|
|
|
|
24037
|
$g->add_edge( $i, $i + 1 ); |
|
33
|
|
|
|
|
|
|
} |
|
34
|
|
|
|
|
|
|
|
|
35
|
32
|
|
|
|
|
2960
|
return $g; |
|
36
|
|
|
|
|
|
|
} |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
############################################################################## |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
sub spoof_known_hamiltonian_graph { |
|
41
|
25
|
|
|
25
|
1
|
19654
|
my ( $v, $e ) = @_; |
|
42
|
|
|
|
|
|
|
|
|
43
|
25
|
100
|
66
|
|
|
186
|
croak "Please provide the number of vertices." unless defined $v and $v; |
|
44
|
24
|
100
|
|
|
|
94
|
croak "A graph with 2 vertices cannot be Hamiltonian." if $v == 2; |
|
45
|
|
|
|
|
|
|
|
|
46
|
23
|
|
66
|
|
|
99
|
$e ||= get_random_edge_count($v); |
|
47
|
|
|
|
|
|
|
|
|
48
|
23
|
100
|
|
|
|
74
|
croak "The number of edges must be >= number of vertices." if $e < $v; |
|
49
|
|
|
|
|
|
|
|
|
50
|
22
|
|
|
|
|
65
|
my $g = spoof_canonical_hamiltonian_graph($v); |
|
51
|
22
|
|
|
|
|
109
|
$g = get_random_isomorph($g); |
|
52
|
22
|
100
|
|
|
|
160
|
$g = add_random_edges( $g, $e - $v ) if ( $e - $v ) > 0; |
|
53
|
|
|
|
|
|
|
|
|
54
|
22
|
|
|
|
|
110
|
return $g; |
|
55
|
|
|
|
|
|
|
} |
|
56
|
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
############################################################################## |
|
58
|
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
sub spoof_random_graph { |
|
60
|
|
|
|
|
|
|
|
|
61
|
44
|
|
|
44
|
1
|
16894
|
my ( $v, $e ) = @_; |
|
62
|
44
|
|
66
|
|
|
124
|
$e //= get_random_edge_count($v); |
|
63
|
|
|
|
|
|
|
|
|
64
|
44
|
|
|
|
|
247
|
my $g = Graph::Undirected->new( vertices => [ 0 .. $v-1 ] ); |
|
65
|
44
|
50
|
|
|
|
19364
|
$g = add_random_edges( $g, $e ) if $e; |
|
66
|
|
|
|
|
|
|
|
|
67
|
44
|
|
|
|
|
117
|
return $g; |
|
68
|
|
|
|
|
|
|
} |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
############################################################################## |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
sub spoof_randomish_graph { |
|
73
|
|
|
|
|
|
|
|
|
74
|
22
|
|
|
22
|
1
|
198385
|
my ( $v, $e ) = @_; |
|
75
|
22
|
|
66
|
|
|
80
|
$e ||= get_random_edge_count($v); |
|
76
|
|
|
|
|
|
|
|
|
77
|
22
|
|
|
|
|
60
|
my $g = spoof_random_graph( $v, $e ); |
|
78
|
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
### Seek out vertices with degree < 2 |
|
80
|
|
|
|
|
|
|
### and add random edges to them. |
|
81
|
22
|
|
|
|
|
37
|
my $edges_to_remove = 0; |
|
82
|
22
|
|
|
|
|
64
|
foreach my $vertex1 ( $g->vertices() ) { |
|
83
|
253
|
|
|
|
|
848
|
my $degree = $g->degree($vertex1); |
|
84
|
|
|
|
|
|
|
|
|
85
|
253
|
100
|
|
|
|
86585
|
next if $degree > 1; |
|
86
|
33
|
|
|
|
|
54
|
my $added_edges = 0; |
|
87
|
33
|
|
|
|
|
74
|
while ( $added_edges < (2 - $degree) ) { |
|
88
|
50
|
|
|
|
|
199
|
my $vertex2 = int( rand($v) ); |
|
89
|
50
|
100
|
|
|
|
92
|
next if $vertex1 == $vertex2; |
|
90
|
45
|
100
|
|
|
|
95
|
next if $g->has_edge($vertex1, $vertex2); |
|
91
|
42
|
|
|
|
|
1553
|
$g->add_edge($vertex1,$vertex2); |
|
92
|
42
|
|
|
|
|
4250
|
$added_edges++; |
|
93
|
42
|
|
|
|
|
129
|
$edges_to_remove++; |
|
94
|
|
|
|
|
|
|
} |
|
95
|
|
|
|
|
|
|
} |
|
96
|
|
|
|
|
|
|
|
|
97
|
22
|
|
|
|
|
59
|
my $try_count = 0; |
|
98
|
22
|
|
|
|
|
45
|
my $max_tries = 2 * $edges_to_remove; |
|
99
|
|
|
|
|
|
|
### Seek out vertices with degree > 2 |
|
100
|
|
|
|
|
|
|
### with neighbor of degree < 3 |
|
101
|
|
|
|
|
|
|
### and delete edges. |
|
102
|
|
|
|
|
|
|
### Try to delete the same number of edges, |
|
103
|
|
|
|
|
|
|
### as the random edges added. |
|
104
|
22
|
|
100
|
|
|
91
|
while ( $edges_to_remove and ($try_count < $max_tries) ) { |
|
105
|
72
|
|
|
|
|
11327
|
$try_count++; |
|
106
|
|
|
|
|
|
|
LOOP: |
|
107
|
72
|
|
|
|
|
186
|
foreach my $vertex1 ( $g->vertices() ) { |
|
108
|
1000
|
100
|
|
|
|
195539
|
next if $g->degree($vertex1) < 3; |
|
109
|
|
|
|
|
|
|
|
|
110
|
96
|
|
|
|
|
27207
|
foreach my $vertex2 ( $g->neighbors($vertex1) ) { |
|
111
|
348
|
100
|
|
|
|
59175
|
next if $g->degree($vertex2) < 3; |
|
112
|
16
|
|
|
|
|
4220
|
$g->delete_edge($vertex1,$vertex2); |
|
113
|
16
|
|
|
|
|
1395
|
$edges_to_remove--; |
|
114
|
16
|
|
|
|
|
79
|
last LOOP; |
|
115
|
|
|
|
|
|
|
} |
|
116
|
|
|
|
|
|
|
} |
|
117
|
|
|
|
|
|
|
} |
|
118
|
|
|
|
|
|
|
|
|
119
|
22
|
100
|
|
|
|
1055
|
carp "Exiting with $edges_to_remove extra edges.\n" if $edges_to_remove; |
|
120
|
|
|
|
|
|
|
|
|
121
|
22
|
|
|
|
|
90
|
return $g; |
|
122
|
|
|
|
|
|
|
} |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
############################################################################## |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
sub get_random_edge_count { |
|
127
|
34
|
|
|
34
|
0
|
69
|
my ( $v ) = @_; |
|
128
|
|
|
|
|
|
|
|
|
129
|
34
|
|
|
|
|
135
|
my %h = ( 0 => 0, 1 => 0, 2 => 1, 3 => 3, 4 => 4 ); |
|
130
|
34
|
|
|
|
|
97
|
my $e = $h{$v}; |
|
131
|
34
|
100
|
|
|
|
103
|
return $e if defined $e; |
|
132
|
|
|
|
|
|
|
|
|
133
|
28
|
|
|
|
|
71
|
my $max_edges = ( $v * $v - $v ) / 2; |
|
134
|
28
|
|
|
|
|
73
|
my $range = $max_edges - 2 * $v + 2; |
|
135
|
28
|
|
|
|
|
65
|
$e = int( rand( $range ) ) + $v; |
|
136
|
|
|
|
|
|
|
|
|
137
|
28
|
|
|
|
|
103
|
return $e; |
|
138
|
|
|
|
|
|
|
} |
|
139
|
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
############################################################################## |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
1; # End of Graph::Undirected::Hamiltonicity::Spoof |