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 |