AI-ParticleSwarmOptimization-MCE
view release on metacpan or search on metacpan
Revision history for Perl extension AI::ParticleSwarmOptimization::MCE.
1.006 Mon, 09 Jan 2023 22:17:01 +0100
- Fix in POD.
1.005 Mon, 09 Jan 2023 22:05:16 +0100
- Update of Changes file.
1.004 Mon, 09 Jan 2023 22:05:16 +0100
- First release with Dist::Zilla.
1.003 Thu, 05 Jan 2023 11:16:26 +0100
- Fix: MANIFEST
1.002 Sun, 16 Oct 2022 15:02:03 +0200
- Improvements in a range of efficiency (thanks to Mario Roy :-)
1.001 Fri, 07 Oct 2022 18:19:01 +0200
- Fix in Makefile.pl
1.000 Fri, 07 Oct 2022 10:33:30 +0200
- First release.
This software is Copyright (c) 2023 by Åukasz Strzelecki.
This is free software, licensed under:
The GNU Lesser General Public License, Version 2.1, February 1999
The GNU Lesser General Public License (LGPL)
Version 2.1, February 1999
(The master copy of this license lives on the GNU website.)
Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also
counts as the successor of the GNU Library Public License,
version 2, hence the version number 2.1.]
You may charge a fee for the physical act of transferring a
copy, and you may at your option offer warranty protection in
exchange for a fee.
2. You may modify your copy or copies of the Library or any
portion of it, thus forming a work based on the Library, and
copy and distribute such modifications or work under the
terms of Section 1 above, provided that you also meet all of
these conditions:
a) The modified work must itself be a software
library.
b) You must cause the files modified to carry
prominent notices stating that you changed the
files and the date of any change.
c) You must cause the whole of the work to be
licensed at no charge to all third parties under
the terms of this License.
d) If a facility in the modified Library refers to a
function or a table of data to be supplied by an
application program that uses the facility, other
than as an argument passed when the facility
is invoked, then you must make a good faith
effort to ensure that, in the event an application
does not supply such function or table, the
facility still operates, and performs whatever
part of its purpose remains meaningful.
(For example, a function in a library to
compute square roots has a purpose that is
entirely well-defined independent of the
application. Therefore, Subsection 2d requires
that any application-supplied function or table
used by this function must be optional: if the
application does not supply it, the square root
function must still compute square roots.)
These requirements apply to the modified work
as a whole. If identifiable sections of that work
are not derived from the Library, and can be
reasonably considered independent and
separate works in themselves, then this
License, and its terms, do not apply to those
sections when you distribute them as separate
works. But when you distribute the same
sections as part of a whole which is a work
based on the Library, the distribution of the
whole must be on the terms of this License,
whose permissions for other licensees extend
to the entire whole, and thus to each and every
part regardless of who wrote it.
Thus, it is not the intent of this section to claim
rights or contest your rights to work written
entirely by you; rather, the intent is to exercise
the right to control the distribution of derivative
or collective works based on the Library.
In addition, mere aggregation of another work
not based on the Library with the Library (or
with a work based on the Library) on a volume
of a storage or distribution medium does not
bring the other work under the scope of this
License.
3. You may opt to apply the terms of the ordinary GNU
General Public License instead of this License to a given
copy of the Library. To do this, you must alter all the notices
that refer to this License, so that they refer to the ordinary
GNU General Public License, version 2, instead of to this
License. (If a newer version than version 2 of the ordinary
GNU General Public License has appeared, then you can
specify that version instead if you wish.) Do not make any
other change in these notices.
such modifications.
You must give prominent notice with each copy of the work
that the Library is used in it and that the Library and its use
are covered by this License. You must supply a copy of this
License. If the work during execution displays copyright
notices, you must include the copyright notice for the Library
among them, as well as a reference directing the user to the
copy of this License. Also, you must do one of these things:
a) Accompany the work with the complete
corresponding machine-readable source code
for the Library including whatever changes were
used in the work (which must be distributed
under Sections 1 and 2 above); and, if the work
is an executable linked with the Library, with
the complete machine-readable "work that
uses the Library", as object code and/or
source code, so that the user can modify the
Library and then relink to produce a modified
executable containing the modified Library. (It
is understood that the user who changes the
contents of definitions files in the Library will
not necessarily be able to recompile the
application to use the modified definitions.)
b) Use a suitable shared library mechanism for
linking with the Library. A suitable mechanism
is one that (1) uses at run time a copy of the
library already present on the user's computer
system, rather than copying library functions
into the executable, and (2) will operate
properly with a modified version of the library, if
the user installs one, as long as the modified
version is interface-compatible with the version
that the work was made with.
c) Accompany the work with a written offer,
valid for at least three years, to give the same
user the materials specified in Subsection 6a,
above, for a charge no more than the cost of
performing this distribution.
d) If distribution of the work is made by offering
access to copy from a designated place, offer
equivalent access to copy the above specified
materials from the same place.
e) Verify that the user has already received a
copy of these materials or that you have
already sent this user a copy.
For an executable, the required form of the "work that uses
the Library" must include any data and utility programs
needed for reproducing the executable from it. However, as a
special exception, the materials to be distributed need not
include anything that is normally distributed (in either source
or binary form) with the major components (compiler, kernel,
and so on) of the operating system on which the executable
runs, unless that component itself accompanies the
executable.
an executable that you distribute.
7. You may place library facilities that are a work based on
the Library side-by-side in a single library together with other
library facilities not covered by this License, and distribute
such a combined library, provided that the separate
distribution of the work based on the Library and of the other
library facilities is otherwise permitted, and provided that you
do these two things:
a) Accompany the combined library with a
copy of the same work based on the Library,
uncombined with any other library facilities.
This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined
library of the fact that part of it is a work based
on the Library, and explaining where to find the
accompanying uncombined form of the same
work.
8. You may not copy, modify, sublicense, link with, or
distribute the Library except as expressly provided under this
License. Any attempt otherwise to copy, modify, sublicense,
link with, or distribute the Library is void, and will
automatically terminate your rights under this License.
However, parties who have received copies, or rights, from
you under this License will not have their licenses terminated
so long as such parties remain in full compliance.
{
"abstract" : "Particle Swarm Optimization (object oriented) with support for multi-core processing",
"author" : [
"\u0141ukasz Strzelecki <lukasz@strzeleccy.eu>"
],
"dynamic_config" : 0,
"generated_by" : "Dist::Zilla version 6.017, CPAN::Meta::Converter version 2.150010",
"license" : [
"lgpl_2_1"
],
"meta-spec" : {
"url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
"version" : 2
},
"name" : "AI-ParticleSwarmOptimization-MCE",
"prereqs" : {
"configure" : {
"requires" : {
"ExtUtils::MakeMaker" : "0"
}
},
"runtime" : {
"requires" : {
"AI::ParticleSwarmOptimization" : "1.006",
"Class::Accessor::Fast" : "0",
"Clone" : "0",
"List::Util" : "0",
"MCE" : "1.874",
"MCE::Map" : "1.874",
"MCE::Util" : "1.874",
"Storable" : "0"
}
}
},
"release_status" : "stable",
"resources" : {
"homepage" : "https://github.com/d-strzelec/AI-ParticleSwarmOptimization-MCE",
"repository" : {
"type" : "git",
"url" : "https://github.com/d-strzelec/AI-ParticleSwarmOptimization-MCE.git",
"web" : "https://github.com/d-strzelec/AI-ParticleSwarmOptimization-MCE"
}
},
"version" : "1.006",
"x_Dist_Zilla" : {
"perl" : {
"version" : "5.032001"
},
"plugins" : [
{
"class" : "Dist::Zilla::Plugin::GatherDir",
"config" : {
"Dist::Zilla::Plugin::GatherDir" : {
"exclude_filename" : [],
"exclude_match" : [],
"follow_symlinks" : 0,
"include_dotfiles" : 0,
"prefix" : "",
"prune_directory" : [],
"root" : "."
}
},
"name" : "GatherDir",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::PruneCruft",
"name" : "PruneCruft",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::PruneFiles",
"name" : "PruneFiles",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::ManifestSkip",
"name" : "ManifestSkip",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::MetaYAML",
"name" : "MetaYAML",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::MetaJSON",
"name" : "MetaJSON",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::License",
"name" : "License",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::MakeMaker",
"config" : {
"Dist::Zilla::Role::TestRunner" : {
"default_jobs" : 1
}
},
"name" : "MakeMaker",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::Manifest",
"name" : "Manifest",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::PkgVersion",
"name" : "PkgVersion",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::ReadmeFromPod",
"name" : "ReadmeFromPod",
"version" : "0.37"
},
{
"class" : "Dist::Zilla::Plugin::MetaConfig",
"name" : "MetaConfig",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::Prereqs",
"config" : {
"Dist::Zilla::Plugin::Prereqs" : {
"phase" : "runtime",
"type" : "requires"
}
},
"name" : "Prereqs",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::GithubMeta",
"name" : "GithubMeta",
"version" : "0.58"
},
{
"class" : "Dist::Zilla::Plugin::Git::Commit",
"config" : {
"Dist::Zilla::Plugin::Git::Commit" : {
"add_files_in" : [],
"commit_msg" : "Release v-%v%n%n%c",
"signoff" : 0
},
"Dist::Zilla::Role::Git::DirtyFiles" : {
"allow_dirty" : [
"Changes",
"dist.ini"
],
"allow_dirty_match" : [
"(?^u:.*(?:\\.pm|README|\\*.t)$)"
],
"changelog" : "Changes"
},
"Dist::Zilla::Role::Git::Repo" : {
"git_version" : "2.30.2",
"repo_root" : "."
},
"Dist::Zilla::Role::Git::StringFormatter" : {
"time_zone" : "local"
}
},
"name" : "Git::Commit",
"version" : "2.047"
},
{
"class" : "Dist::Zilla::Plugin::Git::Push",
"config" : {
"Dist::Zilla::Plugin::Git::Push" : {
"push_to" : [
"d-strzelec"
],
"remotes_must_exist" : 1
},
"Dist::Zilla::Role::Git::Repo" : {
"git_version" : "2.30.2",
"repo_root" : "."
}
},
"name" : "Git::Push",
"version" : "2.047"
},
{
"class" : "Dist::Zilla::Plugin::TestRelease",
"name" : "TestRelease",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::ConfirmRelease",
"name" : "ConfirmRelease",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::UploadToCPAN",
"name" : "UploadToCPAN",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":InstallModules",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":IncModules",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":TestFiles",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":ExtraTestFiles",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":ExecFiles",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":PerlExecFiles",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":ShareFiles",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":MainModule",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":AllFiles",
"version" : "6.017"
},
{
"class" : "Dist::Zilla::Plugin::FinderCode",
"name" : ":NoFiles",
"version" : "6.017"
}
],
"zilla" : {
"class" : "Dist::Zilla::Dist::Builder",
"config" : {
"is_trial" : 0
},
"version" : "6.017"
}
},
"x_generated_by_perl" : "v5.32.1",
"x_serialization_backend" : "Cpanel::JSON::XS version 4.25",
"x_spdx_expression" : "LGPL-2.1"
}
---
abstract: 'Particle Swarm Optimization (object oriented) with support for multi-core processing'
author:
- 'Åukasz Strzelecki <lukasz@strzeleccy.eu>'
build_requires: {}
configure_requires:
ExtUtils::MakeMaker: '0'
dynamic_config: 0
generated_by: 'Dist::Zilla version 6.017, CPAN::Meta::Converter version 2.150010'
license: lgpl
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
version: '1.4'
name: AI-ParticleSwarmOptimization-MCE
requires:
AI::ParticleSwarmOptimization: '1.006'
Class::Accessor::Fast: '0'
Clone: '0'
List::Util: '0'
MCE: '1.874'
MCE::Map: '1.874'
MCE::Util: '1.874'
Storable: '0'
resources:
homepage: https://github.com/d-strzelec/AI-ParticleSwarmOptimization-MCE
repository: https://github.com/d-strzelec/AI-ParticleSwarmOptimization-MCE.git
version: '1.006'
x_Dist_Zilla:
perl:
version: '5.032001'
plugins:
-
class: Dist::Zilla::Plugin::GatherDir
config:
Dist::Zilla::Plugin::GatherDir:
exclude_filename: []
exclude_match: []
follow_symlinks: 0
include_dotfiles: 0
prefix: ''
prune_directory: []
root: .
name: GatherDir
version: '6.017'
-
class: Dist::Zilla::Plugin::PruneCruft
name: PruneCruft
version: '6.017'
-
class: Dist::Zilla::Plugin::PruneFiles
name: PruneFiles
version: '6.017'
-
class: Dist::Zilla::Plugin::ManifestSkip
name: ManifestSkip
version: '6.017'
-
class: Dist::Zilla::Plugin::MetaYAML
name: MetaYAML
version: '6.017'
-
class: Dist::Zilla::Plugin::MetaJSON
name: MetaJSON
version: '6.017'
-
class: Dist::Zilla::Plugin::License
name: License
version: '6.017'
-
class: Dist::Zilla::Plugin::MakeMaker
config:
Dist::Zilla::Role::TestRunner:
default_jobs: 1
name: MakeMaker
version: '6.017'
-
class: Dist::Zilla::Plugin::Manifest
name: Manifest
version: '6.017'
-
class: Dist::Zilla::Plugin::PkgVersion
name: PkgVersion
version: '6.017'
-
class: Dist::Zilla::Plugin::ReadmeFromPod
name: ReadmeFromPod
version: '0.37'
-
class: Dist::Zilla::Plugin::MetaConfig
name: MetaConfig
version: '6.017'
-
class: Dist::Zilla::Plugin::Prereqs
config:
Dist::Zilla::Plugin::Prereqs:
phase: runtime
type: requires
name: Prereqs
version: '6.017'
-
class: Dist::Zilla::Plugin::GithubMeta
name: GithubMeta
version: '0.58'
-
class: Dist::Zilla::Plugin::Git::Commit
config:
Dist::Zilla::Plugin::Git::Commit:
add_files_in: []
commit_msg: 'Release v-%v%n%n%c'
signoff: 0
Dist::Zilla::Role::Git::DirtyFiles:
allow_dirty:
- Changes
- dist.ini
allow_dirty_match:
- (?^u:.*(?:\.pm|README|\*.t)$)
changelog: Changes
Dist::Zilla::Role::Git::Repo:
git_version: 2.30.2
repo_root: .
Dist::Zilla::Role::Git::StringFormatter:
time_zone: local
name: Git::Commit
version: '2.047'
-
class: Dist::Zilla::Plugin::Git::Push
config:
Dist::Zilla::Plugin::Git::Push:
push_to:
- d-strzelec
remotes_must_exist: 1
Dist::Zilla::Role::Git::Repo:
git_version: 2.30.2
repo_root: .
name: Git::Push
version: '2.047'
-
class: Dist::Zilla::Plugin::TestRelease
name: TestRelease
version: '6.017'
-
class: Dist::Zilla::Plugin::ConfirmRelease
name: ConfirmRelease
version: '6.017'
-
class: Dist::Zilla::Plugin::UploadToCPAN
name: UploadToCPAN
version: '6.017'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':InstallModules'
version: '6.017'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':IncModules'
version: '6.017'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':TestFiles'
version: '6.017'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':ExtraTestFiles'
version: '6.017'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':ExecFiles'
version: '6.017'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':PerlExecFiles'
version: '6.017'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':ShareFiles'
version: '6.017'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':MainModule'
version: '6.017'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':AllFiles'
version: '6.017'
-
class: Dist::Zilla::Plugin::FinderCode
name: ':NoFiles'
version: '6.017'
zilla:
class: Dist::Zilla::Dist::Builder
config:
is_trial: '0'
version: '6.017'
x_generated_by_perl: v5.32.1
x_serialization_backend: 'YAML::Tiny version 1.73'
x_spdx_expression: LGPL-2.1
Makefile.PL view on Meta::CPAN
# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.017.
use strict;
use warnings;
use ExtUtils::MakeMaker;
my %WriteMakefileArgs = (
"ABSTRACT" => "Particle Swarm Optimization (object oriented) with support for multi-core processing",
"AUTHOR" => "\x{141}ukasz Strzelecki <lukasz\@strzeleccy.eu>",
"CONFIGURE_REQUIRES" => {
"ExtUtils::MakeMaker" => 0
},
"DISTNAME" => "AI-ParticleSwarmOptimization-MCE",
"LICENSE" => "lgpl",
"NAME" => "AI::ParticleSwarmOptimization::MCE",
"PREREQ_PM" => {
"AI::ParticleSwarmOptimization" => "1.006",
"Class::Accessor::Fast" => 0,
"Clone" => 0,
"List::Util" => 0,
"MCE" => "1.874",
"MCE::Map" => "1.874",
"MCE::Util" => "1.874",
"Storable" => 0
},
"VERSION" => "1.006",
"test" => {
"TESTS" => "t/*.t"
}
);
my %FallbackPrereqs = (
"AI::ParticleSwarmOptimization" => "1.006",
"Class::Accessor::Fast" => 0,
"Clone" => 0,
"List::Util" => 0,
"MCE" => "1.874",
"MCE::Map" => "1.874",
"MCE::Util" => "1.874",
"Storable" => 0
);
unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) {
delete $WriteMakefileArgs{TEST_REQUIRES};
delete $WriteMakefileArgs{BUILD_REQUIRES};
$WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs;
}
delete $WriteMakefileArgs{CONFIGURE_REQUIRES}
unless eval { ExtUtils::MakeMaker->VERSION(6.52) };
WriteMakefile(%WriteMakefileArgs);
NAME
AI::ParticleSwarmOptimization::MCE - Particle Swarm Optimization
(object oriented) with support for multi-core processing
SYNOPSIS
use AI::ParticleSwarmOptimization::MCE;
my $pso = AI::ParticleSwarmOptimization::MCE->new (
-fitFunc => \&calcFit,
-dimensions => 3,
-iterations => 10,
-numParticles => 1000,
# only for many-core version # the best if == $#cores of your system
# selecting best value if undefined
-workers => 4,
);
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;
select( undef, undef, undef, 0.01 ); # Simulation of heavy processing...
$sum += ($_ - $offset++) ** 2 for @values;
return $sum;
}
Description
This module is enhancement of on original AI::ParticleSwarmOptimization
to support multi-core processing with use of MCE. Below you can find
original documentation of that module, but with one difference. There
is new parameter "-workers", which one can use to define of number of
parallel processes that will be used during computations.
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.
This pure Perl module is an implementation of the Particle Swarm
Optimization technique for finding minima of hyper surfaces. It
presents an object oriented interface that facilitates easy
configuration of the optimization parameters and (in principle) allows
the creation of derived classes to reimplement all aspects of the
optimization engine (a future version will describe the replaceable
engine components).
This implementation allows communication of a local best point between
a selected number of neighbours. It does not support a single global
best position that is known to all particles in the swarm.
Methods
AI::ParticleSwarmOptimization provides the following public methods.
The parameter lists shown for the methods denote optional parameters by
showing them in [].
new (%parameters)
Create an optimization object. The following parameters may be used:
-workers: positive number, optional
The number of workers (processes), that will be used during
computations.
-dimensions: positive number, required
The number of dimensions of the hypersurface being searched.
-exitFit: number, optional
If provided -exitFit allows early termination of optimize if the
fitness value becomes equal or less than -exitFit.
-fitFunc: required
-fitFunc is a reference to the fitness function used by the search.
If extra parameters need to be passed to the fitness function an
array ref may be used with the code ref as the first array element
and parameters to be passed into the fitness function as following
elements. User provided parameters are passed as the first
parameters to the fitness function when it is called:
my $pso = AI::ParticleSwarmOptimization::MCE->new(
-fitFunc => [\&calcFit, $context],
-dimensions => 3,
);
...
sub calcFit {
my ($context, @values) = @_;
...
return $fitness;
}
In addition to any user provided parameters the list of values
representing the current particle position in the hyperspace is
passed in. There is one value per hyperspace dimension.
-inertia: positive or zero number, optional
Determines what proportion of the previous velocity is carried
forward to the next iteration. Defaults to 0.9
See also -meWeight and -themWeight.
-iterations: number, optional
Number of optimization iterations to perform. Defaults to 1000.
-meWeight: number, optional
Coefficient determining the influence of the current local best
position on the next iterations velocity. Defaults to 0.5.
See also -inertia and -themWeight.
-numNeighbors: positive number, optional
Number of local particles considered to be part of the
neighbourhood of the current particle. Defaults to the square root
of the total number of particles.
-numParticles: positive number, optional
Number of particles in the swarm. Defaults to 10 times the number
of dimensions.
-posMax: number, optional
Maximum coordinate value for any dimension in the hyper space.
Defaults to 100.
-posMin: number, optional
Minimum coordinate value for any dimension in the hyper space.
Defaults to --posMax (if -posMax is negative -posMin should be set
more negative).
-randSeed: number, optional
Seed for the random number generator. Useful if you want to rerun
an optimization, perhaps for benchmarking or test purposes.
-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 --posMax - -posMin is used for the
initial speed in each dimension of the velocity vector if a random
start velocity is used.
-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.
By default -stallSpeed is undefined but particles with a speed of 0
will be repositioned.
-themWeight: number, optional
Coefficient determining the influence of the neighbourhod best
position on the next iterations velocity. Defaults to 0.5.
See also -inertia and -meWeight.
-exitPlateau: boolean, optional
Set true to have the optimization check for plateaus (regions where
the fit hasn't improved much for a while) during the search. The
optimization ends when a suitable plateau is detected following the
burn in period.
Defaults to undefined (option disabled).
-exitPlateauDP: number, optional
Specify the number of decimal places to compare between the current
fitness function value and the mean of the previous
-exitPlateauWindow values.
Defaults to 10.
-exitPlateauWindow: number, optional
Specify the size of the window used to calculate the mean for
comparison to the current output of the fitness function.
Correlates to the minimum size of a plateau needed to end the
optimization.
Defaults to 10% of the number of iterations (-iterations).
-exitPlateauBurnin: number, optional
Determines how many iterations to run before checking for plateaus.
Defaults to 50% of the number of iterations (-iterations).
-verbose: flags, optional
If set to a non-zero value -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:
* kLogBetter
prints particle details when its fit becomes bebtter than its
previous best.
* kLogStall
prints particle details when its velocity reaches 0 or falls
below the stall threshold.
* kLogIter
Shows the current iteration number.
* kLogDetail
Shows additional details for some of the other logging options.
* kLogIterDetail
Shorthand for kLogIter | kLogIterDetail
setParams (%parameters)
Set or change optimization parameters. See -new above for a
description of the parameters that may be supplied.
init ()
Reinitialize the optimization. init () will be called during the
first call to optimize () if it hasn't already been called.
optimize ()
Runs the minimization optimization. Returns the fit value of the best
fit found. The best possible fit is negative infinity.
optimize () may be called repeatedly to continue the fitting process.
The fit processing on each subsequent call will continue from where
the last call left off.
getParticleState ()
Returns the vector of position
getBestParticles ([$n])
Takes an optional count.
Returns a list containing the best $n particle numbers. If $n is not
specified only the best particle number is returned.
getParticleBestPos ($particleNum)
Returns a list containing the best value of the fit and the vector of
its point in hyper space.
my ($fit, @vector) = $pso->getParticleBestPos (3)
getIterationCount ()
Return the number of iterations performed. This may be useful when
the -exitFit criteria has been met or where multiple calls to
optimize have been made.
BUGS
None... I hope.
If any: A small script which yields the problem will probably be of
help.
SEE ALSO
http://en.wikipedia.org/wiki/Particle_swarm_optimization
THANKS
Mario Roy for suggestions about efficiency.
AUTHOR
Strzelecki Lukasz <lukasz@strzeleccy.eu>
SEE ALSO
AI::ParticleSwarmOptimization AI::ParticleSwarmOptimization::Pmap
COPYRIGHT
Copyright (c) Strzelecki Lukasz. All rights reserved. This program is
free software; you can redistribute it and/or modify it under the same
terms as Perl itself.
example/PSOTest-MultiCore.pl view on Meta::CPAN
use strict;
use warnings;
use lib '../lib/';
#-----------------------------------------------------------------------
#use AI::ParticleSwarmOptimization;
use AI::ParticleSwarmOptimization::MCE;
#use AI::ParticleSwarmOptimization::Pmap;
use Data::Dumper; $::Data::Dumper::Sortkeys = 1;
#=======================================================================
sub calcFit {
my @values = @_;
my $offset = int (-@values / 2);
my $sum;
select( undef, undef, undef, 0.01 ); # Simulation of heavy processing...
$sum += ($_ - $offset++) ** 2 for @values;
return $sum;
}
#=======================================================================
++$|;
#-----------------------------------------------------------------------
#my $pso = AI::ParticleSwarmOptimization::Pmap->new( # Multi-core
my $pso = AI::ParticleSwarmOptimization::MCE->new( # Multi-core
#my $pso = AI::ParticleSwarmOptimization->new( # Single-core
-fitFunc => \&calcFit,
-dimensions => 10,
-iterations => 10,
-numParticles => 1000,
# only for many-core version # the best if == $#cores of your system
# selecting best value if undefined
-workers => 4,
);
my $beg = time;
$pso->init();
my $fitValue = $pso->optimize ();
my ( $best ) = $pso->getBestParticles (1);
my ( $fit, @values ) = $pso->getParticleBestPos ($best);
lib/AI/ParticleSwarmOptimization/MCE.pm view on Meta::CPAN
package AI::ParticleSwarmOptimization::MCE;
$AI::ParticleSwarmOptimization::MCE::VERSION = '1.006';
use strict;
use warnings;
use base qw(
AI::ParticleSwarmOptimization
Class::Accessor::Fast
);
#-----------------------------------------------------------------------
use Clone qw( clone );
use List::Util qw( min shuffle );
use Storable;
use MCE ( Sereal => 0 );
use MCE::Map;
use MCE::Util;
#-----------------------------------------------------------------------
__PACKAGE__->mk_accessors( qw(
_pop
_tpl
_wrk
));
#-----------------------------------------------------------------------
$Storable::Deparse = 1;
$Storable::Eval = 1;
#=======================================================================
sub new {
my ($class, %params) = @_;
#-------------------------------------------------------------------
my $self = bless {}, $class;
$self->SUPER::setParams( %params );
#-------------------------------------------------------------------
$self->_init_mce( \%params );
$self->_init_pop( \%params );
$self->_init_tpl( \%params );
#-------------------------------------------------------------------
return $self;
}
#=======================================================================
sub _init_tpl {
my ( $self, $params ) = @_;
my $cln = clone( $params );
delete $cln->{ $_ } for qw(
-iterCount
-iterations
-numParticles
-workers
_pop
_tpl
_wrk
);
$self->_tpl( $cln );
return;
}
#=======================================================================
sub _init_pop {
my ( $self, $params ) = @_;
my $pop = int( $self->{ numParticles } / $self->_wrk );
my $rst = $self->{ numParticles } % $self->_wrk;
my @pop = ( $pop ) x $self->_wrk;
$pop[ 0 ] += $rst;
$self->_pop( \@pop );
}
#=======================================================================
sub _init_mce {
my ( $self, $params ) = @_;
#-------------------------------------------------------------------
$self->_wrk( $params->{ '-workers' } || MCE::Util::get_ncpu() );
#-------------------------------------------------------------------
MCE::Map->init(
chunk_size => 1, # Thanks Roy :-)
#chunk_size => q[auto], # The old one. Currently it should be the same...
max_workers => $self->_wrk,
posix_exit => 1, # Thanks Roy :-)
);
#-------------------------------------------------------------------
return;
}
#=======================================================================
sub setParams {
my ( $self, %params ) = @_;
my $fles = __PACKAGE__->new( %params );
$self->{ $_ } = $fles->{ $_ } for keys %$fles;
return 1;
}
#=======================================================================
sub init {
my ( $self ) = @_;
#-------------------------------------------------------------------
my $pop = $self->{ numParticles };
$self->{ numParticles } = 1;
$self->SUPER::init();
$self->{ numParticles } = $pop;
$self->{ prtcls } = [ ];
#-------------------------------------------------------------------
my $cnt = 0;
my $tpl = $self->_tpl;
@{ $self->{ prtcls } } = map {
$_->{ id } = $cnt++;
$_
} mce_map {
my $arg = clone( $tpl );
$arg->{ -numParticles } = $_;
my $swm = AI::ParticleSwarmOptimization->new( %$arg );
$swm->init;
@{ $swm->{ prtcls } };
} @{ $self->_pop };
#-------------------------------------------------------------------
return 1;
}
#=======================================================================
sub _chunks {
my ( $self ) = @_;
#-------------------------------------------------------------------
@{ $self->{ prtcls } } = shuffle @{ $self->{ prtcls } };
#-------------------------------------------------------------------
my @chk;
for my $idx ( 0 .. $#{ $self->_pop } ){
#my $cnt = 0;
#my @tmp = map {
# $_->{ id } = $cnt++;
# $_
#} splice @{ $self->{ prtcls } }, 0, $self->_pop->[ $idx ];
# Faster and smaller memory consumption...
my $cnt = 0;
my @tmp = splice @{ $self->{ prtcls } }, 0, $self->_pop->[ $idx ];
$_->{ id } = $cnt++ for @tmp;
push @chk, \@tmp;
}
#-------------------------------------------------------------------
return \@chk;
}
#=======================================================================
sub _updateVelocities {
my ( $self, $iter ) = @_;
#-------------------------------------------------------------------
print "Iter $iter\n" if $self->{verbose} & AI::ParticleSwarmOptimization::kLogIter;
my $tpl = $self->_tpl;
my @lst = mce_map {
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
my $ary = $_;
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
my $arg = clone( $tpl );
$arg->{ -numParticles } = 1;
my $swm = AI::ParticleSwarmOptimization->new( %$arg );
$swm->init;
$swm->{ numParticles } = scalar( @$ary );
$swm->{ prtcls } = $ary;
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
$swm->_updateVelocities( $iter );
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[
$swm->{ prtcls },
$swm->{ bestBest },
]
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
} $self->_chunks;
#-------------------------------------------------------------------
#my $cnt = 0;
#@{ $self->{ prtcls } } = map {
# $_->{ id } = $cnt++;
# $_
#} map {
# @{ $_->[ 0 ] }
#} @lst;
# Faster and smaller memory consumption...
my $cnt = 0;
@{ $self->{ prtcls } } = map { @{ $_->[ 0 ] } } @lst;
$_->{ id } = $cnt++ for @{ $self->{ prtcls } };
#-------------------------------------------------------------------
$self->{ bestBest } = min grep { defined $_ } map { $_->[ 1 ] } @lst;
#-------------------------------------------------------------------
return;
}
#=======================================================================
sub _moveParticles {
my ( $self, $iter ) = @_;
#-------------------------------------------------------------------
print "Iter $iter\n" if $self->{verbose} & AI::ParticleSwarmOptimization::kLogIter;
my $tpl = $self->_tpl;
my @lst = mce_map {
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
my $ary = $_;
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
my $arg = clone( $tpl );
$arg->{ -numParticles } = 1;
my $swm = AI::ParticleSwarmOptimization->new( %$arg );
$swm->init;
$swm->{ numParticles } = scalar( @$ary );
$swm->{ prtcls } = $ary;
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[
$swm->_moveParticles( $iter ),
$swm->{ prtcls }
]
#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
} $self->_chunks;
#-------------------------------------------------------------------
#my $cnt = 0;
#@{ $self->{ prtcls } } = map {
# $_->{ id } = $cnt++;
# $_
#} map {
# @{ $_->[ 1 ] }
#} @lst;
# Faster and smaller memory consumption...
my $cnt = 0;
@{ $self->{ prtcls } } = map { @{ $_->[ 1 ] } } @lst;
$_->{ id } = $cnt++ for @{ $self->{ prtcls } };
#-------------------------------------------------------------------
return unless grep { defined $_ } map { $_->[ 0 ] } @lst;
return 1;
}
#=======================================================================
1;
__END__
=head1 NAME
AI::ParticleSwarmOptimization::MCE - Particle Swarm Optimization (object oriented) with support for multi-core processing
=head1 SYNOPSIS
use AI::ParticleSwarmOptimization::MCE;
my $pso = AI::ParticleSwarmOptimization::MCE->new (
-fitFunc => \&calcFit,
-dimensions => 3,
-iterations => 10,
-numParticles => 1000,
# only for many-core version # the best if == $#cores of your system
# selecting best value if undefined
-workers => 4,
);
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;
select( undef, undef, undef, 0.01 ); # Simulation of heavy processing...
$sum += ($_ - $offset++) ** 2 for @values;
return $sum;
}
=head1 Description
This module is enhancement of on original AI::ParticleSwarmOptimization to support
multi-core processing with use of MCE. Below you can find original documentation
of that module, but with one difference. There is new parameter "-workers", which
one can use to define of number of parallel processes that will be used during
computations.
The Particle Swarm Optimization technique uses communication of the current best
lib/AI/ParticleSwarmOptimization/MCE.pm view on Meta::CPAN
fitness value becomes equal or less than I<-exitFit>.
=item I<-fitFunc>: required
I<-fitFunc> is a reference to the fitness function used by the search. If extra
parameters need to be passed to the fitness function an array ref may be used
with the code ref as the first array element and parameters to be passed into
the fitness function as following elements. User provided parameters are passed
as the first parameters to the fitness function when it is called:
my $pso = AI::ParticleSwarmOptimization::MCE->new(
-fitFunc => [\&calcFit, $context],
-dimensions => 3,
);
...
sub calcFit {
my ($context, @values) = @_;
...
return $fitness;
}
In addition to any user provided parameters the list of values representing the
current particle position in the hyperspace is passed in. There is one value per
hyperspace dimension.
=item I<-inertia>: positive or zero number, optional
Determines what proportion of the previous velocity is carried forward to the
next iteration. Defaults to 0.9
lib/AI/ParticleSwarmOptimization/MCE.pm view on Meta::CPAN
Takes an optional count.
Returns a list containing the best $n particle numbers. If $n is not specified
only the best particle number is returned.
=item B<getParticleBestPos ($particleNum)>
Returns a list containing the best value of the fit and the vector of its point
in hyper space.
my ($fit, @vector) = $pso->getParticleBestPos (3)
=item B<getIterationCount ()>
Return the number of iterations performed. This may be useful when the
I<-exitFit> criteria has been met or where multiple calls to I<optimize> have
been made.
=back
=head1 BUGS
t/01_pso_multi.t view on Meta::CPAN
=head1 DESCRIPTION
Test AI::ParticleSwarmOptimization::MCE
=cut
plan (tests => 1);
# Calculation tests.
my $pso = AI::ParticleSwarmOptimization::MCE->new (
-fitFunc => \&calcFit,
-dimensions => 10,
-iterations => 10,
-numParticles => 1000,
# only for many-core version # the best if == $#cores of your system
# selecting best value if undefined
-workers => 4,
);
$pso->init();
my $fitValue = $pso->optimize ();
my ( $best ) = $pso->getBestParticles (1);
my ( $fit, @values ) = $pso->getParticleBestPos ($best);
my $iters = $pso->getIterationCount();
ok ( $fit > 100, 'Computations');
sub calcFit {
my @values = @_;
my $offset = int (-@values / 2);
my $sum;
$sum += ($_ - $offset++)**2 for @values;
return $sum;
}
( run in 0.312 second using v1.01-cache-2.11-cpan-4d50c553e7e )