aGrUM 2.3.2
a C++ library for (probabilistic) graphical models
lazyPropagation.h
Go to the documentation of this file.
1/****************************************************************************
2 * This file is part of the aGrUM/pyAgrum library. *
3 * *
4 * Copyright (c) 2005-2025 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-2025 *
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
49#ifndef GUM_LAZY_PROPAGATION_H
50#define GUM_LAZY_PROPAGATION_H
51
52#include <utility>
53
54#include <agrum/agrum.h>
55
62
63namespace gum {
64
65
66 // the function used to combine two tables
67 template < typename GUM_SCALAR >
68 INLINE static Tensor< GUM_SCALAR > LPNewmultiTensor(const Tensor< GUM_SCALAR >& t1,
69 const Tensor< GUM_SCALAR >& t2) {
70 return t1 * t2;
71 }
72
73 // the function used to combine two tables with summations
74 template < typename GUM_SCALAR >
75 INLINE static Tensor< GUM_SCALAR > LPNewprojTensor(const Tensor< GUM_SCALAR >& t1,
76 const gum::VariableSet& del_vars) {
77 return t1.sumOut(del_vars);
78 }
79
80 // the function used to combine two tables with max
81 template < typename GUM_SCALAR >
82 INLINE static Tensor< GUM_SCALAR > LPMaxprojTensor(const Tensor< GUM_SCALAR >& t1,
83 const gum::VariableSet& del_vars) {
84 return t1.maxOut(del_vars);
85 }
86
94 template < typename GUM_SCALAR >
96 public JointTargetedInference< GUM_SCALAR >,
97 public EvidenceInference< GUM_SCALAR >,
98 public ScheduledInference {
99 public:
100 // ############################################################################
102 // ############################################################################
104
110 bool use_binary_join_tree = true);
111
114
117
120
122
123
124 // ############################################################################
126 // ############################################################################
128
130 void setTriangulation(const Triangulation& new_triangulation);
131
133
142
144
150
152
156
158
163
165 GUM_SCALAR evidenceProbability() final;
166
168
179
192 std::pair< Instantiation, GUM_SCALAR > mpeLog2Posterior();
193
195
196
197 protected:
199 void onEvidenceAdded_(const NodeId id, bool isHardEvidence) final;
200
202 void onEvidenceErased_(const NodeId id, bool isHardEvidence) final;
203
205 void onAllEvidenceErased_(bool has_hard_evidence) final;
206
214 void onEvidenceChanged_(const NodeId id, bool hasChangedSoftHard) final;
215
217
218 void onMarginalTargetAdded_(const NodeId id) final;
219
221
222 void onMarginalTargetErased_(const NodeId id) final;
223
225 void onModelChanged_(const GraphicalModel* bn) final;
226
228
229 void onJointTargetAdded_(const NodeSet& set) final;
230
232
233 void onJointTargetErased_(const NodeSet& set) final;
234
237
240
243
246
248 void onStateChanged_() final {};
249
251
255
257
261
263
264 void makeInference_() final;
265
266
268
269 const Tensor< GUM_SCALAR >& posterior_(NodeId id) final;
270
272
274 const Tensor< GUM_SCALAR >& jointPosterior_(const NodeSet& set) final;
275
283 const Tensor< GUM_SCALAR >& jointPosterior_(const NodeSet& wanted_target,
284 const NodeSet& declared_target) final;
285
287 Tensor< GUM_SCALAR >* unnormalizedJointPosterior_(NodeId id) final;
288
290 Tensor< GUM_SCALAR >* unnormalizedJointPosterior_(const NodeSet& set) final;
291
292
293 private:
294 using _TensorSet_ = Set< const Tensor< GUM_SCALAR >* >;
296
297
301
306 gum::VariableSet& kept_vars);
307
310
312 Tensor< GUM_SCALAR > (*_projection_op_)(const Tensor< GUM_SCALAR >&,
314
316 Tensor< GUM_SCALAR > (*_combination_op_)(const Tensor< GUM_SCALAR >&,
317 const Tensor< GUM_SCALAR >&){LPNewmultiTensor};
318
321
325
327
333
335 JoinTree* _JT_{nullptr};
336
339
341
345
347
354
357
360
362
368
370
373
375
381
383
385
387
389
395
397
401
403
410
412
420
423
426
430
432 bool _use_schedules_{false};
433
435 static constexpr double _schedule_threshold_{1000000.0};
436
438 static constexpr GUM_SCALAR _one_minus_epsilon_{GUM_SCALAR(1.0 - 1e-6)};
439
440
442 bool _isNewJTNeeded_() const;
443
446
449
452
454 void _setProjectionFunction_(Tensor< GUM_SCALAR > (*proj)(const Tensor< GUM_SCALAR >&,
455 const gum::VariableSet&));
456
458 void _setCombinationFunction_(Tensor< GUM_SCALAR > (*comb)(const Tensor< GUM_SCALAR >&,
459 const Tensor< GUM_SCALAR >&));
460
462 void _diffuseMessageInvalidations_(NodeId from_id, NodeId to_id, NodeSet& invalidated_cliques);
463
466
469
473 gum::VariableSet& kept_vars);
474
478 gum::VariableSet& kept_vars);
479
483 gum::VariableSet& kept_vars);
484
489
493
496 _ScheduleMultiDimSet_& pot_list,
497 gum::VariableSet& del_vars);
498
501
505 _ScheduleMultiDimSet_ pot_list,
506 gum::VariableSet& del_vars,
507 gum::VariableSet& kept_vars);
508
512 gum::VariableSet& del_vars,
513 gum::VariableSet& kept_vars);
514
516 void _produceMessage_(Schedule& schedule, NodeId from_id, NodeId to_id);
517
519 void _produceMessage_(NodeId from_id, NodeId to_id);
520
522 void _collectMessage_(Schedule& schedule, NodeId id, NodeId from);
523
526
528 Tensor< GUM_SCALAR >* _unnormalizedJointPosterior_(Schedule& schedule, NodeId id);
529
531 Tensor< GUM_SCALAR >* _unnormalizedJointPosterior_(NodeId id);
532
534 Tensor< GUM_SCALAR >* _unnormalizedJointPosterior_(Schedule& schedule, const NodeSet& set);
535
537 Tensor< GUM_SCALAR >* _unnormalizedJointPosterior_(const NodeSet& set);
538 };
539
540
541#ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
542 extern template class LazyPropagation< double >;
543#endif
544
545
546} /* namespace gum */
547
549
550#endif /* GUM_LAZY_PROPAGATION_H */
Detect barren nodes for inference in Bayesian networks.
virtual const IBayesNet< GUM_SCALAR > & BN() const final
Returns a constant reference over the IBayesNet referenced by this class.
EvidenceInference(const IBayesNet< GUM_SCALAR > *bn)
default constructor
Virtual base class for probabilistic graphical models.
Class representing the minimal interface for Bayesian network with no numerical data.
Definition IBayesNet.h:75
The Table-agnostic base class of scheduleMultiDim.
Class for assigning/browsing values to tuples of discrete variables.
JointTargetedInference(const IBayesNet< GUM_SCALAR > *bn)
default constructor
Implementation of a Shafer-Shenoy's-like version of lazy propagation for inference in Bayesian networ...
HashTable< NodeSet, NodeId > _joint_target_to_clique_
for each set target, assign a clique in the JT that contains it
bool _use_schedules_
indicates whether we should use schedules for inference
ArcProperty< _ScheduleMultiDimSet_ > _separator_tensors_
the list of all tensors stored in the separators after inferences
void onStateChanged_() final
fired when the state of the inference engine is changed
_ScheduleMultiDimSet_ _marginalizeOut_(_ScheduleMultiDimSet_ &pot_list, gum::VariableSet &del_vars, gum::VariableSet &kept_vars)
removes variables del_vars from a list of tensors and returns the resulting list directly without sch...
FindBarrenNodesType _barren_nodes_type_
the type of barren nodes computation we wish
NodeProperty< EvidenceChangeType > _evidence_changes_
indicates which nodes of the BN have evidence that changed since the last inference
void _findRelevantTensorsWithdSeparation2_(_ScheduleMultiDimSet_ &pot_list, gum::VariableSet &kept_vars)
update a set of tensors: the remaining are those to be combined to produce a message on a separator
void onMarginalTargetAdded_(const NodeId id) final
fired after a new single target is inserted
void updateOutdatedTensors_() final
prepares inference when the latter is in OutdatedTensors state
void makeInference_() final
called when the inference has to be performed effectively
void _findRelevantTensorsGetAll_(_ScheduleMultiDimSet_ &pot_list, gum::VariableSet &kept_vars)
update a set of tensors: the remaining are those to be combined to produce a message on a separator
UndiGraph _graph_
the undigraph extracted from the BN and used to construct the join tree
Tensor< GUM_SCALAR > * _unnormalizedJointPosterior_(const NodeSet &set)
returns a fresh tensor equal to P(argument,evidence) without using schedules
EvidenceChangeType
the possible types of evidence changes
Tensor< GUM_SCALAR > * _unnormalizedJointPosterior_(NodeId id)
computes the unnormalized posterior of a node without using schedules
const Tensor< GUM_SCALAR > & jointPosterior_(const NodeSet &set) final
returns the posterior of a declared target set
GUM_SCALAR evidenceProbability() final
returns the probability of evidence
void _diffuseMessageInvalidations_(NodeId from_id, NodeId to_id, NodeSet &invalidated_cliques)
invalidate all the messages sent from a given clique
void _setCombinationFunction_(Tensor< GUM_SCALAR >(*comb)(const Tensor< GUM_SCALAR > &, const Tensor< GUM_SCALAR > &))
sets the operator for performing the combinations
std::pair< Instantiation, GUM_SCALAR > mpeLog2Posterior()
returns the most probable explanation and its probability, i.e., (X*, log2(P(X*|e))),...
void _createNewJT_()
create a new junction tree as well as its related data structures
void onEvidenceAdded_(const NodeId id, bool isHardEvidence) final
fired after a new evidence is inserted
void onEvidenceChanged_(const NodeId id, bool hasChangedSoftHard) final
fired after an evidence is changed, in particular when its status (soft/hard) changes
static constexpr GUM_SCALAR _one_minus_epsilon_
for comparisons with 1 - epsilon
void _findRelevantTensorsXX_(_ScheduleMultiDimSet_ &pot_list, gum::VariableSet &kept_vars)
update a set of tensors: the remaining are those to be combined to produce a message on a separator
JoinTree * _JT_
the join (or junction) tree used to answer the last inference query
_TensorSet_ _removeBarrenVariables_(_TensorSet_ &pot_list, gum::VariableSet &del_vars)
remove barren variables without schedules and return the newly created projected tensors
void onJointTargetAdded_(const NodeSet &set) final
fired after a new joint target is inserted
_ScheduleMultiDimSet_ _removeBarrenVariables_(Schedule &schedule, _ScheduleMultiDimSet_ &pot_list, gum::VariableSet &del_vars)
remove barren variables using schedules and return the newly created projected tensors
const JoinTree * joinTree()
returns the current join tree used
LazyPropagation< GUM_SCALAR > & operator=(const LazyPropagation< GUM_SCALAR > &)=delete
avoid copy operators
NodeProperty< const IScheduleMultiDim * > _node_to_hard_ev_projected_CPTs_
the CPTs that were projected due to hard evidence nodes
_ScheduleMultiDimSet_ _marginalizeOut_(Schedule &schedule, _ScheduleMultiDimSet_ pot_list, gum::VariableSet &del_vars, gum::VariableSet &kept_vars)
removes variables del_vars from a list of tensors and returns the resulting list using schedules
Tensor< GUM_SCALAR > * unnormalizedJointPosterior_(NodeId id) final
returns a fresh tensor equal to P(argument,evidence)
void _setProjectionFunction_(Tensor< GUM_SCALAR >(*proj)(const Tensor< GUM_SCALAR > &, const gum::VariableSet &))
sets the operator for performing the projections
Set< const IScheduleMultiDim * > _ScheduleMultiDimSet_
ArcProperty< _ScheduleMultiDimSet_ > _arc_to_created_tensors_
the set of tensors created for the last inference messages
void _produceMessage_(Schedule &schedule, NodeId from_id, NodeId to_id)
creates the message sent by clique from_id to clique to_id using schedules
Set< const Tensor< GUM_SCALAR > * > _TensorSet_
void onAllJointTargetsErased_() final
fired before all the joint targets are removed
void setRelevantTensorsFinderType(RelevantTensorsFinderType type)
sets how we determine the relevant tensors to combine
void onModelChanged_(const GraphicalModel *bn) final
fired after a new Bayes net has been assigned to the inference engine
void onMarginalTargetErased_(const NodeId id) final
fired before a single target is removed
void _findRelevantTensorsWithdSeparation3_(_ScheduleMultiDimSet_ &pot_list, gum::VariableSet &kept_vars)
update a set of tensors: the remaining are those to be combined to produce a message on a separator
void onAllMarginalTargetsAdded_() final
fired after all the nodes of the BN are added as single targets
~LazyPropagation()
destructor
void onEvidenceErased_(const NodeId id, bool isHardEvidence) final
fired before an evidence is removed
void(LazyPropagation< GUM_SCALAR >::* _findRelevantTensors_)(Set< const IScheduleMultiDim * > &pot_list, gum::VariableSet &kept_vars)
update a set of tensors: the remaining are those to be combined to produce a message on a separator
void _computeJoinTreeRoots_()
compute a root for each connected component of JT
void updateOutdatedStructure_() final
prepares inference when the latter is in OutdatedStructure state
void _initializeJTCliques_()
put all the CPTs into the cliques when creating the JT without using a schedule
LazyPropagation(const IBayesNet< GUM_SCALAR > *BN, RelevantTensorsFinderType=RelevantTensorsFinderType::DSEP_BAYESBALL_TENSORS, FindBarrenNodesType=FindBarrenNodesType::FIND_BARREN_NODES, bool use_binary_join_tree=true)
default constructor
bool _use_binary_join_tree_
indicates whether we should transform junction trees into binary join trees
NodeProperty< const Tensor< GUM_SCALAR > * > _target_posteriors_
the set of single posteriors computed during the last inference
Tensor< GUM_SCALAR >(* _combination_op_)(const Tensor< GUM_SCALAR > &, const Tensor< GUM_SCALAR > &)
the operator for performing the combinations
Tensor< GUM_SCALAR >(* _projection_op_)(const Tensor< GUM_SCALAR > &, const gum::VariableSet &)
the operator for performing the projections
static constexpr double _schedule_threshold_
minimal number of operations to perform in the JT to use schedules
RelevantTensorsFinderType _find_relevant_tensor_type_
the type of relevant tensor finding algorithm to be used
void onAllEvidenceErased_(bool has_hard_evidence) final
fired before all the evidence are erased
NodeProperty< GUM_SCALAR > _constants_
the constants resulting from the projections of CPTs defined over only hard evidence nodes @TODO remo...
void setFindBarrenNodesType(FindBarrenNodesType type)
sets how we determine barren nodes
void _collectMessage_(NodeId id, NodeId from)
perform the collect phase directly without schedules
HashTable< NodeId, NodeId > _node_to_clique_
for each node of graph (~ in the Bayes net), associate an ID in the JT
NodeProperty< const IScheduleMultiDim * > _node_to_soft_evidence_
the soft evidence stored in the cliques per their assigned node in the BN
NodeSet _hard_ev_nodes_
the hard evidence nodes which were projected in CPTs
ArcProperty< bool > _messages_computed_
indicates whether a message (from one clique to another) has been computed
LazyPropagation(const LazyPropagation< GUM_SCALAR > &)=delete
avoid copy constructors
NodeSet _roots_
a clique node used as a root in each connected component of JT
bool _is_new_jt_needed_
indicates whether a new join tree is needed for the next inference
void _initializeJTCliques_(Schedule &schedule)
put all the CPTs into the cliques when creating the JT using a schedule
Instantiation mpe()
returns the most probable explanation, i.e., X* = argmax_X P(X|e)
void setTriangulation(const Triangulation &new_triangulation)
use a new triangulation algorithm
Triangulation * _triangulation_
the triangulation class creating the junction tree used for inference
HashTable< NodeSet, const Tensor< GUM_SCALAR > * > _joint_target_posteriors_
the set of set target posteriors computed during the last inference
void _collectMessage_(Schedule &schedule, NodeId id, NodeId from)
perform the collect phase using schedules
JunctionTree * _junctionTree_
the junction tree to answer the last inference query
void _findRelevantTensorsWithdSeparation_(_ScheduleMultiDimSet_ &pot_list, gum::VariableSet &kept_vars)
update a set of tensors: the remaining are those to be combined to produce a message on a separator
void _invalidateAllMessages_()
invalidate all messages, posteriors and created tensors
void _produceMessage_(NodeId from_id, NodeId to_id)
creates the message sent by clique from_id to clique to_id without schedules
NodeProperty< _ScheduleMultiDimSet_ > _clique_tensors_
the list of all tensors stored in the cliques
const Tensor< GUM_SCALAR > & posterior_(NodeId id) final
returns the posterior of a given variable
void onJointTargetErased_(const NodeSet &set) final
fired before a joint target is removed
void onAllTargetsErased_() final
fired before all single and joint targets are removed
void onAllMarginalTargetsErased_() final
fired before all the single targets are removed
bool _isNewJTNeeded_() const
check whether a new join tree is really needed for the next inference
Tensor< GUM_SCALAR > * _unnormalizedJointPosterior_(Schedule &schedule, const NodeSet &set)
returns a fresh tensor equal to P(argument,evidence) using schedules
const JunctionTree * junctionTree()
returns the current junction tree
Tensor< GUM_SCALAR > * _unnormalizedJointPosterior_(Schedule &schedule, NodeId id)
computes the unnormalized posterior of a node using schedules
Class containing a schedule of operations to perform on multidims.
Definition schedule.h:80
ScheduledInference(Size max_nb_threads=0, double max_megabyte_memory=0.0)
default constructor
Representation of a set.
Definition set.h:131
aGrUM's Tensor is a multi-dimensional array with tensor operators.
Definition tensor.h:85
Interface for all the triangulation methods.
Base class for undirected graphs.
Definition undiGraph.h:128
Class for computing default triangulations of graphs.
This file contains the abstract class definition for computing the probability of evidence entered in...
Size NodeId
Type for node ids.
HashTable< Arc, VAL > ArcProperty
Property on graph elements.
HashTable< NodeId, VAL > NodeProperty
Property on graph elements.
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
This file contains the abstract inference class definition for computing (incrementally) joint poster...
Implementation of lazy propagation for inference in Bayesian networks.
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
static INLINE Tensor< GUM_SCALAR > LPNewmultiTensor(const Tensor< GUM_SCALAR > &t1, const Tensor< GUM_SCALAR > &t2)
FindBarrenNodesType
type of algorithm to determine barren nodes
Set< const DiscreteVariable * > VariableSet
static INLINE Tensor< GUM_SCALAR > LPNewprojTensor(const Tensor< GUM_SCALAR > &t1, const gum::VariableSet &del_vars)
CliqueGraph JoinTree
a join tree is a clique graph satisfying the running intersection property (but some cliques may be i...
static INLINE Tensor< GUM_SCALAR > LPMaxprojTensor(const Tensor< GUM_SCALAR > &t1, const gum::VariableSet &del_vars)
CliqueGraph JunctionTree
a junction tree is a clique graph satisfying the running intersection property and such that no cliqu...
RelevantTensorsFinderType
type of algorithm for determining the relevant tensors for combinations using some d-separation analy...
STL namespace.
the type of algorithm to use to perform relevant reasoning in Bayes net inference
The class enabling flexible inferences using schedules.