45#ifndef DOXYGEN_SHOULD_SKIP_THIS
49 double _safeRatio_(
double numerator,
double denom) {
50 return (denom == 0.0) ? 0.0 : numerator / denom;
53 double _safeFScore_(
double precision,
double recall) {
54 return _safeRatio_(2 * precision * recall, precision + recall);
65 if (ref.size() != test.size()) {
GUM_ERROR(OperationNotAllowed,
"Graphs of different sizes") }
66 for (
const NodeId node: ref.asNodeSet()) {
67 if (!test.existsNode(node)) {
68 GUM_ERROR(InvalidNode,
"Test doesn't contain all nodes from ref")
86 for (
const Arc& arc: ref.arcs()) {
87 if (test.existsArc(arc)) {
89 }
else if (test.existsArc(arc.head(), arc.tail())) {
95 for (
const Arc& arc: test.arcs()) {
96 if (!ref.existsArc(arc) && !ref.existsArc(arc.head(), arc.tail())) { ++
_wrong_arc_none_; }
104 if (ref.size() != test.size()) {
GUM_ERROR(OperationNotAllowed,
"Graphs of different sizes") }
105 for (
const NodeId node: ref.asNodeSet()) {
106 if (!test.existsNode(node)) {
107 GUM_ERROR(InvalidNode,
"Test doesn't contain all nodes from ref")
125 for (
const Edge& edge: ref.edges()) {
126 if (test.existsEdge(edge)) {
132 for (
const Edge& edge: test.edges()) {
141 if (ref.size() != test.size()) {
GUM_ERROR(OperationNotAllowed,
"Graphs of different sizes") }
142 for (
const NodeId node: ref.asNodeSet()) {
143 if (!test.existsNode(node)) {
144 GUM_ERROR(InvalidNode,
"Test doesn't contain all nodes from ref")
161 for (
const Arc& arc: ref.arcs()) {
162 if (test.existsArc(arc)) {
164 }
else if (test.existsArc(arc.head(), arc.tail())) {
166 }
else if (test.existsEdge(arc.tail(), arc.head())) {
172 for (
const Edge& edge: ref.edges()) {
173 if (test.existsEdge(edge)) {
175 }
else if (test.existsArc(edge.first(), edge.second())
176 || test.existsArc(edge.second(), edge.first())) {
182 for (
const Arc& arc: test.arcs()) {
183 if (!ref.existsArc(arc) && !ref.existsArc(arc.head(), arc.tail())
184 && !ref.existsEdge(arc.tail(), arc.head())) {
188 for (
const Edge& edge: test.edges()) {
189 if (!ref.existsEdge(edge) && !ref.existsArc(edge.first(), edge.second())
190 && !ref.existsArc(edge.second(), edge.first())) {
250 if (ref.size() != test.size()) {
GUM_ERROR(OperationNotAllowed,
"Graphs of different sizes") }
251 for (
const NodeId node: ref.asNodeSet()) {
252 if (!test.existsNode(node)) {
253 GUM_ERROR(InvalidNode,
"test does not contain all nodes from ref")
259 for (
const NodeId i: ref.asNodeSet()) {
260 DE.insert(i, ref.descendants(i));
268 for (
const NodeId i: ref.asNodeSet()) {
269 const NodeSet& paG = ref.parents(i);
270 const NodeSet& paH = test.parents(i);
272 if (paG == paH)
continue;
274 for (
const NodeId j: ref.asNodeSet()) {
275 if (j == i)
continue;
277 const bool ijGNull = !DE[i].contains(j);
278 const bool ijHNull = paH.contains(j);
281 if (!ijGNull && ijHNull) {
286 if (ijGNull && ijHNull) {
continue; }
290 bool violated_2a =
false;
291 for (
const NodeId c: ref.children(i)) {
294 if (paH.contains(c)) {
298 for (
const NodeId z: paH) {
304 if (violated_2a)
break;
314 std::vector< NodeId > arcs_removed;
315 for (
const NodeId c: ref.children(i)) {
317 G.eraseArc(
Arc(i, c));
318 arcs_removed.push_back(c);
322 if (!G.dSeparation(i, j, paH)) { errors += 1; }
325 for (
const NodeId c: arcs_removed) {
Base class for all oriented graphs.
Base class for partially directed acyclic graphs.
double _wrong_edge_arc_
Confusion matrix.
StructuralMetrics()
default constructor
double fn_skeleton() const
Confusion matrix.
double tp() const
Measures for the graphs.
double _true_arc_
Confusion matrix.
double _misoriented_arc_
Confusion matrix.
double recall_skeleton() const
Confusion matrix.
double precision() const
Confusion matrix.
double shd_skeleton() const
Confusion matrix.
double recall() const
Confusion matrix.
double _wrong_edge_none_
Confusion matrix.
double fp() const
Confusion matrix.
double _wrong_arc_edge_
Confusion matrix.
double fn() const
Confusion matrix.
double _wrong_none_arc_
Confusion matrix.
double tn() const
Confusion matrix.
double fp_skeleton() const
Confusion matrix.
double precision_skeleton() const
Confusion matrix.
double f_score_skeleton() const
Confusion matrix.
double f_score() const
Confusion matrix.
double _wrong_arc_none_
Confusion matrix.
void compare(const DiGraph &ref, const DiGraph &test)
compare two DiGraphs (nodes matched by NodeId, no alignment)
double _true_edge_
Confusion matrix.
double _wrong_none_edge_
Confusion matrix.
~StructuralMetrics()
destructor
double _true_none_
Confusion matrix.
double sid(const DAG &ref, const DAG &test) const
Confusion matrix.
Size _size_
Number of nodes in the compared graphs (set by compare()).
double shd() const
Confusion matrix.
double tp_skeleton() const
Measures for the skeleton, aka graph without orientations.
double tn_skeleton() const
Confusion matrix.
Base class for undirected graphs.
#define GUM_ERROR(type, msg)
Size NodeId
Type for node ids.
HashTable< NodeId, VAL > NodeProperty
Property on graph elements.
Set< NodeId > NodeSet
Some typdefs and define for shortcuts ...
bool contains(std::string_view s, std::string_view needle)
true if needle in s
gum is the global namespace for all aGrUM entities
A class for comparing graphs based on their structures.