File Coverage

blib/lib/Graph/Clique.pm
Criterion Covered Total %
statement 15 47 31.9
branch n/a
condition n/a
subroutine 5 8 62.5
pod 0 3 0.0
total 20 58 34.4


line stmt bran cond sub pod time code
1             package Graph::Clique;
2              
3 1     1   762 use 5.008;
  1         4  
  1         33  
4 1     1   5 use strict;
  1         2  
  1         31  
5 1     1   14 use warnings;
  1         3  
  1         46  
6 1     1   5 use re 'eval';
  1         1  
  1         63  
7              
8 1     1   6 use base qw(Exporter);
  1         1  
  1         700  
9              
10             our @EXPORT = qw(getcliques);
11              
12             our @EXPORT_OK = qw(_internalfunctions);
13              
14             our %EXPORT_TAGS = (all => \@EXPORT,
15             test => \@EXPORT_OK,
16             );
17              
18             our $VERSION = '0.02';
19              
20             # Below is stub documentation for your module. You'd better edit it!
21              
22             =head1 NAME
23              
24             Graph::Clique - Return all k-cliques in a graph
25              
26             =head1 SYNOPSIS
27              
28             use Graph::Clique;
29            
30             #Edges in the form of LoL (numerical values required)
31             my @edges = (
32             [1,2], [1,3], [1,4], [1,5],
33             [2,3], [2,4],
34             [3,4],
35             [5,6], [5,7], [5,9],
36             [6,9],
37             [7,8],
38             [8,9],
39             );
40              
41             my $k = shift || 3;
42              
43             my @cliques = getcliques($k,\@edges);
44              
45             print join("\n", @cliques), "\n";
46              
47             #Output:
48             #1 2 3
49             #1 2 4
50             #1 3 4
51             #2 3 4
52             #5 6 9
53            
54              
55             =head1 DESCRIPTION
56              
57             This module extends Greg Bacon's implementation on clique reduction with regular expression.
58             Originally can be found at: L
59              
60             The function take clique size (k) and vertices (list of lists) and return all the vertices
61             that form the clique.
62              
63             K-clique problem is known to be NP-complete, so it is advisable to limit the number
64             of edges according to your predefined threshold, rather than exhaustively searching them.
65              
66             =head1 ACKNOWLEDGEMENT
67              
68             Greg Bacon who started all this, Mike Rosulek
69             and Roy Johnson for his advice on ways to return all k-cliques.
70             Finally all guys in Perlmonks.org, and beginners.perl who has helped
71             me in many ways.
72              
73              
74             =head1 SEE ALSO
75              
76             L
77              
78             =head1 AUTHOR
79              
80             Edward Wijaya,
81              
82             =head1 COPYRIGHT AND LICENSE
83              
84             Copyright 2004 by Edward Wijaya
85              
86             This library is free software; you can redistribute it and/or modify
87             it under the same terms as Perl itself.
88              
89             =cut
90              
91             # Preloaded methods go here.
92             sub getcliques {
93              
94 0     0 0   my ($k,$edges) = @_;
95 0           my @cliques = ();
96 0           my @vertices = ();
97            
98 0           @vertices = edges2vertices(@{$edges});
  0            
99              
100 0           my $string = (join ',' => @vertices) . ';'
101 0           . (join ',' => map "$_->[0]-$_->[1]", @{$edges});
102              
103 0           my $regex = '^ .*\b '
104             . join(' , .*\b ' => ('(\d+)') x $k)
105             . '\b .* ;'
106             . "\n";
107              
108 0           for (my $i = 1; $i < $k; $i++) {
109 0           for (my $j = $i+1; $j <= $k; $j++) {
110 0           $regex .= '(?= .* \b ' . "\\$i-\\$j" . ' \b)' . "\n";
111             }
112             }
113              
114             # Backtrack to regain all the identified k-cliques (Credit Mike Mikero)
115 0           $regex .= '(?{ push (@cliques, join(" ", map $$_, 1..$k) ) })(?!)';
116 0           $string =~ /$regex/x;
117            
118 0           return sort @cliques;
119             }
120              
121             #----Subroutines -------------------
122             sub edges2vertices {
123 0     0 0   my @edges = @_;
124 0           my %hTemp;
125             my @vertices;
126            
127 0           my @aTemp = map{@{$_}} @edges;
  0            
  0            
128 0           @hTemp{@aTemp} = ();
129 0           @vertices = sort keys %hTemp;
130 0           return @vertices;
131             }
132              
133             sub edges2vertices_slow {
134             #AoA to uniq array;
135              
136 0     0 0   my @edges = @_;
137 0           my @vertices;
138             my @uniqv;
139            
140 0           for my $i ( 0 .. $#edges ) {
141 0           for my $j ( 0 .. $#{$edges[$i]} ) {
  0            
142 0           push @vertices, $edges[$i][$j];
143             }
144             }
145              
146 0           @uniqv = sort keys %{{map {$_,1} @vertices}};
  0            
  0            
147 0           return @uniqv;
148             }
149              
150              
151             1;
152             __END__