5 #ifndef BPP_PHYL_LIKELIHOOD_DATAFLOW_DATAFLOW_H
6 #define BPP_PHYL_LIKELIHOOD_DATAFLOW_DATAFLOW_H
16 #include <unordered_map>
17 #include <unordered_set>
33 template<
typename T>
void combineHash (std::size_t& seed,
const T& t)
36 seed ^= hasher (t) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
40 template<
typename T>
class Value;
61 void writeGraphToDot (
const std::string& filename,
const std::vector<const Node_DF*>& nodes,
68 std::ostringstream out;
70 out << std::fixed << a_value;
84 template<
typename T>
using ValueRef = std::shared_ptr<Value<T>>;
100 std::size_t expectedSize, std::size_t givenSize);
103 std::size_t depIndex,
104 const std::type_info& expectedType,
105 const std::type_info& givenNodeType);
151 class Node_DF :
public std::enable_shared_from_this<Node_DF>
293 n->unregisterNode (
this);
301 n->registerNode (
this);
320 template<
typename T,
typename U> std::shared_ptr<T>
convertRef (
const std::shared_ptr<U>& from)
322 auto p = std::dynamic_pointer_cast<T>(from);
333 const std::unordered_map<const Node_DF*, NodeRef>& substitutions);
355 template<
typename ... Args>
358 value_(std::forward<Args>(args)...)
361 template<
typename ... Args>
364 value_(std::forward<Args>(args)...)
391 return convertRef<Value<T>>(this->
derive(c, node));
427 return static_cast<const Value<T>&
>(node).accessValueConst ();
434 std::size_t expectedSize);
438 std::size_t expectedMinSize);
450 const auto& dep = *deps[index];
451 if (
dynamic_cast<const T*
>(&dep) ==
nullptr)
456 template<
typename T1,
typename T2>
460 const auto& dep = *deps[index];
461 if (
dynamic_cast<const T1*
>(&dep) ==
nullptr &&
462 (
dynamic_cast<const T2*
>(&dep) ==
nullptr))
474 std::size_t start, std::size_t end)
476 for (std::size_t i = start; i < end; ++i)
478 checkNthDependencyIs<T>(contextNodeType, deps, i);
487 checkNthDependencyIs<Value<T>>(contextNodeType, deps, index);
493 std::size_t start, std::size_t end)
495 for (std::size_t i = start; i < end; ++i)
497 checkNthDependencyIsValue<T>(contextNodeType, deps, i);
605 std::unordered_set<CachedNodeRef, CachedNodeRefHash>
nodeCache_;
611 template<
typename T> std::shared_ptr<T>
cachedAs (
Context& c, std::shared_ptr<T>&& newNode)
614 return std::static_pointer_cast<T>(c.
cached (std::move(newNode)));
617 template<
typename T> std::shared_ptr<T>
cachedAs (
Context& c, std::shared_ptr<T>& newNode)
620 return std::static_pointer_cast<T>(c.
cached(newNode));
Context for dataflow node construction.
void clear()
Clear the context.
std::unordered_set< CachedNodeRef, CachedNodeRefHash > nodeCache_
NodeRef cached(NodeRef &&newNode)
For a newly created node, return its equivalent from the cache. If not already present in the cache,...
bool erase(const NodeRef &r)
Remove an element from the map, only if it has no dependent nodes, and likewise down the graph.
std::vector< const Node_DF * > getAllNodes() const
Returns the vector of all pointers to all nodes.
Base dataflow Node class.
Node_DF(const Node_DF &)=delete
virtual std::string description() const
Node pretty name (default = type name).
NodeRefVec dependencyNodes_
virtual std::size_t hashAdditionalArguments() const
Return the hash of node-specific configuration.
virtual void compute()=0
Computation implementation.
const NodeRef & dependency(std::size_t i) const noexcept
virtual std::string debugInfo() const
Node debug info (default = ""): user defined detailed info for DF graph debug.
virtual NodeRef derive(Context &c, const Node_DF &node)
Returns a node computing d(this_node_expression)/d(node_expression).
void resetDependencies_(NodeRefVec &&dependenciesArg)
virtual bool hasNumericalProperty(NumericalProperty prop) const
Test if the node has the given numerical property.
virtual NodeRef recreate(Context &c, NodeRefVec &&deps)
Recreate the node with different dependencies.
bool isValid() const noexcept
void registerNode(Node_DF *n)
std::size_t nbDependentNodes() const noexcept
Number of dependent nodes (ie nodes that depend on this)
const std::vector< Node_DF * > & dependentNodes() const noexcept
virtual bool compareAdditionalArguments(const Node_DF &other) const
Compare node-specific configuration to another.
void unregisterNode(const Node_DF *n)
Node_DF & operator=(Node_DF &&)=delete
Node_DF(Node_DF &&)=delete
void makeValid() noexcept
void computeRecursively()
Compute this node value, recomputing dependencies (transitively) as needed.
void invalidateRecursively() noexcept
Invalidate (transitively) dependent nodes from this one.
virtual std::string shape() const
std::vector< Node_DF * > dependentNodes_
virtual std::string color() const
Node_DF & operator=(const Node_DF &)=delete
std::size_t nbDependencies() const noexcept
Number of dependencies (ie nodes we depend on)
const NodeRefVec & dependencies() const noexcept
void makeInvalid() noexcept
Abstract Node storing a value of type T.
Value(const NodeRefVec &deps, Args &&... args)
Value(NodeRefVec &&deps, Args &&... args)
ValueRef< T > deriveAsValue(Context &c, const Node_DF &node)
const T & accessValueConst() const noexcept
Raw value access (const).
const T & targetValue()
Access value, recompute if needed.
void modify(Callable &&modifier, bool makeValid)
General case for modification of the T object.
T & accessValueMutable() noexcept
Defines the basic types of data flow nodes.
std::shared_ptr< T > cachedAs(Context &c, std::shared_ptr< T > &&newNode)
Helper: Same as Context::cached but with a shared_ptr<T> node.
std::shared_ptr< Value< T > > ValueRef
Shared pointer alias for Value<T>.
void checkDependenciesNotNull(const std::type_info &contextNodeType, const NodeRefVec &deps)
Checks that all dependencies are not null, throws if not.
DotOptions operator|(DotOptions a, DotOptions b)
void checkNthDependencyIs(const std::type_info &contextNodeType, const NodeRefVec &deps, std::size_t index)
Checks that deps[index] is a T node, throws if not.
std::string to_string(const NoDimension &)
void checkNthDependencyNotNull(const std::type_info &contextNodeType, const NodeRefVec &deps, std::size_t index)
std::string to_string_with_precision(const T a_value, const int n=6)
Output with given precision.
const T & accessValueConstCast(const Node_DF &node)
std::vector< NodeRef > NodeRefVec
Alias for a dependency vector (of NodeRef).
std::string prettyTypeName(const std::type_info &ti)
Debug: return a readable name for a C++ type descriptor (from typeid operator).
void checkDependencyRangeIsValue(const std::type_info &contextNodeType, const NodeRefVec &deps, std::size_t start, std::size_t end)
Check that deps[start, end[ contains Value<T> nodes, throws if not.
std::shared_ptr< T > convertRef(const std::shared_ptr< U > &from)
Convert a node ref with runtime type check.
NumericalProperty
Numerical properties for DF Node.
void failureDependencyNumberMismatch(const std::type_info &contextNodeType, std::size_t expectedSize, std::size_t givenSize)
NodeRef recreateWithSubstitution(Context &c, const NodeRef &node, const std::unordered_map< const Node_DF *, NodeRef > &substitutions)
Recreate node by transitively replacing dependencies according to substitutions mapping.
void checkDependencyVectorSize(const std::type_info &contextNodeType, const NodeRefVec &deps, std::size_t expectedSize)
void failureDependencyTypeMismatch(const std::type_info &contextNodeType, std::size_t depIndex, const std::type_info &expectedType, const std::type_info &givenNodeType)
bool isTransitivelyDependentOn(const Node_DF &searchedDependency, const Node_DF &node)
Check if searchedDependency if a transitive dependency of node.
void checkDependencyVectorMinSize(const std::type_info &contextNodeType, const NodeRefVec &deps, std::size_t expectedMinSize)
Checks the minimum size of a dependency vector, throws if mismatch.
void writeGraphToDot(std::ostream &os, const std::vector< const Node_DF * > &nodes, DotOptions opt)
Write dataflow graph starting at nodes to output stream.
void failureNodeConversion(const std::type_info &handleType, const Node_DF &node)
void failureEmptyDependency(const std::type_info &contextNodeType, std::size_t depIndex)
void combineHash(std::size_t &seed, const T &t)
Combine hashable value to a hash, from Boost library.
void failureComputeWasCalled(const std::type_info &nodeType)
std::shared_ptr< Node_DF > NodeRef
void checkNthDependencyIsValue(const std::type_info &contextNodeType, const NodeRefVec &deps, std::size_t index)
Checks that deps[index] is a Value<T> node, throws if not.
void checkDependencyRangeIs(const std::type_info &contextNodeType, const NodeRefVec &deps, std::size_t start, std::size_t end)
Check that deps[start, end[ contains T, throws if not.
bool operator&(DotOptions a, DotOptions b)
std::size_t operator()(const CachedNodeRef &ref) const
NodeRef is hashable and comparable as a pointer. CachedNodeRef is hashable and comparable,...
bool operator==(const CachedNodeRef &other) const
CachedNodeRef(NodeRef &&r)
CachedNodeRef(NodeRef &r)