File Coverage

blib/lib/Graph/SocialMap.pm
Criterion Covered Total %
statement 109 136 80.1
branch 16 28 57.1
condition n/a
subroutine 16 19 84.2
pod 2 14 14.2
total 143 197 72.5


line stmt bran cond sub pod time code
1             package Graph::SocialMap;
2 7     7   114818 use Spiffy 0.21 qw(-Base field);
  7         42659  
  7         57  
3 7     7   43595 use Graph 0.54;
  7     7   19  
  7     7   250  
  7         38  
  7         17  
  7         284  
  7         17894  
  7         1238861  
  7         329  
4 7     7   10289 use Quantum::Superpositions;
  7         143685  
  7         83  
5             our $VERSION = '0.12';
6              
7 7     7 1 343 sub paired_arguments {qw(-relation -file -format)}
  7         27  
8              
9             # Cached fields
10             field '_relation';
11             field '_issues';
12             field '_people';
13              
14             # weight of person: number of occurences of a person in whole relation.
15             field '_wop';
16              
17             # under lying Graph::* object
18             field '_type1';
19             field '_type2';
20             field '_type3';
21             field '_apsp';
22             field '_issue_network';
23              
24             # graphviz parameters
25             field layout => 'neato';
26             field rank => 'same';
27             field ranksep => 1.5;
28             field no_overlap => 0;
29             field splines => 'false';
30             field arrowsize => 0.5;
31             field fontsize => 12;
32             field ordering => 'out';
33             field epsilon => 1;
34             field concentrate => 'true';
35             field ratio => 'auto';
36              
37 12     12 0 232 sub relation {
38 12         19 my $newval = shift;
39 12 100       32 if($newval) {
40 4         224 $self->_relation($newval);
41 4         64 for(qw(_people _issues _type1 _type2 _type3 _apsp _wop
42             _issue_network)) {
43 32         904 $self->$_(undef);
44             }
45             }
46 12         284 return $self->_relation;
47             }
48              
49 3     3 0 6 sub issues {
50 3 50       67 return $self->_issues if $self->_issues;
51 3         24 my $issues = [keys %{$self->relation}];
  3         10  
52 3         89 $self->_issues($issues);
53 3         21 return $issues;
54             }
55              
56 2     2 0 4 sub people {
57 2 50       49 return $self->_people if ($self->_people);
58 2         20 my $p={};
59 2         7 my $r=$self->relation;
60 2         19 for(keys %$r) {
61 13         21 $p->{$_}++ for @{$r->{$_}};
  13         136  
62             }
63 2         50 $self->_wop($p);
64 2         24 my $people = [keys %$p];
65 2         49 $self->_people($people);
66 2         11 return $people;
67             }
68              
69 1     1 0 13 sub wop {
70 1 50       20 return $self->_wop if $self->_wop;
71 1         9 $self->people;
72 1         20 $self->_wop;
73             }
74              
75 1     1 0 3 sub type2 {
76 1 50       47 return $self->_type2 if ($self->_type2);
77 1         11 my $isu = $self->issues;
78 1         5 my $rel = $self->relation;
79 1         13 my $type2 = Graph->new;
80              
81 1         292 for my $i (@$isu) {
82 5         115 for my $e ($self->pairs(@{$rel->{$i}})) {
  5         17  
83 4 50       14 unless($type2->has_edge($e->[0],$e->[1])) {
84 4         65 $type2->add_edge($e->[0],$e->[1]);
85 4         365 $type2->add_edge($e->[1],$e->[0]);
86             }
87             }
88             }
89 1         77 $self->_type2($type2);
90 1         16 return $type2;
91             }
92              
93             *people_network = \&type2;
94              
95 1     1 1 14 sub issue_network {
96 1 50       21 return $self->_issue_network if $self->_issue_network;
97 1         10 my $isu = $self->issues;
98 1         3 my $rel = $self->relation;
99 1         35 my $n = Graph::Undirected->new;
100 1         325 for my $i ($self->pairs(@$isu)) {
101 28 50       96493 next if $n->has_edge($i->[0],$i->[1]);
102 28         109 $n->add_edge($i->[0],$i->[1])
103 28 100       445 if any(@{$rel->{$i->[0]}}) eq any(@{$rel->{$i->[1]}});
  28         224  
104             }
105 1         1409 $self->_issue_network($n);
106 1         13 return $n;
107             }
108              
109 14     14 0 17 sub apsp {
110 14 100       368 return $self->_apsp if($self->_apsp);
111 1         22 my $a = $self->type2->APSP_Floyd_Warshall;
112 1         9463 $self->_apsp($a);
113 1         11 return $a;
114             }
115              
116 1     1 0 16 sub type1 {
117 1 50       24 return $self->_type1 if ($self->_type1);
118 1         19 my $type1 = Graph::Undirected->new;
119 1         361 my $people = $self->people;
120 1         5 my $isu = $self->issues;
121 1         3 my $rel = $self->relation;
122              
123 1         7 for (@$people) {
124 31         2293 my $node_name = "People/$_";
125 31         79 $type1->add_vertex($node_name);
126 31         1794 $type1->set_vertex_attribute($node_name,shape => 'plaintext');
127 31         2449 $type1->set_vertex_attribute($node_name,label => $_);
128             }
129              
130 1         84 for my $i (@$isu) {
131 8         4039 my $node_name = "Issue/$i";
132 8         22 $type1->add_vertex($node_name);
133 8         466 $type1->set_vertex_attribute($node_name, shape => "box");
134 8         670 $type1->set_vertex_attribute($node_name, label => $i);
135 8         567 $type1->add_edge("People/$_",$node_name) for @{$rel->{$i}};
  8         55  
136             }
137              
138 1         1900 $self->_type1($type1);
139 1         11 return $type1;
140             }
141              
142             *affiliation_network = \&type1;
143              
144             # type3, directed people-to-people graph, in the given order
145 0     0 0 0 sub type3 {
146 0 0       0 return $self->_type3 if ($self->_type3);
147 0         0 my $rel = $self->relation;
148 0         0 my $isu = $self->issues;
149 0         0 my $type3 = Graph->new;
150 0         0 my $people = $self->people;
151              
152 0         0 $type3->add_vertices(@$people);
153 0         0 for my $i (@$isu) {
154 0         0 my @list = @{$rel->{$i}};
  0         0  
155 0         0 for my $i (0..$#list-1) {
156 0         0 for my $j ($i+1..$#list) {
157 0 0       0 $type3->add_edge(@list[$j,$i])
158             unless($type3->has_edge(@list[$j,$i]));
159             }
160             }
161             }
162              
163 0         0 $self->_type3($type3);
164 0         0 return $type3;
165             }
166              
167 0     0 0 0 sub type3_adj_matrix {
168 0         0 my $m = {};
169 0         0 for($self->type3->edges) {
170 0         0 $m->{$_->[0]}->{$_->[1]} = 1;
171             }
172 0         0 return $m;
173             }
174              
175             # Degree of seperation of two people.
176 14     14 0 1581 sub dos {
177 14         28 my ($alice,$bob) = @_;
178 14         34 my $apsp = $self->apsp;
179 14         22881 my $w = $apsp->path_length($alice,$bob);
180 14 100       534 $w = -1 if(!defined $w);
181 14         65 return $w;
182             }
183              
184             # retrurn all-pair dos
185 0     0 0 0 sub all_dos {
186 0         0 my $people = $self->people;
187 0         0 my $d = {};
188 0         0 for my $alice (@$people) {
189 0         0 for my $bob (@$people) {
190 0         0 $d->{$alice}->{$bob} = $self->dos($alice,$bob);
191             }
192             }
193 0         0 return $d;
194             }
195              
196             # return a list of all pairs.
197 9     9 0 23029 sub pairs {
198 9         27 my @list = @_;
199 9         9 my @pairs;
200 9         26 for my $i (0..$#list) {
201 26         62 for my $j ($i+1..$#list) {
202 42         60 my ($a,$b) = @list[$i,$j];
203 42         138 push @pairs, [$a,$b];
204             }
205             }
206 9         38 return @pairs;
207             }
208