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 {
29 
30  /// destructor
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;
45  _wrong_arc_edge_ = 0;
47  // these will be filled
48  _true_arc_ = 0;
49  _true_none_ = 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())) {
59  } else {
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
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;
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;
91 
92  for (const Edge& edge: ref.edges()) {
93  if (test.existsEdge(edge)) {
94  ++_true_edge_;
95  } else {
97  }
98  }
99  for (const Edge& edge: test.edges()) {
100  if (!ref.existsEdge(edge)) { ++_wrong_edge_none_; }
101  }
102  // TN = #possible edges - #existing edges
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())) {
132  } else if (test.existsEdge(arc.tail(), arc.head())) {
134  } else {
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())) {
144  } else {
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())) {
152  }
153  }
154  for (const Edge& edge: test.edges()) {
156  && !ref.existsArc(edge.second(), edge.first())) {
158  }
159  }
160  // TN = #possible edges - #existing edges
164  }
165 
166  double StructuralComparator::precision_skeleton() const {
167  double tp, fp, precision;
170  precision = tp / (tp + fp);
171  return precision;
172  }
173 
174  double StructuralComparator::recall_skeleton() const {
175  double tp, fn, recall;
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;
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;
199  precision = tp / (tp + fp);
200  return precision;
201  }
202 
203  double StructuralComparator::recall() const {
204  double tp, fn, recall;
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;
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 */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643