bpp-phyl3  3.0.0
Parametrizable.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: The Bio++ Development Group
2 //
3 // SPDX-License-Identifier: CECILL-2.1
4 
5 #ifndef BPP_PHYL_LIKELIHOOD_DATAFLOW_PARAMETRIZABLE_H
6 #define BPP_PHYL_LIKELIHOOD_DATAFLOW_PARAMETRIZABLE_H
7 
8 #include <Bpp/Exceptions.h>
13 #include <functional>
14 #include <iostream>
15 #include <unordered_map>
16 
17 #include "Definitions.h"
18 
19 namespace bpp
20 {
26 std::unordered_map<std::string, std::shared_ptr<ConfiguredParameter>>
27 createParameterMap(Context& c, const Parametrizable& parametrizable);
28 
29 std::unordered_map<std::string, std::shared_ptr<ConfiguredParameter>>
30 createParameterMap(Context& c, const ParameterAliasable& parametrizable);
31 
32 
41  const std::function<NodeRef(const std::string&)>& getParameter);
42 
44  const std::function<NodeRef(const std::string&)>& getParameter);
45 
46 
48 {
49 public:
59  template<typename Object, typename Self>
60  static std::shared_ptr<Self> createConfigured (Context& c, NodeRefVec&& deps,
61  std::unique_ptr<Object>&& object,
62  typename std::enable_if<std::is_base_of<ParameterAliasable, Object>::value>::type* = 0)
63  {
64  if (!object)
65  {
66  throw Exception ("createConfigured(): nullptr object");
67  }
68  // Check dependencies
69  const auto nbParameters = object->getIndependentParameters ().size ();
70  checkDependenciesNotNull(typeid (Self), deps);
71  checkDependencyVectorSize(typeid (Self), deps, nbParameters);
72  checkDependencyRangeIsValue<Parameter*>(typeid (Self), deps, 0, nbParameters);
73  return cachedAs<Self>(c, std::make_shared<Self>(c, std::move (deps), std::move (object)));
74  }
75 
76 
85  template<typename Object, typename Self>
86  static std::shared_ptr<Self> createConfigured (Context& c, NodeRefVec&& deps,
87  std::unique_ptr<Object>&& object,
88  typename std::enable_if<!std::is_base_of<ParameterAliasable, Object>::value>::type* = 0)
89  {
90  if (!object)
91  {
92  throw Exception ("createConfigured(): nullptr object");
93  }
94  // Check dependencies
95  const auto nbParameters = object->getParameters ().size ();
96  checkDependenciesNotNull (typeid (Self), deps);
97  checkDependencyVectorSize (typeid (Self), deps, nbParameters);
98  checkDependencyRangeIsValue<Parameter*>(typeid (Self), deps, 0, nbParameters);
99  return cachedAs<Self>(c, std::make_shared<Self>(c, std::move (deps), std::move (object)));
100  }
101 
102 
108  template<typename Object, typename Self>
109  static std::shared_ptr<Self> createConfigured (Context& context, std::unique_ptr<Object>&& object)
110  {
111  auto objectParameters = createParameterMap(context, *object);
112 
113  auto depvecObject = createDependencyVector(
114  *object, [&objectParameters](const std::string& paramName) { return objectParameters[paramName]; });
115 
116  auto objectNode = ConfiguredParametrizable::createConfigured<Object, Self>(
117  context,
118  std::move(depvecObject),
119  std::move(object));
120 
121 
122  return objectNode;
123  }
124 
135  template<typename Object, typename Self>
136  static std::shared_ptr<Self> createConfigured(Context& context, const Object& object, ParameterList& parList, const std::string& suff = "")
137  {
138  auto nObject = std::unique_ptr<Object>(dynamic_cast<Object*>(object.clone()));
139 
140  auto pa = dynamic_cast<const ParameterAliasable*>(&object);
141 
142  const ParameterList& lParams = pa ? pa->getIndependentParameters() : object.getParameters();
143 
144  std::vector<NodeRef> dep;
145  for (size_t i = 0; i < lParams.size(); i++)
146  {
147  std::string name = lParams[i].getName() + suff;
148  if (!parList.hasParameter(name) && suff == "")
149  {
150  if (!parList.hasParameter(lParams[i].getName() + "_1"))
151  throw Exception("createConfigured: unknown ConfiguredParameter " + name);
152  else name = lParams[i].getName() + "_1";
153  }
154  auto confPar = dynamic_cast<ConfiguredParameter*>(parList.getParameter(name).get());
155  if (!confPar)
156  throw Exception("createConfigured: unknown ConfiguredParameter " + name);
157 
158  dep.push_back(ConfiguredParameter::create(context, {confPar->dependency(0)}, lParams[i]));
159  }
160  return ConfiguredParametrizable::createConfigured<Object, Self>(context, std::move(dep), std::move(nObject));
161  }
162 
163 
169  template<typename ConfiguredObject, typename Self>
170  static ValueRef<double>
172  {
173  checkDependenciesNotNull (typeid (Self), deps);
174  checkDependencyVectorSize (typeid (Self), deps, 1);
175  checkNthDependencyIs<ConfiguredObject>(typeid (Self), deps, 0);
176  return cachedAs<Value<double>>(c, std::make_shared<Self>(std::move (deps)));
177  }
178 
186  template<typename ConfiguredObject, typename Self, typename Row>
187  static ValueRef<Row>
189  const Dimension<Row>& dim)
190  {
191  checkDependencyVectorMinSize (typeid (Self), deps, 1);
192  checkNthDependencyNotNull (typeid (Self), deps, 0);
193  checkNthDependencyIs<ConfiguredObject>(typeid (Self), deps, 0);
194  return cachedAs<Value<Row>>(c, std::make_shared<Self>(std::move (deps), dim));
195  }
196 
197  template<typename ConfiguredObject, typename Self, typename Col>
198  static ValueRef<Col>
200  const Dimension<Col>& dim)
201  {
202  checkDependencyVectorMinSize (typeid (Self), deps, 1);
203  checkNthDependencyNotNull (typeid (Self), deps, 0);
204  checkNthDependencyIs<ConfiguredObject>(typeid (Self), deps, 0);
205  return cachedAs<Value<Col>>(c, std::make_shared<Self>(std::move (deps), dim));
206  }
207 
213  template<typename ConfiguredObject, typename Self, typename Matrix>
214  static ValueRef<Matrix>
216  const Dimension<Matrix>& dim)
217  {
218  checkDependencyVectorMinSize (typeid (Self), deps, 1);
219  checkNthDependencyNotNull (typeid (Self), deps, 0);
220  if (deps.size() > 1)
221  checkNthDependencyNotNull (typeid (Self), deps, 1);
222  checkNthDependencyIs<ConfiguredObject>(typeid (Self), deps, 0);
223  if (deps.size() > 1)
224  checkNthDependencyIs<ConfiguredParameter>(typeid (Self), deps, 1);
225 
226  return cachedAs<Value<Matrix>>(c, std::make_shared<Self>(std::move (deps), dim));
227  }
228 
229 
230  /* Helper function for generating numerical derivatives of
231  * computation nodes. Assuming we have a v = f(object, stuff)
232  * node, with v of type T. df/dn = sum_i df/dx_i * dx_i/dn +
233  * df/dstuff * dstuff/dn.
234  * This function returns a NodeRefVec containing the nodes:
235  * {df/dx_i * dx_i/dn} for i in order.
236  *
237  * buildFWithFreqSet(newFreqSet) should create the f(newFS,
238  * stuff) node.
239  */
240  template<typename ConfiguredObject, typename T, typename B>
242  Context& c, ConfiguredObject& object, const Node_DF& derivationNode, const Dimension<T>& targetDimension, B buildFWithNewObject)
243  {
244  NodeRefVec derivativeSumDeps;
245 
246  for (std::size_t i = 0; i < object.nbDependencies (); ++i)
247  {
248  // First compute dxi_dn. If this maps to a constant 0, do not compute df_dxi at all (costly).
249  if (!object.dependency(i))
250  continue;
251 
252  auto dxi_dn = object.dependency (i)->derive (c, derivationNode);
253  if (!dxi_dn->hasNumericalProperty (NumericalProperty::ConstantZero))
254  {
255  auto buildFWithNewXi = [&c, i, &object, &buildFWithNewObject](std::shared_ptr<ConfiguredParameter> newDep) {
256  // The sub-graph that will be replicated with shifted inputs is: f(freqset(x_i), stuff)
257  NodeRefVec newObjectDeps = object.dependencies ();
258  newObjectDeps[i] = std::move (newDep);
259  auto newObject = object.recreate (c, std::move (newObjectDeps));
260  return buildFWithNewObject (std::move (newObject));
261  };
262 
263  auto df_dxi = generateNumericalDerivative<T>(
264  c, object.config, object.dependency (i), targetDimension, buildFWithNewXi);
265 
266  if (dxi_dn->hasNumericalProperty (NumericalProperty::ConstantOne))
267  derivativeSumDeps.emplace_back (std::move (df_dxi));
268  else
269  derivativeSumDeps.emplace_back (CWiseMul<T, std::tuple<double, T>>::create (
270  c, {std::move (dxi_dn), std::move (df_dxi)}, targetDimension));
271  }
272  }
273  return derivativeSumDeps;
274  }
275 };
276 } // namespace bpp
277 #endif // BPP_PHYL_LIKELIHOOD_DATAFLOW_PARAMETRIZABLE_H
Data flow node representing a parameter.
Definition: Parameter.h:27
static std::shared_ptr< Self > create(Context &c, NodeRefVec &&deps, const Parameter &param)
Build a new ConfiguredParameter node.
Definition: Parameter.h:36
static std::shared_ptr< Self > createConfigured(Context &c, NodeRefVec &&deps, std::unique_ptr< Object > &&object, typename std::enable_if< std::is_base_of< ParameterAliasable, Object >::value >::type *=0)
Create a new node to an Aliased Parameterized object from a dependency vector of Independent Paramete...
static std::shared_ptr< Self > createConfigured(Context &context, const Object &object, ParameterList &parList, const std::string &suff="")
Create a new node from a clonable object. Object parameters are get from ConfiguredParameters PREVIOU...
static ValueRef< double > createDouble(Context &c, NodeRefVec &&deps)
static ValueRef< Row > createRowVector(Context &c, NodeRefVec &&deps, const Dimension< Row > &dim)
static ValueRef< Matrix > createMatrix(Context &c, NodeRefVec &&deps, const Dimension< Matrix > &dim)
static std::shared_ptr< Self > createConfigured(Context &c, NodeRefVec &&deps, std::unique_ptr< Object > &&object, typename std::enable_if<!std::is_base_of< ParameterAliasable, Object >::value >::type *=0)
Create a new node to a Parameterized object from a dependency vector of Parameters (which are already...
static ValueRef< Col > createVector(Context &c, NodeRefVec &&deps, const Dimension< Col > &dim)
static std::shared_ptr< Self > createConfigured(Context &context, std::unique_ptr< Object > &&object)
Create a new node to a Parameterized object ConfiguredParameters are built from its set of independen...
static NodeRefVec generateDerivativeSumDepsForComputations(Context &c, ConfiguredObject &object, const Node_DF &derivationNode, const Dimension< T > &targetDimension, B buildFWithNewObject)
Context for dataflow node construction.
Definition: DataFlow.h:527
Base dataflow Node class.
Definition: DataFlow.h:152
virtual bool hasParameter(const std::string &name) const
size_t size() const
virtual const std::shared_ptr< Parameter > & getParameter(size_t i) const
Defines the basic types of data flow nodes.
std::shared_ptr< Value< T > > ValueRef
Shared pointer alias for Value<T>.
Definition: DataFlow.h:84
void checkDependenciesNotNull(const std::type_info &contextNodeType, const NodeRefVec &deps)
Checks that all dependencies are not null, throws if not.
Definition: DataFlow.cpp:103
NodeRefVec createDependencyVector(const Parametrizable &parametrizable, const std::function< NodeRef(const std::string &)> &parameter)
void checkNthDependencyNotNull(const std::type_info &contextNodeType, const NodeRefVec &deps, std::size_t index)
Definition: DataFlow.cpp:114
std::vector< NodeRef > NodeRefVec
Alias for a dependency vector (of NodeRef).
Definition: DataFlow.h:81
void checkDependencyVectorSize(const std::type_info &contextNodeType, const NodeRefVec &deps, std::size_t expectedSize)
Definition: DataFlow.cpp:83
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.
Definition: DataFlow.cpp:93
std::unordered_map< std::string, std::shared_ptr< ConfiguredParameter > > createParameterMap(Context &c, const ParameterAliasable &parametrizable)
std::shared_ptr< Node_DF > NodeRef
Definition: DataFlow.h:78
Store a dimension for type T.