AI-ParticleSwarmOptimization-MCE

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

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.

LICENSE  view on Meta::CPAN

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.]

LICENSE  view on Meta::CPAN

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.

LICENSE  view on Meta::CPAN

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.

LICENSE  view on Meta::CPAN

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.

META.json  view on Meta::CPAN

{
   "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"
}

META.yml  view on Meta::CPAN

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

README  view on Meta::CPAN

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 )