file jswarm/jswarm.cpp

[No description available] More…

Functions

Name
scanner_plugin(jswarm , version(1, 0, 0) )

Detailed Description

Author: Pat Scott (pat.scott@uq.edu.au)

Date: 2019 Oct

j-Swarm: particle swarm optimisation with meta-optimisation a la jDE.


Authors (add name and date if you modify):


Functions Documentation

function scanner_plugin

scanner_plugin(
    jswarm ,
    version(1, 0, 0) 
)

Source code

//   GAMBIT: Global and Modular BSM Inference Tool
//   *********************************************
///  \file
///
///  j-Swarm: particle swarm optimisation with
///  meta-optimisation a la jDE.
///
///  *********************************************
///
///  Authors (add name and date if you modify):
///
///  \author Pat Scott
///          (pat.scott@uq.edu.au)
///  \date 2019 Oct
///
///  *********************************************

#include <vector>
#include "gambit/ScannerBit/scanners/jswarm/jswarm.hpp"

scanner_plugin(jswarm, version(1, 0, 0))
{

  // Access jswarm stuff and standard Gambit things
  using namespace Gambit;
  using namespace Gambit::jswarm_1_0_0;

  // Error thrown if the following entries are not present in the inifile
  reqd_inifile_entries("NP");

  // Make a new particle swarm
  particle_swarm swarm;

  // Code to execute when the plugin is loaded.
  plugin_constructor
  {
    // Retrieve the external likelihood calculator
    swarm.likelihood_function = get_purpose(get_inifile_value<std::string>("like"));
    if (swarm.likelihood_function->getRank() == 0) cout << "Loading j-Swarm plugin for ScannerBit." << std::endl;
    // Retrieve the external printer
    swarm.printer = &(get_printer());
    // Do not allow GAMBIT's own likelihood calculator to directly shut down the scan.
    // j-Swarm will assume responsibility for this process, triggered externally by
    // the 'plugin_info.early_shutdown_in_progress()' function.
    swarm.likelihood_function->disable_external_shutdown();
  }

  int plugin_main (void)
  {
    // Path to save j-Swarm samples, resume files, etc
    str defpath = get_inifile_value<str>("default_output_path");
    str root = Utils::ensure_path_exists(get_inifile_value<str>("path",defpath+"j-Swarm/native"));
    swarm.path = root;

    // Ask the printer if this is a resumed run or not, and check that the necessary files exist if so.
    bool resume = get_printer().resume_mode();
    if (resume)
    {
      bool good = true;
      static const std::vector<str> names = initVector<str>(root+".settings.yaml", root+".lastgen");
      for (auto it = names.begin(); it != names.end(); ++it)
      {
        std::ifstream file(*it);
        good = good and file.good() and (file.peek() != std::ifstream::traits_type::eof());
        file.close();
      }
      if (not good)
      {
        std::ostringstream warning;
        warning << "Cannot resume previous j-Swarm run because one or all of" << endl;
        for (auto it = names.begin(); it != names.end(); ++it) warning << " " << *it << endl;
        warning << "is missing or empty.  This is probably because your last run didn't " << endl
                << "complete even one generation. j-Swarm will start from scratch, " << endl
                << "as if you had specified -r.";
        if (swarm.likelihood_function->getRank() == 0) cout << "WARNING: " << warning.str() << endl;
        scan_warn << warning.str() << scan_end;
        resume = false;
      }
    }
    swarm.resume = resume;

    // Retrieve the global option specifying the minimum interesting likelihood.
    double gl0 = get_inifile_value<double>("likelihood: model_invalid_for_lnlike_below");
    // Retrieve the global option specifying the likelihood offset to use
    double offset = get_inifile_value<double>("likelihood: lnlike_offset", 1e-4*gl0);
    // Make sure the likleihood functor knows to apply the offset internally in ScannerBit
    swarm.likelihood_function->setPurposeOffset(offset);
    // Offset the minimum interesting likelihood by the offset.
    gl0 = gl0 + offset;

    // Other j-Swarm run parameters
    swarm.nPar                = get_dimension();                                         // Dimensionality of the parameter space
    swarm.nDerived            =                                                 0;       // Number of derived quantities to output (GAMBIT printers handle these).
    swarm.nDiscrete           = get_inifile_value<int>   ("nDiscrete",          0);      // Number of parameters that are to be treated as discrete
    swarm.maxgen              = get_inifile_value<int>   ("maxgen",             5000);   // Maximum number of generations
    swarm.NP                  = get_inifile_value<int>   ("NP");                         // Population size (individuals per generation)
    swarm.omega               = get_inifile_value<double>("omega",              0.7298); // Inertial weight (default is Constriction Coefficient PSO)
    swarm.phi1                = get_inifile_value<double>("phi1",               1.5);    // Cognitive weight (default is Constriction Coefficient PSO)
    swarm.phi2                = get_inifile_value<double>("phi2",               1.5);    // Social weight (default is Constriction Coefficient PSO)
    swarm.bndry               = get_inifile_value<int>   ("bndry",              3);      // Boundary constraint: 1=brick wall, 2=random re-initialization, 3=reflection
    swarm.adapt_phi           = get_inifile_value<bool>  ("adaptive_phi",       false);  // Use self-optimising adaptive choices for phi1 and phi2
    swarm.adapt_omega         = get_inifile_value<bool>  ("adaptive_omega",     false);  // Use self-optimising adaptive choices for omega
    swarm.convthresh          = get_inifile_value<double>("convthresh",         1.e-3);  // Threshold for gen-level convergence: smoothed fractional improvement in the mean personal best population value
    swarm.convsteps           = get_inifile_value<int>   ("convsteps",          10);     // Number of steps to smooth over when checking convergence
    swarm.savecount           = get_inifile_value<int>   ("savecount",          1);      // Save progress every savecount generations
    swarm.init_pop_strategy   = get_inifile_value<int>   ("init_population_strategy", 2);// Initialisation strategy: 0=one shot, 1=n-shot, 2=n-shot with error if no valid vectors found.
    swarm.init_stationary     = get_inifile_value<bool>  ("init_stationary", false);     // Initialise particle velocities to to zero
    swarm.max_ini_attempts    = get_inifile_value<int>   ("max_initialisation_attempts", 10000); // Maximum number of times to try to find a valid vector for each slot in the initial population.
    swarm.min_acceptable_value= get_inifile_value<double>("min_acceptable_value",0.9999*gl0); // Minimum function value to accept for the initial generation if init_population_strategy > 0.
    swarm.verbose             = get_inifile_value<int>   ("verbosity",          1);      // Output verbosity: 0=only error messages, 1=basic info, 2=generation-level info, 3+=particle-level info
    swarm.seed                = get_inifile_value<int>   ("seed",               -1);     // Base seed for random number generation; non-positive means seed from the system clock
    swarm.allow_new_settings  = get_inifile_value<bool>  ("allow_new_settings", false);  // Allow settings to be overridden with new values when resuming
    swarm.save_particles_natively = get_inifile_value<bool>("save_particles_natively", false); // Save full particle data from every generation

    // Initialise the swarm
    swarm.init();

    // Unit cube boundaries
    for (int i = 0; i < swarm.nPar; i++)
    {
      swarm.lowerbounds.at(i) = 0.0;
      swarm.upperbounds.at(i) = 1.0;
    }

    // Discrete parameters
    for (int i = 0; i < swarm.nDiscrete; i++)
    {
      swarm.discrete.at(i) = 0; //Inidices of discrete parameters (C-style, starting at 0)
    }                           //TODO Needs to be set automatically somehow?  Not yet sure how to deal with discrete parameters in GAMBIT.

    // Run the swarm
    if (swarm.likelihood_function->getRank() == 0) cout << "Starting j-Swarm run...\n" << std::endl;
    swarm.run();
    if (swarm.likelihood_function->getRank() == 0) cout << "j-Swarm run finished!" << std::endl;
    return 0;

  }

}

Updated on 2025-02-12 at 15:36:40 +0000