gambit is hosted by Hepforge, IPPP Durham
GAMBIT  v1.5.0-252-gf9a3f78
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 305 of file depresolver.cpp.

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

310  : boundCore(&core),
311  boundClaw(&claw),
312  boundIniFile(&iniFile),
313  boundTEs(&equiv_classes),
315  index(get(vertex_index,masterGraph)),
316  activeFunctorGraphFile(Utils::runtime_scratch()+"GAMBIT_active_functor_graph.gv")
317  {
318  addFunctors();
320  logger() << "#######################################" << endl;
321  logger() << "# List of Type Equivalency Classes #" << endl;
322  logger() << "#######################################";
323  for (std::set<std::set<str> >::const_iterator it = boundTEs->equivalency_classes.begin(); it != boundTEs->equivalency_classes.end(); ++it)
324  {
325  logger() << endl << *it;
326  }
327  logger() << EOM;
328  }
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:99
Printers::BasePrinter * boundPrinter
Printer object to which this dependency resolver is bound.
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 the the run-specific scratch directory.
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 803 of file depresolver.cpp.

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

Referenced by DependencyResolver().

804  {
805  // Add primary model functors to masterGraph
806  for (std::vector<primary_model_functor *>::const_iterator
807  it = boundCore->getPrimaryModelFunctors().begin();
808  it != boundCore->getPrimaryModelFunctors().end();
809  ++it)
810  {
811  // Ignore functors with status set to 0 or less in order to ignore primary_model_functors
812  // that are not to be used for the scan.
813  if ( (*it)->status() > 0 )
814  {
815  boost::add_vertex(*it, this->masterGraph);
816  }
817  }
818  // Add module functors to masterGraph
819  for (std::vector<functor *>::const_iterator
820  it = boundCore->getModuleFunctors().begin();
821  it != boundCore->getModuleFunctors().end();
822  ++it)
823  {
824  boost::add_vertex(*it, this->masterGraph);
825  }
826  }
MasterGraphType masterGraph
The central boost graph object.
const pmfVec & getPrimaryModelFunctors() const
Get a reference to the list of primary model functors.
Definition: core.cpp:250
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:241
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 626 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().

627  {
628  if (SortedParentVertices.find(vertex) == SortedParentVertices.end())
629  core_error().raise(LOCAL_INFO, "Tried to calculate a function not in or not at top of dependency graph.");
630  std::vector<VertexID> order = SortedParentVertices.at(vertex);
631 
632  for (std::vector<VertexID>::iterator it = order.begin(); it != order.end(); ++it)
633  {
634  std::ostringstream ss;
635  ss << "Calling " << masterGraph[*it]->name() << " from " << masterGraph[*it]->origin() << "...";
637  masterGraph[*it]->calculate();
638  if (boundIniFile->getValueOrDef<bool>(
639  false, "dependency_resolution", "log_runtime") )
640  {
641  double T = masterGraph[*it]->getRuntimeAverage();
643  "Runtime, averaged over multiple calls [s]: " << T << EOM;
644  }
645  invalid_point_exception* e = masterGraph[*it]->retrieve_invalid_point_exception();
646  if (e != NULL) throw(*e);
647  }
648  // Reset the cout output precision, in case any backends have messed with it during the ObsLike evaluation.
649  cout << std::setprecision(boundCore->get_outprec());
650  }
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:99
int get_outprec() const
Getter for precision to use for cout.
Definition: core.cpp:76
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 697 of file depresolver.cpp.

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

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

698  {
699  for (auto it = types.begin(); it != types.end(); ++it)
700  {
701  if (typeComp(*it, masterGraph[vertex]->type(), *boundTEs, false)) return *it;
702  }
703  std::stringstream msg;
704  msg << "All quantities with purpose \"" << purpose << "\" in your yaml file must have one " << endl
705  << "of the following types: " << endl << " " << types << endl
706  << "You have tried to assign this purpose to " << masterGraph[vertex]->origin() << "::"
707  << masterGraph[vertex]->name() << "," << endl << "which has capability: " << endl
708  << " " << masterGraph[vertex]->capability() << endl << "and result type: " << endl
709  << " [" << masterGraph[vertex]->type() << "]" << endl << "Please assign a different purpose to this entry.";
710  core_error().raise(LOCAL_INFO, msg.str());
711  return "If you make core errors non-fatal you deserve what you get.";
712  }
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 922 of file depresolver.cpp.

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

Referenced by resolveDependencyFromRules().

923  {
924  // In case of doubt (and if not explicitely disabled in the ini-file), prefer functors
925  // that are more specifically tailored for the model being scanned. Do not consider functors
926  // that are accessible via INTERPRET_AS_X links, as these are all considered to be equally 'far'
927  // from the model being scanned, with the 'distance' being one step further than the most distant
928  // ancestor.
929 
930  // Work up the model ancestry one step at a time, and stop as soon as one or more valid model-specific functors is
931  // found at a given level in the hierarchy.
932  std::vector<DRes::VertexID> newCandidates;
933  std::set<str> s = boundClaw->get_activemodels();
934  std::vector<str> parentModelList(s.begin(), s.end());
935  while (newCandidates.size() == 0 and not parentModelList.empty())
936  {
937  for (std::vector<str>::iterator mit = parentModelList.begin(); mit != parentModelList.end(); ++mit)
938  {
939  // Test each vertex candidate to see if it has been explicitly set up to work with the model *mit
940  for (std::vector<DRes::VertexID>::iterator it = candidates.begin(); it != candidates.end(); ++it)
941  {
942  if ( masterGraph[*it]->modelExplicitlyAllowed(*mit) ) newCandidates.push_back(*it);
943  }
944  // Step up a level in the model hierarchy for this model.
945  *mit = boundClaw->get_parent(*mit);
946  }
947  parentModelList.erase(std::remove(parentModelList.begin(), parentModelList.end(), "none"), parentModelList.end());
948  }
949  if (newCandidates.size() != 0)
950  return newCandidates;
951  else
952  return candidates;
953  }
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 956 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().

957  {
958  YAML::Node nodes;
959  YAML::Node zlevels;
960 
961  #ifdef DEPRES_DEBUG
962  cout << "Searching options for " << masterGraph[vertex]->capability() << endl;
963  #endif
964 
965  const IniParser::ObservablesType & entries = boundIniFile->getRules();
966  for (IniParser::ObservablesType::const_iterator it =
967  entries.begin(); it != entries.end(); ++it)
968  {
969  if (moduleFuncMatchesIniEntry(masterGraph[vertex], *it, *boundTEs))
970  {
971  #ifdef DEPRES_DEBUG
972  cout << "Getting option from: " << it->capability << " " << it->type << endl;
973  #endif
974  for (auto jt = it->options.begin(); jt != it->options.end(); ++jt)
975  {
976  if ( not nodes[jt->first.as<std::string>()] )
977  {
978  #ifdef DEPRES_DEBUG
979  cout << jt->first.as<std::string>() << ": " << jt->second << endl;
980  #endif
981  nodes[jt->first.as<std::string>()] = jt->second;
982  zlevels[jt->first.as<std::string>()] = getEntryLevelForOptions(*it);
983  }
984  else
985  {
986  if ( zlevels[jt->first.as<std::string>()].as<int>() < getEntryLevelForOptions(*it) )
987  {
988  #ifdef DEPRES_DEBUG
989  cout << "Replaced : " << jt->first.as<std::string>() << ": " << jt->second << endl;
990  #endif
991  zlevels[jt->first.as<std::string>()] = getEntryLevelForOptions(*it);
992  nodes[jt->first.as<std::string>()] = jt->second;
993  }
994  else if ( zlevels[jt->first.as<std::string>()].as<int>() == getEntryLevelForOptions(*it) )
995  {
996  std::ostringstream errmsg;
997  errmsg << "ERROR! Multiple option entries with same level for key: " << jt->first.as<std::string>();
998  dependency_resolver_error().raise(LOCAL_INFO,errmsg.str());
999  }
1000  }
1001  }
1002  }
1003  }
1004  return Options(nodes);
1005  }
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 1008 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().

1009  {
1010  #ifdef DEPRES_DEBUG
1011  cout << "Searching for subcaps of " << masterGraph[vertex]->capability() << endl;
1012  #endif
1013 
1014  YAML::Node nodes;
1016 
1017  // Iterate over the ObsLikes entries
1018  for (auto it = entries.begin(); it != entries.end(); ++it)
1019  {
1020  // Select only those entries that match the current graph vertex (i.e. module function)
1021  if (moduleFuncMatchesIniEntry(masterGraph[vertex], *it, *boundTEs) and not it->subcaps.IsNull())
1022  {
1023  #ifdef DEPRES_DEBUG
1024  cout << "Found subcaps for " << it->capability << " " << it->type << " " << it->module << ":" << endl;
1025  #endif
1026  // The user has given just a single entry as a subcap
1027  if (it->subcaps.IsScalar())
1028  {
1029  str key = it->subcaps.as<str>();
1030  if (nodes[key]) dependency_resolver_error().raise(LOCAL_INFO,"Duplicate sub-capability for " + key + ".");
1031  nodes[key] = YAML::Node();
1032  }
1033  // The user has passed a simple list of subcaps
1034  else if (it->subcaps.IsSequence())
1035  {
1036  for (auto jt = it->subcaps.begin(); jt != it->subcaps.end(); ++jt)
1037  {
1038  if (not jt->IsScalar())
1039  dependency_resolver_error().raise(LOCAL_INFO,"Attempt to pass map using sequence syntax for subcaps of "+it->capability+".");
1040  str key = jt->as<str>();
1041  if (nodes[key]) dependency_resolver_error().raise(LOCAL_INFO,"Duplicate sub-capability for " + key + ".");
1042  nodes[key] = YAML::Node();
1043  }
1044  }
1045  // The user has passed some more complicated subcap structure than just a list of strings
1046  else if (it->subcaps.IsMap())
1047  {
1048  for (auto jt = it->subcaps.begin(); jt != it->subcaps.end(); ++jt)
1049  {
1050  str key = jt->first.as<str>();
1051  if (nodes[key]) dependency_resolver_error().raise(LOCAL_INFO,"Duplicate sub-capability for " + key + ".");
1052  nodes[key] = jt->second.as<YAML::Node>();
1053  }
1054  }
1055  #ifdef DEPRES_DEBUG
1056  cout << nodes << endl;
1057  #endif
1058  }
1059  }
1060  return Options(nodes);
1061  }
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 336 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().

337  {
338  const IniParser::ObservablesType & observables = boundIniFile->getObservables();
339  // (cap., typ) --> dep. vertex map
340  std::queue<QueueEntry> parQueue;
341  QueueEntry queueEntry;
342 
343  // Set up list of target ObsLikes
345  logger() << "#######################################" << endl;
346  logger() << "# List of Target ObsLikes #" << endl;
347  logger() << "# #" << endl;
348  logger() << "# format: Capability (Type) [Purpose] #" << endl;
349  logger() << "#######################################";
350  for (auto it = observables.begin(); it != observables.end(); ++it)
351  {
352  // Format output
353  logger() << LogTags::dependency_resolver << endl << it->capability << " (" << it->type << ") [" << it->purpose << "]";
354  queueEntry.first.first = it->capability;
355  queueEntry.first.second = it->type;
356  queueEntry.second = OBSLIKE_VERTEXID;
357  queueEntry.printme = it->printme;
358  parQueue.push(queueEntry);
359  }
360  logger() << EOM;
361 
362  // Activate functors compatible with model we scan over (and deactivate the rest)
364 
365  // Generate dependency tree (the core of the dependency resolution)
366  generateTree(parQueue);
367 
368  // Find one execution order for activated vertices that is compatible
369  // with dependency structure
371 
372  // Loop manager initialization: Notify them about their nested functions
373  for (std::map<VertexID, std::set<VertexID>>::iterator it =
374  loopManagerMap.begin(); it != loopManagerMap.end(); ++it)
375  {
376  // Generate topologically sorted list of vertex IDs that are nested
377  // within loop manager (*it) ...
378  std::vector<VertexID> vertexList = sortVertices(it->second, function_order);
379  // ... map this on functor pointers...
380  std::vector<functor*> functorList;
381  for (std::vector<VertexID>::iterator jt = vertexList.begin(); jt != vertexList.end(); ++jt)
382  {
383  functorList.push_back(masterGraph[*jt]);
384  }
385  // ...and store it into loop manager functor
386  masterGraph[it->first]->setNestedList(functorList);
387  }
388 
389  // Initialise the printer object with a list of functors that are set to print
391 
392 #ifdef HAVE_GRAPHVIZ
393  // Generate graphviz plot if running in dry-run mode.
395  {
396  std::ofstream outf(activeFunctorGraphFile);
397  write_graphviz(outf, masterGraph, labelWriter(&masterGraph), edgeWriter(&masterGraph));
398  }
399 #endif
400 
401  // Pre-compute the individually ordered vertex lists for each of the ObsLike entries.
402  std::vector<VertexID> order = getObsLikeOrder();
403  for(auto it = order.begin(); it != order.end(); ++it)
404  {
406  }
407 
408  // Done
409  }
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:99
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:132
#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:

◆ 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 1707 of file depresolver.cpp.

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

Referenced by generateTree().

1709  {
1710  // Set the default printing flag for functors to pass to the parQueue constructor.
1711  bool printme_default = false;
1712 
1713  // Tell the logger what the following messages are about.
1715 
1716  // Digest capability of loop manager (if defined)
1717  str lmcap = (*masterGraph[vertex]).loopManagerCapability();
1718  str lmtype = (*masterGraph[vertex]).loopManagerType();
1719  if (lmcap != "none")
1720  {
1721  logger() << "Adding module function loop manager to resolution queue:" << endl;
1722  logger() << lmcap << " ()" << endl;
1723  parQueue->push(QueueEntry(sspair(lmcap, lmtype), vertex, LOOP_MANAGER_DEPENDENCY, printme_default));
1724  }
1725 
1726  // Digest regular dependencies
1727  std::set<sspair> s = (*masterGraph[vertex]).dependencies();
1728  if (s.size() > 0) logger() << "Add dependencies of new module function to queue" << endl;
1729  for (std::set<sspair>::iterator it = s.begin(); it != s.end(); ++it)
1730  {
1731  // If the loop manager requirement exists and is type-specific, it is a true depencency,
1732  // and thus appears in the output of functor.dependencies(). So, we need to take care
1733  // not to double-count it for entry into the parQueue.
1734  if (lmcap == "none" or lmtype == "any" or lmcap != it->first or lmtype != it->second)
1735  {
1736  logger() << it->first << " (" << it->second << ")" << endl;
1737  parQueue->push(QueueEntry(*it, vertex, NORMAL_DEPENDENCY, printme_default));
1738  }
1739  }
1740 
1741  // Tell the logger we're done here.
1742  logger() << EOM;
1743  }
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:99
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 1780 of file depresolver.cpp.

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

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

1782  {
1783  std::vector<const IniParser::ObservableType*> obsEntryCandidates;
1784  for (IniParser::ObservablesType::const_iterator it =
1785  entries.begin(); it != entries.end(); ++it)
1786  {
1787  if ( capabilityMatchesIniEntry(quantity, *it) ) // use same criteria than for normal dependencies
1788  {
1789  obsEntryCandidates.push_back(&(*it));
1790  }
1791  }
1792  if ( obsEntryCandidates.size() == 0 ) return NULL;
1793  else if ( obsEntryCandidates.size() != 1 )
1794  {
1795  str errmsg = "Found multiple " + errtag + " entries for ";
1796  errmsg += quantity.first + " (" + quantity.second + ")";
1797  dependency_resolver_error().raise(LOCAL_INFO,errmsg);
1798  }
1799  return obsEntryCandidates[0]; // obsEntryCandidates.size() == 1
1800  }
#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 1754 of file depresolver.cpp.

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

1756  {
1757  std::vector<const IniParser::ObservableType*> auxEntryCandidates;
1758  for (IniParser::ObservablesType::const_iterator it =
1759  entries.begin(); it != entries.end(); ++it)
1760  {
1761  if ( moduleFuncMatchesIniEntry(masterGraph[toVertex], *it, *boundTEs) and it->capability != "" )
1762  {
1763  auxEntryCandidates.push_back(&(*it));
1764  }
1765  }
1766  if ( auxEntryCandidates.size() == 0 ) return NULL;
1767  else if ( auxEntryCandidates.size() != 1 )
1768  {
1769  str errmsg = "Found multiple " + errtag + " entries for ";
1770  errmsg += masterGraph[toVertex]->capability() +" (" +
1771  masterGraph[toVertex]->type() + ") [" +
1772  masterGraph[toVertex]->name() + ", " +
1773  masterGraph[toVertex]->origin() + "]";
1774  dependency_resolver_error().raise(LOCAL_INFO, errmsg);
1775  }
1776  return auxEntryCandidates[0]; // auxEntryCandidates.size() == 1
1777  }
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 1463 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().

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

References masterGraph.

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

687  {
688  graph_traits<DRes::MasterGraphType>::vertex_iterator vi, vi_end;
689  for (boost::tie(vi, vi_end) = vertices(masterGraph); vi != vi_end; ++vi)
690  {
691  if (*vi == id) return masterGraph[id];
692  }
693  return NULL;
694  }
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 728 of file depresolver.cpp.

References outputVertexInfos.

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

729  {
730  for (std::vector<OutputVertexInfo>::iterator it = outputVertexInfos.begin();
731  it != outputVertexInfos.end(); it++)
732  {
733  if (it->vertex == v)
734  return it->iniEntry;
735  }
736  return NULL;
737  }
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 577 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().

578  {
579  std::vector<VertexID> unsorted;
580  std::vector<VertexID> sorted;
581  std::set<VertexID> parents, colleages, colleages_min;
582  // Copy unsorted vertexIDs --> unsorted
583  for (std::vector<OutputVertexInfo>::iterator it = outputVertexInfos.begin();
584  it != outputVertexInfos.end(); it++)
585  {
586  unsorted.push_back(it->vertex);
587  }
588  // Sort iteratively (unsorted --> sorted)
589  while (unsorted.size() > 0)
590  {
591  double t2p_now;
592  double t2p_min = -1;
593  std::vector<VertexID>::iterator it_min;
594  for (std::vector<VertexID>::iterator it = unsorted.begin(); it !=
595  unsorted.end(); ++it)
596  {
597  parents.clear();
598  getParentVertices(*it, masterGraph, parents);
599  parents.insert(*it);
600  // Remove vertices that were already calculated from the ist
601  for ( auto cit = colleages.begin(); cit != colleages.end(); cit++)
602  {
603  parents.erase(*cit);
604  }
605  t2p_now = (double) getTimeEstimate(parents, masterGraph);
606  t2p_now /= masterGraph[*it]->getInvalidationRate();
607  if (t2p_min < 0 or t2p_now < t2p_min)
608  {
609  t2p_min = t2p_now;
610  it_min = it;
611  colleages_min = parents;
612  }
613  }
614  // Extent list of calculated vertices
615  colleages.insert(colleages_min.begin(), colleages_min.end());
616  double prop = masterGraph[*it_min]->getInvalidationRate();
617  logger() << LogTags::dependency_resolver << "Estimated T [s]: " << t2p_min*prop << EOM;
618  logger() << LogTags::dependency_resolver << "Estimated p: " << prop << EOM;
619  sorted.push_back(*it_min);
620  unsorted.erase(it_min);
621  }
622  return sorted;
623  }
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:99
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 870 of file depresolver.cpp.

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

Referenced by doResolution().

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

References masterGraph.

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

716  {
717  if (isnan)
718  {
719  masterGraph[vertex]->notifyOfInvalidation("NaN returned for likelihood value.");
720  }
721  else
722  {
723  masterGraph[vertex]->notifyOfInvalidation("Cumulative log-likelihood pushed below threshold.");
724  }
725  }
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 830 of file depresolver.cpp.

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

Referenced by doResolution(), and printFunctorList().

831  {
832  // Run just once
833  static bool already_run = false;
834  if (already_run) return;
835 
836  graph_traits<DRes::MasterGraphType>::vertex_iterator vi, vi_end;
837  std::vector<functor *>::const_iterator fi, fi_end = boundCore->getBackendFunctors().end();
838  std::set<str> modelList = boundClaw->get_activemodels();
839 
840  // Activate those module functors that match the combination of models being scanned.
841  for (boost::tie(vi, vi_end) = vertices(masterGraph); vi != vi_end; ++vi)
842  {
843  if (masterGraph[*vi]->status() >= 0 and masterGraph[*vi]->modelComboAllowed(modelList))
844  {
845  for (std::set<str>::iterator it = modelList.begin(); it != modelList.end(); ++it)
846  {
847  masterGraph[*vi]->notifyOfModel(*it);
848  masterGraph[*vi]->setStatus(1);
849  }
850  }
851  }
852 
853  // Activate those backend functors that match one of the models being scanned.
854  for (std::set<str>::iterator it = modelList.begin(); it != modelList.end(); ++it)
855  {
856  for (fi = boundCore->getBackendFunctors().begin(); fi != fi_end; ++fi)
857  {
858  // Activate if the backend vertex permits the model and has not been (severely) disabled by the backend system
859  if ( (*fi)->status() >= 0 and (*fi)->modelAllowed(*it) )
860  {
861  (*fi)->setStatus(1);
862  }
863  }
864  }
865  already_run = true;
866  }
MasterGraphType masterGraph
The central boost graph object.
const fVec & getBackendFunctors() const
Get a reference to the list of backend model functors.
Definition: core.cpp:247
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 442 of file depresolver.cpp.

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

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

◆ printFunctorList()

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

Pretty print module functor information.

List of masterGraph content.

Definition at line 412 of file depresolver.cpp.

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

413  {
414  // Activate functors compatible with model we scan over (and deactivate the rest)
416 
417  graph_traits<DRes::MasterGraphType>::vertex_iterator vi, vi_end;
418  const str formatString = "%-20s %-32s %-32s %-32s %-15s %-7i %-5i %-5i\n";
419  logger() << LogTags::dependency_resolver << endl << "Vertices registered in masterGraph" << endl;
420  logger() << "----------------------------------" << endl;
421  logger() << boost::format(formatString)%
422  "MODULE (VERSION)"% "FUNCTION"% "CAPABILITY"% "TYPE"% "PURPOSE"% "STATUS"% "#DEPs"% "#BE_REQs";
423  for (boost::tie(vi, vi_end) = vertices(masterGraph); vi != vi_end; ++vi)
424  {
425  logger() << boost::format(formatString)%
426  ((*masterGraph[*vi]).origin() + " (" + (*masterGraph[*vi]).version() + ")") %
427  (*masterGraph[*vi]).name()%
428  (*masterGraph[*vi]).capability()%
429  (*masterGraph[*vi]).type()%
430  (*masterGraph[*vi]).purpose()%
431  (*masterGraph[*vi]).status()%
432  (*masterGraph[*vi]).dependencies().size()%
433  (*masterGraph[*vi]).backendreqs().size();
434  }
435  logger() << "Registered Backend vertices" << endl;
436  logger() << "---------------------------" << endl;
438  logger() << EOM;
439  }
MasterGraphType masterGraph
The central boost graph object.
const fVec & getBackendFunctors() const
Get a reference to the list of backend model functors.
Definition: core.cpp:247
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:99
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:

◆ printGenericFunctorList() [1/2]

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

Pretty print backend functor information.

Definition at line 781 of file depresolver.cpp.

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

782  {
783  const str formatString = "%-20s %-32s %-48s %-32s %-7i\n";
784  std::ostringstream stream;
785  stream << boost::format(formatString)%"ORIGIN (VERSION)"% "FUNCTION"% "CAPABILITY"% "TYPE"% "STATUS";
786  for (std::vector<functor *>::const_iterator
787  it = functorList.begin();
788  it != functorList.end();
789  ++it)
790  {
791  stream << boost::format(formatString)%
792  ((*it)->origin() + " (" + (*it)->version() + ")") %
793  (*it)->name()%
794  (*it)->capability()%
795  (*it)->type()%
796  (*it)->status();
797  }
798  return stream.str();
799  }
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 770 of file depresolver.cpp.

References masterGraph, and printGenericFunctorList().

771  {
772  std::vector<functor*> functorList;
773  for ( auto it = vertexIDs.begin(); it != vertexIDs.end(); ++it )
774  {
775  functorList.push_back(masterGraph[*it]);
776  }
777  return printGenericFunctorList(functorList);
778  }
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 653 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().

654  {
655  // pointID is supplied by the scanner, and is used to tell the printer which model
656  // point the results should be associated with.
657 
658  if (SortedParentVertices.find(vertex) == SortedParentVertices.end())
659  core_error().raise(LOCAL_INFO, "Tried to calculate a function not in or not at top of dependency graph.");
660  std::vector<VertexID> order = SortedParentVertices.at(vertex);
661 
662  for (std::vector<VertexID>::iterator it = order.begin(); it != order.end(); ++it)
663  {
664  std::ostringstream ss;
665  ss << "Printing " << masterGraph[*it]->name() << " from " << masterGraph[*it]->origin() << "...";
667 
668  if (not typeComp(masterGraph[*it]->type(), "void", *boundTEs, false))
669  {
670  // Note that this prints from thread index 0 only, i.e. results created by
671  // threads other than the main one need to be accessed with
672  // masterGraph[*it]->print(boundPrinter,pointID,index);
673  // where index is some integer s.t. 0 <= index <= number of hardware threads.
674  // At the moment GAMBIT only prints results of thread 0, under the expectation
675  // that nested module functions are all designed to gather their results into
676  // thread 0.
677  masterGraph[*it]->print(boundPrinter,pointID);
678  }
679  }
680  }
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:99
Printers::BasePrinter * boundPrinter
Printer object to which this dependency resolver is bound.
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 754 of file depresolver.cpp.

References masterGraph, and OBSLIKE_VERTEXID.

Referenced by generateTree(), and resolveDependencyFromRules().

755  {
756  str s = quantity.first + " (" + quantity.second + ")";
757  s += ", required by ";
758  if ( vertex != OBSLIKE_VERTEXID )
759  {
760  s += (*masterGraph[vertex]).capability() + " (";
761  s += (*masterGraph[vertex]).type() + ") [";
762  s += (*masterGraph[vertex]).name() + ", ";
763  s += (*masterGraph[vertex]).origin() + "]";
764  }
765  else
766  s += "Core";
767  return s;
768  }
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 683 of file depresolver.cpp.

References print_timing.

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

683 { 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 740 of file depresolver.cpp.

References masterGraph.

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

741  {
742  graph_traits<DRes::MasterGraphType>::vertex_iterator vi, vi_end;
743  for (boost::tie(vi, vi_end) = vertices(masterGraph); vi != vi_end; ++vi)
744  {
745  if (masterGraph[*vi]->status() == 2) masterGraph[*vi]->reset();
746  }
747  }
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 1329 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().

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

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

2209  {
2210  (*masterGraph[vertex]).resolveBackendReq(func);
2212  logger() << "Resolved by: [" << func->name() << ", ";
2213  logger() << func->origin() << " (" << func->version() << ")]";
2214  logger() << EOM;
2215  }
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:99
Funk func(double(*f)(funcargs...), Args... args)
Definition: daFunk.hpp:768
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 1803 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().

1804  {
1805  functor* solution;
1806  std::vector<functor*> previous_successes;
1807  std::set<str> remaining_groups;
1808  std::set<sspair> remaining_reqs;
1809  bool allow_deferral = true;
1810 
1811  // If there are no backend requirements, and thus nothing to do, return.
1812  if ((*masterGraph[vertex]).backendreqs().size() == 0) return;
1813 
1814  // Get started.
1815  logger() << LogTags::dependency_resolver << "Doing backend function resolution..." << EOM;
1816 
1817  // Check whether this vertex is mentioned in the inifile.
1818  const IniParser::ObservableType * auxEntry = findIniEntry(vertex, boundIniFile->getRules(), "Rules");
1819 
1820  // Collect the list of groups that the backend requirements of this vertex exist in.
1821  std::set<str> groups = (*masterGraph[vertex]).backendgroups();
1822 
1823  // Collect the list of orphan (i.e. groupless) backend requirements.
1824  std::set<sspair> orphan_reqs = (*masterGraph[vertex]).backendreqs("none");
1825 
1826  // Loop until no further backend resolutions are possible, or no more are required.
1827  while ( not ( groups.empty() and orphan_reqs.empty() ) )
1828  {
1829 
1830  // Loop over all groups, including the null group (group="none").
1831  for (std::set<str>::iterator it = groups.begin(); it != groups.end(); ++it)
1832  {
1833  // Switch depending on whether this is a real group or not.
1834  if (*it == "none")
1835  {
1836  // Loop over all the orphan requirements.
1837  for (std::set<sspair>::iterator req = orphan_reqs.begin(); req != orphan_reqs.end(); ++req)
1838  {
1840  logger() << "Resolving ungrouped requirement " << req->first;
1841  logger() << " (" << req->second << ")..." << EOM;
1842 
1843  // Find a backend function that fulfills the backend requirement.
1844  std::set<sspair> reqsubset;
1845  reqsubset.insert(*req);
1846  solution = solveRequirement(reqsubset,auxEntry,vertex,previous_successes,allow_deferral);
1847 
1848  // Check if a valid solution has been returned
1849  if (solution != NULL)
1850  {
1851  // It has, so resolve the backend requirement with that function and add it to the list of successful resolutions.
1852  resolveRequirement(solution,vertex);
1853  previous_successes.push_back(solution);
1854 
1855  // If *req is in remaining_reqs, remove it
1856  if (remaining_reqs.find(*req) != remaining_reqs.end())
1857  {
1858  remaining_reqs.erase(*req);
1859  }
1860  }
1861  else // No valid solution found, but deferral has been suggested - so defer resolution of this group until later.
1862  {
1863  remaining_reqs.insert(*req);
1865  logger() << "Resolution of ungrouped requirement " << req->first;
1866  logger() << " (" << req->second << ") deferred until later." << EOM;
1867  }
1868  }
1869  if (not remaining_reqs.empty()) remaining_groups.insert(*it);
1870  }
1871  else
1872  {
1874  logger() << "Resolving from group " << *it << "..." << EOM;
1875 
1876  // Collect the list of backend requirements in this group.
1877  std::set<sspair> reqs = (*masterGraph[vertex]).backendreqs(*it);
1878 
1879  // Find a backend function that fulfills one of the backend requirements in the group.
1880  solution = solveRequirement(reqs,auxEntry,vertex,previous_successes,allow_deferral,*it);
1881 
1882  // Check if a valid solution has been returned
1883  if (solution != NULL)
1884  {
1885  // It has, so resolve the backend requirement with that function and add it to the list of successful resolutions.
1886  resolveRequirement(solution,vertex);
1887  previous_successes.push_back(solution);
1888  }
1889  else // No valid solution found, but deferral has been suggested - so defer resolution of this group until later.
1890  {
1891  remaining_groups.insert(*it);
1893  logger() << "Resolution from group " << *it;
1894  logger() << "deferred until later." << EOM;
1895  }
1896  }
1897  }
1898 
1899  // If there has been no improvement this round, turn off deferral and make the next round the last attempt.
1900  if (orphan_reqs == remaining_reqs and groups == remaining_groups)
1901  {
1902  allow_deferral = false;
1903  }
1904  else // Otherwise try again to resolve the remaining groups and orphan requirements, now that some others are known.
1905  {
1906  orphan_reqs = remaining_reqs;
1907  groups = remaining_groups;
1908  remaining_reqs.clear();
1909  remaining_groups.clear();
1910  }
1911 
1912  }
1913 
1914  }
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:99
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 1746 of file depresolver.cpp.

References masterGraph.

Referenced by doResolution().

1747  {
1748  std::list<VertexID> topo_order;
1749  topological_sort(masterGraph, front_inserter(topo_order));
1750  return topo_order;
1751  }
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 1917 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().

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