AI-ParticleSwarmOptimization

 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);
}



( run in 0.286 second using v1.01-cache-2.11-cpan-26ccb49234f )