File Coverage

blib/lib/AI/ParticleSwarmOptimization/MCE.pm
Criterion Covered Total %
statement 105 133 78.9
branch 3 6 50.0
condition 1 3 33.3
subroutine 17 21 80.9
pod 3 3 100.0
total 129 166 77.7


line stmt bran cond sub pod time code
1             package AI::ParticleSwarmOptimization::MCE;
2             $AI::ParticleSwarmOptimization::MCE::VERSION = '1.006';
3 2     2   79183 use strict;
  2         33  
  2         70  
4 2     2   25 use warnings;
  2         5  
  2         69  
5 2         1370 use base qw(
6             AI::ParticleSwarmOptimization
7             Class::Accessor::Fast
8 2     2   12 );
  2         5  
9             #-----------------------------------------------------------------------
10 2     2   12249 use Clone qw( clone );
  2         4828  
  2         132  
11 2     2   15 use List::Util qw( min shuffle );
  2         4  
  2         197  
12 2     2   1293 use Storable;
  2         6452  
  2         118  
13 2     2   1378 use MCE ( Sereal => 0 );
  2         108415  
  2         13  
14 2     2   1407 use MCE::Map;
  2         6516  
  2         15  
15 2     2   841 use MCE::Util;
  2         11  
  2         2761  
16             #-----------------------------------------------------------------------
17             __PACKAGE__->mk_accessors( qw(
18             _pop
19             _tpl
20             _wrk
21             ));
22             #-----------------------------------------------------------------------
23             $Storable::Deparse = 1;
24             $Storable::Eval = 1;
25             #=======================================================================
26             sub new {
27 1     1 1 868 my ($class, %params) = @_;
28            
29             #-------------------------------------------------------------------
30 1         15 my $self = bless {}, $class;
31 1         11 $self->SUPER::setParams( %params );
32            
33             #-------------------------------------------------------------------
34 1         106 $self->_init_mce( \%params );
35 1         5 $self->_init_pop( \%params );
36 1         10 $self->_init_tpl( \%params );
37            
38             #-------------------------------------------------------------------
39 1         3 return $self;
40             }
41             #=======================================================================
42             sub _init_tpl {
43 1     1   3 my ( $self, $params ) = @_;
44            
45 1         12 my $cln = clone( $params );
46 1         8 delete $cln->{ $_ } for qw(
47             -iterCount
48             -iterations
49             -numParticles
50             -workers
51            
52             _pop
53             _tpl
54             _wrk
55             );
56            
57 1         22 $self->_tpl( $cln );
58            
59 1         8 return;
60             }
61             #=======================================================================
62             sub _init_pop {
63 1     1   3 my ( $self, $params ) = @_;
64            
65 1         20 my $pop = int( $self->{ numParticles } / $self->_wrk );
66 1         22 my $rst = $self->{ numParticles } % $self->_wrk;
67            
68 1         21 my @pop = ( $pop ) x $self->_wrk;
69 1         7 $pop[ 0 ] += $rst;
70            
71 1         20 $self->_pop( \@pop );
72             }
73             #=======================================================================
74             sub _init_mce {
75 1     1   4 my ( $self, $params ) = @_;
76            
77             #-------------------------------------------------------------------
78 1   33     37 $self->_wrk( $params->{ '-workers' } || MCE::Util::get_ncpu() );
79            
80             #-------------------------------------------------------------------
81 1         28 MCE::Map->init(
82             chunk_size => 1, # Thanks Roy :-)
83             #chunk_size => q[auto], # The old one. Currently it should be the same...
84             max_workers => $self->_wrk,
85             posix_exit => 1, # Thanks Roy :-)
86             );
87            
88             #-------------------------------------------------------------------
89 1         30 return;
90             }
91             #=======================================================================
92             sub setParams {
93 0     0 1 0 my ( $self, %params ) = @_;
94            
95 0         0 my $fles = __PACKAGE__->new( %params );
96            
97 0         0 $self->{ $_ } = $fles->{ $_ } for keys %$fles;
98            
99 0         0 return 1;
100             }
101             #=======================================================================
102             sub init {
103 1     1 1 6 my ( $self ) = @_;
104            
105             #-------------------------------------------------------------------
106 1         3 my $pop = $self->{ numParticles };
107 1         3 $self->{ numParticles } = 1;
108 1         6 $self->SUPER::init();
109 1         482 $self->{ numParticles } = $pop;
110 1         5 $self->{ prtcls } = [ ];
111            
112             #-------------------------------------------------------------------
113 1         4 my $cnt = 0;
114 1         25 my $tpl = $self->_tpl;
115            
116 1         33 @{ $self->{ prtcls } } = map {
117 1000         106908 $_->{ id } = $cnt++;
118 1000         1776 $_
119             } mce_map {
120 0     0   0 my $arg = clone( $tpl );
121 0         0 $arg->{ -numParticles } = $_;
122            
123 0         0 my $swm = AI::ParticleSwarmOptimization->new( %$arg );
124 0         0 $swm->init;
125            
126 0         0 @{ $swm->{ prtcls } };
  0         0  
127            
128 1         11 } @{ $self->_pop };
  1         19  
129            
130             #-------------------------------------------------------------------
131 1         62 return 1;
132             }
133             #=======================================================================
134             sub _chunks {
135 20     20   115 my ( $self ) = @_;
136            
137             #-------------------------------------------------------------------
138 20         78 @{ $self->{ prtcls } } = shuffle @{ $self->{ prtcls } };
  20         1378  
  20         704  
139            
140             #-------------------------------------------------------------------
141 20         109 my @chk;
142 20         63 for my $idx ( 0 .. $#{ $self->_pop } ){
  20         873  
143             #my $cnt = 0;
144             #my @tmp = map {
145             # $_->{ id } = $cnt++;
146             # $_
147             #} splice @{ $self->{ prtcls } }, 0, $self->_pop->[ $idx ];
148            
149             # Faster and smaller memory consumption...
150 80         764 my $cnt = 0;
151 80         161 my @tmp = splice @{ $self->{ prtcls } }, 0, $self->_pop->[ $idx ];
  80         2018  
152 80         10810 $_->{ id } = $cnt++ for @tmp;
153              
154 80         309 push @chk, \@tmp;
155             }
156            
157             #-------------------------------------------------------------------
158 20         293 return \@chk;
159             }
160             #=======================================================================
161             sub _updateVelocities {
162 10     10   172 my ( $self, $iter ) = @_;
163              
164             #-------------------------------------------------------------------
165 10 50       88 print "Iter $iter\n" if $self->{verbose} & AI::ParticleSwarmOptimization::kLogIter;
166              
167 10         734 my $tpl = $self->_tpl;
168              
169             my @lst = mce_map {
170             #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
171 0     0   0 my $ary = $_;
172             #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
173 0         0 my $arg = clone( $tpl );
174 0         0 $arg->{ -numParticles } = 1;
175            
176 0         0 my $swm = AI::ParticleSwarmOptimization->new( %$arg );
177 0         0 $swm->init;
178 0         0 $swm->{ numParticles } = scalar( @$ary );
179 0         0 $swm->{ prtcls } = $ary;
180             #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
181 0         0 $swm->_updateVelocities( $iter );
182             #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
183             [
184             $swm->{ prtcls },
185             $swm->{ bestBest },
186 0         0 ]
187             #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
188 10         527 } $self->_chunks;
189              
190             #-------------------------------------------------------------------
191             #my $cnt = 0;
192             #@{ $self->{ prtcls } } = map {
193             # $_->{ id } = $cnt++;
194             # $_
195             #} map {
196             # @{ $_->[ 0 ] }
197             #} @lst;
198              
199             # Faster and smaller memory consumption...
200 10         1473244 my $cnt = 0;
201 10         115 @{ $self->{ prtcls } } = map { @{ $_->[ 0 ] } } @lst;
  10         480  
  40         87  
  40         1563  
202 10         132 $_->{ id } = $cnt++ for @{ $self->{ prtcls } };
  10         4252  
203            
204             #-------------------------------------------------------------------
205 10         88 $self->{ bestBest } = min grep { defined $_ } map { $_->[ 1 ] } @lst;
  40         212  
  40         107  
206            
207             #-------------------------------------------------------------------
208 10         1996 return;
209             }
210             #=======================================================================
211             sub _moveParticles {
212 10     10   408 my ( $self, $iter ) = @_;
213              
214             #-------------------------------------------------------------------
215 10 50       80 print "Iter $iter\n" if $self->{verbose} & AI::ParticleSwarmOptimization::kLogIter;
216              
217 10         594 my $tpl = $self->_tpl;
218              
219             my @lst = mce_map {
220             #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
221 0     0   0 my $ary = $_;
222             #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
223 0         0 my $arg = clone( $tpl );
224 0         0 $arg->{ -numParticles } = 1;
225            
226 0         0 my $swm = AI::ParticleSwarmOptimization->new( %$arg );
227 0         0 $swm->init;
228 0         0 $swm->{ numParticles } = scalar( @$ary );
229 0         0 $swm->{ prtcls } = $ary;
230             #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
231             [
232             $swm->_moveParticles( $iter ),
233             $swm->{ prtcls }
234 0         0 ]
235             #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
236 10         683 } $self->_chunks;
237              
238             #-------------------------------------------------------------------
239             #my $cnt = 0;
240             #@{ $self->{ prtcls } } = map {
241             # $_->{ id } = $cnt++;
242             # $_
243             #} map {
244             # @{ $_->[ 1 ] }
245             #} @lst;
246              
247             # Faster and smaller memory consumption...
248 10         734811 my $cnt = 0;
249 10         74 @{ $self->{ prtcls } } = map { @{ $_->[ 1 ] } } @lst;
  10         645  
  40         113  
  40         1730  
250 10         117 $_->{ id } = $cnt++ for @{ $self->{ prtcls } };
  10         4444  
251              
252             #-------------------------------------------------------------------
253 10 50       71 return unless grep { defined $_ } map { $_->[ 0 ] } @lst;
  40         1104  
  40         101  
254 0           return 1;
255             }
256             #=======================================================================
257             1;
258              
259             __END__