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 {
30  }
31 
32  /// destructor
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;
51  wrong_arc_edge__ = 0;
53  // these will be filled
54  true_arc__ = 0;
55  true_none__ = 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())) {
65  } else {
67  }
68  }
69  for (const Arc& arc: test.arcs()) {
70  if (!ref.existsArc(arc) && !ref.existsArc(arc.head(), arc.tail())) {
72  }
73  }
74  // TN = #possible arcs - #existing arcs
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;
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;
100  wrong_none_edge__ = 0;
101 
102  for (const Edge& edge: ref.edges()) {
103  if (test.existsEdge(edge)) {
104  ++true_edge__;
105  } else {
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__
115  }
116 
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())) {
145  } else if (test.existsEdge(arc.tail(), arc.head())) {
147  } else {
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())) {
157  } else {
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())) {
165  }
166  }
167  for (const Edge& edge: test.edges()) {
169  && !ref.existsArc(edge.second(), edge.first())) {
171  }
172  }
173  // TN = #possible edges - #existing edges
174  true_none__ = ref.size() * (ref.size() - 1) / 2 - true_edge__
177  }
178 
179  double StructuralComparator::precision_skeleton() const {
180  double tp, fp, precision;
184  precision = tp / (tp + fp);
185  return precision;
186  }
187 
188  double StructuralComparator::recall_skeleton() const {
189  double tp, fn, recall;
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;
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;
215  precision = tp / (tp + fp);
216  return precision;
217  }
218 
219  double StructuralComparator::recall() const {
220  double tp, fn, recall;
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;
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 */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669