AI-ParticleSwarmOptimization

 view release on metacpan or  search on metacpan

Samples/PSOPlatTest.pl  view on Meta::CPAN

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
my ($fit, @values) = $pso->getParticleBestPos ($best);
my $iters = $pso->getIterationCount ();
print $pso->getSeed();
 
printf ",# Fit %.5f at (%s) after %d iterations\n",
    $fit, join (', ', map {sprintf '%.4f', $_} @values), $iters;
 
 
sub calcFit {
    my @values = @_;
    my $offset = int (-@values / 2);
    my $sum;
 
    $sum += ($_ - $offset++)**2 for @values;
    return $sum;
}

Samples/PSOTest.pl  view on Meta::CPAN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#!/usr/bin/perl
use strict;
use lib '..\lib'; # For development testing
 
++$|;
my $pso = AI::ParticleSwarmOptimization->new ();
 
$pso->setParams (
    -fitFunc    => \&calcFit,
    -dimensions => 3,
    -iterations => 100,
    );
 
for (0 .. 9) {
    $pso->init () unless $_ % 5;
 
    my $fitValue      = $pso->optimize ();
    my ($best)        = $pso->getBestParticles (1);
    my ($fit, @values) = $pso->getParticleBestPos ($best);
    my $iters = $pso->getIterationCount();
 
    printf "Fit %.4f at (%s) after %d iterations\n",
        $fit, join (', ', map {sprintf '%.4f', $_} @values), $iters;
}
 
 
sub calcFit {
    my @values = @_;
    my $offset = int (-@values / 2);
    my $sum;
 
    $sum += ($_ - $offset++) ** 2 for @values;
    return $sum;
}

lib/AI/ParticleSwarmOptimization.pm  view on Meta::CPAN

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
use constant kLogBetter     => 1;
use constant kLogStall      => 2;
use constant kLogIter       => 4;
use constant kLogDetail     => 8;
use constant kLogIterDetail => (kLogIter | kLogDetail);
 
sub new {
    my ($class, %params) = @_;
    my $self = bless {}, $class;
 
    $self->setParams (%params);
    return $self;
}
 
 
sub setParams {
    my ($self, %params) = @_;
 
    if (defined $params{-fitFunc}) {
        # Process required parameters - -fitFunc and -dimensions
        if ('ARRAY' eq ref $params{-fitFunc}) {
            ($self->{fitFunc}, @{$self->{fitParams}}) = @{$params{-fitFunc}};
        } else {
            $self->{fitFunc} = $params{-fitFunc};
        }

lib/AI/ParticleSwarmOptimization.pm  view on Meta::CPAN

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
    $self->{inertia}    ||= 0.9;
    $self->{verbose}    ||= 0;
 
    return 1;
}
 
 
sub init {
    my ($self) = @_;
 
    die "-fitFunc must be set before init or optimize is called"
        unless $self->{fitFunc} and 'CODE' eq ref $self->{fitFunc};
    die
        "-dimensions must be set to 1 or greater before init or optimize is called"
        unless $self->{dimensions} and $self->{dimensions} >= 1;
 
    my $seed =
        int (exists $self->{randSeed} ? $self->{randSeed} : rand (0xffffffff));
 
    $self->{rndGen} = Math::Random::MT->new ($seed);
    $self->{usedRandSeed} = $seed;
 
    $self->{prtcls}         = [];
    $self->{bestBest}       = undef;

lib/AI/ParticleSwarmOptimization.pm  view on Meta::CPAN

290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
        print "\n";
    }
 
    return undef;
}
 
 
sub _saveBest {
    my ($self, $prtcl, $fit, $iter) = @_;
 
    # for each dimension, set the best position as the current position
    @{$prtcl->{bestPos}} = @{$prtcl->{currPos}};
 
    $prtcl->{bestFit} = $fit;
    return if !$self->_betterFit ($fit, $self->{bestBest});
 
    if ($self->{verbose} & kLogBetter) {
        my $velSq;
 
        $velSq += $_**2 for @{$prtcl->{velocity}};
        printf "#%05d: Particle $prtcl->{id} best: %.4f (vel: %.3f)\n",

lib/AI/ParticleSwarmOptimization.pm  view on Meta::CPAN

418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
    my $fitValue       = $pso->optimize ();
    my ($best)         = $pso->getBestParticles (1);
    my ($fit, @values) = $pso->getParticleBestPos ($best);
 
    printf "Fit %.4f at (%s)\n",
        $fit, join ', ', map {sprintf '%.4f', $_} @values;
 
 
    sub calcFit {
        my @values = @_;
        my $offset = int (-@values / 2);
        my $sum;
 
        $sum += ($_ - $offset++) ** 2 for @values;
        return $sum;
    }
 
=head1 Description
 
The Particle Swarm Optimization technique uses communication of the current best
position found between a number of particles moving over a hyper surface as a
technique for locating the best location on the surface (where 'best' is the
minimum of some fitness function). For a Wikipedia discussion of PSO see

lib/AI/ParticleSwarmOptimization.pm  view on Meta::CPAN

525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
Number of particles in the swarm. Defaults to 10 times the number of dimensions.
 
=item I<-posMax>: number, optional
 
Maximum coordinate value for any dimension in the hyper space. Defaults to 100.
 
=item I<-posMin>: number, optional
 
Minimum coordinate value for any dimension in the hyper space. Defaults to
-I<-posMax> (if I<-posMax> is negative I<-posMin> should be set more negative).
 
=item I<-randSeed>: number, optional
 
Seed for the random number generator. Useful if you want to rerun an
optimization, perhaps for benchmarking or test purposes.
 
=item I<-randStartVelocity>: boolean, optional
 
Set true to initialize particles with a random velocity. Otherwise particle
velocity is set to 0 on initalization.
 
A range based on 1/100th of -I<-posMax> - I<-posMin> is used for the initial
speed in each dimension of the velocity vector if a random start velocity is
used.
 
=item I<-stallSpeed>: positive number, optional
 
Speed below which a particle is considered to be stalled and is repositioned to
a new random location with a new initial speed.

lib/AI/ParticleSwarmOptimization.pm  view on Meta::CPAN

587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
Defaults to 10% of the number of iterations (I<-iterations>).
 
=item I<-exitPlateauBurnin>: number, optional
 
Determines how many iterations to run before checking for plateaus.
 
Defaults to 50% of the number of iterations (I<-iterations>).
 
=item I<-verbose>: flags, optional
 
If set to a non-zero value I<-verbose> determines the level of diagnostic print
reporting that is generated during optimization.
 
The following constants may be bitwise ored together to set logging options:
 
=over 4
 
=item * kLogBetter
 
prints particle details when its fit becomes bebtter than its previous best.
 
=item * kLogStall
 
prints particle details when its velocity reaches 0 or falls below the stall

lib/AI/ParticleSwarmOptimization.pm  view on Meta::CPAN

619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
Shows additional details for some of the other logging options.
 
=item * kLogIterDetail
 
Shorthand for C<kLogIter | kLogIterDetail>
 
=back
 
=back
 
=item B<setParams (%parameters)>
 
Set or change optimization parameters. See I<-new> above for a description of
the parameters that may be supplied.
 
=item B<init ()>
 
Reinitialize the optimization. B<init ()> will be called during the first call
to B<optimize ()> if it hasn't already been called.
 
=item B<optimize ()>

t/01_pso_oo.t  view on Meta::CPAN

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
=head1 DESCRIPTION
 
Test AI::ParticleSwarmOptimization
 
=cut
 
plan (tests => 27);
 
ok (my $pso = AI::ParticleSwarmOptimization->new (), 'Constructor');
mustDie ('$pso->setParams (-fitFunc => 1)', 'Bad -fitFunc');
ok ($pso->setParams (-fitFunc => \&fitFunc,), 'Good -fitFunc (setParams)');
ok ($pso = AI::ParticleSwarmOptimization->new (-fitFunc => \&fitFunc,),
    'Good -fitFunc (new)');
ok ($pso->setParams (-fitFunc => [\&fitFunc, 1]), 'Good -fitFunc (array)');
 
mustDie ('$pso->setParams (-dimensions => 0)''-dimensions 0');
mustDie ('$pso->setParams (-dimensions => -1)', '-dimensions -1');
ok ($pso->setParams (-dimensions => 1), '-dimensions good');
 
for my $param (qw/numParticles/) {
    mustDie ("$pso->setParams (-$param => 0); $pso->init ()""-$param zero");
    mustDie ("$pso->setParams (-$param => -1); $pso->init ()", "-$param neg");
    ok (($pso->setParams (-$param => 1), $pso->init ()), "-$param good");
}
 
for my $param (
    qw/inertia iterations meWeight numNeighbors stallSpeed themWeight/)
{
    mustDie ("$pso->setParams (-$param => -1); $pso->init ()", "-$param neg");
    ok (($pso->setParams (-$param => 1), $pso->init ()), "-$param good");
}
 
mustDie (
    '$pso->setParams (-posMax => 0); $pso->setParams (-posMin => 0); $pso->init ()',
    '-posMax == -posMin'
);
mustDie (
    '$pso->setParams (-posMax => -1); $pso->setParams (-posMin => 0); $pso->init ()',
    '-posMax < -posMin'
);
ok (
    '$pso->setParams (-posMax => -1); $pso->setParams (-posMin => -2); $pso->init ()',
    '-posMax > -posMin'
   );
 
# Calculation tests.
$pso = AI::ParticleSwarmOptimization->new (
    -randSeed          => 2626813951,# Fit 0.00006 at (-1.0051, -0.0005, 1.0058) after 258 iterations
    -fitFunc           => \&calcFit,
    -dimensions        => 3,
    -iterations        => 500,
    -exitPlateau       => 1,

t/01_pso_oo.t  view on Meta::CPAN

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
my $iters = $pso->getIterationCount ();
 
ok ($iters > 100 && $iters < 350, 'Low plateau ok');
 
sub fitFunc {
}
 
 
sub calcFit {
    my @values = @_;
    my $offset = int (-@values / 2);
    my $sum;
 
    $sum += ($_ - $offset++)**2 for @values;
    return $sum;
}
 
 
sub mustDie {
    my ($test, $name) = @_;
 
    eval $test;
    ok (defined $@, $name);
}



( run in 0.673 second using v1.01-cache-2.11-cpan-3cd7ad12f66 )