aGrUM
3.2.0
a C++ library for (probabilistic) graphical models
Toggle main menu visibility
dSeparationAlgorithm.cpp
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
48
49
#include <
agrum/base/core/list.h
>
50
#include <
agrum/BN/algorithms/dSeparationAlgorithm.h
>
51
52
#ifdef GUM_NO_INLINE
53
# include <
agrum/BN/algorithms/dSeparationAlgorithm_inl.h
>
54
#endif
// GUM_NO_INLINE
55
56
namespace
gum
{
57
58
// -------------------------------------------------------------------------
59
// Constructors, destructor and assignment operators are defined
60
// out-of-line (not INLINE) on purpose: see the comment in score.cpp for
61
// the MSVC LNK2005 rationale.
62
// -------------------------------------------------------------------------
63
64
// default constructor
65
dSeparationAlgorithm::dSeparationAlgorithm
() { GUM_CONSTRUCTOR(
dSeparationAlgorithm
); }
66
67
// copy constructor
68
dSeparationAlgorithm::dSeparationAlgorithm
(
const
dSeparationAlgorithm
& from) {
69
GUM_CONS_CPY(
dSeparationAlgorithm
);
70
}
71
72
// move constructor
73
dSeparationAlgorithm::dSeparationAlgorithm
(
dSeparationAlgorithm
&& from) {
74
GUM_CONS_MOV(
dSeparationAlgorithm
);
75
}
76
77
// destructor
78
dSeparationAlgorithm::~dSeparationAlgorithm
() { GUM_DESTRUCTOR(
dSeparationAlgorithm
); }
79
80
// copy operator
81
dSeparationAlgorithm
&
dSeparationAlgorithm::operator=
(
const
dSeparationAlgorithm
& from) =
default
;
82
83
// move operator
84
dSeparationAlgorithm
&
dSeparationAlgorithm::operator=
(
dSeparationAlgorithm
&& from) {
85
return
*
this
;
86
}
87
88
// Fill 'requisite' with the requisite nodes in dag given a query and
89
// evidence.
90
void
dSeparationAlgorithm::requisiteNodes
(
const
DAG
& dag,
91
const
NodeSet
& query,
92
const
NodeSet
& hardEvidence,
93
const
NodeSet
& softEvidence,
94
NodeSet
& requisite)
const
{
95
// for the moment, no node is requisite
96
requisite.
clear
();
97
98
// mark the set of ancestors of the evidence
99
NodeSet
ev_ancestors(dag.
size
());
100
{
101
List< NodeId >
anc_to_visit;
102
for
(
const
auto
node: hardEvidence)
103
anc_to_visit.
insert
(node);
104
for
(
const
auto
node: softEvidence)
105
anc_to_visit.
insert
(node);
106
while
(!anc_to_visit.
empty
()) {
107
const
NodeId
node = anc_to_visit.
front
();
108
anc_to_visit.
popFront
();
109
110
if
(!ev_ancestors.
exists
(node)) {
111
ev_ancestors.
insert
(node);
112
for
(
const
auto
par: dag.
parents
(node)) {
113
anc_to_visit.
insert
(par);
114
}
115
}
116
}
117
}
118
119
// create the marks indicating that we have visited a node
120
NodeSet
visited_from_child(dag.
size
());
121
NodeSet
visited_from_parent(dag.
size
());
122
123
// indicate that we will send the ball to all the query nodes (as children):
124
// in list nodes_to_visit, the first element is the next node to send the
125
// ball to and the Boolean indicates whether we shall reach it from one of
126
// its children (true) or from one parent (false)
127
List< std::pair< NodeId, bool >
> nodes_to_visit;
128
for
(
const
auto
node: query) {
129
nodes_to_visit.
insert
(std::pair< NodeId, bool >(node,
true
));
130
}
131
132
// perform the bouncing ball until there is no node in the graph to send
133
// the ball to
134
while
(!nodes_to_visit.
empty
()) {
135
// get the next node to visit
136
const
NodeId
node = nodes_to_visit.
front
().first;
137
const
bool
direction = nodes_to_visit.
front
().second;
138
nodes_to_visit.
popFront
();
139
140
// check if the node has not already been visited in the same direction
141
bool
already_visited;
142
if
(direction) {
143
already_visited = visited_from_child.
exists
(node);
144
if
(!already_visited) { visited_from_child.
insert
(node); }
145
}
else
{
146
already_visited = visited_from_parent.
exists
(node);
147
if
(!already_visited) { visited_from_parent.
insert
(node); }
148
}
149
150
// if this is the first time we meet the node, then visit it
151
if
(!already_visited) {
152
// mark the node as reachable if this is not a hard evidence
153
const
bool
is_hard_evidence = hardEvidence.
exists
(node);
154
if
(!is_hard_evidence) { requisite.
insert
(node); }
155
156
// bounce the ball toward the neighbors
157
if
(direction && !is_hard_evidence) {
// visit from a child
158
// visit the parents
159
for
(
const
auto
par: dag.
parents
(node)) {
160
nodes_to_visit.
insert
(std::pair< NodeId, bool >(par,
true
));
161
}
162
163
// visit the children
164
for
(
const
auto
chi: dag.
children
(node)) {
165
nodes_to_visit.
insert
(std::pair< NodeId, bool >(chi,
false
));
166
}
167
}
else
{
// visit from a parent
168
if
(!hardEvidence.
exists
(node)) {
169
// visit the children
170
for
(
const
auto
chi: dag.
children
(node)) {
171
nodes_to_visit.
insert
(std::pair< NodeId, bool >(chi,
false
));
172
}
173
}
174
if
(ev_ancestors.
exists
(node)) {
175
// visit the parents
176
for
(
const
auto
par: dag.
parents
(node)) {
177
nodes_to_visit.
insert
(std::pair< NodeId, bool >(par,
true
));
178
}
179
}
180
}
181
}
182
}
183
}
184
185
}
/* namespace gum */
gum::ArcGraphPart::parents
const NodeSet & parents(NodeId id) const
returns the set of nodes with arc ingoing to a given node
Definition
arcGraphPart_inl.h:76
gum::ArcGraphPart::children
NodeSet children(const NodeSet &ids) const
returns the set of nodes which consists in the node and its parents returns the set of children of a ...
Definition
arcGraphPart_inl.h:82
gum::DAG
Base class for dag.
Definition
DAG.h:121
gum::List
Generic doubly linked lists.
Definition
list.h:378
gum::List::front
Val & front() const
Returns a reference to first element of a list, if any.
Definition
list_tpl.h:1694
gum::List::insert
Val & insert(const Val &val)
Inserts a new element at the end of the chained list (alias of pushBack).
Definition
list_tpl.h:1508
gum::List::empty
bool empty() const noexcept
Returns a boolean indicating whether the chained list is empty.
Definition
list_tpl.h:1822
gum::List::popFront
void popFront()
Removes the first element of a List, if any.
Definition
list_tpl.h:1816
gum::NodeGraphPart::size
Size size() const
alias for sizeNodes
Definition
nodeGraphPart_inl.h:299
gum::Set::exists
bool exists(const Key &k) const
Indicates whether a given elements belong to the set.
Definition
set_tpl.h:504
gum::Set::clear
void clear()
Removes all the elements, if any, from the set.
Definition
set_tpl.h:315
gum::Set::insert
void insert(const Key &k)
Inserts a new element into the set.
Definition
set_tpl.h:510
gum::dSeparationAlgorithm
the d-separation algorithm as described in Koller & Friedman (2009)
Definition
dSeparationAlgorithm.h:63
gum::dSeparationAlgorithm::requisiteNodes
void requisiteNodes(const DAG &dag, const NodeSet &query, const NodeSet &hardEvidence, const NodeSet &softEvidence, NodeSet &requisite) const
Fill the 'requisite' nodeset with the requisite nodes in dag given a query and evidence.
Definition
dSeparationAlgorithm.cpp:90
gum::dSeparationAlgorithm::~dSeparationAlgorithm
~dSeparationAlgorithm()
destructor
Definition
dSeparationAlgorithm.cpp:78
gum::dSeparationAlgorithm::operator=
dSeparationAlgorithm & operator=(const dSeparationAlgorithm &from)
copy operator
gum::dSeparationAlgorithm::dSeparationAlgorithm
dSeparationAlgorithm()
default constructor
Definition
dSeparationAlgorithm.cpp:65
dSeparationAlgorithm.h
d-separation analysis (as described in Koller & Friedman 2009)
dSeparationAlgorithm_inl.h
d-separation analysis (as described in Koller & Friedman 2009)
gum::NodeId
Size NodeId
Type for node ids.
Definition
graphElements.h:117
gum::NodeSet
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
Definition
graphElements.h:392
list.h
Generic class for manipulating lists.
gum
gum is the global namespace for all aGrUM entities
Definition
agrum.h:46
aGrUM
3.2.0
© PHW&CG&others - 2022
DoXyGeN 1.18.0