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