aGrUM 3.1.1
a C++ library for (probabilistic) graphical models
layerGenerator_tpl.h
Go to the documentation of this file.
1/****************************************************************************
2 * This file is part of the aGrUM/pyAgrum library. *
3 * *
4 * Copyright (c) 2005-2026 by *
5 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
6 * - Christophe GONZALES(_at_AMU) *
7 * *
8 * The aGrUM/pyAgrum library is free software; you can redistribute it *
9 * and/or modify it under the terms of either : *
10 * *
11 * - the GNU Lesser General Public License as published by *
12 * the Free Software Foundation, either version 3 of the License, *
13 * or (at your option) any later version, *
14 * - the MIT license (MIT), *
15 * - or both in dual license, as here. *
16 * *
17 * (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) *
18 * *
19 * This aGrUM/pyAgrum library is distributed in the hope that it will be *
20 * useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
21 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS *
22 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
26 * OTHER DEALINGS IN THE SOFTWARE. *
27 * *
28 * See LICENCES for more details. *
29 * *
30 * SPDX-FileCopyrightText: Copyright 2005-2026 *
31 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
32 * - Christophe GONZALES(_at_AMU) *
33 * SPDX-License-Identifier: LGPL-3.0-or-later OR MIT *
34 * *
35 * Contact : info_at_agrum_dot_org *
36 * homepage : http://agrum.gitlab.io *
37 * gitlab : https://gitlab.com/agrumery/agrum *
38 * *
39 ****************************************************************************/
40
41#pragma once
42
43
51
52namespace gum {
53 namespace prm {
54
55 template < GUM_Numeric GUM_SCALAR >
57 if (_layers_.size() == 0) {
58 GUM_ERROR(OperationNotAllowed, "cannot generate a layered PRM<GUM_SCALAR> without layers")
59 }
60
61 std::vector< MyData > l;
63 std::string type = _generateType_(factory);
64 _generateInterfaces_(factory, type, l);
65 _generateClasses_(factory, type, l);
66 _generateSystem_(factory, l);
67 return factory.prm();
68 }
69
70 template < GUM_Numeric GUM_SCALAR >
72 std::string name = this->name_gen_.nextName(PRMObject::prm_type::TYPE);
73 factory.startDiscreteType(name);
74
75 for (Size i = 0; i < _domain_size_; ++i) {
76 factory.addLabel(std::format("{}", i));
77 }
78
79 factory.endDiscreteType();
80 return name;
81 }
82
83 template < GUM_Numeric GUM_SCALAR >
86 std::string_view type,
87 std::vector< typename LayerGenerator< GUM_SCALAR >::MyData >& l) {
88 for (Size lvl = 0; lvl < _layers_.size(); ++lvl) {
90 l[lvl].i = this->name_gen_.nextName(PRMObject::prm_type::PRM_INTERFACE);
91 f.startInterface(l[lvl].i);
92
93 for (Size a = 0; a < _layers_[lvl].a; ++a) {
94 l[lvl].a.push_back(this->name_gen_.nextName(PRMObject::prm_type::CLASS_ELT));
95 f.addAttribute(type, l[lvl].a.back());
96 }
97
98 if (lvl) {
99 for (Size g = 0; g < _layers_[lvl].g; ++g) {
100 l[lvl].g.push_back(this->name_gen_.nextName(PRMObject::prm_type::CLASS_ELT));
101 f.addAttribute("boolean", l[lvl].g.back());
102 }
103
104 l[lvl].r = this->name_gen_.nextName(PRMObject::prm_type::CLASS_ELT);
105 f.addReferenceSlot(l[lvl - 1].i, l[lvl].r, true);
106 }
107
108 f.endInterface();
109 }
110 }
111
112 template < GUM_Numeric GUM_SCALAR >
115 std::string_view type,
116 std::vector< typename LayerGenerator< GUM_SCALAR >::MyData >& l) {
117 Size size = 0;
118 GUM_SCALAR sum = 0.0;
120
121 for (Size lvl = 0; lvl < _layers_.size(); ++lvl) {
122 i.insert(l[lvl].i);
123
124 for (Size c = 0; c < _layers_[lvl].c; ++c) {
125 l[lvl].c.push_back(this->name_gen_.nextName(PRMObject::prm_type::CLASS));
126 f.startClass(l[lvl].c.back(), "", &i);
127
128 if (lvl) f.addReferenceSlot(l[lvl - 1].i, l[lvl].r, true);
129
130 DAG dag;
132 _generateClassDag_(lvl, dag, names, l);
133
134 // Adding aggregates
135 if (lvl) {
136 for (std::vector< std::string >::iterator g = l[lvl].g.begin(); g != l[lvl].g.end();
137 ++g) {
138 std::vector< std::string > chain(
139 1,
140 std::format("{}.{}", l[lvl].r, l[lvl - 1].a[randomValue(l[lvl - 1].a.size())])),
141 param(1, "1");
142 f.addAggregator(*g, "exists", chain, param);
143 }
144 }
145
146 // Adding attributes
147 for (std::vector< std::string >::iterator a = l[lvl].a.begin(); a != l[lvl].a.end();
148 ++a) {
149 f.startAttribute(type, *a, true);
150 size = getDomainSize();
151
152 for (const auto par: dag.parents(names.second(*a))) {
153 f.addParent(names.first(par));
154 size *= f.retrieveClass(l[lvl].c.back()).get(names.first(par)).type()->domainSize();
155 }
156
157 std::vector< GUM_SCALAR > cpf(size), val(getDomainSize());
158
159 for (size_t norms = 0; norms < size; norms += getDomainSize()) {
160 sum = 0.0;
161
162 for (size_t idx = 0; idx < getDomainSize(); ++idx) {
163 val[idx] = 1 + std::rand();
164 sum += val[idx];
165 }
166
167 for (size_t idx = 0; idx < getDomainSize(); ++idx)
168 cpf[norms + idx] = val[idx] / sum;
169 }
170
171 f.setRawCPFByLines(cpf);
172 f.endAttribute();
173 }
174
175 f.endClass();
176 }
177
178 i.erase(l[lvl].i);
179 }
180 }
181
182 template < GUM_Numeric GUM_SCALAR >
184 Size lvl,
185 DAG& dag,
187 std::vector< typename LayerGenerator< GUM_SCALAR >::MyData >& l) {
188 float density = _layers_[lvl].inner_density;
189 std::vector< NodeId > nodes;
190 NodeId id = 0;
191
192 if (lvl) {
193 for (const auto& agg: l[lvl].g) {
194 id = dag.addNode();
195 names.insert(agg, id);
196 nodes.push_back(id);
197 }
198 }
199
200 for (const auto& attr: l[lvl].a) {
201 id = dag.addNode();
202 names.insert(attr, id);
203
204 for (const auto node: nodes)
205 if (randomProba() < density) dag.addArc(node, names.second(attr));
206
207 nodes.push_back(id);
208 }
209
210 // For each nodes with #parents > _max_parents_ we randomly remove parents
211 // until
212 // #parents <= _max_parents_
213 for (const auto node: dag.nodes()) {
214 if (dag.parents(node).size() > getMaxParents()) {
215 std::vector< NodeId > v;
216
217 for (const auto par: dag.parents(node))
218 v.push_back(par);
219
220 while (dag.parents(node).size() > getMaxParents()) {
221 size_t idx = randomValue(v.size());
222 Arc arc(v[idx], node);
223 GUM_ASSERT(dag.existsArc(arc));
224 dag.eraseArc(arc);
225 v[idx] = v.back();
226 v.pop_back();
227 }
228 }
229 }
230 }
231
232 template < GUM_Numeric GUM_SCALAR >
235 std::vector< typename LayerGenerator< GUM_SCALAR >::MyData >& l) {
236 factory.startSystem(this->name_gen_.nextName(PRMObject::prm_type::SYSTEM));
237 std::vector< std::vector< std::string > > o(_layers_.size());
238 std::string name;
239 size_t idx = 0;
240
241 for (size_t lvl = 0; lvl < _layers_.size(); ++lvl) {
242 float density = _layers_[lvl].outter_density;
243
244 for (size_t count = 0; count < _layers_[lvl].o; ++count) {
245 name = this->name_gen_.nextName(PRMObject::prm_type::PRM_INTERFACE);
246 factory.addInstance(l[lvl].c[randomValue(l[lvl].c.size())], name);
247 o[lvl].push_back(name);
248
249 if (lvl) {
250 std::string chain = std::format("{}.{}", name, l[lvl].r);
251 std::vector< std::string > ref2add;
252
253 for (std::vector< std::string >::iterator iter = o[lvl - 1].begin();
254 iter != o[lvl - 1].end();
255 ++iter)
256 if (randomProba() <= density) ref2add.push_back(*iter);
257
258 if (ref2add.empty())
259 factory.setReferenceSlot(chain, o[lvl - 1][randomValue(o[lvl - 1].size())]);
260
261 while (ref2add.size() > getMaxParents()) {
262 idx = randomValue(ref2add.size());
263 ref2add[idx] = ref2add.back();
264 ref2add.pop_back();
265 }
266
267 for (std::vector< std::string >::iterator iter = ref2add.begin(); iter != ref2add.end();
268 ++iter)
269 factory.setReferenceSlot(chain, *iter);
270 }
271 }
272 }
273
274 factory.endSystem();
275 }
276
277 template < GUM_Numeric GUM_SCALAR >
282
283 template < GUM_Numeric GUM_SCALAR >
289
290 template < GUM_Numeric GUM_SCALAR >
294
295 template < GUM_Numeric GUM_SCALAR >
303
304 template < GUM_Numeric GUM_SCALAR >
308
309 template < GUM_Numeric GUM_SCALAR >
313
314 template < GUM_Numeric GUM_SCALAR >
318
319 template < GUM_Numeric GUM_SCALAR >
323
324 template < GUM_Numeric GUM_SCALAR >
326 const std::vector< typename LayerGenerator< GUM_SCALAR >::LayerData >& v) {
327 _layers_ = v;
328 }
329
330 template < GUM_Numeric GUM_SCALAR >
331 std::vector< typename LayerGenerator< GUM_SCALAR >::LayerData >&
335
336 template < GUM_Numeric GUM_SCALAR >
337 const std::vector< typename LayerGenerator< GUM_SCALAR >::LayerData >&
341
342 } /* namespace prm */
343} /* namespace gum */
bool existsArc(const Arc &arc) const
indicates whether a given arc exists
const NodeSet & parents(NodeId id) const
returns the set of nodes with arc ingoing to a given node
virtual void eraseArc(const Arc &arc)
removes an arc from the ArcGraphPart
The base class for all directed edges.
Base class for dag.
Definition DAG.h:121
void addArc(NodeId tail, NodeId head) final
insert a new arc into the directed graph
Definition DAG_inl.h:75
const NodeGraphPart & nodes() const
return *this as a NodeGraphPart
virtual NodeId addNode()
insert a new node and return its id
Exception : operation not allowed.
void insert(const Key &k)
Inserts a new element into the set.
Definition set_tpl.h:510
Size size() const noexcept
Returns the number of elements in the set.
Definition set_tpl.h:607
<agrum/PRM/generator/layerGenerator.h>
Size getDomainSize() const
Returns the domain size of generated types.
Size getMaxParents() const
Returns the max number of parents allowed for any attribute or aggregator.
void _generateClassDag_(Size lvl, DAG &dag, Bijection< std::string, NodeId > &names, std::vector< typename LayerGenerator::MyData > &l)
std::string _generateType_(PRMFactory< GUM_SCALAR > &f)
void setLayers(const std::vector< LayerData > &v)
Defines the structure of each layers.
virtual PRM< GUM_SCALAR > * generate()
Proceeds with the generation of the PRM<GUM_SCALAR>.
void setDomainSize(Size s)
Set the domain size of generated types.
LayerGenerator & operator=(const LayerGenerator &source)
Copy operator.
void _generateClasses_(PRMFactory< GUM_SCALAR > &f, std::string_view type, std::vector< typename LayerGenerator::MyData > &l)
std::vector< LayerData > _layers_
void _generateSystem_(PRMFactory< GUM_SCALAR > &factory, std::vector< typename LayerGenerator::MyData > &l)
void _generateInterfaces_(PRMFactory< GUM_SCALAR > &f, std::string_view type, std::vector< MyData > &l)
virtual ~LayerGenerator()
Destructor.
std::vector< LayerData > & getLayer()
Returns the domain size of generated types.
void setMaxParents(Size s)
Returns the max number of parents allowed for any attribute or aggregator.
LayerGenerator()
Default constructor.
Factory which builds a PRM<GUM_SCALAR>.
Definition PRMFactory.h:90
void addLabel(std::string_view l, std::string_view ext="") override
Add a label to the current discrete type.
void startDiscreteType(std::string_view name, std::string_view super="") override
Start a discrete subtype declaration.
void addReferenceSlot(std::string_view type, std::string_view name, bool isArray) override
Tells the factory that we started declaring a slot.
void endInterface() override
Tells the factory that we finished an interface declaration.
void setReferenceSlot(std::string_view left_instance, std::string_view left_reference, std::string_view right_instance) override
Instantiate a reference in the current model.
void startInterface(std::string_view i, std::string_view ext="", bool delayInheritance=false) override
Tells the factory that we start an interface declaration.
PRM< GUM_SCALAR > * prm() const
Returns a pointer on the PRM<GUM_SCALAR> created by this factory.
void addAttribute(std::string_view type, std::string_view name) override
Add an attribute to an interface.
void setRawCPFByLines(const std::vector< GUM_SCALAR > &array)
Gives the factory the CPF in its raw form.
PRMClass< GUM_SCALAR > & retrieveClass(std::string_view name)
Returns a reference over a Class<GUM_SCALAR> given its name.
void startSystem(std::string_view name) override
Tells the factory that we started declaring a model.
void addInstance(std::string_view type, std::string_view name) override
Add an instance to the model.
void addAggregator(std::string_view name, std::string_view agg_type, const std::vector< std::string > &chains, const std::vector< std::string > &params, std::string_view type="") override
Add an aggregator in the current declared class.
void startAttribute(std::string_view type, std::string_view name, bool scalar_atttr=false) override
Tells the factory that we start an attribute declaration.
void endClass(bool checkImplementations=true) override
Tells the factory that we finished a class declaration.
void startClass(std::string_view c, std::string_view ext="", const Set< std::string > *implements=nullptr, bool delayInheritance=false) override
Tells the factory that we start a class declaration.
void endAttribute() override
Tells the factory that we finished declaring an attribute.
void endSystem() override
Tells the factory that we finished declaring a model.
void addParent(std::string_view name) override
Tells the factory that we add a parent to the current declared attribute.
void endDiscreteType() override
End the current discrete type declaration.
NameGenerator name_gen_
The name generator used by this class.
This class represents a Probabilistic Relational PRMSystem<GUM_SCALAR>.
Definition PRM.h:74
#define GUM_ERROR(type, msg)
Definition exceptions.h:76
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition types.h:74
Size NodeId
Type for node ids.
Idx randomValue(const Size max=2)
Returns a random Idx between 0 and max-1 included.
double randomProba()
Returns a random double between 0 and 1 included (i.e.
Headers of LayerGenerator.
namespace for all probabilistic relational models entities
Definition agrum.h:68
gum is the global namespace for all aGrUM entities
Definition agrum.h:46