gambit is hosted by Hepforge, IPPP Durham
GAMBIT  v1.5.0-2191-ga4742ac
a Global And Modular Bsm Inference Tool

Main dependency resolver. More...

#include <depresolver.hpp>

Collaboration diagram for Gambit::DRes::DependencyResolver:

Public Member Functions

 DependencyResolver (const gambit_core &, const Models::ModelFunctorClaw &, const IniParser::IniFile &, const Utils::type_equivalency &, Printers::BasePrinter &)
 Constructor, provide module and backend functor lists. More...
 
void doResolution ()
 The dependency resolution. More...
 
void printFunctorList ()
 Pretty print module functor information. More...
 
void printFunctorEvalOrder (bool toterminal=false)
 Pretty print function evaluation order. More...
 
std::vector< VertexIDgetObsLikeOrder ()
 Retrieve the order in which target vertices are to be evaluated. More...
 
void calcObsLike (VertexID)
 Calculate a single target vertex. More...
 
void printObsLike (VertexID, const int)
 Print a single target vertex. More...
 
bool printTiming ()
 Getter for print_timing flag (used by LikelihoodContainer) More...
 
functorget_functor (VertexID)
 Get the functor corresponding to a single VertexID. More...
 
str checkTypeMatch (VertexID, const str &, const std::vector< str > &)
 Ensure that the type of a given vertex is equivalent to at least one of a provided list, and return the matching list entry. More...
 
template<typename TYPE >
TYPE getObsLike (VertexID vertex)
 Return the result of a functor. More...
 
const IniParser::ObservableTypegetIniEntry (VertexID)
 
void invalidatePointAt (VertexID, bool)
 
void resetAll ()
 

Static Public Member Functions

static MasterGraphType cullInactiveFunctors (MasterGraphType &)
 Helper function that returns a new graph with all inactive vertices removed. More...
 

Private Member Functions

void addFunctors ()
 Adds list of functor pointers to master graph. More...
 
str printGenericFunctorList (const std::vector< functor *> &)
 Pretty print backend functor information. More...
 
str printGenericFunctorList (const std::vector< VertexID > &)
 
str printQuantityToBeResolved (const sspair &quantity, const DRes::VertexID &vertex)
 Print quantity to be resolved. More...
 
void initialisePrinter ()
 Initialise the printer object with a list of functors for it to expect to be printed. More...
 
void makeFunctorsModelCompatible ()
 Deactivate functors that are not allowed to be used with the model(s) being scanned. More...
 
boost::tuple< const IniParser::ObservableType *, DRes::VertexIDresolveDependency (DRes::VertexID toVertex, sspair quantity)
 Resolution of individual module function dependencies. More...
 
DRes::VertexID resolveDependencyFromRules (const DRes::VertexID &toVertex, const sspair &quantity)
 Resolution of individual module function dependencies. More...
 
Options collectIniOptions (const DRes::VertexID &vertex)
 Derive options from ini-entries. More...
 
Options collectSubCaps (const DRes::VertexID &vertex)
 Collect sub-capabilities. More...
 
void generateTree (std::queue< QueueEntry > parQueue)
 Generate full dependency tree. More...
 
void fillParQueue (std::queue< QueueEntry > *parQueue, DRes::VertexID vertex)
 Helper functions/arrays. More...
 
std::list< VertexIDrun_topological_sort ()
 Topological sort. More...
 
void resolveVertexBackend (VertexID)
 Main function for resolution of backend requirements. More...
 
functorsolveRequirement (std::set< sspair >, const IniParser::ObservableType *, VertexID, std::vector< functor *>, bool, str group="none")
 Find backend function matching any one of a number of capability-type pairs. More...
 
void resolveRequirement (functor *, VertexID)
 Resolve a specific backend requirement. More...
 
std::vector< DRes::VertexIDclosestCandidateForModel (std::vector< DRes::VertexID > candidates)
 Find candidate functions that are tailor made for models that are scanned over. More...
 
const IniParser::ObservableTypefindIniEntry (sspair quantity, const IniParser::ObservablesType &, const str &)
 Find entries (comparison of inifile entry with quantity or functor) More...
 
const IniParser::ObservableTypefindIniEntry (DRes::VertexID toVertex, const IniParser::ObservablesType &, const str &)
 Find rules entry that matches vertex. More...
 

Private Attributes

const gambit_coreboundCore
 Core to which this dependency resolver is bound. More...
 
const Models::ModelFunctorClawboundClaw
 Model claw to which this dependency resolver is bound. More...
 
const IniParser::IniFileboundIniFile
 ini file to which this dependency resolver is bound More...
 
const Utils::type_equivalencyboundTEs
 Type equivalency object to which this dependency resolver is bound. More...
 
Printers::BasePrinter * boundPrinter
 Printer object to which this dependency resolver is bound. More...
 
std::vector< OutputVertexInfooutputVertexInfos
 Output Vertex Infos. More...
 
MasterGraphType masterGraph
 The central boost graph object. More...
 
std::list< VertexIDfunction_order
 Saved calling order for functions. More...
 
std::map< VertexID, std::vector< VertexID > > SortedParentVertices
 Saved calling order for functions required to compute single ObsLike entries. More...
 
std::map< VertexID, std::set< VertexID > > loopManagerMap
 Temporary map for loop manager -> list of nested functions. More...
 
std::map< VertexID, std::set< VertexID > > edges_to_force_on_manager
 Map from nested function -> list of fulfilled dependencies that need to be passed on to its loop manager when it is selected. More...
 
IndexMap index
 Indices associated with graph vertices (used by printers to identify functors) More...
 
const str activeFunctorGraphFile
 Output filename for graph of active functors. More...
 
bool print_timing = false
 Global flag for triggering printing of timing data. More...
 
bool print_unitcube = false
 Global flag for triggering printing of unitCubeParameters. More...
 

Detailed Description

Main dependency resolver.

Definition at line 117 of file depresolver.hpp.

Constructor & Destructor Documentation

◆ DependencyResolver()

Gambit::DRes::DependencyResolver::DependencyResolver ( const gambit_core core,
const Models::ModelFunctorClaw claw,
const IniParser::IniFile iniFile,
const Utils::type_equivalency equiv_classes,
Printers::BasePrinter &  printer 
)

Constructor, provide module and backend functor lists.

Definition at line 308 of file depresolver.cpp.

References addFunctors(), boundTEs, Gambit::LogTags::dependency_resolver, Gambit::EOM, Gambit::Utils::type_equivalency::equivalency_classes, and Gambit::logger().

313  : boundCore(&core),
314  boundClaw(&claw),
315  boundIniFile(&iniFile),
316  boundTEs(&equiv_classes),
318  index(get(vertex_index,masterGraph)),
319  activeFunctorGraphFile(Utils::runtime_scratch()+"GAMBIT_active_functor_graph.gv")
320  {
321  addFunctors();
323  logger() << "#######################################" << endl;
324  logger() << "# List of Type Equivalency Classes #" << endl;
325  logger() << "#######################################";
326  for (std::set<std::set<str> >::const_iterator it = boundTEs->equivalency_classes.begin(); it != boundTEs->equivalency_classes.end(); ++it)
327  {
328  logger() << endl << *it;
329  }
330  logger() << EOM;
331  }
MasterGraphType masterGraph
The central boost graph object.
const gambit_core * boundCore
Core to which this dependency resolver is bound.
std::set< std::set< str > > equivalency_classes
}@ The total set of equivalency classes
void addFunctors()
Adds list of functor pointers to master graph.
const Utils::type_equivalency * boundTEs
Type equivalency object to which this dependency resolver is bound.
IndexMap index
Indices associated with graph vertices (used by printers to identify functors)
const Logging::endofmessage EOM
Explicit const instance of the end of message struct in Gambit namespace.
Definition: logger.hpp:100
Printers::BasePrinter * boundPrinter
Printer object to which this dependency resolver is bound.
EXPORT_SYMBOLS Logging::LogMaster & logger()
Function to retrieve a reference to the Gambit global log object.
Definition: logger.cpp:95
Printers::BaseBasePrinter printer
Type of the printer objects.
const IniParser::IniFile * boundIniFile
ini file to which this dependency resolver is bound
EXPORT_SYMBOLS const str & runtime_scratch()
Return the path to the run-specific scratch directory Don&#39;t call this from a destructor, as the internal static str may have already been destroyed.
const Models::ModelFunctorClaw * boundClaw
Model claw to which this dependency resolver is bound.
const str activeFunctorGraphFile
Output filename for graph of active functors.
Here is the call graph for this function:

Member Function Documentation

◆ addFunctors()

void Gambit::DRes::DependencyResolver::addFunctors ( )
private

Adds list of functor pointers to master graph.

Definition at line 806 of file depresolver.cpp.

References boundCore, Gambit::gambit_core::getModuleFunctors(), Gambit::gambit_core::getPrimaryModelFunctors(), and masterGraph.

Referenced by DependencyResolver().

807  {
808  // Add primary model functors to masterGraph
809  for (std::vector<primary_model_functor *>::const_iterator
810  it = boundCore->getPrimaryModelFunctors().begin();
811  it != boundCore->getPrimaryModelFunctors().end();
812  ++it)
813  {
814  // Ignore functors with status set to 0 or less in order to ignore primary_model_functors
815  // that are not to be used for the scan.
816  if ( (*it)->status() > 0 )
817  {
818  boost::add_vertex(*it, this->masterGraph);
819  }
820  }
821  // Add module functors to masterGraph
822  for (std::vector<functor *>::const_iterator
823  it = boundCore->getModuleFunctors().begin();
824  it != boundCore->getModuleFunctors().end();
825  ++it)
826  {
827  boost::add_vertex(*it, this->masterGraph);
828  }
829  }
MasterGraphType masterGraph
The central boost graph object.
const pmfVec & getPrimaryModelFunctors() const
Get a reference to the list of primary model functors.
Definition: core.cpp:241
const gambit_core * boundCore
Core to which this dependency resolver is bound.
const fVec & getModuleFunctors() const
Get a reference to the list of module functors.
Definition: core.cpp:232
Here is the call graph for this function:
Here is the caller graph for this function:

◆ calcObsLike()

void Gambit::DRes::DependencyResolver::calcObsLike ( VertexID  vertex)

Calculate a single target vertex.

Definition at line 629 of file depresolver.cpp.

References boundCore, boundIniFile, Gambit::core_error(), Gambit::LogTags::debug, Gambit::LogTags::dependency_resolver, Gambit::EOM, Gambit::gambit_core::get_outprec(), Gambit::IniParser::Parser::getValueOrDef(), Gambit::LogTags::info, LOCAL_INFO, Gambit::logger(), masterGraph, and SortedParentVertices.

Referenced by Gambit::Likelihood_Container::main().

630  {
631  if (SortedParentVertices.find(vertex) == SortedParentVertices.end())
632  core_error().raise(LOCAL_INFO, "Tried to calculate a function not in or not at top of dependency graph.");
633  std::vector<VertexID> order = SortedParentVertices.at(vertex);
634 
635  for (std::vector<VertexID>::iterator it = order.begin(); it != order.end(); ++it)
636  {
637  std::ostringstream ss;
638  ss << "Calling " << masterGraph[*it]->name() << " from " << masterGraph[*it]->origin() << "...";
640  masterGraph[*it]->calculate();
641  if (boundIniFile->getValueOrDef<bool>(
642  false, "dependency_resolution", "log_runtime") )
643  {
644  double T = masterGraph[*it]->getRuntimeAverage();
646  "Runtime, averaged over multiple calls [s]: " << T << EOM;
647  }
648  invalid_point_exception* e = masterGraph[*it]->retrieve_invalid_point_exception();
649  if (e != NULL) throw(*e);
650  }
651  // Reset the cout output precision, in case any backends have messed with it during the ObsLike evaluation.
652  cout << std::setprecision(boundCore->get_outprec());
653  }
MasterGraphType masterGraph
The central boost graph object.
TYPE getValueOrDef(TYPE def, const args &... keys) const
#define LOCAL_INFO
Definition: local_info.hpp:34
error & core_error()
Core errors.
const gambit_core * boundCore
Core to which this dependency resolver is bound.
const Logging::endofmessage EOM
Explicit const instance of the end of message struct in Gambit namespace.
Definition: logger.hpp:100
int get_outprec() const
Getter for precision to use for cout.
Definition: core.cpp:73
EXPORT_SYMBOLS Logging::LogMaster & logger()
Function to retrieve a reference to the Gambit global log object.
Definition: logger.cpp:95
std::map< VertexID, std::vector< VertexID > > SortedParentVertices
Saved calling order for functions required to compute single ObsLike entries.
const IniParser::IniFile * boundIniFile
ini file to which this dependency resolver is bound
Here is the call graph for this function:
Here is the caller graph for this function:

◆ checkTypeMatch()

str Gambit::DRes::DependencyResolver::checkTypeMatch ( VertexID  vertex,
const str purpose,
const std::vector< str > &  types 
)

Ensure that the type of a given vertex is equivalent to at least one of a provided list, and return the matching list entry.

Definition at line 700 of file depresolver.cpp.

References boundTEs, Gambit::core_error(), LOCAL_INFO, masterGraph, and Gambit::DRes::typeComp().

Referenced by Gambit::Likelihood_Container::Likelihood_Container().

701  {
702  for (auto it = types.begin(); it != types.end(); ++it)
703  {
704  if (typeComp(*it, masterGraph[vertex]->type(), *boundTEs, false)) return *it;
705  }
706  std::stringstream msg;
707  msg << "All quantities with purpose \"" << purpose << "\" in your yaml file must have one " << endl
708  << "of the following types: " << endl << " " << types << endl
709  << "You have tried to assign this purpose to " << masterGraph[vertex]->origin() << "::"
710  << masterGraph[vertex]->name() << "," << endl << "which has capability: " << endl
711  << " " << masterGraph[vertex]->capability() << endl << "and result type: " << endl
712  << " [" << masterGraph[vertex]->type() << "]" << endl << "Please assign a different purpose to this entry.";
713  core_error().raise(LOCAL_INFO, msg.str());
714  return "If you make core errors non-fatal you deserve what you get.";
715  }
MasterGraphType masterGraph
The central boost graph object.
#define LOCAL_INFO
Definition: local_info.hpp:34
error & core_error()
Core errors.
bool typeComp(str, str, const Utils::type_equivalency &, bool with_regex=true)
Type comparison taking into account equivalence classes.
const Utils::type_equivalency * boundTEs
Type equivalency object to which this dependency resolver is bound.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ closestCandidateForModel()

std::vector< DRes::VertexID > Gambit::DRes::DependencyResolver::closestCandidateForModel ( std::vector< DRes::VertexID candidates)
private

Find candidate functions that are tailor made for models that are scanned over.

Definition at line 925 of file depresolver.cpp.

References boundClaw, Gambit::Models::ModelFunctorClaw::get_activemodels(), Gambit::Models::ModelFunctorClaw::get_parent(), and masterGraph.

Referenced by resolveDependencyFromRules().

926  {
927  // In case of doubt (and if not explicitely disabled in the ini-file), prefer functors
928  // that are more specifically tailored for the model being scanned. Do not consider functors
929  // that are accessible via INTERPRET_AS_X links, as these are all considered to be equally 'far'
930  // from the model being scanned, with the 'distance' being one step further than the most distant
931  // ancestor.
932 
933  // Work up the model ancestry one step at a time, and stop as soon as one or more valid model-specific functors is
934  // found at a given level in the hierarchy.
935  std::vector<DRes::VertexID> newCandidates;
936  std::set<str> s = boundClaw->get_activemodels();
937  std::vector<str> parentModelList(s.begin(), s.end());
938  while (newCandidates.size() == 0 and not parentModelList.empty())
939  {
940  for (std::vector<str>::iterator mit = parentModelList.begin(); mit != parentModelList.end(); ++mit)
941  {
942  // Test each vertex candidate to see if it has been explicitly set up to work with the model *mit
943  for (std::vector<DRes::VertexID>::iterator it = candidates.begin(); it != candidates.end(); ++it)
944  {
945  if ( masterGraph[*it]->modelExplicitlyAllowed(*mit) ) newCandidates.push_back(*it);
946  }
947  // Step up a level in the model hierarchy for this model.
948  *mit = boundClaw->get_parent(*mit);
949  }
950  parentModelList.erase(std::remove(parentModelList.begin(), parentModelList.end(), "none"), parentModelList.end());
951  }
952  if (newCandidates.size() != 0)
953  return newCandidates;
954  else
955  return candidates;
956  }
MasterGraphType masterGraph
The central boost graph object.
str get_parent(const str &) const
Retrieve the parent model for a given model.
Definition: models.cpp:244
std::set< str > get_activemodels() const
Return the set of active models;.
Definition: models.cpp:106
const Models::ModelFunctorClaw * boundClaw
Model claw to which this dependency resolver is bound.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ collectIniOptions()

Options Gambit::DRes::DependencyResolver::collectIniOptions ( const DRes::VertexID vertex)
private

Derive options from ini-entries.

Collect ini options.

Definition at line 959 of file depresolver.cpp.

References boundIniFile, boundTEs, Gambit::DRes::dependency_resolver_error(), Gambit::DRes::getEntryLevelForOptions(), Gambit::IniParser::IniFile::getRules(), LOCAL_INFO, masterGraph, and Gambit::DRes::moduleFuncMatchesIniEntry().

Referenced by generateTree().

960  {
961  YAML::Node nodes;
962  YAML::Node zlevels;
963 
964  #ifdef DEPRES_DEBUG
965  cout << "Searching options for " << masterGraph[vertex]->capability() << endl;
966  #endif
967 
968  const IniParser::ObservablesType & entries = boundIniFile->getRules();
969  for (IniParser::ObservablesType::const_iterator it =
970  entries.begin(); it != entries.end(); ++it)
971  {
972  if (moduleFuncMatchesIniEntry(masterGraph[vertex], *it, *boundTEs))
973  {
974  #ifdef DEPRES_DEBUG
975  cout << "Getting option from: " << it->capability << " " << it->type << endl;
976  #endif
977  for (auto jt = it->options.begin(); jt != it->options.end(); ++jt)
978  {
979  if ( not nodes[jt->first.as<std::string>()] )
980  {
981  #ifdef DEPRES_DEBUG
982  cout << jt->first.as<std::string>() << ": " << jt->second << endl;
983  #endif
984  nodes[jt->first.as<std::string>()] = jt->second;
985  zlevels[jt->first.as<std::string>()] = getEntryLevelForOptions(*it);
986  }
987  else
988  {
989  if ( zlevels[jt->first.as<std::string>()].as<int>() < getEntryLevelForOptions(*it) )
990  {
991  #ifdef DEPRES_DEBUG
992  cout << "Replaced : " << jt->first.as<std::string>() << ": " << jt->second << endl;
993  #endif
994  zlevels[jt->first.as<std::string>()] = getEntryLevelForOptions(*it);
995  nodes[jt->first.as<std::string>()] = jt->second;
996  }
997  else if ( zlevels[jt->first.as<std::string>()].as<int>() == getEntryLevelForOptions(*it) )
998  {
999  std::ostringstream errmsg;
1000  errmsg << "ERROR! Multiple option entries with same level for key: " << jt->first.as<std::string>();
1001  dependency_resolver_error().raise(LOCAL_INFO,errmsg.str());
1002  }
1003  }
1004  }
1005  }
1006  }
1007  return Options(nodes);
1008  }
MasterGraphType masterGraph
The central boost graph object.
#define LOCAL_INFO
Definition: local_info.hpp:34
const ObservablesType & getRules() const
Definition: yaml_parser.cpp:68
int getEntryLevelForOptions(const IniParser::ObservableType &e)
bool moduleFuncMatchesIniEntry(functor *f, const IniParser::ObservableType &e, const Utils::type_equivalency &eq)
const Utils::type_equivalency * boundTEs
Type equivalency object to which this dependency resolver is bound.
std::vector< ObservableType > ObservablesType
Definition: yaml_parser.hpp:86
const IniParser::IniFile * boundIniFile
ini file to which this dependency resolver is bound
error & dependency_resolver_error()
Dependency resolver errors.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ collectSubCaps()

Options Gambit::DRes::DependencyResolver::collectSubCaps ( const DRes::VertexID vertex)
private

Collect sub-capabilities.

Definition at line 1011 of file depresolver.cpp.

References boundIniFile, boundTEs, Gambit::DRes::dependency_resolver_error(), Gambit::IniParser::IniFile::getObservables(), LOCAL_INFO, masterGraph, and Gambit::DRes::moduleFuncMatchesIniEntry().

Referenced by generateTree().

1012  {
1013  #ifdef DEPRES_DEBUG
1014  cout << "Searching for subcaps of " << masterGraph[vertex]->capability() << endl;
1015  #endif
1016 
1017  YAML::Node nodes;
1019 
1020  // Iterate over the ObsLikes entries
1021  for (auto it = entries.begin(); it != entries.end(); ++it)
1022  {
1023  // Select only those entries that match the current graph vertex (i.e. module function)
1024  if (moduleFuncMatchesIniEntry(masterGraph[vertex], *it, *boundTEs) and not it->subcaps.IsNull())
1025  {
1026  #ifdef DEPRES_DEBUG
1027  cout << "Found subcaps for " << it->capability << " " << it->type << " " << it->module << ":" << endl;
1028  #endif
1029  // The user has given just a single entry as a subcap
1030  if (it->subcaps.IsScalar())
1031  {
1032  str key = it->subcaps.as<str>();
1033  if (nodes[key]) dependency_resolver_error().raise(LOCAL_INFO,"Duplicate sub-capability for " + key + ".");
1034  nodes[key] = YAML::Node();
1035  }
1036  // The user has passed a simple list of subcaps
1037  else if (it->subcaps.IsSequence())
1038  {
1039  for (auto jt = it->subcaps.begin(); jt != it->subcaps.end(); ++jt)
1040  {
1041  if (not jt->IsScalar())
1042  dependency_resolver_error().raise(LOCAL_INFO,"Attempt to pass map using sequence syntax for subcaps of "+it->capability+".");
1043  str key = jt->as<str>();
1044  if (nodes[key]) dependency_resolver_error().raise(LOCAL_INFO,"Duplicate sub-capability for " + key + ".");
1045  nodes[key] = YAML::Node();
1046  }
1047  }
1048  // The user has passed some more complicated subcap structure than just a list of strings
1049  else if (it->subcaps.IsMap())
1050  {
1051  for (auto jt = it->subcaps.begin(); jt != it->subcaps.end(); ++jt)
1052  {
1053  str key = jt->first.as<str>();
1054  if (nodes[key]) dependency_resolver_error().raise(LOCAL_INFO,"Duplicate sub-capability for " + key + ".");
1055  nodes[key] = jt->second.as<YAML::Node>();
1056  }
1057  }
1058  #ifdef DEPRES_DEBUG
1059  cout << nodes << endl;
1060  #endif
1061  }
1062  }
1063  return Options(nodes);
1064  }
const ObservablesType & getObservables() const
Getters for private observable and rules entries.
Definition: yaml_parser.cpp:67
MasterGraphType masterGraph
The central boost graph object.
#define LOCAL_INFO
Definition: local_info.hpp:34
bool moduleFuncMatchesIniEntry(functor *f, const IniParser::ObservableType &e, const Utils::type_equivalency &eq)
const Utils::type_equivalency * boundTEs
Type equivalency object to which this dependency resolver is bound.
std::vector< ObservableType > ObservablesType
Definition: yaml_parser.hpp:86
std::string str
Shorthand for a standard string.
Definition: Analysis.hpp:35
const IniParser::IniFile * boundIniFile
ini file to which this dependency resolver is bound
error & dependency_resolver_error()
Dependency resolver errors.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ cullInactiveFunctors()

static MasterGraphType Gambit::DRes::DependencyResolver::cullInactiveFunctors ( MasterGraphType )
static

Helper function that returns a new graph with all inactive vertices removed.

◆ doResolution()

void Gambit::DRes::DependencyResolver::doResolution ( )

The dependency resolution.

Definition at line 339 of file depresolver.cpp.

References activeFunctorGraphFile, boundCore, boundIniFile, Gambit::LogTags::dependency_resolver, Gambit::EOM, Gambit::DRes::QueueEntry::first, function_order, generateTree(), Gambit::IniParser::IniFile::getObservables(), getObsLikeOrder(), Gambit::DRes::getSortedParentVertices(), initialisePrinter(), Gambit::logger(), loopManagerMap, makeFunctorsModelCompatible(), masterGraph, OBSLIKE_VERTEXID, Gambit::DRes::QueueEntry::printme, run_topological_sort(), Gambit::DRes::QueueEntry::second, Gambit::gambit_core::show_runorder, SortedParentVertices, and Gambit::DRes::sortVertices().

Referenced by main().

340  {
341  const IniParser::ObservablesType & observables = boundIniFile->getObservables();
342  // (cap., typ) --> dep. vertex map
343  std::queue<QueueEntry> parQueue;
344  QueueEntry queueEntry;
345 
346  // Set up list of target ObsLikes
348  logger() << "#######################################" << endl;
349  logger() << "# List of Target ObsLikes #" << endl;
350  logger() << "# #" << endl;
351  logger() << "# format: Capability (Type) [Purpose] #" << endl;
352  logger() << "#######################################";
353  for (auto it = observables.begin(); it != observables.end(); ++it)
354  {
355  // Format output
356  logger() << LogTags::dependency_resolver << endl << it->capability << " (" << it->type << ") [" << it->purpose << "]";
357  queueEntry.first.first = it->capability;
358  queueEntry.first.second = it->type;
359  queueEntry.second = OBSLIKE_VERTEXID;
360  queueEntry.printme = it->printme;
361  parQueue.push(queueEntry);
362  }
363  logger() << EOM;
364 
365  // Activate functors compatible with model we scan over (and deactivate the rest)
367 
368  // Generate dependency tree (the core of the dependency resolution)
369  generateTree(parQueue);
370 
371  // Find one execution order for activated vertices that is compatible
372  // with dependency structure
374 
375  // Loop manager initialization: Notify them about their nested functions
376  for (std::map<VertexID, std::set<VertexID>>::iterator it =
377  loopManagerMap.begin(); it != loopManagerMap.end(); ++it)
378  {
379  // Generate topologically sorted list of vertex IDs that are nested
380  // within loop manager (*it) ...
381  std::vector<VertexID> vertexList = sortVertices(it->second, function_order);
382  // ... map this on functor pointers...
383  std::vector<functor*> functorList;
384  for (std::vector<VertexID>::iterator jt = vertexList.begin(); jt != vertexList.end(); ++jt)
385  {
386  functorList.push_back(masterGraph[*jt]);
387  }
388  // ...and store it into loop manager functor
389  masterGraph[it->first]->setNestedList(functorList);
390  }
391 
392  // Initialise the printer object with a list of functors that are set to print
394 
395 #ifdef HAVE_GRAPHVIZ
396  // Generate graphviz plot if running in dry-run mode.
398  {
399  std::ofstream outf(activeFunctorGraphFile);
400  write_graphviz(outf, masterGraph, labelWriter(&masterGraph), edgeWriter(&masterGraph));
401  }
402 #endif
403 
404  // Pre-compute the individually ordered vertex lists for each of the ObsLike entries.
405  std::vector<VertexID> order = getObsLikeOrder();
406  for(auto it = order.begin(); it != order.end(); ++it)
407  {
409  }
410 
411  // Done
412  }
const ObservablesType & getObservables() const
Getters for private observable and rules entries.
Definition: yaml_parser.cpp:67
MasterGraphType masterGraph
The central boost graph object.
std::vector< VertexID > sortVertices(const std::set< VertexID > &set, const std::list< VertexID > &topoOrder)
std::list< VertexID > function_order
Saved calling order for functions.
std::list< VertexID > run_topological_sort()
Topological sort.
const gambit_core * boundCore
Core to which this dependency resolver is bound.
std::vector< VertexID > getSortedParentVertices(const VertexID &vertex, const DRes::MasterGraphType &graph, const std::list< VertexID > &topoOrder)
std::vector< VertexID > getObsLikeOrder()
Retrieve the order in which target vertices are to be evaluated.
void makeFunctorsModelCompatible()
Deactivate functors that are not allowed to be used with the model(s) being scanned.
graph_traits< MasterGraphType >::vertex_descriptor VertexID
Definition: depresolver.hpp:61
std::vector< ObservableType > ObservablesType
Definition: yaml_parser.hpp:86
const Logging::endofmessage EOM
Explicit const instance of the end of message struct in Gambit namespace.
Definition: logger.hpp:100
EXPORT_SYMBOLS Logging::LogMaster & logger()
Function to retrieve a reference to the Gambit global log object.
Definition: logger.cpp:95
std::map< VertexID, std::vector< VertexID > > SortedParentVertices
Saved calling order for functions required to compute single ObsLike entries.
void generateTree(std::queue< QueueEntry > parQueue)
Generate full dependency tree.
const IniParser::IniFile * boundIniFile
ini file to which this dependency resolver is bound
int show_runorder
Flags set by command line options Flag to trigger dependency resolver to report functor run order...
Definition: core.hpp:129
#define OBSLIKE_VERTEXID
Definition: depresolver.cpp:60
const str activeFunctorGraphFile
Output filename for graph of active functors.
std::map< VertexID, std::set< VertexID > > loopManagerMap
Temporary map for loop manager -> list of nested functions.
void initialisePrinter()
Initialise the printer object with a list of functors for it to expect to be printed.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ fillParQueue()

void Gambit::DRes::DependencyResolver::fillParQueue ( std::queue< QueueEntry > *  parQueue,
DRes::VertexID  vertex 
)
private

Helper functions/arrays.

Push module function dependencies onto the parameter queue.

Definition at line 1706 of file depresolver.cpp.

References Gambit::LogTags::dependency_resolver, Gambit::EOM, Gambit::logger(), LOOP_MANAGER_DEPENDENCY, masterGraph, and NORMAL_DEPENDENCY.

Referenced by generateTree().

1708  {
1709  // Set the default printing flag for functors to pass to the parQueue constructor.
1710  bool printme_default = false;
1711 
1712  // Tell the logger what the following messages are about.
1714 
1715  // Digest capability of loop manager (if defined)
1716  str lmcap = (*masterGraph[vertex]).loopManagerCapability();
1717  str lmtype = (*masterGraph[vertex]).loopManagerType();
1718  if (lmcap != "none")
1719  {
1720  logger() << "Adding module function loop manager to resolution queue:" << endl;
1721  logger() << lmcap << " ()" << endl;
1722  parQueue->push(QueueEntry(sspair(lmcap, lmtype), vertex, LOOP_MANAGER_DEPENDENCY, printme_default));
1723  }
1724 
1725  // Digest regular dependencies
1726  std::set<sspair> s = (*masterGraph[vertex]).dependencies();
1727  if (s.size() > 0) logger() << "Add dependencies of new module function to queue" << endl;
1728  for (std::set<sspair>::iterator it = s.begin(); it != s.end(); ++it)
1729  {
1730  // If the loop manager requirement exists and is type-specific, it is a true depencency,
1731  // and thus appears in the output of functor.dependencies(). So, we need to take care
1732  // not to double-count it for entry into the parQueue.
1733  if (lmcap == "none" or lmtype == "any" or lmcap != it->first or lmtype != it->second)
1734  {
1735  logger() << it->first << " (" << it->second << ")" << endl;
1736  parQueue->push(QueueEntry(*it, vertex, NORMAL_DEPENDENCY, printme_default));
1737  }
1738  }
1739 
1740  // Tell the logger we're done here.
1741  logger() << EOM;
1742  }
MasterGraphType masterGraph
The central boost graph object.
#define NORMAL_DEPENDENCY
Definition: depresolver.cpp:63
#define LOOP_MANAGER_DEPENDENCY
Definition: depresolver.cpp:64
std::pair< str, str > sspair
Shorthand for a pair of standard strings.
Definition: util_types.hpp:64
const Logging::endofmessage EOM
Explicit const instance of the end of message struct in Gambit namespace.
Definition: logger.hpp:100
EXPORT_SYMBOLS Logging::LogMaster & logger()
Function to retrieve a reference to the Gambit global log object.
Definition: logger.cpp:95
std::string str
Shorthand for a standard string.
Definition: Analysis.hpp:35
Here is the call graph for this function:
Here is the caller graph for this function:

◆ findIniEntry() [1/2]

const IniParser::ObservableType * Gambit::DRes::DependencyResolver::findIniEntry ( sspair  quantity,
const IniParser::ObservablesType entries,
const str errtag 
)
private

Find entries (comparison of inifile entry with quantity or functor)

Find observable entry that matches capability/type.

Definition at line 1779 of file depresolver.cpp.

References Gambit::DRes::capabilityMatchesIniEntry(), Gambit::DRes::dependency_resolver_error(), and LOCAL_INFO.

Referenced by generateTree(), resolveDependency(), resolveVertexBackend(), and solveRequirement().

1781  {
1782  std::vector<const IniParser::ObservableType*> obsEntryCandidates;
1783  for (IniParser::ObservablesType::const_iterator it =
1784  entries.begin(); it != entries.end(); ++it)
1785  {
1786  if ( capabilityMatchesIniEntry(quantity, *it) ) // use same criteria than for normal dependencies
1787  {
1788  obsEntryCandidates.push_back(&(*it));
1789  }
1790  }
1791  if ( obsEntryCandidates.size() == 0 ) return NULL;
1792  else if ( obsEntryCandidates.size() != 1 )
1793  {
1794  str errmsg = "Found multiple " + errtag + " entries for ";
1795  errmsg += quantity.first + " (" + quantity.second + ")";
1796  dependency_resolver_error().raise(LOCAL_INFO,errmsg);
1797  }
1798  return obsEntryCandidates[0]; // obsEntryCandidates.size() == 1
1799  }
#define LOCAL_INFO
Definition: local_info.hpp:34
std::string str
Shorthand for a standard string.
Definition: Analysis.hpp:35
bool capabilityMatchesIniEntry(const sspair &quantity, const IniParser::ObservableType &observable)
error & dependency_resolver_error()
Dependency resolver errors.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ findIniEntry() [2/2]

const IniParser::ObservableType * Gambit::DRes::DependencyResolver::findIniEntry ( DRes::VertexID  toVertex,
const IniParser::ObservablesType entries,
const str errtag 
)
private

Find rules entry that matches vertex.

Definition at line 1753 of file depresolver.cpp.

References boundTEs, Gambit::DRes::dependency_resolver_error(), LOCAL_INFO, masterGraph, and Gambit::DRes::moduleFuncMatchesIniEntry().

1755  {
1756  std::vector<const IniParser::ObservableType*> auxEntryCandidates;
1757  for (IniParser::ObservablesType::const_iterator it =
1758  entries.begin(); it != entries.end(); ++it)
1759  {
1760  if ( moduleFuncMatchesIniEntry(masterGraph[toVertex], *it, *boundTEs) and it->capability != "" )
1761  {
1762  auxEntryCandidates.push_back(&(*it));
1763  }
1764  }
1765  if ( auxEntryCandidates.size() == 0 ) return NULL;
1766  else if ( auxEntryCandidates.size() != 1 )
1767  {
1768  str errmsg = "Found multiple " + errtag + " entries for ";
1769  errmsg += masterGraph[toVertex]->capability() +" (" +
1770  masterGraph[toVertex]->type() + ") [" +
1771  masterGraph[toVertex]->name() + ", " +
1772  masterGraph[toVertex]->origin() + "]";
1773  dependency_resolver_error().raise(LOCAL_INFO, errmsg);
1774  }
1775  return auxEntryCandidates[0]; // auxEntryCandidates.size() == 1
1776  }
MasterGraphType masterGraph
The central boost graph object.
#define LOCAL_INFO
Definition: local_info.hpp:34
bool moduleFuncMatchesIniEntry(functor *f, const IniParser::ObservableType &e, const Utils::type_equivalency &eq)
const Utils::type_equivalency * boundTEs
Type equivalency object to which this dependency resolver is bound.
std::string str
Shorthand for a standard string.
Definition: Analysis.hpp:35
error & dependency_resolver_error()
Dependency resolver errors.
Here is the call graph for this function:

◆ generateTree()

void Gambit::DRes::DependencyResolver::generateTree ( std::queue< QueueEntry parQueue)
private

Generate full dependency tree.

Set up dependency tree.

Definition at line 1466 of file depresolver.cpp.

References boundCore, boundIniFile, collectIniOptions(), collectSubCaps(), Gambit::core_error(), Gambit::LogTags::dependency_resolver, Gambit::DRes::dependency_resolver_error(), edges_to_force_on_manager, Gambit::EOM, fillParQueue(), findIniEntry(), Gambit::IniParser::IniFile::getObservables(), Gambit::IniParser::IniFile::getRules(), Gambit::IniParser::Parser::getValueOrDef(), Gambit::DRes::OutputVertexInfo::iniEntry, LOCAL_INFO, Gambit::logger(), LOOP_MANAGER_DEPENDENCY, loopManagerMap, masterGraph, OBSLIKE_VERTEXID, Gambit::IniParser::Types::Observable::options, outputVertexInfos, print_timing, print_unitcube, printGenericFunctorList(), printQuantityToBeResolved(), resolveDependency(), resolveDependencyFromRules(), resolveVertexBackend(), Gambit::gambit_core::show_runorder, and Gambit::DRes::OutputVertexInfo::vertex.

Referenced by doResolution().

1467  {
1468  OutputVertexInfo outInfo;
1469  DRes::VertexID fromVertex, toVertex;
1470  DRes::EdgeID edge;
1471  // Inifile entry of ObsLike (if relevant)
1472  const IniParser::ObservableType * iniEntry;
1473  bool ok;
1474  sspair quantity;
1475  int dependency_type;
1476  bool printme;
1477 
1478  logger() << LogTags::dependency_resolver << endl;
1479  logger() << "################################################" << endl;
1480  logger() << "# Starting dependency resolution #" << endl;
1481  logger() << "# #" << endl;
1482  logger() << "# format: Capability (Type) [Function, Module] #" << endl;
1483  logger() << "################################################" << EOM;
1484 
1485  // Print something to stdout as well
1486  #ifdef DEPRES_DEBUG
1487  std::cout << "Resolving dependency graph..." << std::endl;
1488  #endif
1489 
1490  // Read ini entries
1491  use_regex = boundIniFile->getValueOrDef<bool>(true, "dependency_resolution", "use_regex");
1492  print_timing = boundIniFile->getValueOrDef<bool>(false, "print_timing_data");
1493  print_unitcube = boundIniFile->getValueOrDef<bool>(false, "print_unitcube");
1494 
1495  if ( use_regex ) logger() << "Using regex for string comparison." << endl;
1496  if ( print_timing ) logger() << "Will output timing information for all functors (via printer system)" << EOM;
1497  if ( print_unitcube ) logger() << "Printing of unitCubeParameters will be enabled." << EOM;
1498 
1499  //
1500  // Main loop: repeat until dependency queue is empty
1501  //
1502 
1503  while (not parQueue.empty())
1504  {
1505 
1506  // Retrieve capability, type and vertex ID of dependency of interest
1507  quantity = parQueue.front().first; // (capability, type) pair
1508  toVertex = parQueue.front().second; // dependent vertex
1509  dependency_type = parQueue.front().third; // Normal or loop-manager
1510  printme = parQueue.front().printme; // bool
1511 
1512  // Print information about required quantity and dependent vertex
1514  logger() << "Resolving ";
1515  logger() << printQuantityToBeResolved(quantity, toVertex) << endl << endl;
1516 
1517  // Check that ObsLike vertices have non-empty capability
1518  if ( toVertex == OBSLIKE_VERTEXID and quantity.first == "" )
1519  {
1520  str errmsg = "ObsLike entry without without capability "
1521  "information encountered.\n";
1522  dependency_resolver_error().raise(LOCAL_INFO,errmsg);
1523  }
1524 
1525  // Figure out how to resolve dependency
1526  if ( boundIniFile->getValueOrDef<bool>(false, "dependency_resolution", "use_old_routines") )
1527  {
1528  boost::tie(iniEntry, fromVertex) = resolveDependency(toVertex, quantity);
1529  }
1530  else
1531  {
1532  fromVertex = resolveDependencyFromRules(toVertex, quantity);
1533  }
1534 
1535  // Print user info.
1537  logger() << "Resolved by: [";
1538  logger() << (*masterGraph[fromVertex]).name() << ", ";
1539  logger() << (*masterGraph[fromVertex]).origin() << "]" << endl;
1540 
1541  // Check if we wanted to output this observable to the printer system.
1542  if ( toVertex==OBSLIKE_VERTEXID ) masterGraph[fromVertex]->setPrintRequirement(printme);
1543  // Check if the flag to output timing data is set
1544  if(print_timing) masterGraph[fromVertex]->setTimingPrintRequirement(true);
1545 
1546  // Apply resolved dependency to masterGraph and functors
1547  if ( toVertex != OBSLIKE_VERTEXID )
1548  {
1549  // Resolve dependency on functor level...
1550  //
1551  // In case the fromVertex is a loop manager, store nested function
1552  // temporarily in loopManagerMap (they have to be sorted later)
1553  if (dependency_type == LOOP_MANAGER_DEPENDENCY)
1554  {
1555  // Check whether fromVertex is allowed to manage loops
1556  if (not masterGraph[fromVertex]->canBeLoopManager())
1557  {
1558  str errmsg = "Trying to resolve dependency on loop manager with\n"
1559  "module function that is not declared as loop manager.\n"
1560  + printGenericFunctorList(initVector<functor*>(masterGraph[fromVertex]));
1561  dependency_resolver_error().raise(LOCAL_INFO,errmsg);
1562  }
1563  std::set<DRes::VertexID> v;
1564  if (loopManagerMap.count(fromVertex) == 1)
1565  {
1566  v = loopManagerMap[fromVertex];
1567  }
1568  v.insert(toVertex);
1569  loopManagerMap[fromVertex] = v;
1570  (*masterGraph[toVertex]).resolveLoopManager(masterGraph[fromVertex]);
1571 
1572  // Take any dependencies of loop-managed vertices that have already been resolved,
1573  // and add them as "hidden" dependencies to this loop manager.
1574  if (edges_to_force_on_manager.find(toVertex) != edges_to_force_on_manager.end())
1575  {
1576  for (auto it = edges_to_force_on_manager.at(toVertex).begin();
1577  it != edges_to_force_on_manager.at(toVertex).end(); ++it)
1578  {
1579  logger() << "Dynamically adding dependency of " << (*masterGraph[fromVertex]).origin()
1580  << "::" << (*masterGraph[fromVertex]).name() << " on "
1581  << (*masterGraph[*it]).origin() << "::" << (*masterGraph[*it]).name() << endl;
1582  boost::tie(edge, ok) = add_edge(*it, fromVertex, masterGraph);
1583  }
1584  }
1585  }
1586  // Default is to resolve dependency on functor level of toVertex
1587  else
1588  {
1589  (*masterGraph[toVertex]).resolveDependency(masterGraph[fromVertex]);
1590  }
1591  // ...and on masterGraph level.
1592  boost::tie(edge, ok) = add_edge(fromVertex, toVertex, masterGraph);
1593 
1594  // In the case that toVertex is a nested function, add fromVertex to
1595  // the edges of toVertex's loop manager.
1596  str to_lmcap = (*masterGraph[toVertex]).loopManagerCapability();
1597  str to_lmtype = (*masterGraph[toVertex]).loopManagerType();
1598  str from_lmcap = (*masterGraph[fromVertex]).loopManagerCapability();
1599  str from_lmtype = (*masterGraph[fromVertex]).loopManagerType();
1600  bool is_same_lmcap = to_lmcap == from_lmcap;
1601  bool is_same_lmtype = to_lmtype == "any" or from_lmtype == "any" or to_lmtype == from_lmtype;
1602  if (to_lmcap != "none")
1603  {
1604  // This function runs nested. Check if its loop manager has been resolved yet.
1605  if ((*masterGraph[toVertex]).loopManagerName() == "none")
1606  {
1607  // toVertex's loop manager has not yet been determined.
1608  // Add the edge to the list to deal with when the loop manager dependency is resolved,
1609  // as long as toVertex and fromVertex cannot end up inside the same loop.
1610  if (!is_same_lmcap or !is_same_lmtype)
1611  {
1612  if (edges_to_force_on_manager.find(toVertex) == edges_to_force_on_manager.end())
1613  edges_to_force_on_manager[toVertex] = std::set<DRes::VertexID>();
1614  edges_to_force_on_manager.at(toVertex).insert(fromVertex);
1615  }
1616  }
1617  else
1618  {
1619  // toVertex's loop manager has already been resolved.
1620  // If fromVertex is not the manager itself, and is not
1621  // itself a nested function that has the possibility to
1622  // end up in the same loop as toVertex, then add
1623  // fromVertex as an edge of the manager.
1624  str name = (*masterGraph[toVertex]).loopManagerName();
1625  str origin = (*masterGraph[toVertex]).loopManagerOrigin();
1626  bool is_itself = (name == (*masterGraph[fromVertex]).name() and origin == (*masterGraph[fromVertex]).origin());
1627  if (!is_itself and (!is_same_lmcap or !is_same_lmtype) )
1628  {
1629  // Hunt through the edges of toVertex and find the one that corresponds to its loop manager.
1630  graph_traits<DRes::MasterGraphType>::in_edge_iterator ibegin, iend;
1631  boost::tie(ibegin, iend) = in_edges(toVertex, masterGraph);
1632  if (ibegin != iend)
1633  {
1634  DRes::VertexID managerVertex;
1635  for (; ibegin != iend; ++ibegin)
1636  {
1637  managerVertex = source(*ibegin, masterGraph);
1638  if ((*masterGraph[managerVertex]).name() == name and
1639  (*masterGraph[managerVertex]).origin() == origin) break;
1640  }
1641  logger() << "Dynamically adding dependency of " << (*masterGraph[managerVertex]).origin()
1642  << "::" << (*masterGraph[managerVertex]).name() << " on "
1643  << (*masterGraph[fromVertex]).origin() << "::" << (*masterGraph[fromVertex]).name() << endl;
1644  boost::tie(edge, ok) = add_edge(fromVertex, managerVertex, masterGraph);
1645  }
1646  else
1647  {
1648  core_error().raise(LOCAL_INFO, "toVertex has no edges! So its loop manager hasn't been added as a dependency?!");
1649  }
1650  }
1651  }
1652  }
1653  }
1654  else // if output vertex
1655  {
1656  iniEntry = findIniEntry(quantity, boundIniFile->getObservables(), "ObsLike");
1657  outInfo.vertex = fromVertex;
1658  outInfo.iniEntry = iniEntry;
1659  outputVertexInfos.push_back(outInfo);
1660  // Don't need subcaps during dry-run
1661  if (not boundCore->show_runorder)
1662  {
1663  Options mySubCaps = collectSubCaps(fromVertex);
1664  masterGraph[fromVertex]->notifyOfSubCaps(mySubCaps);
1665  }
1666  }
1667 
1668  // If fromVertex is new, activate it
1669  if ( (*masterGraph[fromVertex]).status() != 2 )
1670  {
1671  logger() << LogTags::dependency_resolver << "Activate new module function" << endl;
1672  masterGraph[fromVertex]->setStatus(2); // activate node
1673  resolveVertexBackend(fromVertex);
1674 
1675  // Don't need options during dry-run, so skip this (just to simplify terminal output)
1676  if(not boundCore->show_runorder)
1677  {
1678  if ( boundIniFile->getValueOrDef<bool>( false, "dependency_resolution", "use_old_routines") )
1679  {
1680  // Generate options object from ini-file entry that corresponds to
1681  // fromVertex (overwrite iniEntry) and pass it to the fromVertex for later use
1682  iniEntry = findIniEntry(fromVertex, boundIniFile->getRules(), "Rules");
1683  if ( iniEntry != NULL )
1684  {
1685  Options myOptions(iniEntry->options);
1686  masterGraph[fromVertex]->notifyOfIniOptions(myOptions);
1687  }
1688  }
1689  else
1690  {
1691  Options myOptions = collectIniOptions(fromVertex);
1692  masterGraph[fromVertex]->notifyOfIniOptions(myOptions);
1693  }
1694  }
1695  // Fill parameter queue with dependencies of fromVertex
1696  fillParQueue(&parQueue, fromVertex);
1697  }
1698 
1699  // Done.
1700  logger() << EOM;
1701  parQueue.pop();
1702  }
1703  }
const ObservablesType & getObservables() const
Getters for private observable and rules entries.
Definition: yaml_parser.cpp:67
MasterGraphType masterGraph
The central boost graph object.
graph_traits< MasterGraphType >::edge_descriptor EdgeID
Definition: depresolver.hpp:62
void fillParQueue(std::queue< QueueEntry > *parQueue, DRes::VertexID vertex)
Helper functions/arrays.
const IniParser::ObservableType * findIniEntry(sspair quantity, const IniParser::ObservablesType &, const str &)
Find entries (comparison of inifile entry with quantity or functor)
boost::tuple< const IniParser::ObservableType *, DRes::VertexID > resolveDependency(DRes::VertexID toVertex, sspair quantity)
Resolution of individual module function dependencies.
TYPE getValueOrDef(TYPE def, const args &... keys) const
#define LOCAL_INFO
Definition: local_info.hpp:34
std::map< VertexID, std::set< VertexID > > edges_to_force_on_manager
Map from nested function -> list of fulfilled dependencies that need to be passed on to its loop mana...
error & core_error()
Core errors.
const ObservablesType & getRules() const
Definition: yaml_parser.cpp:68
const gambit_core * boundCore
Core to which this dependency resolver is bound.
#define LOOP_MANAGER_DEPENDENCY
Definition: depresolver.cpp:64
str printQuantityToBeResolved(const sspair &quantity, const DRes::VertexID &vertex)
Print quantity to be resolved.
str printGenericFunctorList(const std::vector< functor *> &)
Pretty print backend functor information.
std::pair< str, str > sspair
Shorthand for a pair of standard strings.
Definition: util_types.hpp:64
graph_traits< MasterGraphType >::vertex_descriptor VertexID
Definition: depresolver.hpp:61
bool use_regex
Global flag for regex use.
bool print_timing
Global flag for triggering printing of timing data.
void resolveVertexBackend(VertexID)
Main function for resolution of backend requirements.
Options collectIniOptions(const DRes::VertexID &vertex)
Derive options from ini-entries.
const Logging::endofmessage EOM
Explicit const instance of the end of message struct in Gambit namespace.
Definition: logger.hpp:100
EXPORT_SYMBOLS Logging::LogMaster & logger()
Function to retrieve a reference to the Gambit global log object.
Definition: logger.cpp:95
Types::Observable ObservableType
Definition: yaml_parser.hpp:85
std::string str
Shorthand for a standard string.
Definition: Analysis.hpp:35
const IniParser::IniFile * boundIniFile
ini file to which this dependency resolver is bound
int show_runorder
Flags set by command line options Flag to trigger dependency resolver to report functor run order...
Definition: core.hpp:129
#define OBSLIKE_VERTEXID
Definition: depresolver.cpp:60
Options collectSubCaps(const DRes::VertexID &vertex)
Collect sub-capabilities.
DRes::VertexID resolveDependencyFromRules(const DRes::VertexID &toVertex, const sspair &quantity)
Resolution of individual module function dependencies.
std::vector< OutputVertexInfo > outputVertexInfos
Output Vertex Infos.
bool print_unitcube
Global flag for triggering printing of unitCubeParameters.
std::map< VertexID, std::set< VertexID > > loopManagerMap
Temporary map for loop manager -> list of nested functions.
error & dependency_resolver_error()
Dependency resolver errors.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_functor()

functor * Gambit::DRes::DependencyResolver::get_functor ( VertexID  id)

Get the functor corresponding to a single VertexID.

Definition at line 689 of file depresolver.cpp.

References masterGraph.

Referenced by Gambit::Likelihood_Container::main().

690  {
691  graph_traits<DRes::MasterGraphType>::vertex_iterator vi, vi_end;
692  for (boost::tie(vi, vi_end) = vertices(masterGraph); vi != vi_end; ++vi)
693  {
694  if (*vi == id) return masterGraph[id];
695  }
696  return NULL;
697  }
MasterGraphType masterGraph
The central boost graph object.
Here is the caller graph for this function:

◆ getIniEntry()

const IniParser::ObservableType * Gambit::DRes::DependencyResolver::getIniEntry ( VertexID  v)

Definition at line 731 of file depresolver.cpp.

References outputVertexInfos.

Referenced by Gambit::Likelihood_Container::Likelihood_Container().

732  {
733  for (std::vector<OutputVertexInfo>::iterator it = outputVertexInfos.begin();
734  it != outputVertexInfos.end(); it++)
735  {
736  if (it->vertex == v)
737  return it->iniEntry;
738  }
739  return NULL;
740  }
std::vector< OutputVertexInfo > outputVertexInfos
Output Vertex Infos.
Here is the caller graph for this function:

◆ getObsLike()

template<typename TYPE >
TYPE Gambit::DRes::DependencyResolver::getObsLike ( VertexID  vertex)
inline

Return the result of a functor.

Definition at line 155 of file depresolver.hpp.

References Gambit::core_error(), combine_hdf5::group, LOCAL_INFO, and Gambit::functor::origin().

Referenced by Gambit::Likelihood_Container::main().

156  {
157  module_functor<TYPE>* module_ptr = dynamic_cast<module_functor<TYPE>*>(masterGraph[vertex]);
158  if (module_ptr == NULL)
159  {
160  str msg = "Attempted to retrieve result of " + masterGraph[vertex]->origin() + "::" +
161  masterGraph[vertex]->name() + "\nwith incorrect type. The type should be: " +
162  masterGraph[vertex]->type() + ".";
163  core_error().raise(LOCAL_INFO, msg);
164  }
165  // This always accesses the 0-index result, which is the one-thread result
166  // or the 'final result' when more than one thread has run the functor.
167  return (*module_ptr)(0);
168  }
MasterGraphType masterGraph
The central boost graph object.
#define LOCAL_INFO
Definition: local_info.hpp:34
error & core_error()
Core errors.
std::string str
Shorthand for a standard string.
Definition: Analysis.hpp:35
Here is the call graph for this function:
Here is the caller graph for this function:

◆ getObsLikeOrder()

std::vector< VertexID > Gambit::DRes::DependencyResolver::getObsLikeOrder ( )

Retrieve the order in which target vertices are to be evaluated.

Definition at line 580 of file depresolver.cpp.

References Gambit::LogTags::dependency_resolver, double, Gambit::EOM, Gambit::DRes::getParentVertices(), Gambit::DRes::getTimeEstimate(), Gambit::logger(), masterGraph, and outputVertexInfos.

Referenced by doResolution(), Gambit::Likelihood_Container::Likelihood_Container(), and printFunctorEvalOrder().

581  {
582  std::vector<VertexID> unsorted;
583  std::vector<VertexID> sorted;
584  std::set<VertexID> parents, colleages, colleages_min;
585  // Copy unsorted vertexIDs --> unsorted
586  for (std::vector<OutputVertexInfo>::iterator it = outputVertexInfos.begin();
587  it != outputVertexInfos.end(); it++)
588  {
589  unsorted.push_back(it->vertex);
590  }
591  // Sort iteratively (unsorted --> sorted)
592  while (unsorted.size() > 0)
593  {
594  double t2p_now;
595  double t2p_min = -1;
596  std::vector<VertexID>::iterator it_min;
597  for (std::vector<VertexID>::iterator it = unsorted.begin(); it !=
598  unsorted.end(); ++it)
599  {
600  parents.clear();
601  getParentVertices(*it, masterGraph, parents);
602  parents.insert(*it);
603  // Remove vertices that were already calculated from the ist
604  for ( auto cit = colleages.begin(); cit != colleages.end(); cit++)
605  {
606  parents.erase(*cit);
607  }
608  t2p_now = (double) getTimeEstimate(parents, masterGraph);
609  t2p_now /= masterGraph[*it]->getInvalidationRate();
610  if (t2p_min < 0 or t2p_now < t2p_min)
611  {
612  t2p_min = t2p_now;
613  it_min = it;
614  colleages_min = parents;
615  }
616  }
617  // Extent list of calculated vertices
618  colleages.insert(colleages_min.begin(), colleages_min.end());
619  double prop = masterGraph[*it_min]->getInvalidationRate();
620  logger() << LogTags::dependency_resolver << "Estimated T [s]: " << t2p_min*prop << EOM;
621  logger() << LogTags::dependency_resolver << "Estimated p: " << prop << EOM;
622  sorted.push_back(*it_min);
623  unsorted.erase(it_min);
624  }
625  return sorted;
626  }
DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry DecayTable::Entry double
MasterGraphType masterGraph
The central boost graph object.
double getTimeEstimate(const std::set< VertexID > &vertexList, const DRes::MasterGraphType &graph)
void getParentVertices(const VertexID &vertex, const DRes::MasterGraphType &graph, std::set< VertexID > &myVertexList)
Definition: depresolver.cpp:84
const Logging::endofmessage EOM
Explicit const instance of the end of message struct in Gambit namespace.
Definition: logger.hpp:100
EXPORT_SYMBOLS Logging::LogMaster & logger()
Function to retrieve a reference to the Gambit global log object.
Definition: logger.cpp:95
std::vector< OutputVertexInfo > outputVertexInfos
Output Vertex Infos.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ initialisePrinter()

void Gambit::DRes::DependencyResolver::initialisePrinter ( )
private

Initialise the printer object with a list of functors for it to expect to be printed.

Set up printer object.

Definition at line 873 of file depresolver.cpp.

References boundPrinter, Gambit::Printers::get_param_id(), index, masterGraph, and print_unitcube.

Referenced by doResolution().

874  {
875  // Send the state of the "print_unitcube" flag to the printer
876  boundPrinter->set_printUnitcube(print_unitcube);
877 
878  std::vector<int> functors_to_print;
879  graph_traits<MasterGraphType>::vertex_iterator vi, vi_end;
880  //IndexMap index = get(vertex_index, masterGraph); // Now done in the constructor
881  //Err does that make sense? There is nothing in masterGraph at that point surely... maybe put this back.
882  //Ok well it does seem to work in the constructor, not sure why though...
883 
884  for (boost::tie(vi, vi_end) = vertices(masterGraph); vi != vi_end; ++vi)
885  {
886  // Inform the active functors of the vertex ID that the masterGraph has assigned to them
887  // (so that later on they can pass this to the printer object to identify themselves)
888  //masterGraph[*vi]->setVertexID(index[*vi]); // Ugh cannot do this, needs to be consistent with get_param_id
889  std::string label = masterGraph[*vi]->label();
890  masterGraph[*vi]->setVertexID(Printers::get_param_id(label));
891  // Same for timing output ID, but get ID number from printer system
892  std::string timing_label = masterGraph[*vi]->timingLabel();
893  masterGraph[*vi]->setTimingVertexID(Printers::get_param_id(timing_label));
894 
895  // Check for non-void type and status==2 (after the dependency resolution) to print only active, printable functors.
896  // TODO: this doesn't currently check for non-void type; that is done at the time of printing in calcObsLike.
897  if( masterGraph[*vi]->requiresPrinting() and (masterGraph[*vi]->status()==2) )
898  {
899  functors_to_print.push_back(index[*vi]); // TODO: Probably obsolete
900  boundPrinter->addToPrintList(label); // Needed mainly by postprocessor.
901  // Trigger a dummy print call for all printable functors. This is used by some printers
902  // to set up buffers for each of these output streams.
903  //logger() << LogTags::dependency_resolver << "Triggering dummy print for functor '"<<masterGraph[*vi]->capability()<<"' ("<<masterGraph[*vi]->type()<<")..." << EOM;
904 
905  //masterGraph[*vi]->print(boundPrinter,-1);
906  }
907  }
908 
909  // Force-reset the printer to erase the dummy calls
910  // (but don't do this if we are in resume mode!)
911  //if(not boundCore->resume) boundPrinter->reset(true);
912  //boundPrinter->reset(true); // Actually *do* do it in resume mode as well. Printers should only reset new data, not destroy old data.
913 
914  // sent vector of ID's of functors to be printed to printer.
915  // (if we want to only print functor output sometimes, and dynamically
916  // switch this on and off, we'll have to rethink the strategy here a
917  // little... for now if the print function of a functor does not get
918  // called, it is up to the printer how it deals with the missing result.
919  // Similarly for extra results, i.e. from any functors not in this
920  // initial list, whose "requiresPrinting" flag later gets set to 'true'
921  // somehow.)
922  boundPrinter->initialise(functors_to_print); // TODO: Probably obsolete
923  }
MasterGraphType masterGraph
The central boost graph object.
EXPORT_SYMBOLS int get_param_id(const std::string &name, bool &is_new)
Consolidated &#39;get id&#39; function, for both main and aux.
IndexMap index
Indices associated with graph vertices (used by printers to identify functors)
Printers::BasePrinter * boundPrinter
Printer object to which this dependency resolver is bound.
bool print_unitcube
Global flag for triggering printing of unitCubeParameters.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ invalidatePointAt()

void Gambit::DRes::DependencyResolver::invalidatePointAt ( VertexID  vertex,
bool  isnan 
)

Definition at line 718 of file depresolver.cpp.

References masterGraph.

Referenced by Gambit::Likelihood_Container::main().

719  {
720  if (isnan)
721  {
722  masterGraph[vertex]->notifyOfInvalidation("NaN returned for likelihood value.");
723  }
724  else
725  {
726  masterGraph[vertex]->notifyOfInvalidation("Cumulative log-likelihood pushed below threshold.");
727  }
728  }
MasterGraphType masterGraph
The central boost graph object.
Here is the caller graph for this function:

◆ makeFunctorsModelCompatible()

void Gambit::DRes::DependencyResolver::makeFunctorsModelCompatible ( )
private

Deactivate functors that are not allowed to be used with the model(s) being scanned.

Activate functors that are allowed to be used with one or more of the models being scanned.

Also activate the model-conditional dependencies and backend requirements of those functors.

Definition at line 833 of file depresolver.cpp.

References boundClaw, boundCore, Gambit::Models::ModelFunctorClaw::get_activemodels(), Gambit::gambit_core::getBackendFunctors(), and masterGraph.

Referenced by doResolution(), and printFunctorList().

834  {
835  // Run just once
836  static bool already_run = false;
837  if (already_run) return;
838 
839  graph_traits<DRes::MasterGraphType>::vertex_iterator vi, vi_end;
840  std::vector<functor *>::const_iterator fi, fi_end = boundCore->getBackendFunctors().end();
841  std::set<str> modelList = boundClaw->get_activemodels();
842 
843  // Activate those module functors that match the combination of models being scanned.
844  for (boost::tie(vi, vi_end) = vertices(masterGraph); vi != vi_end; ++vi)
845  {
846  if (masterGraph[*vi]->status() >= 0 and masterGraph[*vi]->modelComboAllowed(modelList))
847  {
848  for (std::set<str>::iterator it = modelList.begin(); it != modelList.end(); ++it)
849  {
850  masterGraph[*vi]->notifyOfModel(*it);
851  masterGraph[*vi]->setStatus(1);
852  }
853  }
854  }
855 
856  // Activate those backend functors that match one of the models being scanned.
857  for (std::set<str>::iterator it = modelList.begin(); it != modelList.end(); ++it)
858  {
859  for (fi = boundCore->getBackendFunctors().begin(); fi != fi_end; ++fi)
860  {
861  // Activate if the backend vertex permits the model and has not been (severely) disabled by the backend system
862  if ( (*fi)->status() >= 0 and (*fi)->modelAllowed(*it) )
863  {
864  (*fi)->setStatus(1);
865  }
866  }
867  }
868  already_run = true;
869  }
MasterGraphType masterGraph
The central boost graph object.
const fVec & getBackendFunctors() const
Get a reference to the list of backend model functors.
Definition: core.cpp:238
const gambit_core * boundCore
Core to which this dependency resolver is bound.
std::set< str > get_activemodels() const
Return the set of active models;.
Definition: models.cpp:106
const Models::ModelFunctorClaw * boundClaw
Model claw to which this dependency resolver is bound.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ printFunctorEvalOrder()

void Gambit::DRes::DependencyResolver::printFunctorEvalOrder ( bool  toterminal = false)

Pretty print function evaluation order.

Definition at line 445 of file depresolver.cpp.

References activeFunctorGraphFile, Gambit::LogTags::dependency_resolver, Gambit::EOM, getObsLikeOrder(), Gambit::DRes::getParentVertices(), Gambit::logger(), and masterGraph.

Referenced by main().

446  {
447  // Running this lets us check the order of execution. Also helps
448  // to verify that we actually have pointers to all the required
449  // functors.
450 
451  // Get order of evaluation
452  std::set<VertexID> parents;
453  std::set<VertexID> done; //set of vertices already accounted for
454  std::vector<VertexID> order = getObsLikeOrder();
455 
456  str formatString = "%-5s %-25s %-25s %-25s\n";
457  // Might need to check if terminal supports unicode characters...
458  str formatString0 = "%-7s %-23s %-25s %-25s %-25s %-6s\n"; // header
459  str formatString1a= "%-9s %-21s %-25s %-25s %-25s %-6s\n"; // target functors
460  str formatString1b= "%-4s \u2514\u2500\u2500> %-21s %-25s %-25s %-25s %-6s\n"; // target functors
461  str formatString2a= " \u250C\u2500 %-23s %-25s %-25s %-25s %-6s\n"; // parents
462  str formatString2b= " \u251C\u2500 %-23s %-25s %-25s %-25s %-6s\n";
463  str formatString3a= " \u250CX %-23s %-25s %-25s %-25s %-6s\n"; // "already done" parents
464  str formatString3b= " \u251CX %-23s %-25s %-25s %-25s %-6s\n";
465 
466  int i = 0;
467 
468  // Show the order in which the target functors will be attacked.
469  std::ostringstream ss;
470  ss << endl << "Initial target functor evaluation order" << endl;
471  ss << "----------------------------------" << endl;
472  ss << boost::format(formatString)% "#"% "FUNCTION"% "CAPABILITY"% "ORIGIN";
473 
474  for (std::vector<VertexID>::const_iterator
475  vi = order.begin();
476  vi != order.end(); ++vi)
477  {
478  ss << boost::format(formatString)%
479  i%
480  (*masterGraph[*vi]).name()%
481  (*masterGraph[*vi]).capability()%
482  (*masterGraph[*vi]).origin();
483  i++;
484  }
485 
486  ss << endl;
487 
488  i = 0; // Reset counter
489  // Do another loop to show the full initial sequence of functor evaluation
490  // This doesn't figure out the sequence within each target functor group; I'm not 100% sure where that is determined. This does, however, show which groups get evaluated first, and which functors are already evaluated.
491  ss << endl << "Full initial functor evaluation order" << endl;
492  ss << "----------------------------------" << endl;
493  ss << boost::format(formatString0)% "#"% "FUNCTION"% "CAPABILITY"% "TYPE"% "ORIGIN"% "PRINT?";
494 
495  for (std::vector<VertexID>::const_iterator
496  vi = order.begin();
497  vi != order.end(); ++vi)
498  {
499  // loop through parents of each target functor
500  parents.clear();
501  getParentVertices(*vi, masterGraph, parents);
502  parents.insert(*vi);
503  bool first = true;
504  for (std::set<VertexID>::const_iterator
505  vi2 = parents.begin();
506  vi2 != parents.end(); ++vi2)
507  {
508  str formatstr;
509  bool dowrite = false;
510  // Check if parent functor has been ticked off the list
511  bool is_done = done.find(*vi2) != done.end();
512  if( (not is_done) and (*vi != *vi2) )
513  {
514  formatstr = formatString2b;
515  if (first) formatstr = formatString2a;
516  dowrite = true;
517  }
518  else if( *vi != *vi2)
519  {
520  // Might be better to just do nothing here, i.e. set dowrite=false. For now just flagging functor as done with a special format string.
521  formatstr = formatString3b;
522  if (first) formatstr = formatString3a;
523  dowrite = true;
524  }
525 
526  if (dowrite)
527  {
528  ss << boost::format(formatstr)%
529  (*masterGraph[*vi2]).name()%
530  (*masterGraph[*vi2]).capability()%
531  (*masterGraph[*vi2]).type()%
532  (*masterGraph[*vi2]).origin()%
533  (*masterGraph[*vi2]).requiresPrinting();
534  }
535  done.insert(*vi2); // tick parent functor off the list
536  first = false;
537  }
538 
539  // Now show target functor info
540  str formatstr;
541  if(parents.size()==1) { formatstr = formatString1a; }
542  else { formatstr = formatString1b; }
543  ss << boost::format(formatstr)%
544  i%
545  (*masterGraph[*vi]).name()%
546  (*masterGraph[*vi]).capability()%
547  (*masterGraph[*vi]).type()%
548  (*masterGraph[*vi]).origin()%
549  (*masterGraph[*vi]).requiresPrinting();
550  i++;
551 
552  done.insert(*vi); // tick this target functor off the list
553 
554  }
555  ss << "(\"X\" indicates that the functor is pre-evaluated before the marked position)" << endl << endl;
556 
557  if (toterminal)
558  {
559  // There is a command line flag to get this information, since it is very
560  // handy to check before launching a full job. It can always be checked via
561  // the logs, but this feature is more convenient.
562  cout << ss.str();
563  #ifdef HAVE_GRAPHVIZ
564  cout << "To get postscript plot of active functors, please run: " << endl;
565  cout << GAMBIT_DIR << "/Core/scripts/./graphviz.sh " << activeFunctorGraphFile << " no-loners" << endl;
566  #else
567  cout << "To get postscript plot of active functors, please install graphviz, rerun cmake and remake GAMBIT." << endl << endl;
568  #endif
569  }
570 
571  logger() << LogTags::dependency_resolver << ss.str() << EOM;
572  }
MasterGraphType masterGraph
The central boost graph object.
std::vector< VertexID > getObsLikeOrder()
Retrieve the order in which target vertices are to be evaluated.
void getParentVertices(const VertexID &vertex, const DRes::MasterGraphType &graph, std::set< VertexID > &myVertexList)
Definition: depresolver.cpp:84
const Logging::endofmessage EOM
Explicit const instance of the end of message struct in Gambit namespace.
Definition: logger.hpp:100
EXPORT_SYMBOLS Logging::LogMaster & logger()
Function to retrieve a reference to the Gambit global log object.
Definition: logger.cpp:95
std::string str
Shorthand for a standard string.
Definition: Analysis.hpp:35
const str activeFunctorGraphFile
Output filename for graph of active functors.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ printFunctorList()

void Gambit::DRes::DependencyResolver::printFunctorList ( )

Pretty print module functor information.

List of masterGraph content.

Definition at line 415 of file depresolver.cpp.

References boundCore, Gambit::LogTags::dependency_resolver, Gambit::EOM, Gambit::gambit_core::getBackendFunctors(), Gambit::logger(), makeFunctorsModelCompatible(), masterGraph, and printGenericFunctorList().

Referenced by main().

416  {
417  // Activate functors compatible with model we scan over (and deactivate the rest)
419 
420  graph_traits<DRes::MasterGraphType>::vertex_iterator vi, vi_end;
421  const str formatString = "%-20s %-32s %-32s %-32s %-15s %-7i %-5i %-5i\n";
422  logger() << LogTags::dependency_resolver << endl << "Vertices registered in masterGraph" << endl;
423  logger() << "----------------------------------" << endl;
424  logger() << boost::format(formatString)%
425  "MODULE (VERSION)"% "FUNCTION"% "CAPABILITY"% "TYPE"% "PURPOSE"% "STATUS"% "#DEPs"% "#BE_REQs";
426  for (boost::tie(vi, vi_end) = vertices(masterGraph); vi != vi_end; ++vi)
427  {
428  logger() << boost::format(formatString)%
429  ((*masterGraph[*vi]).origin() + " (" + (*masterGraph[*vi]).version() + ")") %
430  (*masterGraph[*vi]).name()%
431  (*masterGraph[*vi]).capability()%
432  (*masterGraph[*vi]).type()%
433  (*masterGraph[*vi]).purpose()%
434  (*masterGraph[*vi]).status()%
435  (*masterGraph[*vi]).dependencies().size()%
436  (*masterGraph[*vi]).backendreqs().size();
437  }
438  logger() << "Registered Backend vertices" << endl;
439  logger() << "---------------------------" << endl;
441  logger() << EOM;
442  }
MasterGraphType masterGraph
The central boost graph object.
const fVec & getBackendFunctors() const
Get a reference to the list of backend model functors.
Definition: core.cpp:238
const gambit_core * boundCore
Core to which this dependency resolver is bound.
str printGenericFunctorList(const std::vector< functor *> &)
Pretty print backend functor information.
void makeFunctorsModelCompatible()
Deactivate functors that are not allowed to be used with the model(s) being scanned.
const Logging::endofmessage EOM
Explicit const instance of the end of message struct in Gambit namespace.
Definition: logger.hpp:100
EXPORT_SYMBOLS Logging::LogMaster & logger()
Function to retrieve a reference to the Gambit global log object.
Definition: logger.cpp:95
std::string str
Shorthand for a standard string.
Definition: Analysis.hpp:35
Here is the call graph for this function:
Here is the caller graph for this function:

◆ printGenericFunctorList() [1/2]

str Gambit::DRes::DependencyResolver::printGenericFunctorList ( const std::vector< functor *> &  functorList)
private

Pretty print backend functor information.

Definition at line 784 of file depresolver.cpp.

Referenced by generateTree(), printFunctorList(), printGenericFunctorList(), resolveDependencyFromRules(), and solveRequirement().

785  {
786  const str formatString = "%-20s %-32s %-48s %-32s %-7i\n";
787  std::ostringstream stream;
788  stream << boost::format(formatString)%"ORIGIN (VERSION)"% "FUNCTION"% "CAPABILITY"% "TYPE"% "STATUS";
789  for (std::vector<functor *>::const_iterator
790  it = functorList.begin();
791  it != functorList.end();
792  ++it)
793  {
794  stream << boost::format(formatString)%
795  ((*it)->origin() + " (" + (*it)->version() + ")") %
796  (*it)->name()%
797  (*it)->capability()%
798  (*it)->type()%
799  (*it)->status();
800  }
801  return stream.str();
802  }
std::string str
Shorthand for a standard string.
Definition: Analysis.hpp:35
Here is the caller graph for this function:

◆ printGenericFunctorList() [2/2]

str Gambit::DRes::DependencyResolver::printGenericFunctorList ( const std::vector< VertexID > &  vertexIDs)
private

Definition at line 773 of file depresolver.cpp.

References masterGraph, and printGenericFunctorList().

774  {
775  std::vector<functor*> functorList;
776  for ( auto it = vertexIDs.begin(); it != vertexIDs.end(); ++it )
777  {
778  functorList.push_back(masterGraph[*it]);
779  }
780  return printGenericFunctorList(functorList);
781  }
MasterGraphType masterGraph
The central boost graph object.
str printGenericFunctorList(const std::vector< functor *> &)
Pretty print backend functor information.
Here is the call graph for this function:

◆ printObsLike()

void Gambit::DRes::DependencyResolver::printObsLike ( VertexID  vertex,
const int  pointID 
)

Print a single target vertex.

Definition at line 656 of file depresolver.cpp.

References boundPrinter, boundTEs, Gambit::core_error(), Gambit::LogTags::debug, Gambit::LogTags::dependency_resolver, Gambit::EOM, Gambit::LogTags::info, LOCAL_INFO, Gambit::logger(), masterGraph, SortedParentVertices, and Gambit::DRes::typeComp().

Referenced by Gambit::Likelihood_Container::main().

657  {
658  // pointID is supplied by the scanner, and is used to tell the printer which model
659  // point the results should be associated with.
660 
661  if (SortedParentVertices.find(vertex) == SortedParentVertices.end())
662  core_error().raise(LOCAL_INFO, "Tried to calculate a function not in or not at top of dependency graph.");
663  std::vector<VertexID> order = SortedParentVertices.at(vertex);
664 
665  for (std::vector<VertexID>::iterator it = order.begin(); it != order.end(); ++it)
666  {
667  std::ostringstream ss;
668  ss << "Printing " << masterGraph[*it]->name() << " from " << masterGraph[*it]->origin() << "...";
670 
671  if (not typeComp(masterGraph[*it]->type(), "void", *boundTEs, false))
672  {
673  // Note that this prints from thread index 0 only, i.e. results created by
674  // threads other than the main one need to be accessed with
675  // masterGraph[*it]->print(boundPrinter,pointID,index);
676  // where index is some integer s.t. 0 <= index <= number of hardware threads.
677  // At the moment GAMBIT only prints results of thread 0, under the expectation
678  // that nested module functions are all designed to gather their results into
679  // thread 0.
680  masterGraph[*it]->print(boundPrinter,pointID);
681  }
682  }
683  }
MasterGraphType masterGraph
The central boost graph object.
#define LOCAL_INFO
Definition: local_info.hpp:34
error & core_error()
Core errors.
bool typeComp(str, str, const Utils::type_equivalency &, bool with_regex=true)
Type comparison taking into account equivalence classes.
const Utils::type_equivalency * boundTEs
Type equivalency object to which this dependency resolver is bound.
const Logging::endofmessage EOM
Explicit const instance of the end of message struct in Gambit namespace.
Definition: logger.hpp:100
Printers::BasePrinter * boundPrinter
Printer object to which this dependency resolver is bound.
EXPORT_SYMBOLS Logging::LogMaster & logger()
Function to retrieve a reference to the Gambit global log object.
Definition: logger.cpp:95
std::map< VertexID, std::vector< VertexID > > SortedParentVertices
Saved calling order for functions required to compute single ObsLike entries.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ printQuantityToBeResolved()

str Gambit::DRes::DependencyResolver::printQuantityToBeResolved ( const sspair quantity,
const DRes::VertexID vertex 
)
private

Print quantity to be resolved.

Definition at line 757 of file depresolver.cpp.

References masterGraph, and OBSLIKE_VERTEXID.

Referenced by generateTree(), and resolveDependencyFromRules().

758  {
759  str s = quantity.first + " (" + quantity.second + ")";
760  s += ", required by ";
761  if ( vertex != OBSLIKE_VERTEXID )
762  {
763  s += (*masterGraph[vertex]).capability() + " (";
764  s += (*masterGraph[vertex]).type() + ") [";
765  s += (*masterGraph[vertex]).name() + ", ";
766  s += (*masterGraph[vertex]).origin() + "]";
767  }
768  else
769  s += "Core";
770  return s;
771  }
MasterGraphType masterGraph
The central boost graph object.
std::string str
Shorthand for a standard string.
Definition: Analysis.hpp:35
#define OBSLIKE_VERTEXID
Definition: depresolver.cpp:60
Here is the caller graph for this function:

◆ printTiming()

bool Gambit::DRes::DependencyResolver::printTiming ( )

Getter for print_timing flag (used by LikelihoodContainer)

Definition at line 686 of file depresolver.cpp.

References print_timing.

Referenced by Gambit::Likelihood_Container::main().

686 { return print_timing; }
bool print_timing
Global flag for triggering printing of timing data.
Here is the caller graph for this function:

◆ resetAll()

void Gambit::DRes::DependencyResolver::resetAll ( )

Definition at line 743 of file depresolver.cpp.

References masterGraph.

Referenced by Gambit::Likelihood_Container::main().

744  {
745  graph_traits<DRes::MasterGraphType>::vertex_iterator vi, vi_end;
746  for (boost::tie(vi, vi_end) = vertices(masterGraph); vi != vi_end; ++vi)
747  {
748  if (masterGraph[*vi]->status() == 2) masterGraph[*vi]->reset();
749  }
750  }
MasterGraphType masterGraph
The central boost graph object.
Here is the caller graph for this function:

◆ resolveDependency()

boost::tuple< const IniParser::ObservableType *, DRes::VertexID > Gambit::DRes::DependencyResolver::resolveDependency ( DRes::VertexID  toVertex,
sspair  quantity 
)
private

Resolution of individual module function dependencies.

Resolve dependency.

Definition at line 1332 of file depresolver.cpp.

References boundClaw, boundIniFile, boundTEs, Gambit::DRes::dependency_resolver_error(), findIniEntry(), Gambit::IniParser::Types::Observable::function, Gambit::Models::ModelFunctorClaw::get_activemodels(), Gambit::Models::ModelFunctorClaw::get_parent(), Gambit::IniParser::IniFile::getObservables(), Gambit::IniParser::IniFile::getRules(), Gambit::IniParser::Parser::getValueOrDef(), LOCAL_INFO, masterGraph, Gambit::IniParser::Types::Observable::module, Gambit::DRes::moduleFuncMatchesIniEntry(), OBSLIKE_VERTEXID, Gambit::DRes::stringComp(), and Gambit::DRes::typeComp().

Referenced by generateTree().

1333  {
1334  graph_traits<DRes::MasterGraphType>::vertex_iterator vi, vi_end;
1335  const IniParser::ObservableType *auxEntry = NULL; // Ptr. on ini-file entry of the dependent vertex (if existent)
1336  const IniParser::ObservableType *depEntry = NULL; // Ptr. on ini-file entry that specifies how to resolve 'quantity'
1337  std::vector<DRes::VertexID> vertexCandidates;
1338  bool entryExists = false; // Ini-file entry to resolve 'quantity' found?
1339 
1340  // First, we check whether the dependent vertex has a unique
1341  // correspondence in the inifile. Final (output) vertices have to be
1342  // treated different from all other vertices, since they do not appear
1343  // as dependencies in the rules section of the inifile. For them,
1344  // we just use the entry from the observable/likelihood section for the
1345  // resolution of ambiguities. A pointer to the relevant inifile entry
1346  // is stored in depEntry.
1347  if ( toVertex == OBSLIKE_VERTEXID )
1348  {
1349  depEntry = findIniEntry(quantity, boundIniFile->getObservables(), "ObsLike");
1350  entryExists = true;
1351  }
1352  // for all other vertices use the rules entries
1353  else
1354  {
1355  auxEntry = findIniEntry(toVertex, boundIniFile->getRules(), "Rules");
1356  if ( auxEntry != NULL )
1357  depEntry = findIniEntry(quantity, (*auxEntry).dependencies, "dependency");
1358  if ( auxEntry != NULL and depEntry != NULL )
1359  {
1360  entryExists = true;
1361  }
1362  }
1363 
1364  // Loop over all available vertices in masterGraph, and make a list of
1365  // functors that fulfill the dependency requirement.
1366  for (tie(vi, vi_end) = vertices(masterGraph); vi != vi_end; ++vi)
1367  {
1368  // Don't allow resolution by deactivated functors
1369  if (masterGraph[*vi]->status() > 0)
1370  {
1371  // Without inifile entry, just match capabilities and types (no type
1372  // comparison when no types are given; this should only happen for
1373  // output nodes)
1374  if ( ( stringComp(masterGraph[*vi]->capability(), quantity.first) and
1375  ( quantity.second == "" or quantity.second == "*" or
1376  typeComp(masterGraph[*vi]->type(), quantity.second, *boundTEs, false) ) )
1377  // with inifile entry, we check capability, type, function name and
1378  // module name.
1379  and ( entryExists ? moduleFuncMatchesIniEntry(masterGraph[*vi], *depEntry, *boundTEs) : true ) )
1380  {
1381  // Add to vertex candidate list
1382  vertexCandidates.push_back(*vi);
1383  }
1384  }
1385  }
1386 
1387  // Die if there is no way to fulfill this dependency.
1388  if ( vertexCandidates.size() == 0 )
1389  {
1390  if ( not entryExists )
1391  {
1392  str errmsg = "I could not find any module function that provides ";
1393  errmsg += quantity.first + " (" + quantity.second + ")"
1394  + "\nCheck your inifile for typos, your modules for consistency, etc.";
1395  dependency_resolver_error().raise(LOCAL_INFO,errmsg);
1396  }
1397  else
1398  {
1399  str errmsg = "I could not find any module function that provides ";
1400  errmsg += quantity.first + " (" + quantity.second + ") ["
1401  + depEntry->function + ", " + depEntry->module + "]"
1402  + "\nCheck your inifile for typos, your modules for consistency, etc.";
1403  dependency_resolver_error().raise(LOCAL_INFO,errmsg);
1404  }
1405  }
1406 
1407  // In case of doubt (and if not explicitely disabled in the ini-file), prefer functors
1408  // that are more specifically tailored for the model being scanned. Do not consider functors
1409  // that are accessible via INTERPRET_AS_X links, as these are all considered to be equally 'far'
1410  // from the model being scanned, with the 'distance' being one step further than the most distant
1411  // ancestor.
1412  if ( vertexCandidates.size() > 1 and boundIniFile->getValueOrDef<bool>(true, "dependency_resolution", "prefer_model_specific_functions") )
1413  {
1414  // Work up the model ancestry one step at a time, and stop as soon as one or more valid model-specific functors is
1415  // found at a given level in the hierarchy.
1416  std::vector<DRes::VertexID> newVertexCandidates;
1417  std::set<str> s = boundClaw->get_activemodels();
1418  std::vector<str> parentModelList(s.begin(), s.end());
1419  while (newVertexCandidates.size() == 0 and not parentModelList.empty())
1420  {
1421  for (std::vector<str>::iterator mit = parentModelList.begin(); mit != parentModelList.end(); ++mit)
1422  {
1423  // Test each vertex candidate to see if it has been explicitly set up to work with the model *mit
1424  for (std::vector<DRes::VertexID>::iterator it = vertexCandidates.begin(); it != vertexCandidates.end(); ++it)
1425  {
1426  if ( masterGraph[*it]->modelExplicitlyAllowed(*mit) ) newVertexCandidates.push_back(*it);
1427  }
1428  // Step up a level in the model hierarchy for this model.
1429  *mit = boundClaw->get_parent(*mit);
1430  }
1431  parentModelList.erase(std::remove(parentModelList.begin(), parentModelList.end(), "none"), parentModelList.end());
1432  }
1433  if (newVertexCandidates.size() != 0) vertexCandidates = newVertexCandidates;
1434  }
1435 
1436  if ( vertexCandidates.size() > 1 )
1437  {
1438  str errmsg = "";
1439  if ( not entryExists )
1440  {
1441  errmsg += "I found too many module functions that provide ";
1442  errmsg += quantity.first + " (" + quantity.second + ")"
1443  + "\nCheck your inifile for typos, your modules for consistency, etc.";
1444  }
1445  else
1446  {
1447  errmsg += "I found too many module functions that provide ";
1448  errmsg += quantity.first + " (" + quantity.second + ") \n"
1449  + "\nneeded by " + depEntry->module + "::" + depEntry->function
1450  + "\nCheck your inifile for typos, your modules for consistency, etc.";
1451  }
1452  if (not boundIniFile->getValueOrDef<bool>(true, "dependency_resolution", "prefer_model_specific_functions"))
1453  errmsg += "\nAlso consider turning on prefer_model_specific_functions in your inifile.";
1454  errmsg += "\nCandidate module functions are:";
1455  for (std::vector<DRes::VertexID>::iterator it = vertexCandidates.begin(); it != vertexCandidates.end(); ++it)
1456  {
1457  errmsg += "\n [" + masterGraph[*it]->name() + "," + masterGraph[*it]->origin() + "]";
1458  }
1459  dependency_resolver_error().raise(LOCAL_INFO,errmsg);
1460  }
1461 
1462  return boost::tie(depEntry, vertexCandidates[0]);
1463  }
const ObservablesType & getObservables() const
Getters for private observable and rules entries.
Definition: yaml_parser.cpp:67
MasterGraphType masterGraph
The central boost graph object.
const IniParser::ObservableType * findIniEntry(sspair quantity, const IniParser::ObservablesType &, const str &)
Find entries (comparison of inifile entry with quantity or functor)
TYPE getValueOrDef(TYPE def, const args &... keys) const
#define LOCAL_INFO
Definition: local_info.hpp:34
str get_parent(const str &) const
Retrieve the parent model for a given model.
Definition: models.cpp:244
const ObservablesType & getRules() const
Definition: yaml_parser.cpp:68
bool typeComp(str, str, const Utils::type_equivalency &, bool with_regex=true)
Type comparison taking into account equivalence classes.
bool moduleFuncMatchesIniEntry(functor *f, const IniParser::ObservableType &e, const Utils::type_equivalency &eq)
std::set< str > get_activemodels() const
Return the set of active models;.
Definition: models.cpp:106
bool stringComp(const str &s1, const str &s2, bool with_regex=true)
Check whether s1 (wildcard + regex allowed) matches s2.
const Utils::type_equivalency * boundTEs
Type equivalency object to which this dependency resolver is bound.
Types::Observable ObservableType
Definition: yaml_parser.hpp:85
std::string str
Shorthand for a standard string.
Definition: Analysis.hpp:35
const IniParser::IniFile * boundIniFile
ini file to which this dependency resolver is bound
#define OBSLIKE_VERTEXID
Definition: depresolver.cpp:60
const Models::ModelFunctorClaw * boundClaw
Model claw to which this dependency resolver is bound.
error & dependency_resolver_error()
Dependency resolver errors.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ resolveDependencyFromRules()

DRes::VertexID Gambit::DRes::DependencyResolver::resolveDependencyFromRules ( const DRes::VertexID toVertex,
const sspair quantity 
)
private

Resolution of individual module function dependencies.

Resolve dependency.

Definition at line 1071 of file depresolver.cpp.

References boundIniFile, boundTEs, closestCandidateForModel(), Gambit::LogTags::dependency_resolver, Gambit::DRes::dependency_resolver_error(), Gambit::EOM, Gambit::IniParser::IniFile::getObservables(), Gambit::IniParser::IniFile::getRules(), Gambit::IniParser::Parser::getValueOrDef(), LOCAL_INFO, Gambit::logger(), masterGraph, Gambit::DRes::matchesRules(), Gambit::DRes::moduleFuncMatchesIniEntry(), OBSLIKE_VERTEXID, printGenericFunctorList(), printQuantityToBeResolved(), Gambit::DRes::quantityMatchesIniEntry(), Gambit::DRes::stringComp(), and Gambit::DRes::typeComp().

Referenced by generateTree().

1073  {
1074  graph_traits<DRes::MasterGraphType>::vertex_iterator vi, vi_end;
1075 
1076  // List of candidate vertices
1077  std::vector<DRes::VertexID> vertexCandidates; // enabled
1078  std::vector<DRes::VertexID> disabledVertexCandidates; // disabled
1079  // Rules
1080  std::vector<Rule> rules;
1081  std::vector<Rule> strong_rules;
1082  // Candidate vertices after applying rules
1083  std::vector<DRes::VertexID> filteredVertexCandidates;
1084  std::vector<DRes::VertexID> filteredVertexCandidates2;
1085 
1086  // Make list of candidate vertices.
1087  for (tie(vi, vi_end) = vertices(masterGraph); vi != vi_end; ++vi)
1088  {
1089  // Match capabilities and types (no type comparison when no types are
1090  // given; this can only apply to output nodes or loop managers).
1091  if ( stringComp(masterGraph[*vi]->capability(), quantity.first) and
1092  *vi != toVertex and // No self-resolution
1093  ( quantity.second == "" or quantity.second == "*" or quantity.second == "any" or
1094  typeComp(masterGraph[*vi]->type(), quantity.second, *boundTEs, false) ) )
1095  {
1096  // Add vertex to appropriate candidate list
1097  if (masterGraph[*vi]->status() > 0)
1098  vertexCandidates.push_back(*vi);
1099  else
1100  disabledVertexCandidates.push_back(*vi);
1101  }
1102  }
1103  if (vertexCandidates.size() == 0)
1104  {
1105  std::ostringstream errmsg;
1106  errmsg << "No candidates found while trying to resolve:" << endl;
1107  errmsg << printQuantityToBeResolved(quantity, toVertex) << endl;
1108  if (disabledVertexCandidates.size() != 0)
1109  {
1110  errmsg << "\nNote that viable candidates exist but have been disabled:\n"
1111  << printGenericFunctorList(disabledVertexCandidates)
1112  << endl
1113  << "Status flags:" << endl
1114  << " 0: This function is not compatible with any model you are scanning." << endl
1115  << "-3: This function requires a BOSSed class that is missing. The " << endl
1116  << " backend that provides the class is missing (most likely), the " << endl
1117  << " class is missing from the backend, or the factory functions" << endl
1118  << " for this class have not been BOSSed and loaded correctly." << endl;
1119  }
1120  errmsg << "Please check your yaml file for typos, and make sure that the" << endl
1121  << "models you are scanning are compatible with at least one function" << endl
1122  << "that provides this capability (they may all have been deactivated" << endl
1123  << "due to having ALLOW_MODELS declarations which are" << endl
1124  << "incompatible with the models selected for scanning)." << endl;
1125  dependency_resolver_error().raise(LOCAL_INFO,errmsg.str());
1126  }
1127 
1129  logger() << "List of candidate vertices:" << endl;
1130  logger() << printGenericFunctorList(vertexCandidates) << EOM;
1131 
1132  if (toVertex != OBSLIKE_VERTEXID)
1133  {
1134  // Make list of all relevant 1st and 2nd level dependency rules.
1135  const IniParser::ObservablesType & entries = boundIniFile->getRules();
1136  for (IniParser::ObservablesType::const_iterator
1137  it = entries.begin(); it != entries.end(); ++it)
1138  {
1139  {
1140  // Evaluate "dependencies" section
1141  if (moduleFuncMatchesIniEntry(masterGraph[toVertex], *it, *boundTEs) and
1142  (it->capability != "" or it->function != "" or
1143  it->type != "" or it->module != ""))
1144  {
1145  for (IniParser::ObservablesType::const_iterator
1146  it2 = (*it).dependencies.begin();
1147  it2 != (*it).dependencies.end(); ++it2)
1148  {
1149  if (quantityMatchesIniEntry(quantity, *it2, *boundTEs) and
1150  (it2->capability != "" or it2->type != "") and
1151  (it2->function != "" or it2->module != ""))
1152  {
1153  rules.push_back(Rule(*it2));
1154  if (not it->weakrule and not it2->weakrule)
1155  strong_rules.push_back(Rule(*it2));
1156  }
1157  }
1158  }
1159  // Evaluate "functionChain:" section
1160  if (moduleFuncMatchesIniEntry(masterGraph[toVertex], *it, *boundTEs) and
1161  it->capability != "" and
1162  it->function == "" and
1163  (*it).functionChain.size() > 1)
1164  {
1165  for (auto it2 = (*it).functionChain.begin();
1166  it2 != (*it).functionChain.end() - 1; ++it2)
1167  {
1168  if ((*it2) == masterGraph[toVertex]->name())
1169  {
1170  Rule rule(*(it2+1), masterGraph[toVertex]->origin());
1171  rules.push_back(rule);
1172  if (not it->weakrule)
1173  strong_rules.push_back(rule);
1174  }
1175  }
1176  }
1177  // Evaluate second order rules
1178  if (quantityMatchesIniEntry(quantity, *it, *boundTEs) and
1179  it->dependencies.size()==0 and
1180  (it->capability != "" or it->type != "") and
1181  (it->function != "" or it->module != ""))
1182  {
1183  rules.push_back(Rule(*it));
1184  if (not it->weakrule)
1185  strong_rules.push_back(Rule(*it));
1186  }
1187  }
1188  }
1189  }
1190  else
1191  {
1192  // Add entries in ObsLike and Rules section as 2nd order
1194  for (IniParser::ObservablesType::const_iterator it =
1195  entries.begin(); it != entries.end(); ++it)
1196  {
1197  if (quantityMatchesIniEntry(quantity, *it, *boundTEs) and
1198  (it->capability != "" or it->type != "") and
1199  (it->function != "" or it->module != ""))
1200  {
1201  rules.push_back(Rule(*it));
1202  if (not it->weakrule)
1203  strong_rules.push_back(Rule(*it));
1204  }
1205  // FIXME: Throw error if dependency or options entry exists
1206  }
1207  const IniParser::ObservablesType & entries2 = boundIniFile->getRules();
1208  for (IniParser::ObservablesType::const_iterator it =
1209  entries2.begin(); it != entries2.end(); ++it)
1210  {
1211  if (quantityMatchesIniEntry(quantity, *it, *boundTEs) and
1212  it->dependencies.size()==0 and
1213  (it->capability != "" or it->type != "") and
1214  (it->function != "" or it->module != ""))
1215  {
1216  rules.push_back(Rule(*it));
1217  if (not it->weakrule)
1218  strong_rules.push_back(Rule(*it));
1219  }
1220  }
1221  }
1222 
1223  logger() << "Number of identified rules: " << rules.size() << endl
1224  << "Number of these rules that are marked as !weak: "
1225  << rules.size()-strong_rules.size() << EOM;
1226 
1227  // Make filtered lists
1228  for (std::vector<DRes::VertexID>::const_iterator
1229  it = vertexCandidates.begin();
1230  it != vertexCandidates.end(); it ++)
1231  {
1232  bool valid = true;
1233  for (std::vector<Rule>::const_iterator it2 = rules.begin();
1234  it2 != rules.end(); it2 ++)
1235  {
1236  if ( not matchesRules(masterGraph[*it], *it2) )
1237  {
1238  valid = false;
1239  }
1240  }
1241  if (valid)
1242  filteredVertexCandidates.push_back(*it);
1243  valid = true;
1244  for (std::vector<Rule>::const_iterator it2 = strong_rules.begin();
1245  it2 != strong_rules.end(); it2 ++)
1246  {
1247  if ( not matchesRules(masterGraph[*it], *it2) )
1248  {
1249  valid = false;
1250  }
1251  }
1252  if (valid)
1253  filteredVertexCandidates2.push_back(*it);
1254  }
1255 
1256  if (rules.size() > 0 and filteredVertexCandidates.size() > 0)
1257  {
1258  logger() << "Candidate vertices that fulfill all rules:" << endl;
1259  logger() << printGenericFunctorList(filteredVertexCandidates) << EOM;
1260  }
1261 
1262  if (filteredVertexCandidates.size() == 0)
1263  {
1264  filteredVertexCandidates = filteredVertexCandidates2;
1265  logger() << "Ignoring rules declared as '!weak'" << endl;
1266  logger() << "Candidate vertices that fulfill all non-weak rules:" << endl;
1267  logger() << printGenericFunctorList(filteredVertexCandidates) << EOM;
1268  }
1269 
1270  // Apply tailor-made filter
1271  if (boundIniFile->getValueOrDef<bool>(
1272  true, "dependency_resolution", "prefer_model_specific_functions")
1273  and filteredVertexCandidates.size() > 1)
1274  {
1275  filteredVertexCandidates = closestCandidateForModel(filteredVertexCandidates);
1276  logger() << "A subset of vertex candidates is tailor-made for the scanned model." << endl;
1277  logger() << "This is used as additional constraint since the YAML rules alone" << endl;
1278  logger() << "are not constraining enough. These vertices are:" << endl;
1279  logger() << printGenericFunctorList(filteredVertexCandidates) << EOM;
1280  }
1281 
1282  // Nothing left?
1283  if ( filteredVertexCandidates.size() == 0 )
1284  {
1285  str errmsg = "None of the vertex candidates for";
1286  errmsg += "\n" + printQuantityToBeResolved(quantity, toVertex);
1287  errmsg += "\nfulfills all rules in the YAML file.";
1288  errmsg += "\nPlease check your YAML file for contradictory rules, and";
1289  errmsg += "\nensure that you have built GAMBIT in the first place with";
1290  errmsg += "\nall of the components that you are trying to use.";
1291  dependency_resolver_error().raise(LOCAL_INFO,errmsg);
1292  }
1293 
1294  // Did vertices survive?
1295  if ( filteredVertexCandidates.size() == 1 )
1296  return filteredVertexCandidates[0]; // And done!
1297 
1298  str errmsg = "Unfortunately, the dependency resolution for";
1299  errmsg += "\n" + printQuantityToBeResolved(quantity, toVertex);
1300  errmsg += "\nis still ambiguous.\n";
1301  errmsg += "\nThe candidate vertices are:\n";
1302  errmsg += printGenericFunctorList(vertexCandidates) +"\n";
1303  errmsg += "See logger output for details on the attempted (but failed) dependency resolution.\n";
1304  errmsg += "\nAn entry in your YAML file that would e.g. select";
1305  errmsg += "\nthe first of the above candidates could read ";
1306  if ( toVertex != OBSLIKE_VERTEXID )
1307  {
1308  errmsg += "as a targeted rule (in the Rules section):\n";
1309  errmsg += "\n - capability: "+masterGraph[toVertex]->capability();
1310  errmsg += "\n function: "+masterGraph[toVertex]->name();
1311  errmsg += "\n dependencies:";
1312  errmsg += "\n - capability: " +masterGraph[vertexCandidates[0]]->capability();
1313  errmsg += "\n function: " +masterGraph[vertexCandidates[0]]->name();
1314  errmsg += "\n module: " +masterGraph[vertexCandidates[0]]->origin() +"\n\nor ";
1315  }
1316  errmsg += "as an untargeted rule (in the Rules or ObsLike section):\n";
1317  errmsg += "\n - capability: "+masterGraph[vertexCandidates[0]]->capability();
1318  errmsg += "\n function: "+masterGraph[vertexCandidates[0]]->name();
1319  errmsg += "\n module: " +masterGraph[vertexCandidates[0]]->origin() +"\n";
1320  if ( toVertex == OBSLIKE_VERTEXID )
1321  {
1322  errmsg += "\n(Note that 1st class rules are not possible for vertices on which the core depends only.)\n";
1323  }
1324 
1325  dependency_resolver_error().raise(LOCAL_INFO,errmsg);
1326 
1327  return 0;
1328  }
const ObservablesType & getObservables() const
Getters for private observable and rules entries.
Definition: yaml_parser.cpp:67
MasterGraphType masterGraph
The central boost graph object.
TYPE getValueOrDef(TYPE def, const args &... keys) const
#define LOCAL_INFO
Definition: local_info.hpp:34
const ObservablesType & getRules() const
Definition: yaml_parser.cpp:68
bool typeComp(str, str, const Utils::type_equivalency &, bool with_regex=true)
Type comparison taking into account equivalence classes.
str printQuantityToBeResolved(const sspair &quantity, const DRes::VertexID &vertex)
Print quantity to be resolved.
str printGenericFunctorList(const std::vector< functor *> &)
Pretty print backend functor information.
bool moduleFuncMatchesIniEntry(functor *f, const IniParser::ObservableType &e, const Utils::type_equivalency &eq)
bool stringComp(const str &s1, const str &s2, bool with_regex=true)
Check whether s1 (wildcard + regex allowed) matches s2.
const Utils::type_equivalency * boundTEs
Type equivalency object to which this dependency resolver is bound.
std::vector< ObservableType > ObservablesType
Definition: yaml_parser.hpp:86
const Logging::endofmessage EOM
Explicit const instance of the end of message struct in Gambit namespace.
Definition: logger.hpp:100
EXPORT_SYMBOLS Logging::LogMaster & logger()
Function to retrieve a reference to the Gambit global log object.
Definition: logger.cpp:95
std::string str
Shorthand for a standard string.
Definition: Analysis.hpp:35
bool quantityMatchesIniEntry(const sspair &quantity, const IniParser::ObservableType &observable, const Utils::type_equivalency &eq)
const IniParser::IniFile * boundIniFile
ini file to which this dependency resolver is bound
#define OBSLIKE_VERTEXID
Definition: depresolver.cpp:60
bool matchesRules(functor *f, const Rule &rule)
std::vector< DRes::VertexID > closestCandidateForModel(std::vector< DRes::VertexID > candidates)
Find candidate functions that are tailor made for models that are scanned over.
error & dependency_resolver_error()
Dependency resolver errors.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ resolveRequirement()

void Gambit::DRes::DependencyResolver::resolveRequirement ( functor func,
VertexID  vertex 
)
private

Resolve a specific backend requirement.

Resolve a backend requirement of a specific module function using a specific backend function.

Definition at line 2207 of file depresolver.cpp.

References Gambit::LogTags::dependency_resolver, Gambit::EOM, Gambit::logger(), masterGraph, Gambit::functor::name(), Gambit::functor::origin(), and Gambit::functor::version().

Referenced by resolveVertexBackend().

2208  {
2209  (*masterGraph[vertex]).resolveBackendReq(func);
2211  logger() << "Resolved by: [" << func->name() << ", ";
2212  logger() << func->origin() << " (" << func->version() << ")]";
2213  logger() << EOM;
2214  }
MasterGraphType masterGraph
The central boost graph object.
const Logging::endofmessage EOM
Explicit const instance of the end of message struct in Gambit namespace.
Definition: logger.hpp:100
Funk func(double(*f)(funcargs...), Args... args)
Definition: daFunk.hpp:768
EXPORT_SYMBOLS Logging::LogMaster & logger()
Function to retrieve a reference to the Gambit global log object.
Definition: logger.cpp:95
Here is the call graph for this function:
Here is the caller graph for this function:

◆ resolveVertexBackend()

void Gambit::DRes::DependencyResolver::resolveVertexBackend ( VertexID  vertex)
private

Main function for resolution of backend requirements.

Node-by-node backend resolution.

Definition at line 1802 of file depresolver.cpp.

References boundIniFile, Gambit::LogTags::dependency_resolver, Gambit::EOM, findIniEntry(), Gambit::IniParser::IniFile::getRules(), Gambit::logger(), masterGraph, resolveRequirement(), and solveRequirement().

Referenced by generateTree().

1803  {
1804  functor* solution;
1805  std::vector<functor*> previous_successes;
1806  std::set<str> remaining_groups;
1807  std::set<sspair> remaining_reqs;
1808  bool allow_deferral = true;
1809 
1810  // If there are no backend requirements, and thus nothing to do, return.
1811  if ((*masterGraph[vertex]).backendreqs().size() == 0) return;
1812 
1813  // Get started.
1814  logger() << LogTags::dependency_resolver << "Doing backend function resolution..." << EOM;
1815 
1816  // Check whether this vertex is mentioned in the inifile.
1817  const IniParser::ObservableType * auxEntry = findIniEntry(vertex, boundIniFile->getRules(), "Rules");
1818 
1819  // Collect the list of groups that the backend requirements of this vertex exist in.
1820  std::set<str> groups = (*masterGraph[vertex]).backendgroups();
1821 
1822  // Collect the list of orphan (i.e. groupless) backend requirements.
1823  std::set<sspair> orphan_reqs = (*masterGraph[vertex]).backendreqs("none");
1824 
1825  // Loop until no further backend resolutions are possible, or no more are required.
1826  while ( not ( groups.empty() and orphan_reqs.empty() ) )
1827  {
1828 
1829  // Loop over all groups, including the null group (group="none").
1830  for (std::set<str>::iterator it = groups.begin(); it != groups.end(); ++it)
1831  {
1832  // Switch depending on whether this is a real group or not.
1833  if (*it == "none")
1834  {
1835  // Loop over all the orphan requirements.
1836  for (std::set<sspair>::iterator req = orphan_reqs.begin(); req != orphan_reqs.end(); ++req)
1837  {
1839  logger() << "Resolving ungrouped requirement " << req->first;
1840  logger() << " (" << req->second << ")..." << EOM;
1841 
1842  // Find a backend function that fulfills the backend requirement.
1843  std::set<sspair> reqsubset;
1844  reqsubset.insert(*req);
1845  solution = solveRequirement(reqsubset,auxEntry,vertex,previous_successes,allow_deferral);
1846 
1847  // Check if a valid solution has been returned
1848  if (solution != NULL)
1849  {
1850  // It has, so resolve the backend requirement with that function and add it to the list of successful resolutions.
1851  resolveRequirement(solution,vertex);
1852  previous_successes.push_back(solution);
1853 
1854  // If *req is in remaining_reqs, remove it
1855  if (remaining_reqs.find(*req) != remaining_reqs.end())
1856  {
1857  remaining_reqs.erase(*req);
1858  }
1859  }
1860  else // No valid solution found, but deferral has been suggested - so defer resolution of this group until later.
1861  {
1862  remaining_reqs.insert(*req);
1864  logger() << "Resolution of ungrouped requirement " << req->first;
1865  logger() << " (" << req->second << ") deferred until later." << EOM;
1866  }
1867  }
1868  if (not remaining_reqs.empty()) remaining_groups.insert(*it);
1869  }
1870  else
1871  {
1873  logger() << "Resolving from group " << *it << "..." << EOM;
1874 
1875  // Collect the list of backend requirements in this group.
1876  std::set<sspair> reqs = (*masterGraph[vertex]).backendreqs(*it);
1877 
1878  // Find a backend function that fulfills one of the backend requirements in the group.
1879  solution = solveRequirement(reqs,auxEntry,vertex,previous_successes,allow_deferral,*it);
1880 
1881  // Check if a valid solution has been returned
1882  if (solution != NULL)
1883  {
1884  // It has, so resolve the backend requirement with that function and add it to the list of successful resolutions.
1885  resolveRequirement(solution,vertex);
1886  previous_successes.push_back(solution);
1887  }
1888  else // No valid solution found, but deferral has been suggested - so defer resolution of this group until later.
1889  {
1890  remaining_groups.insert(*it);
1892  logger() << "Resolution from group " << *it;
1893  logger() << "deferred until later." << EOM;
1894  }
1895  }
1896  }
1897 
1898  // If there has been no improvement this round, turn off deferral and make the next round the last attempt.
1899  if (orphan_reqs == remaining_reqs and groups == remaining_groups)
1900  {
1901  allow_deferral = false;
1902  }
1903  else // Otherwise try again to resolve the remaining groups and orphan requirements, now that some others are known.
1904  {
1905  orphan_reqs = remaining_reqs;
1906  groups = remaining_groups;
1907  remaining_reqs.clear();
1908  remaining_groups.clear();
1909  }
1910 
1911  }
1912 
1913  }
MasterGraphType masterGraph
The central boost graph object.
const IniParser::ObservableType * findIniEntry(sspair quantity, const IniParser::ObservablesType &, const str &)
Find entries (comparison of inifile entry with quantity or functor)
const ObservablesType & getRules() const
Definition: yaml_parser.cpp:68
functor * solveRequirement(std::set< sspair >, const IniParser::ObservableType *, VertexID, std::vector< functor *>, bool, str group="none")
Find backend function matching any one of a number of capability-type pairs.
void resolveRequirement(functor *, VertexID)
Resolve a specific backend requirement.
const Logging::endofmessage EOM
Explicit const instance of the end of message struct in Gambit namespace.
Definition: logger.hpp:100
EXPORT_SYMBOLS Logging::LogMaster & logger()
Function to retrieve a reference to the Gambit global log object.
Definition: logger.cpp:95
Types::Observable ObservableType
Definition: yaml_parser.hpp:85
const IniParser::IniFile * boundIniFile
ini file to which this dependency resolver is bound
Here is the call graph for this function:
Here is the caller graph for this function:

◆ run_topological_sort()

std::list< VertexID > Gambit::DRes::DependencyResolver::run_topological_sort ( )
private

Topological sort.

Boost lib topological sort.

Definition at line 1745 of file depresolver.cpp.

References masterGraph.

Referenced by doResolution().

1746  {
1747  std::list<VertexID> topo_order;
1748  topological_sort(masterGraph, front_inserter(topo_order));
1749  return topo_order;
1750  }
MasterGraphType masterGraph
The central boost graph object.
Here is the caller graph for this function:

◆ solveRequirement()

functor * Gambit::DRes::DependencyResolver::solveRequirement ( std::set< sspair reqs,
const IniParser::ObservableType auxEntry,
VertexID  vertex,
std::vector< functor *>  previous_successes,
bool  allow_deferral,
str  group = "none" 
)
private

Find backend function matching any one of a number of capability-type pairs.

Find a backend function that matches any one of a vector of capability-type pairs.

Definition at line 1916 of file depresolver.cpp.

References Gambit::DRes::backendFuncMatchesIniEntry(), boundClaw, boundCore, boundIniFile, boundTEs, Gambit::DRes::dependency_resolver_error(), findIniEntry(), Gambit::Models::ModelFunctorClaw::get_activemodels(), Gambit::Models::ModelFunctorClaw::get_parent(), Gambit::gambit_core::getBackendFunctors(), Gambit::IniParser::Parser::getValueOrDef(), combine_hdf5::group, LOCAL_INFO, masterGraph, printGenericFunctorList(), and Gambit::DRes::typeComp().

Referenced by resolveVertexBackend().

1919  {
1920  std::vector<functor*> vertexCandidates;
1921  std::vector<functor*> vertexCandidatesWithIniEntry;
1922  std::vector<functor*> disabledVertexCandidates;
1923 
1924  // Loop over all existing backend vertices, and make a list of
1925  // functors that are available and fulfill the backend requirement
1926  for (std::vector<functor *>::const_iterator
1927  itf = boundCore->getBackendFunctors().begin();
1928  itf != boundCore->getBackendFunctors().end();
1929  ++itf)
1930  {
1931  const IniParser::ObservableType * reqEntry = NULL;
1932  bool entryExists = false;
1933 
1934  // Find relevant iniFile entry from Rules section
1935  if ( auxEntry != NULL ) reqEntry = findIniEntry((*itf)->quantity(), (*auxEntry).backends, "backend");
1936  if ( reqEntry != NULL) entryExists = true;
1937 
1938  // Look for a match to at least one backend requirement, taking into account type equivalency classes.
1939  bool simple_match = false;
1940  for (std::set<sspair>::const_iterator
1941  itr = reqs.begin();
1942  itr != reqs.end();
1943  ++itr)
1944  {
1945  if ((*itf)->capability() == itr->first and typeComp((*itf)->type(), itr->second, *boundTEs))
1946  {
1947  simple_match = true;
1948  break;
1949  }
1950  }
1951 
1952  // If there is a relevant inifile entry, we also check for a match to the capability, type, function name and backend name in that entry.
1953  if ( simple_match and ( entryExists ? backendFuncMatchesIniEntry(*itf, *reqEntry, *boundTEs) : true ) )
1954  {
1955 
1956  // Has the backend vertex already been disabled by the backend system?
1957  bool disabled = ( (*itf)->status() <= 0 );
1958 
1959  // Is it permitted to be used to fill this backend requirement?
1960  // First we create the backend-version pair for the backend vertex and its semi-generic form (where any version is OK).
1961  sspair itf_signature((*itf)->origin(), (*itf)->version());
1962  sspair itf_generic((*itf)->origin(), "any");
1963  // Then we find the set of backend-version pairs that are permitted.
1964  std::set<sspair> permitted_bes = (*masterGraph[vertex]).backendspermitted((*itf)->quantity());
1965  // Then we see if any match. First we test for generic matches, where any version of any backend is allowed.
1966  bool permitted = ( permitted_bes.empty()
1967  // Next we test for semi-generic matches, where the backend matches and any version of that backend is allowed.
1968  or std::find(permitted_bes.begin(), permitted_bes.end(), itf_generic) != permitted_bes.end()
1969  // Finally we test for specific matches, where both the backend and version match what is allowed.
1970  or std::find(permitted_bes.begin(), permitted_bes.end(), itf_signature) != permitted_bes.end() );
1971 
1972  // If the backend vertex is able and allowed,
1973  if (permitted and not disabled)
1974  {
1975  // add it to the overall vertex candidate list
1976  vertexCandidates.push_back(*itf);
1977  // if it has an inifile entry, add it to the candidate list with inifile entries
1978  if (entryExists) vertexCandidatesWithIniEntry.push_back(*itf);
1979  }
1980  else
1981  {
1982  // otherwise, add it to disabled vertex candidate list
1983  if (not disabled) (*itf)->setStatus(1);
1984  disabledVertexCandidates.push_back(*itf);
1985  }
1986  }
1987  }
1988 
1989  // If too many candidates, prefer those with entries in the inifile.
1990  if (vertexCandidates.size() > 1 and vertexCandidatesWithIniEntry.size() >= 1)
1991  {
1992  // Loop over the remaining candidates, and disable those without entries in the inifile.
1993  for (std::vector<functor *>::iterator it = vertexCandidates.begin(); it != vertexCandidates.end(); ++it)
1994  {
1995  if (std::find(vertexCandidatesWithIniEntry.begin(), vertexCandidatesWithIniEntry.end(), *it) == vertexCandidatesWithIniEntry.end() )
1996  disabledVertexCandidates.push_back(*it);
1997  }
1998  // Set the new list of vertex candidates to be only those with inifile entries.
1999  vertexCandidates = vertexCandidatesWithIniEntry;
2000  }
2001 
2002  // Purge all candidates that conflict with a backend-matching rule.
2003  // Start by making a new vector to hold the candidates that survive the purge.
2004  std::vector<functor *> survivingVertexCandidates;
2005  // Loop over the current candidates.
2006  for (std::vector<functor *>::const_iterator it = vertexCandidates.begin(); it != vertexCandidates.end(); ++it)
2007  {
2008  // Set up a flag to keep track of whether anything has indicated that the candidate should be thrown out.
2009  bool keeper = true;
2010  // Retrieve the tags of the candidate.
2011  std::set<str> tags = (*masterGraph[vertex]).backendreq_tags((*it)->quantity());
2012  // Loop over the tags
2013  for (std::set<str>::iterator tagit = tags.begin(); tagit != tags.end(); ++tagit)
2014  {
2015  // Find out which other backend requirements exhibiting this tag must be filled from the same backend as the req this candidate would fill.
2016  std::set<sspair> must_match = (*masterGraph[vertex]).forcematchingbackend(*tagit);
2017  // Set up a flag to keep track of whether any of the other backend reqs have already been filled.
2018  bool others_filled = false;
2019  // Set up a string to keep track of which backend the other backend reqs have been filled from (if any).
2020  str common_backend_and_version;
2021  // Loop over the other backend reqs.
2022  for (std::set<sspair>::iterator mit = must_match.begin(); mit != must_match.end(); ++mit)
2023  {
2024  // Set up a flag to indicate if the other backend req in question has been filled yet.
2025  bool other_filled = false;
2026  // Set up a string to keep track of which backend the other backend req in question has been filled from (if any).
2027  str filled_from;
2028  // Loop over the backend functors that have successfully filled backend reqs already for this funcition
2029  for (std::vector<functor*>::const_iterator
2030  itf = previous_successes.begin();
2031  itf != previous_successes.end();
2032  ++itf)
2033  {
2034  // Check if the current previous successful resolution (itf) was of the same backend requirement as the
2035  // current one of the backend requirements (mit) that must be filled from the same backend as the current candidate (it).
2036  if ((*itf)->quantity() == *mit)
2037  {
2038  // Note that mit (the current backend req that must be filled from the same backend as the current candidate) has indeed been filled, by itf
2039  other_filled = true;
2040  // Note which backend mit has been filled from (i.e. where does itf come from?)
2041  filled_from = (*itf)->origin() + " v" + (*itf)->version();
2042  break;
2043  }
2044  }
2045  // If the other req has been filled, updated the tracker of whether any of the reqs linked to this flag have been filled,
2046  // and compare the filling backend to the one used to fill any other reqs associated with this tag.
2047  if (other_filled)
2048  {
2049  others_filled = true;
2050  if (common_backend_and_version.empty()) common_backend_and_version = filled_from; // Save the filling backend
2051  if (filled_from != common_backend_and_version) // Something buggy has happened and the rule is already broken(!)
2052  {
2053  str errmsg = "A backend-matching rule has been violated!";
2054  errmsg += "\nFound whilst checking which backends have been used"
2055  "\nto fill requirements with tag " + *tagit + " in function "
2056  "\n" + (*masterGraph[vertex]).name() + " of " + (*masterGraph[vertex]).origin() + "."
2057  "\nOne requirement was filled from " + common_backend_and_version + ", "
2058  "\nwhereas another was filled from " + filled_from + "."
2059  "\nThis should not happen and is probably a bug in GAMBIT.";
2060  dependency_resolver_error().raise(LOCAL_INFO,errmsg);
2061  }
2062  }
2063  }
2064  // Try to keep this candidate if it comes from the same backend as those already filled, or if none of the others are filled yet.
2065  keeper = (not others_filled or common_backend_and_version == (*it)->origin() + " v" + (*it)->version());
2066  if (not keeper) break;
2067  }
2068  if (keeper) survivingVertexCandidates.push_back(*it); else disabledVertexCandidates.push_back(*it);
2069  }
2070  // Replace the previous list of candidates with the survivors.
2071  vertexCandidates = survivingVertexCandidates;
2072 
2073  // Only print the status flags -5 or -6 if any of the disabled vertices has it
2074  bool printMathematicaStatus = false;
2075  for(unsigned int j=0; j < disabledVertexCandidates.size(); j++)
2076  if(disabledVertexCandidates[j]->status() == -5)
2077  printMathematicaStatus = true;
2078  bool printPythonStatus = false;
2079  for(unsigned int j=0; j < disabledVertexCandidates.size(); j++)
2080  if(disabledVertexCandidates[j]->status() == -6)
2081  printPythonStatus = true;
2082 
2083  // No candidates? Death.
2084  if (vertexCandidates.size() == 0)
2085  {
2086  std::ostringstream errmsg;
2087  errmsg
2088  << "Found no candidates for backend requirements of "
2089  << masterGraph[vertex]->origin() << "::" << masterGraph[vertex]->name() << ":\n"
2090  << reqs << "\nfrom group: " << group;
2091  if (disabledVertexCandidates.size() != 0)
2092  {
2093  errmsg << "\nNote that viable candidates exist but have been disabled:\n"
2094  << printGenericFunctorList(disabledVertexCandidates)
2095  << endl
2096  << "Status flags:" << endl
2097  << " 1: This function is available, but the backend version is not compatible with all your requests." << endl
2098  << " 0: This function is not compatible with any model you are scanning." << endl
2099  << "-1: The backend that provides this function is missing." << endl
2100  << "-2: The backend is present, but function is absent or broken." << endl;
2101  if(printMathematicaStatus)
2102  errmsg << "-5: The backend requires Mathematica, but Mathematica is absent." << endl;
2103  if(printPythonStatus)
2104  errmsg << "-6: The backend requires Python, but pybind11 is absent." << endl;
2105  errmsg << endl
2106  << "Make sure to check your YAML file, especially the rules" << endl
2107  << "pertaining to backends." << endl
2108  << endl
2109  << "Please also check that all shared objects exist for the" << endl
2110  << "necessary backends, and that they contain all the" << endl
2111  << "necessary functions required for this scan. You may" << endl
2112  << "check the status of different backends by running" << endl
2113  << " ./gambit backends" << endl
2114  << "You may also wish to check the specified search paths for each" << endl
2115  << "backend shared library in " << endl;
2116  if (Backends::backendInfo().custom_locations_exist())
2117  {
2118  errmsg << " " << Backends::backendInfo().backend_locations() << endl << "and" << endl;
2119  }
2120  errmsg << " " << Backends::backendInfo().default_backend_locations() << endl;
2121  }
2122  dependency_resolver_error().raise(LOCAL_INFO,errmsg.str());
2123  }
2124 
2125  // Still more than one candidate...
2126  if (vertexCandidates.size() > 1)
2127  {
2128  // Check whether any of the remaining candidates is subject to a backend-matching rule,
2129  // and might therefore be uniquely chosen over the other(s) if resolution for this req is attempted again, after
2130  // another of the reqs subject to the same rule is resolved.
2131  bool rule_exists = false;
2132  // Loop over the remaining candidates.
2133  for (std::vector<functor *>::const_iterator it = vertexCandidates.begin(); it != vertexCandidates.end(); ++it)
2134  {
2135  // Retrieve the tags of the candidate.
2136  std::set<str> tags = (*masterGraph[vertex]).backendreq_tags((*it)->quantity());
2137  // Loop over the tags
2138  for (std::set<str>::iterator tagit = tags.begin(); tagit != tags.end(); ++tagit)
2139  {
2140  // Find if there is a backend-matching rule associated with this tag.
2141  rule_exists = not (*masterGraph[vertex]).forcematchingbackend(*tagit).empty();
2142  if (rule_exists) break;
2143  }
2144  if (rule_exists) break;
2145  }
2146 
2147  // If deferral is allowed and appears to be potentially useful, defer resolution until later.
2148  if (allow_deferral and rule_exists)
2149  {
2150  return NULL;
2151  }
2152 
2153  // If not, we have just one more trick up our sleeves... use the models scanned to narrow things down.
2154  if (boundIniFile->getValueOrDef<bool>(true, "dependency_resolution", "prefer_model_specific_functions"))
2155  {
2156  // Prefer backend functors that are more specifically tailored for the model being scanned. Do not
2157  // consider backend functors that are accessible via INTERPRET_AS_X links, as these are all considered
2158  // to be equally 'far' from the model being scanned, with the 'distance' being one step further than
2159  // the most distant ancestor.
2160  std::vector<functor*> newCandidates;
2161  std::set<str> s = boundClaw->get_activemodels();
2162  std::vector<str> parentModelList(s.begin(), s.end());
2163  while (newCandidates.size() == 0 and not parentModelList.empty())
2164  {
2165  for (std::vector<str>::iterator mit = parentModelList.begin(); mit != parentModelList.end(); ++mit)
2166  {
2167  // Test each vertex candidate to see if it has been explicitly set up to work with the model *mit
2168  for (std::vector<functor*>::iterator it = vertexCandidates.begin(); it != vertexCandidates.end(); ++it)
2169  {
2170  if ( (*it)->modelExplicitlyAllowed(*mit) ) newCandidates.push_back(*it);
2171  }
2172  // Step up a level in the model hierarchy for this model.
2173  *mit = boundClaw->get_parent(*mit);
2174  }
2175  parentModelList.erase(std::remove(parentModelList.begin(), parentModelList.end(), "none"), parentModelList.end());
2176  }
2177  if (newCandidates.size() != 0) vertexCandidates = newCandidates;
2178  }
2179 
2180  // Still more than one candidate, so the game is up.
2181  if (vertexCandidates.size() > 1)
2182  {
2183  str errmsg = "Found too many candidates for backend requirement ";
2184  if (reqs.size() == 1) errmsg += reqs.begin()->first + " (" + reqs.begin()->second + ")";
2185  else errmsg += "group " + group;
2186  errmsg += " of module function " + masterGraph[vertex]->origin() + "::" + masterGraph[vertex]->name()
2187  + "\nViable candidates are:\n" + printGenericFunctorList(vertexCandidates);
2188  errmsg += "\nIf you don't need all the above backends, you can resolve the ambiguity simply by";
2189  errmsg += "\nuninstalling the backends you don't use.";
2190  errmsg += "\n\nAlternatively, you can add an entry in your YAML file that selects which backend";
2191  errmsg += "\nthe module function " + masterGraph[vertex]->origin() + "::" + masterGraph[vertex]->name() + " should use. A YAML file entry";
2192  errmsg += "\nthat selects e.g. the first candidate above could read\n";
2193  errmsg += "\n - capability: "+masterGraph[vertex]->capability();
2194  errmsg += "\n function: "+masterGraph[vertex]->name();
2195  errmsg += "\n backends:";
2196  errmsg += "\n - {backend: "+vertexCandidates.at(0)->origin()+", version: "+vertexCandidates.at(0)->version()+"}\n";
2197  dependency_resolver_error().raise(LOCAL_INFO,errmsg);
2198  }
2199  }
2200 
2201  // Just one candidate. Jackpot.
2202  return vertexCandidates[0];
2203 
2204  }
bool backendFuncMatchesIniEntry(functor *f, const IniParser::ObservableType &e, const Utils::type_equivalency &eq)
MasterGraphType masterGraph
The central boost graph object.
const IniParser::ObservableType * findIniEntry(sspair quantity, const IniParser::ObservablesType &, const str &)
Find entries (comparison of inifile entry with quantity or functor)
TYPE getValueOrDef(TYPE def, const args &... keys) const
#define LOCAL_INFO
Definition: local_info.hpp:34
str get_parent(const str &) const
Retrieve the parent model for a given model.
Definition: models.cpp:244
const fVec & getBackendFunctors() const
Get a reference to the list of backend model functors.
Definition: core.cpp:238
bool typeComp(str, str, const Utils::type_equivalency &, bool with_regex=true)
Type comparison taking into account equivalence classes.
const gambit_core * boundCore
Core to which this dependency resolver is bound.
str printGenericFunctorList(const std::vector< functor *> &)
Pretty print backend functor information.
std::pair< str, str > sspair
Shorthand for a pair of standard strings.
Definition: util_types.hpp:64
std::set< str > get_activemodels() const
Return the set of active models;.
Definition: models.cpp:106
const Utils::type_equivalency * boundTEs
Type equivalency object to which this dependency resolver is bound.
Types::Observable ObservableType
Definition: yaml_parser.hpp:85
std::string str
Shorthand for a standard string.
Definition: Analysis.hpp:35
const IniParser::IniFile * boundIniFile
ini file to which this dependency resolver is bound
const Models::ModelFunctorClaw * boundClaw
Model claw to which this dependency resolver is bound.
error & dependency_resolver_error()
Dependency resolver errors.
Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ activeFunctorGraphFile

const str Gambit::DRes::DependencyResolver::activeFunctorGraphFile
private

Output filename for graph of active functors.

Definition at line 279 of file depresolver.hpp.

Referenced by doResolution(), and printFunctorEvalOrder().

◆ boundClaw

const Models::ModelFunctorClaw* Gambit::DRes::DependencyResolver::boundClaw
private

Model claw to which this dependency resolver is bound.

Definition at line 245 of file depresolver.hpp.

Referenced by closestCandidateForModel(), makeFunctorsModelCompatible(), resolveDependency(), and solveRequirement().

◆ boundCore

const gambit_core* Gambit::DRes::DependencyResolver::boundCore
private

Core to which this dependency resolver is bound.

Definition at line 242 of file depresolver.hpp.

Referenced by addFunctors(), calcObsLike(), doResolution(), generateTree(), makeFunctorsModelCompatible(), printFunctorList(), and solveRequirement().

◆ boundIniFile

const IniParser::IniFile* Gambit::DRes::DependencyResolver::boundIniFile
private

◆ boundPrinter

Printers::BasePrinter* Gambit::DRes::DependencyResolver::boundPrinter
private

Printer object to which this dependency resolver is bound.

Definition at line 254 of file depresolver.hpp.

Referenced by initialisePrinter(), and printObsLike().

◆ boundTEs

const Utils::type_equivalency* Gambit::DRes::DependencyResolver::boundTEs
private

Type equivalency object to which this dependency resolver is bound.

Definition at line 251 of file depresolver.hpp.

Referenced by checkTypeMatch(), collectIniOptions(), collectSubCaps(), DependencyResolver(), findIniEntry(), printObsLike(), resolveDependency(), resolveDependencyFromRules(), and solveRequirement().

◆ edges_to_force_on_manager

std::map<VertexID, std::set<VertexID> > Gambit::DRes::DependencyResolver::edges_to_force_on_manager
private

Map from nested function -> list of fulfilled dependencies that need to be passed on to its loop manager when it is selected.

Definition at line 273 of file depresolver.hpp.

Referenced by generateTree().

◆ function_order

std::list<VertexID> Gambit::DRes::DependencyResolver::function_order
private

Saved calling order for functions.

Definition at line 263 of file depresolver.hpp.

Referenced by doResolution().

◆ index

IndexMap Gambit::DRes::DependencyResolver::index
private

Indices associated with graph vertices (used by printers to identify functors)

Definition at line 276 of file depresolver.hpp.

Referenced by initialisePrinter().

◆ loopManagerMap

std::map<VertexID, std::set<VertexID> > Gambit::DRes::DependencyResolver::loopManagerMap
private

Temporary map for loop manager -> list of nested functions.

Definition at line 269 of file depresolver.hpp.

Referenced by doResolution(), and generateTree().

◆ masterGraph

◆ outputVertexInfos

std::vector<OutputVertexInfo> Gambit::DRes::DependencyResolver::outputVertexInfos
private

Output Vertex Infos.

Definition at line 257 of file depresolver.hpp.

Referenced by generateTree(), getIniEntry(), and getObsLikeOrder().

◆ print_timing

bool Gambit::DRes::DependencyResolver::print_timing = false
private

Global flag for triggering printing of timing data.

Definition at line 282 of file depresolver.hpp.

Referenced by generateTree(), and printTiming().

◆ print_unitcube

bool Gambit::DRes::DependencyResolver::print_unitcube = false
private

Global flag for triggering printing of unitCubeParameters.

Definition at line 285 of file depresolver.hpp.

Referenced by generateTree(), and initialisePrinter().

◆ SortedParentVertices

std::map<VertexID, std::vector<VertexID> > Gambit::DRes::DependencyResolver::SortedParentVertices
private

Saved calling order for functions required to compute single ObsLike entries.

Definition at line 266 of file depresolver.hpp.

Referenced by calcObsLike(), doResolution(), and printObsLike().


The documentation for this class was generated from the following files: