view release on metacpan or search on metacpan
Samples/PSOPlatTest.pl view on Meta::CPAN
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
#!/usr/bin/perl
use strict;
use warnings;
use lib '..\lib'; # For development testing
use AI::ParticleSwarmOptimization;
++$|;
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
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
$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
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
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
http://en.wikipedia.org/wiki/Particle_swarm_optimization.
lib/AI/ParticleSwarmOptimization.pm view on Meta::CPAN
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
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
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
=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
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);
}