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
19namespace bpp
20{
26std::unordered_map<std::string, std::shared_ptr<ConfiguredParameter>>
27createParameterMap(Context& c, const Parametrizable& parametrizable);
28
29std::unordered_map<std::string, std::shared_ptr<ConfiguredParameter>>
30createParameterMap(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{
49public:
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 ValueRef< Matrix > createMatrix(Context &c, NodeRefVec &&deps, const Dimension< Matrix > &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 ValueRef< Row > createRowVector(Context &c, NodeRefVec &&deps, const Dimension< Row > &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 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< Col > createVector(Context &c, NodeRefVec &&deps, const Dimension< Col > &dim)
static ValueRef< double > createDouble(Context &c, NodeRefVec &&deps)
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 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.