aGrUM 2.3.2
a C++ library for (probabilistic) graphical models
variableElimination.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_VARIABLE_ELIMINATION_H
50#define GUM_VARIABLE_ELIMINATION_H
51
52#include <utility>
53
54#include <agrum/agrum.h>
55
61
62namespace gum {
63
64
65 // the function used to combine two tables
66 template < typename GUM_SCALAR >
67 INLINE static Tensor< GUM_SCALAR > VENewmultiTensor(const Tensor< GUM_SCALAR >& t1,
68 const Tensor< GUM_SCALAR >& t2) {
69 return t1 * t2;
70 }
71
72 // the function used to combine two tables
73 template < typename GUM_SCALAR >
74 INLINE static Tensor< GUM_SCALAR > VENewprojTensor(const Tensor< GUM_SCALAR >& t1,
75 const gum::VariableSet& del_vars) {
76 return t1.sumOut(del_vars);
77 }
78
86 template < typename GUM_SCALAR >
88 public JointTargetedInference< GUM_SCALAR >,
89 public ScheduledInference {
90 public:
91 // ############################################################################
93 // ############################################################################
95
101
104
107
110
112
113
114 // ############################################################################
116 // ############################################################################
118
120 void setTriangulation(const Triangulation& new_triangulation);
121
123
132
134
140
143
145
146
147 protected:
149 void onEvidenceAdded_(const NodeId id, bool isHardEvidence) final;
150
152 void onEvidenceErased_(const NodeId id, bool isHardEvidence) final;
153
155 void onAllEvidenceErased_(bool has_hard_evidence) final;
156
164 void onEvidenceChanged_(const NodeId id, bool hasChangedSoftHard) final;
165
167
168 void onMarginalTargetAdded_(const NodeId id) final;
169
171
172 void onMarginalTargetErased_(const NodeId id) final;
173
175 virtual void onModelChanged_(const GraphicalModel* bn) final;
176
178
179 void onJointTargetAdded_(const NodeSet& set) final;
180
182
183 void onJointTargetErased_(const NodeSet& set) final;
184
187
190
193
196
198 void onStateChanged_() final {};
199
201
205
207
211
213
214 void makeInference_() final;
215
216
218
219 const Tensor< GUM_SCALAR >& posterior_(NodeId id) final;
220
222
224 const Tensor< GUM_SCALAR >& jointPosterior_(const NodeSet& set) final;
225
233 const Tensor< GUM_SCALAR >& jointPosterior_(const NodeSet& wanted_target,
234 const NodeSet& declared_target) final;
235
237 Tensor< GUM_SCALAR >* unnormalizedJointPosterior_(NodeId id) final;
238
240 Tensor< GUM_SCALAR >* unnormalizedJointPosterior_(const NodeSet& set) final;
241
242
243 private:
244 using _TensorSet_ = Set< const Tensor< GUM_SCALAR >* >;
246
247
251
256 gum::VariableSet& kept_vars);
257
260
262 Tensor< GUM_SCALAR > (*_projection_op_)(const Tensor< GUM_SCALAR >&,
264
266 Tensor< GUM_SCALAR > (*_combination_op_)(const Tensor< GUM_SCALAR >&,
267 const Tensor< GUM_SCALAR >&){VENewmultiTensor};
268
271
273
279
282
285
288
291
293
294 Tensor< GUM_SCALAR >* _target_posterior_{nullptr};
295
297 static constexpr double _schedule_threshold_{1000000.0};
298
300 const GUM_SCALAR _one_minus_epsilon_{GUM_SCALAR(1.0 - 1e-6)};
301
302
305
307 void _setProjectionFunction_(Tensor< GUM_SCALAR > (*proj)(const Tensor< GUM_SCALAR >&,
308 const gum::VariableSet&));
309
311 void _setCombinationFunction_(Tensor< GUM_SCALAR > (*comb)(const Tensor< GUM_SCALAR >&,
312 const Tensor< GUM_SCALAR >&));
313
317 gum::VariableSet& kept_vars);
318
322 gum::VariableSet& kept_vars);
323
327 gum::VariableSet& kept_vars);
328
333
337
340 _ScheduleMultiDimSet_& pot_list,
341 gum::VariableSet& del_vars);
342
345
348
350 std::pair< _TensorSet_, _TensorSet_ > _collectMessage_(NodeId id, NodeId from);
351
353 std::pair< _TensorSet_, _TensorSet_ > _NodeTensors_(NodeId node);
354
357
359 std::pair< _TensorSet_, _TensorSet_ >
361 NodeId to_id,
362 std::pair< _TensorSet_, _TensorSet_ >&& incoming_messages);
363
366 NodeId from_id,
367 NodeId to_id,
368 _ScheduleMultiDimSet_&& incoming_messages);
369
373 gum::VariableSet& del_vars,
374 gum::VariableSet& kept_vars);
375
379 _ScheduleMultiDimSet_ pot_list,
380 gum::VariableSet& del_vars,
381 gum::VariableSet& kept_vars);
382
384
385 Tensor< GUM_SCALAR >* _unnormalizedJointPosterior_(NodeId id);
386
388
389 Tensor< GUM_SCALAR >* _unnormalizedJointPosterior_(Schedule& schedule, NodeId id);
390
392
393 Tensor< GUM_SCALAR >* _unnormalizedJointPosterior_(const NodeSet& set,
394 const NodeSet& targets,
395 const NodeSet& hard_evidence_nodes);
396
398
399 Tensor< GUM_SCALAR >* _unnormalizedJointPosterior_(Schedule& schedule,
400 const NodeSet& set,
401 const NodeSet& targets,
402 const NodeSet& hard_evidence_nodes);
403 };
404
405
406#ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
407 extern template class VariableElimination< double >;
408#endif
409
410
411} /* namespace gum */
412
414
415
416#endif /* GUM_VARIABLE_ELIMINATION_ */
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.
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.
JointTargetedInference(const IBayesNet< GUM_SCALAR > *bn)
default constructor
virtual const NodeSet & targets() const noexcept final
returns the list of marginal targets
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
Implementation of a Variable Elimination's-like version of lazy propagation for inference in Bayesian...
void onEvidenceAdded_(const NodeId id, bool isHardEvidence) final
fired after a new evidence is inserted
void onAllMarginalTargetsAdded_() final
fired after all the nodes of the BN are added as single targets
void updateOutdatedTensors_() final
prepares inference when the latter is in OutdatedTensors state
RelevantTensorsFinderType _find_relevant_tensor_type_
the type of relevant tensor finding algorithm to be used
VariableElimination(const IBayesNet< GUM_SCALAR > *BN, RelevantTensorsFinderType=RelevantTensorsFinderType::DSEP_BAYESBALL_TENSORS, FindBarrenNodesType=FindBarrenNodesType::FIND_BARREN_NODES)
default constructor
const Tensor< GUM_SCALAR > & posterior_(NodeId id) final
returns the posterior of a given variable
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
UndiGraph _graph_
the undigraph extracted from the BN and used to construct the join tree
Tensor< GUM_SCALAR >(* _combination_op_)(const Tensor< GUM_SCALAR > &, const Tensor< GUM_SCALAR > &)
the operator for performing the combinations
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
HashTable< NodeId, NodeId > _node_to_clique_
for each node of graph (~ in the Bayes net), associate an ID in the JT
void onStateChanged_() final
fired when the state of the inference engine is changed
void onJointTargetErased_(const NodeSet &set) final
fired before a joint target is removed
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 _setCombinationFunction_(Tensor< GUM_SCALAR >(*comb)(const Tensor< GUM_SCALAR > &, const Tensor< GUM_SCALAR > &))
sets the operator for performing the combinations
Set< const Tensor< GUM_SCALAR > * > _TensorSet_
void(VariableElimination< 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
VariableElimination(const VariableElimination< GUM_SCALAR > &)=delete
avoid copy constructors
void onMarginalTargetAdded_(const NodeId id) final
fired after a new single target is inserted
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
_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
void onEvidenceChanged_(const NodeId id, bool hasChangedSoftHard) final
fired after an evidence is changed, in particular when its status (soft/hard) changes
const Tensor< GUM_SCALAR > & jointPosterior_(const NodeSet &set) final
returns the posterior of a declared target set
void _setProjectionFunction_(Tensor< GUM_SCALAR >(*proj)(const Tensor< GUM_SCALAR > &, const gum::VariableSet &))
sets the operator for performing the projections
_ScheduleMultiDimSet_ _removeBarrenVariables_(Schedule &schedule, _ScheduleMultiDimSet_ &pot_list, gum::VariableSet &del_vars)
remove barren variables using schedules and return the newly created projected tensors
Tensor< GUM_SCALAR > * _unnormalizedJointPosterior_(Schedule &schedule, NodeId id)
returns a fresh tensor equal to P(1st arg,evidence) without using schedules
void onAllTargetsErased_() final
fired before all single and joint targets are removed
void setFindBarrenNodesType(FindBarrenNodesType type)
sets how we determine barren nodes
const JunctionTree * junctionTree(NodeId id)
returns the join tree used for compute the posterior of node id
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
~VariableElimination()
destructor
void onEvidenceErased_(const NodeId id, bool isHardEvidence) final
fired before an evidence is removed
std::pair< _TensorSet_, _TensorSet_ > _produceMessage_(NodeId from_id, NodeId to_id, std::pair< _TensorSet_, _TensorSet_ > &&incoming_messages)
creates the message sent by clique from_id to clique to_id without using schedules
Tensor< GUM_SCALAR > * unnormalizedJointPosterior_(NodeId id) final
returns a fresh tensor equal to P(argument,evidence)
_TensorSet_ _removeBarrenVariables_(_TensorSet_ &pot_list, gum::VariableSet &del_vars)
remove barren variables without schedules and return the newly created projected tensors
HashTable< NodeId, NodeSet > _clique_to_nodes_
for each clique, indicate the set of nodes whose CPTs will be stored into it
void onMarginalTargetErased_(const NodeId id) final
fired before a single target is removed
_ScheduleMultiDimSet_ _NodeTensors_(Schedule &schedule, NodeId node)
returns the CPT + evidence of a node projected w.r.t. hard evidence
static constexpr double _schedule_threshold_
minimal number of operations to perform in the JT to use schedules
void updateOutdatedStructure_() final
prepares inference when the latter is in OutdatedStructure state
JunctionTree * _JT_
the junction tree used to answer the last inference query
void onAllMarginalTargetsErased_() final
fired before all the single targets are removed
void onAllEvidenceErased_(bool has_hard_evidence) final
fired before all the evidence are erased
void setTriangulation(const Triangulation &new_triangulation)
use a new triangulation algorithm
void makeInference_() final
called when the inference has to be performed effectively
Tensor< GUM_SCALAR >(* _projection_op_)(const Tensor< GUM_SCALAR > &, const gum::VariableSet &)
the operator for performing the projections
void onJointTargetAdded_(const NodeSet &set) final
fired after a new joint target is inserted
std::pair< _TensorSet_, _TensorSet_ > _NodeTensors_(NodeId node)
returns the CPT + evidence of a node projected w.r.t. hard evidence
Tensor< GUM_SCALAR > * _unnormalizedJointPosterior_(NodeId id)
returns a fresh tensor equal to P(1st arg,evidence) without using schedules
Tensor< GUM_SCALAR > * _unnormalizedJointPosterior_(Schedule &schedule, const NodeSet &set, const NodeSet &targets, const NodeSet &hard_evidence_nodes)
returns a fresh tensor equal to P(1st arg,evidence) without using schedules
_TensorSet_ _marginalizeOut_(_TensorSet_ 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...
Tensor< GUM_SCALAR > * _target_posterior_
the posterior computed during the last inference
void _createNewJT_(const NodeSet &targets)
create a new junction tree as well as its related data structures
Triangulation * _triangulation_
the triangulation class creating the junction tree used for inference
std::pair< _TensorSet_, _TensorSet_ > _collectMessage_(NodeId id, NodeId from)
perform the collect phase directly without schedules
_ScheduleMultiDimSet_ _collectMessage_(Schedule &schedule, NodeId id, NodeId from)
perform the collect phase using schedules
NodeId _targets2clique_
indicate a clique that contains all the nodes of the target
void onAllJointTargetsErased_() final
fired before all the joint targets are removed
void setRelevantTensorsFinderType(RelevantTensorsFinderType type)
sets how we determine the relevant tensors to combine
const GUM_SCALAR _one_minus_epsilon_
for comparisons with 1 - epsilon
Set< const IScheduleMultiDim * > _ScheduleMultiDimSet_
Tensor< GUM_SCALAR > * _unnormalizedJointPosterior_(const NodeSet &set, const NodeSet &targets, const NodeSet &hard_evidence_nodes)
returns a fresh tensor equal to P(1st arg,evidence) without using schedules
_ScheduleMultiDimSet_ _produceMessage_(Schedule &schedule, NodeId from_id, NodeId to_id, _ScheduleMultiDimSet_ &&incoming_messages)
creates the message sent by clique from_id to clique to_id using schedules
virtual void onModelChanged_(const GraphicalModel *bn) final
fired after a new Bayes net has been assigned to the inference engine
FindBarrenNodesType _barren_nodes_type_
the type of barren nodes computation we wish
VariableElimination< GUM_SCALAR > & operator=(const VariableElimination< GUM_SCALAR > &)=delete
avoid copy operators
Class for computing default triangulations of graphs.
Size NodeId
Type for node ids.
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
This file contains the abstract inference class definition for computing (incrementally) joint poster...
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
FindBarrenNodesType
type of algorithm to determine barren nodes
Set< const DiscreteVariable * > VariableSet
static INLINE Tensor< GUM_SCALAR > VENewprojTensor(const Tensor< GUM_SCALAR > &t1, const gum::VariableSet &del_vars)
static INLINE Tensor< GUM_SCALAR > VENewmultiTensor(const Tensor< GUM_SCALAR > &t1, const Tensor< GUM_SCALAR > &t2)
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...
the type of algorithm to use to perform relevant reasoning in Bayes net inference
The class enabling flexible inferences using schedules.
Implementation of Variable Elimination for inference in Bayesian networks.