// $Id: force.h,v 1.9 2002/07/30 01:44:41 mkkuhner Exp

/*
Copyright 2002-2005 Mary K. Kuhner, Peter Beerli, and Joseph Felsenstein

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

/* Authors: Peter Beerli, Mary Kuhner, Jon Yamato and Joseph Felsenstein */


#ifndef FORCE_H
#define FORCE_H

#include <deque>
#include <string>
#include <utility>                      // std::pair
#include <vector>

#include "constants.h"
#include "parameter.h"                  // for Parameter member object
#include "plforces.h"                   // for PLForces classes
#include "stringx.h"
#include "types.h"
#include "vectorx.h"
#include "xml_strings.h"                // for string constants in GetXMLName()
#include "epoch.h"
#include "paramstat.h"

// in .cpp
// #include "forcesummary.h"   for forcesummary getter functions
// #include "event.h"          to set up Event vectors in arrangers

//------------------------------------------------------------------------------------

class Event;
class Registry;
class ChainPack;
class ChainOut;
class DataPack;
class ForceSummary;
class ForceParameters;
class Summary;
class IntervalData;
class Locus;
class Region;
class UIVarsPrior;

/******************************************************************
 The Force class defines a polymorphic object which embodies
 information about one of the evolutionary forces active in the
 program.  It has four main functions:

 (1)  To indicate, by its presence in the ForceSummary, that the
 force is active.

 (2)  To manage the parameters associated with its force (for
 example, the theta values associated with Coalescence).  It maintains
 a vector of Parameter objects for this purpose.

 (3)  To provide information to the rest of the program about
 its force (quickestimate, name, dimensionality, table headers, etc.)

 (4)  To act as a factory for the Event objects (representing concepts
 such as "a coalescence of two active lineages") used by the Arrangers,
 and for the Summary objects (representing presence of a force) used
 by the TreeSummary.

 A fifth main function, handling force-specific math, may be
 added when we integrate the posterior-likelihood module.

 The only place Force objects normally exist is inside of the
 (singular) ForceSummary object, which owns them.

 Forces are only created after both data reading and user input
 (menu) are completed.

 Forces are by design, neither copyable nor assignable.

 Written by Mary Kuhner and Jon Yamato
 * 04/04/02 Peter Beerli added PLforces objects
 * 11/14/02 Peter Beerli made Profile-modifier force specific
 * 6/9/10 Mary Kuhner and Jon Yamato added DivForce and DivMigForce
 ******************************************************************/

class Force
{
  private:
    // these are undefined because we should not be copying or
    // assigning Forces. The registry creates one force of each
    // used type, and puts them in the ForceSummary object.
    Force();                                // undefined
    Force(const Force& src);                // undefined
    Force&     operator=(const Force& src); // undefined

  protected:

    force_type  m_tag;                  // identifying tag of force
    string      m_name;                 // concise name of the force
    string      m_fullname;             // full name of the force
    string      m_paramname;            // concise name of the parameter type
    string      m_fullparamname;        // full name of the parameter type

    std::vector<Parameter> m_parameters; // all parameters related to this force

    long m_maxevents;                   // maximum "events" of this force allowed per tree
    double m_defvalue;                  // default value of parameters for this force
    double m_maxvalue;                  // maximum allowed value for each initial param estimate
    double m_minvalue;                  // minimum allowed value for each initial param estimate
    double m_maximizer_maxvalue;        // maximum value allowed during maximization
    double m_maximizer_minvalue;        // minimum value allowed during maximiztion

    double m_highval;                   // a reasonable upper guess for the force.
    double m_lowval;                    // a reasonable lower guess for the force.
    double m_highmult;                  // The stepsize up for high guesses.
    double m_lowmult;                   // The stepsize down for low guesses.

    StringVec1d m_axisname;             // name of each table axis

    DoubleVec1d m_paramgroupmultipliers; // dim: by param group, multiplier
    // is ratio first/head param over other param
    // NB Assumes never more than 2 parameters in a multiplicative group!
    // if we ever need more than 2, need to redimension

    // postlike forces related objects that contain functions that are called by
    // point() and wait() in the post-likelihood calculation
    PLForces * m_plforceptr;            // holds force object; OWNING POINTER

    // When parameters are constrained to be equal to one another
    // that information lives here:
    std::vector<ParamGroup> m_identgroups;

    // When parameters are constrained to be multiples of one another
    // that information lives here:
    std::vector<ParamGroup> m_multgroups;

    //This variable is solely for the XML writer.  Hmmm.
    Prior m_defaultPrior;

    // Utility function used by InsertParameters
    DoubleVec1d PopParameters(DoubleVec1d& parameters);

    // used by Force::ToXML()
    virtual std::string MakeOpeningTag(unsigned long nspaces) const;
    std::vector<proftype> GetProfileTypes() const;
    std::vector<ParamStatus> GetParamstatuses() const;

  public:

    Force(   force_type          tag,
             string              name,
             string              fullname,
             string              paramname,
             string              fullparamname,
             std::vector<Parameter>   parameters,
             long int            maxevents,
             double              defvalue,
             double              maxvalue,
             double              minvalue,
             double              maximizer_maxvalue,
             double              maximizer_minvalue,
             double              highval,
             double              lowval,
             double              highmult,
             double              lowmult,
             std::vector<ParamGroup> identgroups,
             std::vector<ParamGroup> multgroups,
             const DoubleVec1d&      paramgroupmults,
             const UIVarsPrior&      prior);

    virtual ~Force() { delete m_plforceptr; };

    // Report writing functions -- these could be implemented at base level
    // except for MigrationParameter
    virtual StringVec1d    MakeStartParamReport() const;
    virtual StringVec1d    MakeChainParamReport(const ChainOut& chout) const;
    virtual bool           HasNoVaryingParameters() const;

    // RTTI for use by ForceSummary::GetPartitionForces()
    virtual bool           IsPartitionForce() const { return false; };
    // RTTI for use by ForceSummary::GetSelectedSites()
    virtual bool           IsLocalPartitionForce() const { return false; };
    virtual bool           IsSexualForce() const    { return false; };
    // RTTI for use by ForceSummary::UsingStick()
    virtual bool           IsStickForce() const     { return false; };

    // Getters
    force_type     GetTag()           const { return m_tag; };
    string         GetFullName()      const { return m_fullname; };
    string         GetFullparamname() const { return m_fullparamname; };
    string         GetShortparamname()const { return m_paramname; };
    virtual string         GetClassName()     const { return "Class"; };
    virtual string         GetXMLName()       const = 0;
    virtual long int       ReportDimensionality() const = 0;
    StringVec1d    GetAxisname()      const { return m_axisname; };
    DoubleVec2d    GetMles()          const;
    DoubleVec1d    GetPopmles()       const;

    long int       GetMaxEvents()     const { return m_maxevents; };
    double         GetDefaultValue()  const { return m_defvalue; };
    MethodTypeVec1d GetMethods()      const;
    long int       GetNParams()       const { return m_parameters.size(); };

    StringVec1d    GetAllParamNames() const;
    double GetHighVal() const  { return m_highval; };
    double GetLowVal() const   { return m_lowval; };
    double GetHighMult() const { return m_highmult; };
    double GetLowMult() const  { return m_lowmult; };
    double GetMaximizerMaxVal() const { return m_maximizer_maxvalue; };
    double GetMaximizerMinVal() const { return m_maximizer_minvalue; };

    std::vector<Parameter>& GetParameters()  { return m_parameters; };
    const std::vector<Parameter>& GetParameters() const { return m_parameters; };

    // used by ForceParameters::SetAllTo(), polymorphic in PartitionForce
    virtual DoubleVec1d CreateVectorOfParametersWithValue(double val) const;

    // returns pointer to PLForces object [that holds the force specific
    // wait() and point() functions
    PLForces * GetPLForceFunction() { return m_plforceptr; };

    // SummarizeProfTypes--used by ReportPage::SetupColhdr()
    proftype       SummarizeProfTypes() const;

    // Handle grouping of parameters constrained to be related to one another
    ULongVec2d     GetIdenticalGroupedParams() const;
    ULongVec2d     GetMultiplicativeGroupedParams() const;
    DoubleVec1d    GetParamGroupMultipliers() const;

    virtual StringVec1d    ToXML(unsigned long int nspaces) const;

    // Setters
    // No setters for intrinsic class qualities like name, as these
    // are built into the subclasses.
    // SetParameters is a helper function for
    // ForceSummary::SetAllParameters() used in ParamVector dtor.
    void        SetParameters(const std::vector<Parameter>& src)
    { m_parameters = src; };
    // true if value is set, false otherwise
    virtual bool        SetPartIndex(long int) { return false; };

    // used by Branch::IsAMember()
    virtual bool        IsAMember(const LongVec1d& m1, const LongVec1d& m2) const;

    // used by ForceSummary::SummarizeData()
    std::deque<bool> UseCalculatedValues() const;
    virtual double      Truncate(double target) const;

    // generally interface into a ForceParameters object
    virtual DoubleVec1d RetrieveGlobalParameters(const ForceParameters& fp) const;
    virtual DoubleVec1d RetrieveRegionalParameters(const ForceParameters& fp) const;
    virtual DoubleVec1d RetrieveGlobalLogParameters(const ForceParameters& fp) const;
    virtual DoubleVec1d RetrieveRegionalLogParameters(const ForceParameters& fp) const;
    // FindOrdinalPosition used by BayesArranger::Rearrange
    unsigned long int FindOrdinalPosition(long int cannonicalorder) const;

    // The following functions manage the Events associated with a particular
    // force.  Events are owned by the recipient (an Arranger).
    virtual std::vector<Event*> MakeEvents(const ForceSummary& fs) const = 0;
    virtual void           ModifyEvents(const ForceSummary&,
                                        std::vector<Event*>&) const {};

    // The following function is used in creating the partition holder in each branch.
    virtual long int      GetNPartitions() const { return 0; };

    // The following is a factory function to make Summary objects for the TreeSummary.
    virtual Summary* CreateSummary(IntervalData& interval, bool shortness) const = 0;
}; // Force

//------------------------------------------------------------------------------------

class RecForce : public Force
{
  private:
    RecForce();                               // unimplemented to block call
    RecForce(const RecForce& src);            // unimplemented to block call
    RecForce& operator=(const RecForce& src); // unimplemented to block call

  public:
    RecForce ( std::vector<Parameter>  parameters,
               long int                maxEvents,
               std::vector<ParamGroup> identgroups,
               std::vector<ParamGroup> multgroups,
               const DoubleVec1d&      paramgroupmults,
               const UIVarsPrior&      prior);
    virtual                ~RecForce() {};

    virtual bool           IsSexualForce() const { return true; };
    virtual string         GetXMLName() const { return xmlstr::XML_TAG_RECOMBINATION; };
    virtual std::vector<Event*> MakeEvents(const ForceSummary& fs) const;
    virtual Summary*       CreateSummary(IntervalData& interval, bool shortness) const;
    virtual long int       ReportDimensionality() const { return 1L; };

}; // RecForce

//------------------------------------------------------------------------------------

class CoalForce : public Force
{
  private:
    CoalForce();                                // unimplemented to block call
    CoalForce(const CoalForce& src);            // unimplemented to block call
    CoalForce& operator=(const CoalForce& src); // unimplemented to block call

  public:
    CoalForce( std::vector<Parameter>   parameters,
               long int            maxEvents,
               bool                withGrowth,
               bool                withLogisticSelection,
               std::vector<ParamGroup> identgroups,
               std::vector<ParamGroup> multgroups,
               const DoubleVec1d&      paramgroupmults,
               const UIVarsPrior&      prior);

    virtual                ~CoalForce() {};

    virtual string         GetXMLName() const { return xmlstr::XML_TAG_COALESCENCE; };
    virtual std::vector<Event*> MakeEvents(const ForceSummary & fs) const;
    virtual Summary*       CreateSummary(IntervalData& interval, bool shortness) const;
    virtual long int       ReportDimensionality() const;

}; // CoalForce

//------------------------------------------------------------------------------------

class GrowthForce : public Force
{
  private:
    GrowthForce();                                  // unimplemented to block call
    GrowthForce(const GrowthForce& src);            // unimplemented to block call
    GrowthForce& operator=(const GrowthForce& src); // unimplemented to block call

  protected:
    virtual std::string MakeOpeningTag(unsigned long int nspaces) const;
  public:
    GrowthForce ( std::vector<Parameter>  parameters,
                  long int                maxEvents,
                  std::vector<ParamGroup> identgroups,
                  std::vector<ParamGroup> multgroups,
                  const DoubleVec1d&      paramgroupmults,
                  const UIVarsPrior&      prior);
    virtual              ~GrowthForce() {};

    virtual string         GetXMLName() const { return xmlstr::XML_TAG_GROWTH; };
    virtual std::vector<Event*> MakeEvents(const ForceSummary& fs)   const;
    virtual void           ModifyEvents(const ForceSummary& fs, std::vector<Event*>& events) const;

    virtual Summary*       CreateSummary(IntervalData& interval, bool shortness) const;

    virtual DoubleVec1d    RetrieveGlobalLogParameters(const ForceParameters& fp) const;
    virtual DoubleVec1d    RetrieveRegionalLogParameters(const ForceParameters& fp) const;

    virtual long int       ReportDimensionality() const;

}; // GrowthForce

//------------------------------------------------------------------------------------

class LogisticSelectionForce : public Force
{
  private:
    LogisticSelectionForce();                                             // unimplemented to block call
    LogisticSelectionForce(const LogisticSelectionForce& src);            // unimplemented to block call
    LogisticSelectionForce& operator=(const LogisticSelectionForce& src); // unimplemented to block call

  protected:
    virtual std::string MakeOpeningTag(unsigned long int nspaces) const;
  public:
    LogisticSelectionForce(std::vector<Parameter>  parameters,
                           long int                maxEvents,
                           long int                paramvecindex,
                           std::vector<ParamGroup> identgroups,
                           std::vector<ParamGroup> multgroups,
                           const DoubleVec1d&      paramgroupmults,
                           const UIVarsPrior&      prior);
    virtual              ~LogisticSelectionForce() {};

    virtual string         GetXMLName() const { return xmlstr::XML_TAG_LOGISTICSELECTION; };
    virtual std::vector<Event*> MakeEvents(const ForceSummary& fs)   const;
    virtual void           ModifyEvents(const ForceSummary& fs, std::vector<Event *> & events) const;

    virtual Summary *      CreateSummary(IntervalData& interval, bool shortness) const;

    virtual DoubleVec1d    RetrieveGlobalLogParameters(const ForceParameters & fp) const;
    virtual DoubleVec1d    RetrieveRegionalLogParameters(const ForceParameters & fp) const;

    virtual long int       ReportDimensionality() const;

}; // LogisticSelectionForce

//------------------------------------------------------------------------------------

class RegionGammaForce : public Force
{
  private:
    RegionGammaForce();                            // unimplemented to block call
    RegionGammaForce(const RegionGammaForce& src); // unimplemented to block call

  public:
    RegionGammaForce(std::vector<Parameter>  parameters,
                     std::vector<ParamGroup> identgroups,
                     std::vector<ParamGroup> multgroups,
                     const DoubleVec1d&      paramgroupmults,
                     const UIVarsPrior&      prior);
    virtual ~RegionGammaForce() {};

    virtual string          GetXMLName() const { return xmlstr::XML_TAG_REGION_GAMMA; };
    virtual std::vector<Event *> MakeEvents(const ForceSummary & fs) const;
    virtual Summary *       CreateSummary(IntervalData& interval, bool shortness) const;
    virtual long int        ReportDimensionality() const;

}; // RegionGammaForce

//------------------------------------------------------------------------------------

class PartitionForce : public Force
{
    PartitionForce();                                     // unimplemented to block call
    PartitionForce(const PartitionForce& src);            // unimplemented to block call
    PartitionForce& operator=(const PartitionForce& src); // unimplemented to block call
  protected:
    long int     m_npartitions;
    long int     m_partindex;   // what is my index in a branch's partitionvector?

    virtual std::string  GetXMLStatusTag() const = 0;

  public:
    PartitionForce( force_type          tag,
                    string              name,
                    string              fullname,
                    string              paramname,
                    string              fullparamname,
                    std::vector<Parameter>   parameters,
                    long int            maxevents,
                    double              defvalue,
                    double              maxvalue,
                    double              minvalue,
                    double              maximizer_maxvalue,
                    double              maximizer_minvalue,
                    double              highval,
                    double              lowval,
                    double              highmult,
                    double              lowmult,
                    long                npartitions,
                    std::vector<ParamGroup> identgroups,
                    std::vector<ParamGroup> multgroups,
                    const DoubleVec1d&      paramgroupmults,
                    const UIVarsPrior&      prior);
    virtual              ~PartitionForce() {};

    // RTTI for use by ForceSummary::GetPartitionForces()
    virtual bool         IsPartitionForce() const { return true; };
    virtual long int     ChoosePartition(long int origpart, long int chosenpart, bool islow, long int midpoint) const;

    virtual void         ModifyEvents(const ForceSummary& fs, std::vector<Event*>& events) const;

    virtual StringVec1d  MakeStartParamReport() const;
    virtual StringVec1d  MakeChainParamReport(const ChainOut& chout) const;

    // used by ForceSummary::SummarizeData()
    virtual bool         SetPartIndex(long int val);

    virtual long int     GetNPartitions() const { return m_npartitions; };
    virtual long int     GetPartIndex() const { return m_partindex; };

    virtual bool         IsAMember(const LongVec1d& m1, const LongVec1d& m2) const;

    virtual DoubleVec1d  CreateVectorOfParametersWithValue(double val) const;

    virtual DoubleVec1d  SumXPartsToParts(const DoubleVec1d& xparts) const;
    virtual DoubleVec1d  SumXPartsToParts(const DoubleVec1d& xparts, const DoubleVec1d& growths, double etime) const;

    // used by SampleXML::ToXML()
    virtual std::string  MakeStatusXML(const std::string& mystatus) const;

}; // PartitionForce

//------------------------------------------------------------------------------------

class LocalPartitionForce : public PartitionForce
{
  private:
    LocalPartitionForce();                                          // undefined
    LocalPartitionForce(const LocalPartitionForce& src);            // undefined
    LocalPartitionForce& operator=(const LocalPartitionForce& src); // undefined

  protected:
    long int m_localsite;               // the site that the force is dependent on

  public:
    LocalPartitionForce(    force_type          tag,
                            string              name,
                            string              fullname,
                            string              paramname,
                            string              fullparamname,
                            std::vector<Parameter>   parameters,
                            long int            maxevents,
                            double              defvalue,
                            double              maxvalue,
                            double              minvalue,
                            double              maximizer_maxvalue,
                            double              maximizer_minvalue,
                            double              highval,
                            double              lowval,
                            double              highmult,
                            double              lowmult,
                            long                npartitions,
                            long                localsite,
                            std::vector<ParamGroup> identgroups,
                            std::vector<ParamGroup> multgroups,
                            const DoubleVec1d&      paramgroupmults,
                            const UIVarsPrior&      prior);
    virtual              ~LocalPartitionForce() {};
    virtual bool         IsLocalPartitionForce() const { return true; };
    virtual long int     ChoosePartition(long int origpart, long int chosenpart, bool islow, long int midpoint) const;

    // getter used by ToXML
    long int     GetLocalSite() const { return m_localsite; };
    virtual StringVec1d  ToXML(unsigned long int nspaces) const;

}; // LocalPartitionForce

//------------------------------------------------------------------------------------

class MigForce : public PartitionForce
{
  private:
    MigForce();                                // undefined
    MigForce(const MigForce& src);             // undefined
    MigForce& operator=(const MigForce& src);  // undefined

  protected:
    virtual std::string    GetXMLStatusTag() const;

  public:
    MigForce ( std::vector<Parameter>   parameters,
               long                maxEvents,
               long                numPops,
               std::vector<ParamGroup> identgroups,
               std::vector<ParamGroup> multgroups,
               const DoubleVec1d&      paramgroupmults,
               const UIVarsPrior&      prior);
    virtual                ~MigForce() {};
    virtual string         GetClassName() const { return "Population"; };

    virtual string         GetXMLName() const { return xmlstr::XML_TAG_MIGRATION; };
    virtual std::vector<Event*> MakeEvents(const ForceSummary& fs)   const;
    virtual Summary*       CreateSummary(IntervalData& interval, bool shortness) const;
    virtual std::string    MakeStatusXML(const std::string&) const { return string(""); };
    virtual long int       ReportDimensionality() const { return 3L; };

}; // MigForce

//------------------------------------------------------------------------------------

class DivMigForce : public PartitionForce
// Migration in the presence of divergence; should never exist unless
// DivForce also exists
{
  private:
    DivMigForce();                                  // undefined
    DivMigForce(const DivMigForce& src);            // undefined
    DivMigForce& operator=(const DivMigForce& src); // undefined

  protected:
    virtual std::string    GetXMLStatusTag() const;

  public:
    DivMigForce ( std::vector<Parameter>   parameters,
                  long                maxEvents,
                  long                numPops,
                  std::vector<ParamGroup> identgroups,
                  std::vector<ParamGroup> multgroups,
                  const DoubleVec1d&      paramgroupmults,
                  const UIVarsPrior&      prior);
    virtual                ~DivMigForce() {};
    virtual string         GetClassName() const { return "Population"; };

    virtual string         GetXMLName() const { return xmlstr::XML_TAG_DIVMIG; };
    virtual std::vector<Event*> MakeEvents(const ForceSummary& fs)   const;
    virtual Summary*       CreateSummary(IntervalData& interval, bool shortness) const;
    virtual std::string    MakeStatusXML(const std::string&) const { return string(""); };
    virtual long int       ReportDimensionality() const { return 3L; };

}; // DivMigForce

//------------------------------------------------------------------------------------

class DiseaseForce : public LocalPartitionForce
{
  private:
    // there exists no quickcalculator equivalent for disease
    DiseaseForce();                                   // undefined
    DiseaseForce(const DiseaseForce& src);            // undefined
    DiseaseForce& operator=(const DiseaseForce& src); // undefined

  protected:
    virtual std::string  GetXMLStatusTag() const;

  public:
    DiseaseForce(const DataPack& dpack, const UIVars& uivars);
    DiseaseForce(std::vector<Parameter>   parameters,
                 long int                 maxEvents,
                 bool                     hasLogisticSelection,
                 long int                 numDiseaseStates,
                 long int                 localsite,
                 std::vector<ParamGroup>  identgroups,
                 std::vector<ParamGroup>  multgroups,
                 const DoubleVec1d&       paramgroupmults,
                 const UIVarsPrior&       prior);
    virtual ~DiseaseForce() {};

    virtual string          GetXMLName() const { return xmlstr::XML_TAG_DISEASE; };
    virtual std::vector<Event *> MakeEvents(const ForceSummary & fs) const;

    virtual Summary *       CreateSummary(IntervalData& interval, bool shortness) const;
    virtual long int        ReportDimensionality() const { return 3L; };

}; // DiseaseForce

//------------------------------------------------------------------------------------

class StickForce : public Force
{
  private:
    // the default ctor, copy ctor, and operator= are all
    // deliberately undefined to block call
    StickForce();
    StickForce(const StickForce& src);
    StickForce& operator=(const StickForce& src);

  protected:
    double m_percentchange;
    StickForce (force_type         tag,
                string             name,
                string             fullname,
                string             paramname,
                string             fullparamname,
                std::vector<Parameter>  parameters,
                long int           maxevents,
                double             defvalue,
                double             maxvalue,
                double             minvalue,
                double             maximizer_maxvalue,
                double             maximizer_minvalue,
                double             highval,
                double             lowval,
                double             highmult,
                double             lowmult,
                std::vector<ParamGroup> identgroups,
                std::vector<ParamGroup> multgroups,
                const DoubleVec1d&      paramgroupmults,
                const UIVarsPrior&      prior);

  public:
    virtual        ~StickForce() {};
    virtual bool   IsStickForce() const     { return true; };
};

//------------------------------------------------------------------------------------

class StickExpGrowForce : public StickForce
{
  private:
    // the default ctor, copy ctor, and operator= are all
    // deliberately undefined to block call
    StickExpGrowForce();
    StickExpGrowForce(const StickExpGrowForce& src);
    StickExpGrowForce& operator=(const StickExpGrowForce& src);

    const double m_negln, m_posln;

  protected:

    virtual std::string MakeOpeningTag(unsigned long int nspaces) const;

  public:
    StickExpGrowForce  ( std::vector<Parameter> parameters,
                         long int          maxEvents,
                         std::vector<ParamGroup> identgroups,
                         std::vector<ParamGroup> multgroups,
                         const DoubleVec1d&      paramgroupmults,
                         const UIVarsPrior&      prior);
    virtual             ~StickExpGrowForce() {};

    virtual string         GetXMLName() const;
    virtual std::vector<Event*> MakeEvents(const ForceSummary& fs) const;
    virtual void           ModifyEvents(const ForceSummary& fs, std::vector<Event*>& events) const;
    virtual Summary*       CreateSummary(IntervalData& interval, bool shortness) const;

    virtual DoubleVec1d    RetrieveGlobalLogParameters
    (const ForceParameters& fp) const;
    virtual DoubleVec1d    RetrieveRegionalLogParameters
    (const ForceParameters& fp) const;

    virtual long int       ReportDimensionality() const;
};

//------------------------------------------------------------------------------------

class StickSelectForce : public StickForce
{
  private:
    // The default ctor, copy ctor, and operator= are all deliberately undefined to block call.
    StickSelectForce();
    StickSelectForce(const StickSelectForce& src);
    StickSelectForce& operator=(const StickSelectForce& src);

  protected:

    virtual std::string MakeOpeningTag(unsigned long int nspaces) const;

  public:
    StickSelectForce  ( std::vector<Parameter> parameters,
                        long int          maxEvents,
                        std::vector<ParamGroup> identgroups,
                        std::vector<ParamGroup> multgroups,
                        const DoubleVec1d&      paramgroupmults,
                        const UIVarsPrior&      prior);
    virtual             ~StickSelectForce() {};

    virtual string         GetXMLName() const;
    virtual long int       ReportDimensionality() const;
    virtual Summary *       CreateSummary(IntervalData& interval, bool shortness) const;

    virtual std::vector<Event*> MakeEvents(const ForceSummary& fs) const ;

    virtual DoubleVec1d    RetrieveGlobalLogParameters
    (const ForceParameters& fp) const;
    virtual DoubleVec1d    RetrieveRegionalLogParameters
    (const ForceParameters& fp) const;
};

//------------------------------------------------------------------------------------

class DivForce : public Force
{
  private:
    // the default ctor, copy ctor, and operator= are all
    // deliberately undefined to block call
    DivForce();
    DivForce(const DivForce& src);
    DivForce& operator=(const DivForce& src);

    std::vector<Epoch> m_epochs;

  public:
    DivForce           ( std::vector<Parameter> parameters,
                         long int          maxEvents,
                         std::vector<ParamGroup> identgroups,
                         std::vector<ParamGroup> multgroups,
                         const DoubleVec1d&      paramgroupmults,
                         const UIVarsPrior&      prior,
                         const std::vector<std::vector<std::string> >& newpops,
                         const std::vector<std::string>& ancestors,
                         const DataPack& dpack);
    virtual             ~DivForce() {};

    virtual string         GetXMLName() const { return xmlstr::XML_TAG_DIVERGENCE; };
    virtual long int       ReportDimensionality() const;
    virtual Summary *       CreateSummary(IntervalData& interval, bool shortness) const;

    virtual std::vector<Event*> MakeEvents(const ForceSummary& fs) const ;
    const std::vector<Epoch>* GetEpochs() const { return &m_epochs; };
    virtual StringVec1d    ToXML(unsigned long int nspaces) const;
};

//------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------

// These free functions pretty-print a matrix of various dimensions

StringVec1d Tabulate(double params, long int width);
StringVec1d Tabulate(const DoubleVec1d & params, long int width);
StringVec1d Tabulate(const DoubleVec2d & params, long int width);

#endif // FORCE_H

//____________________________________________________________________________________
