file src/rule.cpp

[No description available] More…

Namespaces

Name
Gambit
TODO: see if we can use this one:
Gambit::DRes
Forward declaration of Rule and Observables classes for saving pointers to ignored and matched examples.

Detailed Description

Author: Pat Scott (patrickcolinscott@gmail.com)

Date: 2022 Nov

Function implementations for rule classes.


Authors (add name and date if you modify):


Source code

//   GAMBIT: Global and Modular BSM Inference Tool
//   *********************************************
///  \file
///
///  Function implementations for rule classes.
///
///  *********************************************
///
///  Authors (add name and date if you modify):
///
///  \author Pat Scott
///          (patrickcolinscott@gmail.com)
///  \date 2022 Nov
///
///  *********************************************

#include "gambit/Core/rule.hpp"
#include "gambit/Core/error_handlers.hpp"
#include "gambit/Core/resolution_utilities.hpp"
#include "gambit/Elements/functors.hpp"

namespace Gambit
{

  namespace DRes
  {

    /// True if and only if the passed functor matches the base part of an 'if' part of a rule 
    bool Rule::base_antecedent_matches(functor* f, const Utils::type_equivalency& te) const
    {
      bool match = true;
      if (match and if_capability) match = stringComp(capability, f->capability()   ); 
      if (match and if_type)       match = typeComp  (type,       f->type(),      te); 
      if (match and if_function)   match = stringComp(function,   f->name()         ); 
      return match;
    }

    /// True if and only if the passed functor matches the base part of a 'then' part of a rule 
    bool Rule::base_consequent_matches(functor* f, const Utils::type_equivalency& te) const
    {
      bool match = true;
      if (match and then_capability) match = stringComp(capability, f->capability()   ); 
      if (match and then_type)       match = typeComp  (type,       f->type(),      te); 
      if (match and then_function)   match = stringComp(function,   f->name()         ); 
      return match;
    }

    /// Check if a given string is a permitted field of the BackendRule class
    bool BackendRule::permits_field(const str& field)
    {
      static const std::set<str> fields =
      {
        "version",
        "backend",
        "group"
      };
      return (fields.find(field) != fields.end());
    }

    /// True if and only if the passed backend functor matches the 'if' part of a rule
    bool BackendRule::antecedent_matches(functor* f, const Utils::type_equivalency& te, const str& group_being_resolved) const
    {
      // Allow matching only if the antecedent has been properly specified.
      bool match = if_capability or if_type or if_function or if_version or if_backend or if_group;
      // Check if the base class part of the antecedent was matched.
      match = match and base_antecedent_matches(f, te);
      // Check if the derived class part of the antecedent was matched.
      if (match and if_version) match = stringComp(version, f->version()); 
      if (match and if_backend) match = stringComp(backend, f->origin()); 
      if (match and if_group)   match = stringComp(group, group_being_resolved); 
      return match;
    }

    /// True if and only if the passed backend functor matches the 'then' part of a rule
    bool BackendRule::consequent_matches(functor* f, const Utils::type_equivalency& te) const
    {
      // Allow matching only if the consequent has been properly specified.
      bool match = then_capability or then_type or then_function or then_version or then_backend;
      // Check if the base class part of the consequent was matched.
      match = match and base_consequent_matches(f, te);
      // Check if the derived class part of the consequent was matched.
      if (match and then_version) match = stringComp(version, f->version()); 
      if (match and then_backend) match = stringComp(backend, f->origin()); 
      // Log match
      if (match and log_matches) f->addMatchedBackendRule(this);
      return match;
    }

    /// Whether a backend rule allows a given backend functor or not.  
    /// Must be true for a backend functor to be used to resolve a backend requirement.   
    /// True unless the functor passes the antecedent ('if' part of the rule) but fails the consequent ('then' part of the rule). 
    bool BackendRule::allows(functor* f, const Utils::type_equivalency& te, const str& group_being_resolved, bool ignore_if_weak) const
    {
      if (ignore_if_weak and weakrule) return true;
      if (not antecedent_matches(f, te, group_being_resolved)) return true;
      bool result = consequent_matches(f, te);
      return result;
    }

    /// Check if a given string is a permitted field of the ModuleRule class
    bool ModuleRule::permits_field(const str& field)
    {
      static const std::set<str> fields =
      {
        "module",
        "options",
        "dependencies",
        "backends",
        "functionChain"
      };
      return (fields.find(field) != fields.end());
    }

    /// True if and only if the passed module functor matches the 'if' part of a rule
    bool ModuleRule::antecedent_matches(functor* f, const Utils::type_equivalency& te) const
    {
      // Allow matching only if the antecedent has been properly specified.
      bool match = if_capability or if_type or if_function or if_module;
      // Check if the base class part of the antecedent was matched.
      match = match and base_antecedent_matches(f, te);
      // Check if the derived class part of the antecedent was matched.
      if (match and if_module) match = stringComp(module, f->origin()); 
      return match;
    }

    /// True if and only if the passed module functor matches the 'then' part of a rule
    bool ModuleRule::consequent_matches(functor* f, const Utils::type_equivalency& te) const
    {
      // Allow matching only if the consequent has been properly specified.
      bool match = then_capability or then_type or then_function or then_module or
                   then_options or then_dependencies or then_backends or then_functionChain;
      // Check if the base class part of the consequent was matched.
      match = match and base_consequent_matches(f, te);
      // Check if the derived class part of the consequent was matched.
      if (match and then_module) match = stringComp(module, f->origin()); 
      // Log match
      if (match and log_matches) f->addMatchedModuleRule(this);
      return match;
    }

    /// Whether a module rule allows a given module functor or not.  
    /// Must be true for a module functor to be used to resolve a dependency.   
    /// True unless the functor passes the antecedent ('if' part of the rule) but fails the consequent ('then' part of the rule). 
    bool ModuleRule::allows(functor* f, const Utils::type_equivalency& te, bool ignore_if_weak) const
    {
      if (ignore_if_weak and weakrule) return true;
      if (not antecedent_matches(f, te)) return true;
      bool result = consequent_matches(f, te);
      return result;
    }

    /// Whether the set of dependency rules subjugate to this rule allow a given module functor or not. 
    bool ModuleRule::dependencies_allow(functor* f, const Utils::type_equivalency& te, bool ignore_if_weak) const
    {
      if (ignore_if_weak and weakrule) return true;
      bool allow = true;
      for (const ModuleRule& rule : dependencies) allow = allow and rule.allows(f, te, ignore_if_weak);
      return allow;      
    }

    /// Whether the functionChain of this rule allows a given module functor to be used to resolve the dependency of another. 
    bool ModuleRule::function_chain_allows(functor* candidate, functor* dependee, const Utils::type_equivalency& te, bool ignore_if_weak) const
    {
      // Scenarios in which the functionChain is irrelevent.
      if (ignore_if_weak and weakrule) return true;
      if (not then_functionChain) return true;
      if (not stringComp(capability, candidate->capability()) and not typeComp(type, candidate->type(), te)) return true;
      // If the dependee matches the rule, then the candidate is allowed only if it appears at the start of the function chain.
      if (antecedent_matches(dependee, te) and consequent_matches(dependee, te)) return (*functionChain.begin() == candidate->name());
      // Iterate over the entries in the functionChain
      for (auto it = functionChain.begin(); it != functionChain.end() - 1; ++it)
      {
        // Function is allowed if somewhere in the chain it is directly preceeded by the dependent function.
        if ((*it) == dependee->name()) return (*(it+1) == candidate->name());
      }
      return true;
    }

    /// Whether the set of backend rules subjugate to this rule allow a given backend functor or not. 
    bool ModuleRule::backend_reqs_allow(functor* f, const Utils::type_equivalency& te, const str& group_being_resolved, bool ignore_if_weak) const
    {
      if (ignore_if_weak and weakrule) return true;
      bool allow = true;
      for (const BackendRule& rule : backends) allow = allow and rule.allows(f, te, group_being_resolved, ignore_if_weak);
      return allow;      
    }

  }

}

Updated on 2024-07-18 at 13:53:34 +0000