aGrUM
0.20.2
a C++ library for (probabilistic) graphical models
structuralComparator.cpp
Go to the documentation of this file.
1
/**
2
*
3
* Copyright 2005-2020 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
() {
29
GUM_CONSTRUCTOR
(
StructuralComparator
);
30
}
31
32
/// destructor
33
StructuralComparator
::~
StructuralComparator
() {
34
GUM_DESTRUCTOR
(
StructuralComparator
);
35
}
36
37
void
StructuralComparator
::
compare
(
const
DiGraph
&
ref
,
const
DiGraph
&
test
) {
38
if
(
ref
.
size
() !=
test
.
size
()) {
39
GUM_ERROR
(
OperationNotAllowed
,
"Graphs of different sizes"
);
40
}
41
for
(
const
NodeId
node
:
ref
.
asNodeSet
()) {
42
if
(!
test
.
existsNode
(
node
)) {
43
GUM_ERROR
(
InvalidNode
,
"Test doesn't contain all nodes from ref"
);
44
}
45
}
46
// compute the orientation matrix
47
// no edges so these stay null
48
true_edge__
= 0;
49
wrong_edge_arc__
= 0;
50
wrong_edge_none__
= 0;
51
wrong_arc_edge__
= 0;
52
wrong_none_edge__
= 0;
53
// these will be filled
54
true_arc__
= 0;
55
true_none__
= 0;
56
misoriented_arc__
= 0;
57
wrong_arc_none__
= 0;
58
wrong_none_arc__
= 0;
59
60
for
(
const
Arc
&
arc
:
ref
.
arcs
()) {
61
if
(
test
.
existsArc
(
arc
)) {
62
++
true_arc__
;
63
}
else
if
(
test
.
existsArc
(
arc
.
head
(),
arc
.
tail
())) {
64
++
misoriented_arc__
;
65
}
else
{
66
++
wrong_none_arc__
;
67
}
68
}
69
for
(
const
Arc
&
arc
:
test
.
arcs
()) {
70
if
(!
ref
.
existsArc
(
arc
) && !
ref
.
existsArc
(
arc
.
head
(),
arc
.
tail
())) {
71
++
wrong_arc_none__
;
72
}
73
}
74
// TN = #possible arcs - #existing arcs
75
true_none__
=
ref
.
size
() * (
ref
.
size
() - 1) -
true_arc__
-
misoriented_arc__
76
-
wrong_arc_none__
-
wrong_none_arc__
;
77
}
78
79
void
StructuralComparator
::
compare
(
const
UndiGraph
&
ref
,
const
UndiGraph
&
test
) {
80
if
(
ref
.
size
() !=
test
.
size
()) {
81
GUM_ERROR
(
OperationNotAllowed
,
"Graphs of different sizes"
);
82
}
83
for
(
const
NodeId
node
:
ref
.
asNodeSet
()) {
84
if
(!
test
.
existsNode
(
node
)) {
85
GUM_ERROR
(
InvalidNode
,
"Test doesn't contain all nodes from ref"
);
86
}
87
}
88
// compute the orientation matrix
89
// no arcs so these stay null
90
true_arc__
= 0;
91
misoriented_arc__
= 0;
92
wrong_arc_none__
= 0;
93
wrong_none_arc__
= 0;
94
wrong_edge_arc__
= 0;
95
wrong_arc_edge__
= 0;
96
// these will be filled
97
true_edge__
= 0;
98
true_none__
= 0;
99
wrong_edge_none__
= 0;
100
wrong_none_edge__
= 0;
101
102
for
(
const
Edge
&
edge
:
ref
.
edges
()) {
103
if
(
test
.
existsEdge
(
edge
)) {
104
++
true_edge__
;
105
}
else
{
106
++
wrong_none_edge__
;
107
}
108
}
109
for
(
const
Edge
&
edge
:
test
.
edges
()) {
110
if
(!
ref
.
existsEdge
(
edge
)) { ++
wrong_edge_none__
; }
111
}
112
// TN = #possible edges - #existing edges
113
true_none__
=
ref
.
size
() * (
ref
.
size
() - 1) / 2 -
true_edge__
114
-
wrong_edge_none__
-
wrong_none_edge__
;
115
}
116
117
void
StructuralComparator
::
compare
(
const
MixedGraph
&
ref
,
118
const
MixedGraph
&
test
) {
119
if
(
ref
.
size
() !=
test
.
size
()) {
120
GUM_ERROR
(
OperationNotAllowed
,
"Graphs of different sizes"
);
121
}
122
for
(
const
NodeId
node
:
ref
.
asNodeSet
()) {
123
if
(!
test
.
existsNode
(
node
)) {
124
GUM_ERROR
(
InvalidNode
,
"Test doesn't contain all nodes from ref"
);
125
}
126
}
127
128
// compute the orientation matrix
129
true_arc__
= 0;
130
true_edge__
= 0;
131
true_none__
= 0;
132
misoriented_arc__
= 0;
133
wrong_arc_edge__
= 0;
134
wrong_arc_none__
= 0;
135
wrong_edge_arc__
= 0;
136
wrong_edge_none__
= 0;
137
wrong_none_arc__
= 0;
138
wrong_none_edge__
= 0;
139
140
for
(
const
Arc
&
arc
:
ref
.
arcs
()) {
141
if
(
test
.
existsArc
(
arc
)) {
142
++
true_arc__
;
143
}
else
if
(
test
.
existsArc
(
arc
.
head
(),
arc
.
tail
())) {
144
++
misoriented_arc__
;
145
}
else
if
(
test
.
existsEdge
(
arc
.
tail
(),
arc
.
head
())) {
146
++
wrong_edge_arc__
;
147
}
else
{
148
++
wrong_none_arc__
;
149
}
150
}
151
for
(
const
Edge
&
edge
:
ref
.
edges
()) {
152
if
(
test
.
existsEdge
(
edge
)) {
153
++
true_edge__
;
154
}
else
if
(
test
.
existsArc
(
edge
.
first
(),
edge
.
second
())
155
||
test
.
existsArc
(
edge
.
second
(),
edge
.
first
())) {
156
++
wrong_arc_edge__
;
157
}
else
{
158
++
wrong_none_edge__
;
159
}
160
}
161
for
(
const
Arc
&
arc
:
test
.
arcs
()) {
162
if
(!
ref
.
existsArc
(
arc
) && !
ref
.
existsArc
(
arc
.
head
(),
arc
.
tail
())
163
&& !
ref
.
existsEdge
(
arc
.
tail
(),
arc
.
head
())) {
164
++
wrong_arc_none__
;
165
}
166
}
167
for
(
const
Edge
&
edge
:
test
.
edges
()) {
168
if
(!
ref
.
existsEdge
(
edge
) && !
ref
.
existsArc
(
edge
.
first
(),
edge
.
second
())
169
&& !
ref
.
existsArc
(
edge
.
second
(),
edge
.
first
())) {
170
++
wrong_edge_none__
;
171
}
172
}
173
// TN = #possible edges - #existing edges
174
true_none__
=
ref
.
size
() * (
ref
.
size
() - 1) / 2 -
true_edge__
175
-
wrong_edge_none__
-
wrong_none_edge__
-
true_arc__
176
-
misoriented_arc__
-
wrong_arc_none__
-
wrong_none_arc__
;
177
}
178
179
double
StructuralComparator
::
precision_skeleton
()
const
{
180
double
tp
,
fp
,
precision
;
181
tp
=
true_arc__
+
misoriented_arc__
+
true_edge__
+
wrong_edge_arc__
182
+
wrong_arc_edge__
;
183
fp
=
wrong_arc_none__
+
wrong_edge_none__
;
184
precision
=
tp
/ (
tp
+
fp
);
185
return
precision
;
186
}
187
188
double
StructuralComparator
::
recall_skeleton
()
const
{
189
double
tp
,
fn
,
recall
;
190
tp
=
true_arc__
+
misoriented_arc__
+
true_edge__
+
wrong_edge_arc__
191
+
wrong_arc_edge__
;
192
fn
=
wrong_none_arc__
+
wrong_none_edge__
;
193
recall
=
tp
/ (
tp
+
fn
);
194
return
recall
;
195
}
196
197
double
StructuralComparator
::
f_score_skeleton
()
const
{
198
double
tp
,
fp
,
fn
,
precision
,
recall
,
f_score
;
199
tp
=
true_arc__
+
misoriented_arc__
+
true_edge__
+
wrong_edge_arc__
200
+
wrong_arc_edge__
;
201
fp
=
wrong_arc_none__
+
wrong_edge_none__
;
202
fn
=
wrong_none_arc__
+
wrong_none_edge__
;
203
204
precision
=
tp
/ (
tp
+
fp
);
205
recall
=
tp
/ (
tp
+
fn
);
206
f_score
= 2 *
precision
*
recall
/ (
precision
+
recall
);
207
return
f_score
;
208
}
209
210
double
StructuralComparator
::
precision
()
const
{
211
double
tp
,
fp
,
precision
;
212
tp
=
true_arc__
+
true_edge__
;
213
fp
=
wrong_edge_arc__
+
wrong_arc_edge__
+
wrong_arc_none__
+
wrong_edge_none__
214
+
misoriented_arc__
;
215
precision
=
tp
/ (
tp
+
fp
);
216
return
precision
;
217
}
218
219
double
StructuralComparator
::
recall
()
const
{
220
double
tp
,
fn
,
recall
;
221
tp
=
true_arc__
+
true_edge__
;
222
fn
=
wrong_none_arc__
+
wrong_none_edge__
;
223
recall
=
tp
/ (
tp
+
fn
);
224
return
recall
;
225
}
226
227
double
StructuralComparator
::
f_score
()
const
{
228
double
tp
,
fp
,
fn
,
precision
,
recall
,
f_score
;
229
tp
=
true_arc__
+
true_edge__
;
230
fp
=
wrong_edge_arc__
+
wrong_arc_edge__
+
wrong_arc_none__
+
wrong_edge_none__
231
+
misoriented_arc__
;
232
fn
=
wrong_none_arc__
+
wrong_none_edge__
;
233
234
precision
=
tp
/ (
tp
+
fp
);
235
recall
=
tp
/ (
tp
+
fn
);
236
237
f_score
= 2 *
precision
*
recall
/ (
precision
+
recall
);
238
return
f_score
;
239
}
240
241
}
/* namespace gum */
242
243
#
endif
/* DOXYGEN_SHOULD_SKIP_THIS */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:669