aGrUM 3.2.0
a C++ library for (probabilistic) graphical models
gum::KTBNGenerator< GUM_SCALAR > Class Template Reference

Draws a random k-DBN template (structure and, optionally, CPTs). More...

#include <agrum/KTBN/generator/KTBNGenerator.h>

Collaboration diagram for gum::KTBNGenerator< GUM_SCALAR >:
[legend]

Classes

struct  _Arc_
 A (tail, head) endpoint pair, each as (base, slice). More...

Public Member Functions

Constructors / Destructor
 KTBNGenerator (Size k, Size nbTemporal, Size nbAtemporal=0, Size maxArcs=0, Size maxModality=2)
 Constructor.
 ~KTBNGenerator ()
 Destructor.
Generation
void generateKTBN (KTBN< GUM_SCALAR > &out)
 Fills out with a freshly drawn model (its previous content is discarded). Seed it with gum::initRandom() for reproducibility.
KTBN< GUM_SCALAR > generate ()
 Same, returning the model by value.
Configuration (fluent)
KTBNGenerator< GUM_SCALAR > & setDensity (double density)
 Fraction of the legal arc set to draw, in \([0,1]\). Ignored when a non-zero maxArcs was given to the constructor. Default 0.1.
KTBNGenerator< GUM_SCALAR > & setDomainRange (Size minModality, Size maxModality)
 Domain sizes are drawn uniformly in \([min, max]\).
KTBNGenerator< GUM_SCALAR > & setMaxParents (Size maxParents)
 Caps the number of parents of any node, which bounds CPT size. 0 (default) means unlimited — a dense draw can then produce very large CPTs, so set it when generating dense or high-k models.
KTBNGenerator< GUM_SCALAR > & setGuaranteeOrder (bool on)
 Force one arc of lag \(k-1\) into the kernel slice, so the model's effective order equals \(k\) (see the class doc). Default true. No-op when \(k = 1\) or there is no temporal process.
KTBNGenerator< GUM_SCALAR > & setGenerateCPTs (bool on)
 Whether to fill the CPTs with random values (default true). When false only the structure is drawn and the CPTs stay at their default content.
KTBNGenerator< GUM_SCALAR > & setNamePrefixes (const std::string &temporal, const std::string &atemporal)
 Name prefixes; variables are prefix0, prefix1, … Defaults are "X" (temporal) and "A" (atemporal).
Accessors
Size k () const
Size nbLegalArcs () const

Private Member Functions

std::vector< _Arc_ > _legalArcs_ (const std::vector< std::string > &temporal, const std::vector< std::string > &atemporal, const std::vector< Size > &tRank, const std::vector< Size > &aRank) const
 Every arc the k-DBN's rules allow, with the two cycle-prone families (lag 0, atemporal→atemporal) already restricted to the ranks given by tRank / aRank, so the result is acyclic by construction.

Static Private Member Functions

template<typename T>
static void _shuffle_ (std::vector< T > &v)
 Fisher-Yates through gum::randomValue, so gum::initRandom() alone makes a whole generation reproducible.

Private Attributes

Size _k_
Size _nbTemporal_
Size _nbAtemporal_
Size _maxArcs_
Size _minModality_ {2}
Size _maxModality_
Size _maxParents_ {0}
double _density_ {0.1}
bool _guaranteeOrder_ {true}
bool _generateCPTs_ {true}
std::string _temporalPrefix_ {"X"}
std::string _atemporalPrefix_ {"A"}

Detailed Description

template<GUM_Numeric GUM_SCALAR>
class gum::KTBNGenerator< GUM_SCALAR >

Draws a random k-DBN template (structure and, optionally, CPTs).

Usage
initRandom(42); // reproducible
KTBNGenerator<double> gen(3, 4, 1); // k=3, 4 temporal, 1 atemporal
gen.setDensity(0.15).setMaxParents(4);
KTBN<double> model = gen.generate();
KTBNGenerator(Size k, Size nbTemporal, Size nbAtemporal=0, Size maxArcs=0, Size maxModality=2)
Constructor.
Class representing a k-order dynamic Bayesian network (k-DBN).
Definition KTBN.h:197
GUM_SHARED_PUBLIC void initRandom(unsigned int seed=0)
Initialize random generator seed.
Which arcs are legal
Exactly those gum::KTBN accepts: atemporal \(\to\) atemporal, atemporal \(\to\) temporal, and temporal \((b_1,s_1) \to (b_2,s_2)\) with \(s_1 \leq s_2\) (so the lag lies in \([0, k-1]\)). Temporal \(\to\) atemporal is forbidden. nbLegalArcs() counts them.
Acyclicity comes for free
A cross-slice arc can never close a cycle, since the slice index strictly increases along any path made of them. Only lag-0 arcs and atemporal \(\to\)atemporal arcs can. The generator therefore draws one random permutation of the temporal bases and one of the atemporal bases, and admits those two families only from the lower-ranked endpoint to the higher-ranked one. No cycle can be built, so no rejection sampling and no cycle test are needed.
Effective order vs. nominal \(\to\)#48
Drawn uniformly, a "k-TBN" may end up with no arc of lag \(k-1\) into the kernel slice \(k-1\) — its true Markov order is then below \(k\), and no learner can recover \(k\) from data sampled off it, because the data simply does not depend on that far a past. Order-recovery experiments built on such models silently score correct answers as errors, and the effect grows with \(k\) (more lags to miss at a fixed density). setGuaranteeOrder() (on by default) rules this out by forcing one arc of lag exactly \(k-1\) into slice \(k-1\), so the generated model's effective order really is \(k\). Switch it off to study the phenomenon.
Warning
The maximum lag a k-slice template can express is \(k-1\) (slice 0 to slice \(k-1\)), not \(k\): a lag of \(k\) would need \(k+1\) slices. For \(k=1\) there is no lag at all, and setGuaranteeOrder() is a silent no-op.

Definition at line 114 of file KTBNGenerator.h.

Constructor & Destructor Documentation

◆ KTBNGenerator()

template<GUM_Numeric GUM_SCALAR>
gum::KTBNGenerator< GUM_SCALAR >::KTBNGenerator ( Size k,
Size nbTemporal,
Size nbAtemporal = 0,
Size maxArcs = 0,
Size maxModality = 2 )
explicit

Constructor.

Parameters
kOrder of the generated k-DBN (number of template slices). Must be \(\geq 1\).
nbTemporalNumber of temporal processes.
nbAtemporalNumber of atemporal variables.
maxArcsHard cap on the number of arcs. 0 (default) means "derive it from the density" — see setDensity().
maxModalityLargest domain size; domains are drawn uniformly in \([2, maxModality]\). Must be \(\geq 2\).
Exceptions
InvalidArgumentif k is 0 or maxModality is below 2.

Definition at line 71 of file KTBNGenerator_tpl.h.

75 :
78 if (k == 0) GUM_ERROR(InvalidArgument, "KTBNGenerator: k must be >= 1.")
79 if (maxModality < 2) GUM_ERROR(InvalidArgument, "KTBNGenerator: maxModality must be >= 2.")
81 }
Draws a random k-DBN template (structure and, optionally, CPTs).

References KTBNGenerator(), _k_, _maxArcs_, _maxModality_, _nbAtemporal_, _nbTemporal_, GUM_ERROR, and k().

Referenced by KTBNGenerator(), ~KTBNGenerator(), setDensity(), setDomainRange(), setGenerateCPTs(), setGuaranteeOrder(), and setMaxParents().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ~KTBNGenerator()

template<GUM_Numeric GUM_SCALAR>
gum::KTBNGenerator< GUM_SCALAR >::~KTBNGenerator ( )

Destructor.

Definition at line 84 of file KTBNGenerator_tpl.h.

References KTBNGenerator().

Here is the call graph for this function:

Member Function Documentation

◆ _legalArcs_()

template<GUM_Numeric GUM_SCALAR>
std::vector< typename KTBNGenerator< GUM_SCALAR >::_Arc_ > gum::KTBNGenerator< GUM_SCALAR >::_legalArcs_ ( const std::vector< std::string > & temporal,
const std::vector< std::string > & atemporal,
const std::vector< Size > & tRank,
const std::vector< Size > & aRank ) const
private

Every arc the k-DBN's rules allow, with the two cycle-prone families (lag 0, atemporal→atemporal) already restricted to the ranks given by tRank / aRank, so the result is acyclic by construction.

Definition at line 169 of file KTBNGenerator_tpl.h.

172 {
173 const int k = static_cast< int >(_k_);
174 constexpr int AT = KTBN< GUM_SCALAR >::ATEMPORAL;
176 out.reserve(nbLegalArcs());
177
178 // atemporal -> atemporal: only low rank to high rank, which keeps it acyclic
179 for (std::size_t i = 0; i < atemporal.size(); ++i)
180 for (std::size_t j = 0; j < atemporal.size(); ++j)
181 if (aRank[i] < aRank[j]) out.push_back({atemporal[i], AT, atemporal[j], AT});
182
183 // atemporal -> temporal, at any slice: never cyclic, since the k-DBN's own
184 // rules already forbid a temporal variable from parenting an atemporal one.
185 for (const auto& a: atemporal)
186 for (const auto& b: temporal)
187 for (int s = 0; s < k; ++s)
188 out.push_back({a, AT, b, s});
189
190 // temporal, lag >= 1: the slice index strictly increases, so never cyclic
191 for (int s1 = 0; s1 < k; ++s1)
192 for (int s2 = s1 + 1; s2 < k; ++s2)
193 for (const auto& b1: temporal)
194 for (const auto& b2: temporal)
195 out.push_back({b1, s1, b2, s2});
196
197 // temporal, lag 0: the other cycle-prone family, so rank-ordered as well
198 for (int s = 0; s < k; ++s)
199 for (std::size_t i = 0; i < temporal.size(); ++i)
200 for (std::size_t j = 0; j < temporal.size(); ++j)
201 if (tRank[i] < tRank[j]) out.push_back({temporal[i], s, temporal[j], s});
202
203 return out;
204 }

References _k_, gum::KTBN< GUM_SCALAR >::ATEMPORAL, k(), and nbLegalArcs().

Referenced by generateKTBN().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _shuffle_()

template<GUM_Numeric GUM_SCALAR>
template<typename T>
void gum::KTBNGenerator< GUM_SCALAR >::_shuffle_ ( std::vector< T > & v)
staticprivate

Fisher-Yates through gum::randomValue, so gum::initRandom() alone makes a whole generation reproducible.

Definition at line 61 of file KTBNGenerator_tpl.h.

61 {
62 for (std::size_t i = v.size(); i > 1; --i)
63 std::swap(v[i - 1], v[randomValue(static_cast< Size >(i))]);
64 }

References gum::randomValue().

Referenced by generateKTBN().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ generate()

template<GUM_Numeric GUM_SCALAR>
KTBN< GUM_SCALAR > gum::KTBNGenerator< GUM_SCALAR >::generate ( )

Same, returning the model by value.

Definition at line 279 of file KTBNGenerator_tpl.h.

279 {
282 return out;
283 }
void generateKTBN(KTBN< GUM_SCALAR > &out)
Fills out with a freshly drawn model (its previous content is discarded). Seed it with gum::initRando...

References _k_, and generateKTBN().

Here is the call graph for this function:

◆ generateKTBN()

template<GUM_Numeric GUM_SCALAR>
void gum::KTBNGenerator< GUM_SCALAR >::generateKTBN ( KTBN< GUM_SCALAR > & out)

Fills out with a freshly drawn model (its previous content is discarded). Seed it with gum::initRandom() for reproducibility.

Definition at line 207 of file KTBNGenerator_tpl.h.

207 {
209
210 // ---- variables, with domain sizes drawn in [_minModality_, _maxModality_] ----
213 temporal.reserve(_nbTemporal_);
214 atemporal.reserve(_nbAtemporal_);
215
216 for (Size i = 0; i < _nbTemporal_; ++i) {
219 temporal.push_back(name);
220 }
221 for (Size i = 0; i < _nbAtemporal_; ++i) {
224 atemporal.push_back(name);
225 }
226
227 // ---- random ranks for the two cycle-prone arc families ----
229 for (Size i = 0; i < _nbTemporal_; ++i)
230 tPerm[i] = i;
231 for (Size i = 0; i < _nbAtemporal_; ++i)
232 aPerm[i] = i;
235
237 for (Size i = 0; i < _nbTemporal_; ++i)
238 tRank[tPerm[i]] = i;
239 for (Size i = 0; i < _nbAtemporal_; ++i)
240 aRank[aPerm[i]] = i;
241
242 // ---- how many arcs to draw ----
243 const Size legalCount = nbLegalArcs();
244 Size target = (_maxArcs_ != 0)
245 ? _maxArcs_
248
249 Size added = 0;
250
251 // ---- the guaranteed lag-(k-1) kernel arc ----
252 // Slice 0 -> slice k-1 is the widest reach a k-slice template can express, so
253 // this alone pins the model's effective order to k. Placed before the random
254 // fill, and counted against the budget, so density still bounds the total.
255 if (_guaranteeOrder_ && _k_ >= 2 && _nbTemporal_ >= 1) {
258 out.addArc(tail, 0, head, static_cast< int >(_k_) - 1);
259 ++added;
260 }
261
262 // ---- fill with random legal arcs ----
265 for (const auto& a: legal) {
266 if (added >= target) break;
267 if (out.existsArc(a.tailBase, a.tailSlice, a.headBase, a.headSlice)) continue;
268 if (_maxParents_ != 0
269 && static_cast< Size >(out.parents(a.headBase, a.headSlice).size()) >= _maxParents_)
270 continue;
271 out.addArc(a.tailBase, a.tailSlice, a.headBase, a.headSlice);
272 ++added;
273 }
274
275 if (_generateCPTs_) out.generateCPTs();
276 }
std::string _atemporalPrefix_
static void _shuffle_(std::vector< T > &v)
Fisher-Yates through gum::randomValue, so gum::initRandom() alone makes a whole generation reproducib...
std::string _temporalPrefix_
std::vector< _Arc_ > _legalArcs_(const std::vector< std::string > &temporal, const std::vector< std::string > &atemporal, const std::vector< Size > &tRank, const std::vector< Size > &aRank) const
Every arc the k-DBN's rules allow, with the two cycle-prone families (lag 0, atemporal→atemporal) alr...
LabelizedVariable()
(protected) Default constructor

References gum::LabelizedVariable::LabelizedVariable(), _atemporalPrefix_, _density_, _generateCPTs_, _guaranteeOrder_, _k_, _legalArcs_(), _maxArcs_, _maxModality_, _maxParents_, _minModality_, _nbAtemporal_, _nbTemporal_, _shuffle_(), _temporalPrefix_, nbLegalArcs(), and gum::randomValue().

Referenced by generate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ k()

template<GUM_Numeric GUM_SCALAR>
Size gum::KTBNGenerator< GUM_SCALAR >::k ( ) const
Returns
The order of the generated models.

Definition at line 147 of file KTBNGenerator_tpl.h.

147 {
148 return _k_;
149 }

References _k_.

Referenced by KTBNGenerator(), _legalArcs_(), and nbLegalArcs().

Here is the caller graph for this function:

◆ nbLegalArcs()

template<GUM_Numeric GUM_SCALAR>
Size gum::KTBNGenerator< GUM_SCALAR >::nbLegalArcs ( ) const
Returns
How many arcs the k-DBN's own rules allow, given the current shape. The density is a fraction of this, and it is the ceiling any maxArcs is silently clamped to.

Definition at line 152 of file KTBNGenerator_tpl.h.

152 {
153 const Size n = _nbTemporal_, m = _nbAtemporal_, k = _k_;
154 // guarded against unsigned underflow: each term is 0 when its shape is degenerate
155 const Size atemporalPairs = (m >= 2) ? m * (m - 1) / 2 : 0; // atemporal -> atemporal
156 const Size atemporalToAll = m * n * k; // atemporal -> temporal
157 const Size slicePairs = (k >= 2) ? k * (k - 1) / 2 : 0;
158 const Size crossSlice = n * n * slicePairs; // temporal, lag >= 1
159 const Size intraSlice = ((n >= 2) ? n * (n - 1) / 2 : 0) * k; // temporal, lag 0
161 }

References _k_, _nbAtemporal_, _nbTemporal_, and k().

Referenced by _legalArcs_(), and generateKTBN().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setDensity()

template<GUM_Numeric GUM_SCALAR>
KTBNGenerator< GUM_SCALAR > & gum::KTBNGenerator< GUM_SCALAR >::setDensity ( double density)

Fraction of the legal arc set to draw, in \([0,1]\). Ignored when a non-zero maxArcs was given to the constructor. Default 0.1.

Exceptions
OutOfBoundsif density is outside \([0,1]\).

Definition at line 93 of file KTBNGenerator_tpl.h.

93 {
95 GUM_ERROR(OutOfBounds, "KTBNGenerator: density must lie in [0,1].")
97 return *this;
98 }

References KTBNGenerator(), _density_, and GUM_ERROR.

Here is the call graph for this function:

◆ setDomainRange()

template<GUM_Numeric GUM_SCALAR>
KTBNGenerator< GUM_SCALAR > & gum::KTBNGenerator< GUM_SCALAR >::setDomainRange ( Size minModality,
Size maxModality )

Domain sizes are drawn uniformly in \([min, max]\).

Exceptions
InvalidArgumentif minModality < 2 or maxModality < minModality.

Definition at line 101 of file KTBNGenerator_tpl.h.

102 {
103 if (minModality < 2) GUM_ERROR(InvalidArgument, "KTBNGenerator: minModality must be >= 2.")
105 GUM_ERROR(InvalidArgument, "KTBNGenerator: maxModality must be >= minModality.")
108 return *this;
109 }

References KTBNGenerator(), _maxModality_, _minModality_, and GUM_ERROR.

Here is the call graph for this function:

◆ setGenerateCPTs()

template<GUM_Numeric GUM_SCALAR>
KTBNGenerator< GUM_SCALAR > & gum::KTBNGenerator< GUM_SCALAR >::setGenerateCPTs ( bool on)

Whether to fill the CPTs with random values (default true). When false only the structure is drawn and the CPTs stay at their default content.

Definition at line 124 of file KTBNGenerator_tpl.h.

124 {
126 return *this;
127 }

References KTBNGenerator(), and _generateCPTs_.

Here is the call graph for this function:

◆ setGuaranteeOrder()

template<GUM_Numeric GUM_SCALAR>
KTBNGenerator< GUM_SCALAR > & gum::KTBNGenerator< GUM_SCALAR >::setGuaranteeOrder ( bool on)

Force one arc of lag \(k-1\) into the kernel slice, so the model's effective order equals \(k\) (see the class doc). Default true. No-op when \(k = 1\) or there is no temporal process.

Definition at line 118 of file KTBNGenerator_tpl.h.

118 {
120 return *this;
121 }

References KTBNGenerator(), and _guaranteeOrder_.

Here is the call graph for this function:

◆ setMaxParents()

template<GUM_Numeric GUM_SCALAR>
KTBNGenerator< GUM_SCALAR > & gum::KTBNGenerator< GUM_SCALAR >::setMaxParents ( Size maxParents)

Caps the number of parents of any node, which bounds CPT size. 0 (default) means unlimited — a dense draw can then produce very large CPTs, so set it when generating dense or high-k models.

Definition at line 112 of file KTBNGenerator_tpl.h.

112 {
114 return *this;
115 }

References KTBNGenerator(), and _maxParents_.

Here is the call graph for this function:

◆ setNamePrefixes()

template<GUM_Numeric GUM_SCALAR>
KTBNGenerator< GUM_SCALAR > & gum::KTBNGenerator< GUM_SCALAR >::setNamePrefixes ( const std::string & temporal,
const std::string & atemporal )

Name prefixes; variables are prefix0, prefix1, … Defaults are "X" (temporal) and "A" (atemporal).

Exceptions
InvalidArgumentif a prefix is empty or the two are equal.

Definition at line 131 of file KTBNGenerator_tpl.h.

132 {
133 if (temporal.empty() || atemporal.empty())
134 GUM_ERROR(InvalidArgument, "KTBNGenerator: a name prefix cannot be empty.")
136 GUM_ERROR(InvalidArgument, "KTBNGenerator: the two name prefixes must differ.")
139 return *this;
140 }

References _atemporalPrefix_, _temporalPrefix_, and GUM_ERROR.

Member Data Documentation

◆ _atemporalPrefix_

template<GUM_Numeric GUM_SCALAR>
std::string gum::KTBNGenerator< GUM_SCALAR >::_atemporalPrefix_ {"A"}
private

Definition at line 228 of file KTBNGenerator.h.

Referenced by generateKTBN(), and setNamePrefixes().

◆ _density_

template<GUM_Numeric GUM_SCALAR>
double gum::KTBNGenerator< GUM_SCALAR >::_density_ {0.1}
private

Definition at line 223 of file KTBNGenerator.h.

Referenced by generateKTBN(), and setDensity().

◆ _generateCPTs_

template<GUM_Numeric GUM_SCALAR>
bool gum::KTBNGenerator< GUM_SCALAR >::_generateCPTs_ {true}
private

Definition at line 225 of file KTBNGenerator.h.

Referenced by generateKTBN(), and setGenerateCPTs().

◆ _guaranteeOrder_

template<GUM_Numeric GUM_SCALAR>
bool gum::KTBNGenerator< GUM_SCALAR >::_guaranteeOrder_ {true}
private

Definition at line 224 of file KTBNGenerator.h.

Referenced by generateKTBN(), and setGuaranteeOrder().

◆ _k_

template<GUM_Numeric GUM_SCALAR>
Size gum::KTBNGenerator< GUM_SCALAR >::_k_
private

Definition at line 216 of file KTBNGenerator.h.

Referenced by KTBNGenerator(), _legalArcs_(), generate(), generateKTBN(), k(), and nbLegalArcs().

◆ _maxArcs_

template<GUM_Numeric GUM_SCALAR>
Size gum::KTBNGenerator< GUM_SCALAR >::_maxArcs_
private

Definition at line 219 of file KTBNGenerator.h.

Referenced by KTBNGenerator(), and generateKTBN().

◆ _maxModality_

template<GUM_Numeric GUM_SCALAR>
Size gum::KTBNGenerator< GUM_SCALAR >::_maxModality_
private

Definition at line 221 of file KTBNGenerator.h.

Referenced by KTBNGenerator(), generateKTBN(), and setDomainRange().

◆ _maxParents_

template<GUM_Numeric GUM_SCALAR>
Size gum::KTBNGenerator< GUM_SCALAR >::_maxParents_ {0}
private

Definition at line 222 of file KTBNGenerator.h.

Referenced by generateKTBN(), and setMaxParents().

◆ _minModality_

template<GUM_Numeric GUM_SCALAR>
Size gum::KTBNGenerator< GUM_SCALAR >::_minModality_ {2}
private

Definition at line 220 of file KTBNGenerator.h.

Referenced by generateKTBN(), and setDomainRange().

◆ _nbAtemporal_

template<GUM_Numeric GUM_SCALAR>
Size gum::KTBNGenerator< GUM_SCALAR >::_nbAtemporal_
private

Definition at line 218 of file KTBNGenerator.h.

Referenced by KTBNGenerator(), generateKTBN(), and nbLegalArcs().

◆ _nbTemporal_

template<GUM_Numeric GUM_SCALAR>
Size gum::KTBNGenerator< GUM_SCALAR >::_nbTemporal_
private

Definition at line 217 of file KTBNGenerator.h.

Referenced by KTBNGenerator(), generateKTBN(), and nbLegalArcs().

◆ _temporalPrefix_

template<GUM_Numeric GUM_SCALAR>
std::string gum::KTBNGenerator< GUM_SCALAR >::_temporalPrefix_ {"X"}
private

Definition at line 227 of file KTBNGenerator.h.

Referenced by generateKTBN(), and setNamePrefixes().


The documentation for this class was generated from the following files: