aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
structuralComparator.cpp
Go to the documentation of this file.
1
/**
2
*
3
* Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4
* info_at_agrum_dot_org
5
*
6
* This library is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU Lesser General Public License as published by
8
* the Free Software Foundation, either version 3 of the License, or
9
* (at your option) any later version.
10
*
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public License
17
* along with this library. If not, see <http://www.gnu.org/licenses/>.
18
*
19
*/
20
21
22
#
include
<
agrum
/
BN
/
algorithms
/
structuralComparator
.
h
>
23
24
25
#
ifndef
DOXYGEN_SHOULD_SKIP_THIS
26
27
namespace
gum
{
28
StructuralComparator
::
StructuralComparator
() {
GUM_CONSTRUCTOR
(
StructuralComparator
); }
29
30
/// destructor
31
StructuralComparator
::~
StructuralComparator
() {
GUM_DESTRUCTOR
(
StructuralComparator
); }
32
33
void
StructuralComparator
::
compare
(
const
DiGraph
&
ref
,
const
DiGraph
&
test
) {
34
if
(
ref
.
size
() !=
test
.
size
()) {
GUM_ERROR
(
OperationNotAllowed
,
"Graphs of different sizes"
) }
35
for
(
const
NodeId
node
:
ref
.
asNodeSet
()) {
36
if
(!
test
.
existsNode
(
node
)) {
37
GUM_ERROR
(
InvalidNode
,
"Test doesn't contain all nodes from ref"
)
38
}
39
}
40
// compute the orientation matrix
41
// no edges so these stay null
42
_true_edge_
= 0;
43
_wrong_edge_arc_
= 0;
44
_wrong_edge_none_
= 0;
45
_wrong_arc_edge_
= 0;
46
_wrong_none_edge_
= 0;
47
// these will be filled
48
_true_arc_
= 0;
49
_true_none_
= 0;
50
_misoriented_arc_
= 0;
51
_wrong_arc_none_
= 0;
52
_wrong_none_arc_
= 0;
53
54
for
(
const
Arc
&
arc
:
ref
.
arcs
()) {
55
if
(
test
.
existsArc
(
arc
)) {
56
++
_true_arc_
;
57
}
else
if
(
test
.
existsArc
(
arc
.
head
(),
arc
.
tail
())) {
58
++
_misoriented_arc_
;
59
}
else
{
60
++
_wrong_none_arc_
;
61
}
62
}
63
for
(
const
Arc
&
arc
:
test
.
arcs
()) {
64
if
(!
ref
.
existsArc
(
arc
) && !
ref
.
existsArc
(
arc
.
head
(),
arc
.
tail
())) { ++
_wrong_arc_none_
; }
65
}
66
// TN = #possible arcs - #existing arcs
67
_true_none_
=
ref
.
size
() * (
ref
.
size
() - 1) -
_true_arc_
-
_misoriented_arc_
-
_wrong_arc_none_
68
-
_wrong_none_arc_
;
69
}
70
71
void
StructuralComparator
::
compare
(
const
UndiGraph
&
ref
,
const
UndiGraph
&
test
) {
72
if
(
ref
.
size
() !=
test
.
size
()) {
GUM_ERROR
(
OperationNotAllowed
,
"Graphs of different sizes"
) }
73
for
(
const
NodeId
node
:
ref
.
asNodeSet
()) {
74
if
(!
test
.
existsNode
(
node
)) {
75
GUM_ERROR
(
InvalidNode
,
"Test doesn't contain all nodes from ref"
)
76
}
77
}
78
// compute the orientation matrix
79
// no arcs so these stay null
80
_true_arc_
= 0;
81
_misoriented_arc_
= 0;
82
_wrong_arc_none_
= 0;
83
_wrong_none_arc_
= 0;
84
_wrong_edge_arc_
= 0;
85
_wrong_arc_edge_
= 0;
86
// these will be filled
87
_true_edge_
= 0;
88
_true_none_
= 0;
89
_wrong_edge_none_
= 0;
90
_wrong_none_edge_
= 0;
91
92
for
(
const
Edge
&
edge
:
ref
.
edges
()) {
93
if
(
test
.
existsEdge
(
edge
)) {
94
++
_true_edge_
;
95
}
else
{
96
++
_wrong_none_edge_
;
97
}
98
}
99
for
(
const
Edge
&
edge
:
test
.
edges
()) {
100
if
(!
ref
.
existsEdge
(
edge
)) { ++
_wrong_edge_none_
; }
101
}
102
// TN = #possible edges - #existing edges
103
_true_none_
104
=
ref
.
size
() * (
ref
.
size
() - 1) / 2 -
_true_edge_
-
_wrong_edge_none_
-
_wrong_none_edge_
;
105
}
106
107
void
StructuralComparator
::
compare
(
const
MixedGraph
&
ref
,
const
MixedGraph
&
test
) {
108
if
(
ref
.
size
() !=
test
.
size
()) {
GUM_ERROR
(
OperationNotAllowed
,
"Graphs of different sizes"
) }
109
for
(
const
NodeId
node
:
ref
.
asNodeSet
()) {
110
if
(!
test
.
existsNode
(
node
)) {
111
GUM_ERROR
(
InvalidNode
,
"Test doesn't contain all nodes from ref"
)
112
}
113
}
114
115
// compute the orientation matrix
116
_true_arc_
= 0;
117
_true_edge_
= 0;
118
_true_none_
= 0;
119
_misoriented_arc_
= 0;
120
_wrong_arc_edge_
= 0;
121
_wrong_arc_none_
= 0;
122
_wrong_edge_arc_
= 0;
123
_wrong_edge_none_
= 0;
124
_wrong_none_arc_
= 0;
125
_wrong_none_edge_
= 0;
126
127
for
(
const
Arc
&
arc
:
ref
.
arcs
()) {
128
if
(
test
.
existsArc
(
arc
)) {
129
++
_true_arc_
;
130
}
else
if
(
test
.
existsArc
(
arc
.
head
(),
arc
.
tail
())) {
131
++
_misoriented_arc_
;
132
}
else
if
(
test
.
existsEdge
(
arc
.
tail
(),
arc
.
head
())) {
133
++
_wrong_edge_arc_
;
134
}
else
{
135
++
_wrong_none_arc_
;
136
}
137
}
138
for
(
const
Edge
&
edge
:
ref
.
edges
()) {
139
if
(
test
.
existsEdge
(
edge
)) {
140
++
_true_edge_
;
141
}
else
if
(
test
.
existsArc
(
edge
.
first
(),
edge
.
second
())
142
||
test
.
existsArc
(
edge
.
second
(),
edge
.
first
())) {
143
++
_wrong_arc_edge_
;
144
}
else
{
145
++
_wrong_none_edge_
;
146
}
147
}
148
for
(
const
Arc
&
arc
:
test
.
arcs
()) {
149
if
(!
ref
.
existsArc
(
arc
) && !
ref
.
existsArc
(
arc
.
head
(),
arc
.
tail
())
150
&& !
ref
.
existsEdge
(
arc
.
tail
(),
arc
.
head
())) {
151
++
_wrong_arc_none_
;
152
}
153
}
154
for
(
const
Edge
&
edge
:
test
.
edges
()) {
155
if
(!
ref
.
existsEdge
(
edge
) && !
ref
.
existsArc
(
edge
.
first
(),
edge
.
second
())
156
&& !
ref
.
existsArc
(
edge
.
second
(),
edge
.
first
())) {
157
++
_wrong_edge_none_
;
158
}
159
}
160
// TN = #possible edges - #existing edges
161
_true_none_
=
ref
.
size
() * (
ref
.
size
() - 1) / 2 -
_true_edge_
-
_wrong_edge_none_
162
-
_wrong_none_edge_
-
_true_arc_
-
_misoriented_arc_
-
_wrong_arc_none_
163
-
_wrong_none_arc_
;
164
}
165
166
double
StructuralComparator
::
precision_skeleton
()
const
{
167
double
tp
,
fp
,
precision
;
168
tp
=
_true_arc_
+
_misoriented_arc_
+
_true_edge_
+
_wrong_edge_arc_
+
_wrong_arc_edge_
;
169
fp
=
_wrong_arc_none_
+
_wrong_edge_none_
;
170
precision
=
tp
/ (
tp
+
fp
);
171
return
precision
;
172
}
173
174
double
StructuralComparator
::
recall_skeleton
()
const
{
175
double
tp
,
fn
,
recall
;
176
tp
=
_true_arc_
+
_misoriented_arc_
+
_true_edge_
+
_wrong_edge_arc_
+
_wrong_arc_edge_
;
177
fn
=
_wrong_none_arc_
+
_wrong_none_edge_
;
178
recall
=
tp
/ (
tp
+
fn
);
179
return
recall
;
180
}
181
182
double
StructuralComparator
::
f_score_skeleton
()
const
{
183
double
tp
,
fp
,
fn
,
precision
,
recall
,
f_score
;
184
tp
=
_true_arc_
+
_misoriented_arc_
+
_true_edge_
+
_wrong_edge_arc_
+
_wrong_arc_edge_
;
185
fp
=
_wrong_arc_none_
+
_wrong_edge_none_
;
186
fn
=
_wrong_none_arc_
+
_wrong_none_edge_
;
187
188
precision
=
tp
/ (
tp
+
fp
);
189
recall
=
tp
/ (
tp
+
fn
);
190
f_score
= 2 *
precision
*
recall
/ (
precision
+
recall
);
191
return
f_score
;
192
}
193
194
double
StructuralComparator
::
precision
()
const
{
195
double
tp
,
fp
,
precision
;
196
tp
=
_true_arc_
+
_true_edge_
;
197
fp
=
_wrong_edge_arc_
+
_wrong_arc_edge_
+
_wrong_arc_none_
+
_wrong_edge_none_
198
+
_misoriented_arc_
;
199
precision
=
tp
/ (
tp
+
fp
);
200
return
precision
;
201
}
202
203
double
StructuralComparator
::
recall
()
const
{
204
double
tp
,
fn
,
recall
;
205
tp
=
_true_arc_
+
_true_edge_
;
206
fn
=
_wrong_none_arc_
+
_wrong_none_edge_
;
207
recall
=
tp
/ (
tp
+
fn
);
208
return
recall
;
209
}
210
211
double
StructuralComparator
::
f_score
()
const
{
212
double
tp
,
fp
,
fn
,
precision
,
recall
,
f_score
;
213
tp
=
_true_arc_
+
_true_edge_
;
214
fp
=
_wrong_edge_arc_
+
_wrong_arc_edge_
+
_wrong_arc_none_
+
_wrong_edge_none_
215
+
_misoriented_arc_
;
216
fn
=
_wrong_none_arc_
+
_wrong_none_edge_
;
217
218
precision
=
tp
/ (
tp
+
fp
);
219
recall
=
tp
/ (
tp
+
fn
);
220
221
f_score
= 2 *
precision
*
recall
/ (
precision
+
recall
);
222
return
f_score
;
223
}
224
225
}
/* namespace gum */
226
227
#
endif
/* DOXYGEN_SHOULD_SKIP_THIS */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:643