file src/models.cpp
[No description available] More…
Namespaces
Name |
---|
Gambit TODO: see if we can use this one: |
Gambit::Models Forward declaration of Models::ModelFunctorClaw class for use in constructors. |
Detailed Description
Library of Models methods.
Duties:
- Activate primary_model_functors according to the model(s) being scanned
- Check whether all active primary_model_functors are actually used
Authors
(add name and date if you modify)
Ben Farmer (benjamin.farmer@monash.edu.au)
2013 July 17
Pat Scott (patscott@physics.mcgill.ca)
2013 Aug, Sep
2014 Mar
Patrick Stoecker (stoecker@physik.rwth-aachen.de)
2023 Nov
Source code
// GAMBIT: Global and Modular BSM Inference Tool
// *********************************************
/// \file
///
/// Library of Models methods.
///
/// Duties:
/// * Activate primary_model_functors according to
/// the model(s) being scanned
/// * Check whether all active primary_model_functors
/// are actually used
///
/// *********************************************
///
/// Authors
/// =======
///
/// (add name and date if you modify)
///
/// \author Ben Farmer
/// (benjamin.farmer@monash.edu.au)
/// \date 2013 July 17
///
/// \author Pat Scott
/// (patscott@physics.mcgill.ca)
/// \date 2013 Aug, Sep
/// \date 2014 Mar
///
/// \author Patrick Stoecker
/// (stoecker@physik.rwth-aachen.de)
/// \date 2023 Nov
///
/// *********************************************
#include <algorithm>
#include "gambit/Elements/functors.hpp"
#include "gambit/Models/models.hpp"
namespace Gambit
{
namespace Models
{
typedef std::map<std::string, primary_model_functor *>::const_iterator activemodel_it;
/// ModelFunctorClaw function definitions
/// Models object the performs initialisation and checking operations
/// on a primary_model_functor list.
/// @{
// Public functions and data members
/// Model activation function
/// Returns a vector of primary_model_functors to be activated, according to the model(s) being scanned
primodel_vec ModelFunctorClaw::getPrimaryModelFunctorsToActivate (std::set<str> selectedmodels, const primodel_vec& primaryModelFunctors)
{
// Holder for result
primodel_vec result;
// Iterator to elements of 'selectedmodels'
std::set<str>::iterator el;
// Loop through functor list and activate functor if it matches a member of 'selectedmodels'.
for (primodel_vec::const_iterator
it = primaryModelFunctors.begin();
it != primaryModelFunctors.end();
++it)
{
// Check if this functor originates from one of the selected models
el = std::find(selectedmodels.begin(), selectedmodels.end(), (*it)->origin());
if(el != selectedmodels.end())
{
// If yes, flag this functor as available for activation.
(*it)->setStatus(FunctorStatus::Available);
(*it)->setPrintRequirement(true); // Tell printer to output this functor
// Initialise ModelParameters object it contains
(*it)->calculate();
// Add it to the vector of primary model functors to make active (to be returned)
result.push_back(*it);
// Add it to the internal list of active models
activemodels.insert(*el);
// Remove it from the input 'selectedmodels' list
selectedmodels.erase(el);
}
}
// Check that all requested models have been activated
if( selectedmodels.size() != 0 )
{
// Report error
str errmsg = "Error! Some of the requested models could not be activated for \n";
errmsg += "scanning! Probably they have not been defined, or you spelled \n";
errmsg += "their name wrong in the ini file. \n";
errmsg += "Models that cannot be activated: \n";
for (std::set<str>::iterator m = selectedmodels.begin(); m != selectedmodels.end(); ++m)
{
errmsg += (" " + *m + "\n");
}
model_error().raise(LOCAL_INFO,errmsg);
}
return result;
}
/// Searches primary model functor list for specificed model
primary_model_functor* ModelFunctorClaw::getPrimaryModelFunctor(const std::string modelname, const primodel_vec& primaryModelFunctors) const
{
primary_model_functor* result = nullptr;
// Find primary model functor with matching name
auto it = std::find_if(std::begin(primaryModelFunctors), std::end(primaryModelFunctors),
[&] (primary_model_functor* f) {return f->getcontentsPtr()->getModelName() == modelname;});
if(it != primaryModelFunctors.end())
{
result = *it;
}
else
{
std::stringstream err;
err<<"No primary model functor with model name "<<modelname<<" was found! Please check the input name for typos!";
model_error().raise(LOCAL_INFO,err.str());
}
return result;
}
/// Return set of all models recognised by GAMBIT
const std::set<str>& ModelFunctorClaw::get_allmodels() const { return allmodelnames; }
/// Retrieve the internally stored vector of activated models
std::set<str> ModelFunctorClaw::get_activemodels() const { return activemodels; }
/// Active model functor "usefulness" checker
///
/// Checks that all the active primary model functors are actually used for
/// something in the dependency tree. If not throws an error to warn the
/// user.
void ModelFunctorClaw::checkPrimaryModelFunctorUsage(const activemodel_map& activeModelFunctors) const
{
std::vector<std::string> unusedmodels;
std::string modelname;
primary_model_functor* functorPtr;
// Loop through functor list and check that their statuses have all been
// set to 2 ("active"). If not, it means that some of them were not
// activated by the dependency resolver and thus are not used for
// computing anything.
for(activemodel_it it = activeModelFunctors.begin();
it != activeModelFunctors.end(); it++)
{
modelname = it->first;
functorPtr = it->second;
if ( !functorPtr->isActive() )
{
unusedmodels.push_back( modelname );
}
}
// If we found unused models throw an error
if ( unusedmodels.size() > 0 )
{
str errmsg = "Some models selected for scanning are not required by any of\n";
errmsg += "the requested observables/likelihoods! Please switch these \n";
errmsg += "off in the inifile or add a target that actually uses them. \n";
errmsg += "List of unused models: \n";
for (std::vector<std::string>::iterator it = unusedmodels.begin(); it != unusedmodels.end(); ++it)
{
errmsg += (*it + "\n");
}
model_error().raise(LOCAL_INFO,errmsg);
}
}
/// Add a new model to the model database.
void ModelFunctorClaw::declare_model (const str &model, const str &parent)
{
// Register the new model.
allmodelnames.insert(model);
if (parent != "PARENT")
{
// If the parent actually doesn't exist yet, die.
if (not model_exists(parent))
{
str errmsg = "Requested parent model \""+parent+ "\" for model \""+model;
errmsg += "\nis not in the GAMBIT database. Recognised models are:\n" + list_models();
model_error().raise(LOCAL_INFO,errmsg);
}
// Add the parent to the parents database.
myParentsDB[model] = parent;
// Inherit friends from the model's parent.
myFriendsDB[model] = myFriendsDB[parent];
// Inherit lineage from the model's parent.
myLineageDB[model] = myLineageDB[parent];
}
else
{
// Seed empty friend sets and inheritance vector.
myFriendsDB[model] = std::set<str>();
myBestFriendsDB[model] = std::set<str>();
myLineageDB[model] = std::vector<str>();
}
// Add the new model to its own lineage vector.
myLineageDB[model].push_back(model);
// Register the model in each of its parents' descendents vectors.
for (std::set<str>::iterator parent = allmodelnames.begin(); parent != allmodelnames.end(); ++parent)
{
// If this model descends from parent, add it to the parent's descendents vector
if (descended_from(model,*parent)) myDescendantsDB[*parent].push_back(model);
}
}
/// Add a friend, and all its friends and ancestors, to a model's list of friends
void ModelFunctorClaw::add_friend (const str &model, const str &newfriend)
{
// If the new friend actually doesn't exist yet, die.
if (not model_exists(newfriend))
{
str errmsg = "Requested friend model \""+newfriend + "\" for model \""+model;
errmsg += "\nis not in the GAMBIT database. Recognised models are:\n" + list_models();
model_error().raise(LOCAL_INFO,errmsg);
}
// Add the new friend as a best friend.
myBestFriendsDB[model].insert(newfriend);
// Add the new friend's whole lineage vector as regular friends.
std::set<str> temp1, temp2, lineage(myLineageDB[newfriend].begin(), myLineageDB[newfriend].end());
set_union(myFriendsDB[model].begin(), myFriendsDB[model].end(), lineage.begin(), lineage.end(), inserter(temp1, temp1.begin()));
// Also inherit the new friend's friends as regular friends.
set_union(temp1.begin(), temp1.end(), myFriendsDB[newfriend].begin(), myFriendsDB[newfriend].end(), inserter(temp2, temp2.begin()));
myFriendsDB[model] = temp2;
}
/// Indicate whether a model is recognised by GAMBIT or not
bool ModelFunctorClaw::model_exists (const str &model) const
{
return allmodelnames.find(model) != allmodelnames.end();
}
/// List all the models recognised by GAMBIT
str ModelFunctorClaw::list_models() const
{
str temp = "";
for (std::set<str>::iterator it = allmodelnames.begin(); it != allmodelnames.end(); ++it)
{
temp += "\n" + *it;
}
return temp;
}
/// Verify that a string matches a model recognised by GAMBIT, crash otherwise
void ModelFunctorClaw::verify_model(const str &model) const
{
if (not model_exists(model))
{
str errmsg = "Model \"";
errmsg += model + "\" is not in the GAMBIT database.";
errmsg += "\nRecognised models are:" + list_models();
model_error().raise(LOCAL_INFO,errmsg);
}
}
/// Retrieve the descendants for a given model
std::vector<str> ModelFunctorClaw::get_descendants (const str &model) const
{
return myDescendantsDB.find(model) == myDescendantsDB.end() ? std::vector<str>() : myDescendantsDB.at(model);
}
/// Retrieve the parents for a given model
str ModelFunctorClaw::get_parent (const str &model) const
{
return myParentsDB.find(model) == myParentsDB.end() ? "none" : myParentsDB.at(model);
}
/// Retrieve the lineage for a given model
std::vector<str> ModelFunctorClaw::get_lineage (const str &model) const
{
return myLineageDB.find(model) == myLineageDB.end() ? std::vector<str>() : myLineageDB.at(model);
}
/// Retrieve the friends for a given model
std::set<str> ModelFunctorClaw::get_friends (const str &model) const
{
return myFriendsDB.find(model) == myFriendsDB.end() ? std::set<str>() : myFriendsDB.at(model);
}
/// Retrieve the best friends for a given model
std::set<str> ModelFunctorClaw::get_best_friends (const str &model) const
{
return myBestFriendsDB.find(model) == myBestFriendsDB.end() ? std::set<str>() : myBestFriendsDB.at(model);
}
/// Check if model 1 is descended from model 2
bool ModelFunctorClaw::descended_from (const str &model1, const str &model2) const
{
verify_model(model1);
auto lineage = myLineageDB.at(model1);
for (std::vector<str>::const_iterator it = lineage.begin(); it != lineage.end(); ++it)
{
if (model2==*it) return true;
}
return false;
}
/// Check if model 1 is an ancestor of model 2
bool ModelFunctorClaw::ancestor_of (const str &model1, const str &model2) const
{
return descended_from(model2, model1);
}
/// Check if model 1 exists somewhere downstream of (and can be therefore be interpreted as a) model 2
bool ModelFunctorClaw::downstream_of (const str &model1, const str &model2) const
{
if (descended_from(model1, model2)) return true;
if (myFriendsDB.find(model1) != myFriendsDB.end())
{
std::set<str> friends = myFriendsDB.at(model1);
return friends.find(model2) != friends.end();
}
return false;
}
/// Check if model 1 exists somewhere upstream of model 2, allowing model 2 to be interpreted as model 1
bool ModelFunctorClaw::upstream_of (const str &model1, const str &model2) const
{
return downstream_of(model2, model1);
}
/// @}
}
}
Updated on 2024-07-18 at 13:53:33 +0000