Direct Graphical Models  v.1.7.0
GraphPairwise.cpp
1 #include "GraphPairwise.h"
2 #include "macroses.h"
3 
4 namespace DirectGraphicalModels
5 {
7  {
8  m_vNodes.clear();
9  m_vEdges.clear();
10  m_IDx = 0;
11  }
12 
13  // Add a new node to the graph with specified potentional
14  size_t CGraphPairwise::addNode(const Mat &pot)
15  {
16  m_vNodes.push_back(ptr_node_t(new Node(m_IDx, pot)));
17  return m_IDx++;
18  }
19 
20  // Set or change the potential of node idx
21  void CGraphPairwise::setNode(size_t node, const Mat &pot)
22  {
23  DGM_ASSERT_MSG(node < m_vNodes.size(), "Node %zu is out of range %zu", node, m_vNodes.size());
24  DGM_ASSERT_MSG((pot.cols == 1) && (pot.rows == getNumStates()), "Potential size (%d x %d) does not match (%d x %d)", pot.cols, pot.rows, 1, getNumStates());
25 
26  if (!m_vNodes[node]->Pot.empty()) m_vNodes[node]->Pot.release();
27  pot.copyTo(m_vNodes[node]->Pot);
28  }
29 
30  // Return node potential vector
31  void CGraphPairwise::getNode(size_t node, Mat &pot) const
32  {
33  DGM_ASSERT_MSG(node < m_vNodes.size(), "Node %zu is out of range %zu", node, m_vNodes.size());
34  DGM_ASSERT_MSG(!m_vNodes[node]->Pot.empty(), "Specified node %zu is not set", node);
35  m_vNodes[node]->Pot.copyTo(pot);
36  }
37 
38  // Return child nodes ID's
39  void CGraphPairwise::getChildNodes(size_t node, vec_size_t &vNodes) const
40  {
41  DGM_ASSERT_MSG(node < getNumNodes(), "Node %zu is out of range %zu", node, getNumNodes());
42  if (!vNodes.empty()) vNodes.clear();
43  for (size_t e: m_vNodes[node]->to) { vNodes.push_back(m_vEdges[e]->node2); }
44  }
45 
46  // Return parent nodes ID's
47  void CGraphPairwise::getParentNodes(size_t node, vec_size_t &vNodes) const
48  {
49  DGM_ASSERT_MSG(node < getNumNodes(), "Node %zu is out of range %zu", node, getNumNodes());
50  if (!vNodes.empty()) vNodes.clear();
51  for (size_t e: m_vNodes[node]->from) { vNodes.push_back(m_vEdges[e]->node1); }
52  }
53 
54 
55  // Add a new (directed) edge to the graph with specified potentional
56  void CGraphPairwise::addEdge(size_t srcNode, size_t dstNode, byte group, const Mat &pot)
57  {
58  DGM_ASSERT_MSG(srcNode < m_vNodes.size(), "The source node index %zu is out of range %zu", srcNode, m_vNodes.size());
59  DGM_ASSERT_MSG(dstNode < m_vNodes.size(), "The destination node index %zu is out of range %zu", dstNode, m_vNodes.size());
60 
61  // Check if the edge exists
62  if (m_vNodes[srcNode]->to.size() < m_vNodes[dstNode]->from.size())
63  for (size_t &e : m_vNodes[srcNode]->to) { DGM_ASSERT(m_vEdges[e]->node2 != dstNode); }
64  else
65  for (size_t &e : m_vNodes[dstNode]->from) { DGM_ASSERT(m_vEdges[e]->node1 != srcNode); }
66 
67  // Else: create a new one
68  size_t e = m_vEdges.size();
69  m_vEdges.push_back(ptr_edge_t(new Edge(srcNode, dstNode, group, pot)));
70  m_vNodes[srcNode]->to.push_back(e);
71  m_vNodes[dstNode]->from.push_back(e);
72  }
73 
74  // Set or change the potentional of an directed edge
75  void CGraphPairwise::setEdge(size_t srcNode, size_t dstNode, const Mat &pot)
76  {
77  DGM_ASSERT_MSG(srcNode < m_vNodes.size(), "The source node index %zu is out of range %zu", srcNode, m_vNodes.size());
78  DGM_ASSERT_MSG(dstNode < m_vNodes.size(), "The destination node index %zu is out of range %zu", dstNode, m_vNodes.size());
79 
80  vec_size_t::const_iterator e_t = std::find_if(m_vNodes[srcNode]->to.cbegin(), m_vNodes[srcNode]->to.cend(), [&](size_t e) { return (m_vEdges[e]->node2 == dstNode); });
81  DGM_ASSERT_MSG(e_t != m_vNodes[srcNode]->to.end(), "The edge (%zu)->(%zu) is not found", srcNode, dstNode);
82 
83  pot.copyTo(m_vEdges[*e_t]->Pot);
84  }
85 
86  void CGraphPairwise::setEdges(std::optional<byte> group, const Mat& pot)
87  {
88 #ifdef ENABLE_PPL
89  size_t size = m_vEdges.size();
90  size_t rangeSize = size / (concurrency::GetProcessorCount() * 10);
91  rangeSize = MAX(1, rangeSize);
92  //printf("Processors: %d\n", concurrency::GetProcessorCount());
93  concurrency::parallel_for(size_t(0), size, rangeSize, [group, &pot, size, rangeSize, this](size_t i) {
94  for (int j = 0; (j < rangeSize) && (i + j < size); j++) {
95  ptr_edge_t& pEdge = m_vEdges[i + j];
96  if (!group || pEdge->group_id == group.value())
97  pot.copyTo(pEdge->Pot);
98  }
99  });
100 #else
101  for (ptr_edge_t& pEdge : m_vEdges) {
102  if(!group || pEdge->group_id == group.value())
103  pot.copyTo(pEdge->Pot);
104  }
105 #endif
106  }
107 
108  // Return edge potential matrix
109  void CGraphPairwise::getEdge(size_t srcNode, size_t dstNode, Mat &pot) const
110  {
111  DGM_ASSERT_MSG(srcNode < m_vNodes.size(), "The source node index %zu is out of range %zu", srcNode, m_vNodes.size());
112  DGM_ASSERT_MSG(dstNode < m_vNodes.size(), "The destination node index %zu is out of range %zu", dstNode, m_vNodes.size());
113 
114  vec_size_t::const_iterator e_t = std::find_if(m_vNodes[srcNode]->to.cbegin(), m_vNodes[srcNode]->to.cend(), [&](size_t e) { return (m_vEdges[e]->node2 == dstNode); });
115  DGM_ASSERT_MSG(e_t != m_vNodes[srcNode]->to.end(), "The edge (%zu)->(%zu) is not found", srcNode, dstNode);
116  if (m_vEdges[*e_t]->Pot.empty()) {
117  DGM_WARNING("Edge Potential is empty");
118  if (!pot.empty()) pot.release();
119  } else m_vEdges[*e_t]->Pot.copyTo(pot);
120  }
121 
122  void CGraphPairwise::setEdgeGroup(size_t srcNode, size_t dstNode, byte group)
123  {
124  DGM_ASSERT_MSG(srcNode < m_vNodes.size(), "The source node index %zu is out of range %zu", srcNode, m_vNodes.size());
125  DGM_ASSERT_MSG(dstNode < m_vNodes.size(), "The destination node index %zu is out of range %zu", dstNode, m_vNodes.size());
126 
127  vec_size_t::const_iterator e_t = std::find_if(m_vNodes[srcNode]->to.cbegin(), m_vNodes[srcNode]->to.cend(), [&](size_t e) { return (m_vEdges[e]->node2 == dstNode); });
128  DGM_ASSERT_MSG(e_t != m_vNodes[srcNode]->to.end(), "The edge (%zu)->(%zu) is not found", srcNode, dstNode);
129  m_vEdges[*e_t]->group_id = group;
130  }
131 
132  byte CGraphPairwise::getEdgeGroup(size_t srcNode, size_t dstNode) const
133  {
134  DGM_ASSERT_MSG(srcNode < m_vNodes.size(), "The source node index %zu is out of range %zu", srcNode, m_vNodes.size());
135  DGM_ASSERT_MSG(dstNode < m_vNodes.size(), "The destination node index %zu is out of range %zu", dstNode, m_vNodes.size());
136 
137  vec_size_t::const_iterator e_t = std::find_if(m_vNodes[srcNode]->to.cbegin(), m_vNodes[srcNode]->to.cend(), [&](size_t e) { return (m_vEdges[e]->node2 == dstNode); });
138  DGM_ASSERT_MSG(e_t != m_vNodes[srcNode]->to.end(), "The edge (%zu)->(%zu) is not found", srcNode, dstNode);
139 
140  return m_vEdges[*e_t]->group_id;
141  }
142 
143  void CGraphPairwise::removeEdge(size_t srcNode, size_t dstNode)
144  {
145  DGM_ASSERT_MSG(srcNode < m_vNodes.size(), "The source node index %zu is out of range %zu", srcNode, m_vNodes.size());
146  DGM_ASSERT_MSG(dstNode < m_vNodes.size(), "The destination node index %zu is out of range %zu", dstNode, m_vNodes.size());
147 
148  vec_size_t::const_iterator e_t = std::find_if(m_vNodes[srcNode]->to.cbegin(), m_vNodes[srcNode]->to.cend(), [&](size_t e) { return (m_vEdges[e]->node2 == dstNode); });
149 
150  DGM_ASSERT_MSG(e_t != m_vNodes[srcNode]->to.end(), "The edge (%zu)->(%zu) is not found", srcNode, dstNode);
151 
152  removeEdge(*e_t);
153  }
154 
155  bool CGraphPairwise::isEdgeExists(size_t srcNode, size_t dstNode) const
156  {
157  DGM_ASSERT_MSG(srcNode < m_vNodes.size(), "The source node index %zu is out of range %zu", srcNode, m_vNodes.size());
158  DGM_ASSERT_MSG(dstNode < m_vNodes.size(), "The destination node index %zu is out of range %zu", dstNode, m_vNodes.size());
159 
160  auto e_t = std::find_if(m_vNodes[srcNode]->to.cbegin(), m_vNodes[srcNode]->to.cend(), [&](size_t e) { return (m_vEdges[e]->node2 == dstNode); });
161 
162  if (e_t == m_vNodes[srcNode]->to.cend()) return false;
163  else return true;
164  }
165 
166 
167  // ------------------------------ PRIVATE ------------------------------
169  void CGraphPairwise::removeEdge(size_t edge)
170  {
171  DGM_ASSERT_MSG(edge < m_vEdges.size(), "Edge %zu is out of range %zu", edge, m_vEdges.size());
172 
173  size_t srcNode = m_vEdges[edge]->node1;
174  size_t dstNode = m_vEdges[edge]->node2;
175 
176  m_vEdges[edge]->Pot.release();
177  //m_vEdges.erase(m_vEdges.begin() + edge);
178 
179  vec_size_t::const_iterator e_t = std::find(m_vNodes[srcNode]->to.cbegin(), m_vNodes[srcNode]->to.cend(), edge);
180  DGM_ASSERT(e_t != m_vNodes[srcNode]->to.cend());
181  m_vNodes[srcNode]->to.erase(e_t);
182 
183  vec_size_t::const_iterator e_f = std::find(m_vNodes[dstNode]->from.cbegin(), m_vNodes[dstNode]->from.cend(), edge);
184  DGM_ASSERT(e_f != m_vNodes[dstNode]->from.cend());
185  m_vNodes[dstNode]->from.erase(e_f);
186  }
187 }
188 
void setEdges(std::optional< byte > group, const Mat &pot) override
Sets the potential pot to all edges belonging to group group.
void removeEdge(size_t srcNode, size_t dstNode) override
Removes the specified edge.
void addEdge(size_t srcNode, size_t dstNode, byte group, const Mat &pot) override
Adds an additional directed edge with specified potentional.
byte getNumStates(void) const
Returns number of states (classes)
Definition: Graph.h:99
void setNode(size_t node, const Mat &pot) override
Sets or changes the potential of node.
byte getEdgeGroup(size_t srcNode, size_t dstNode) const override
Returns the group of the edge.
void setEdgeGroup(size_t srcNode, size_t dstNode, byte group) override
Assigns a directed edge (srcNode) –> (dstNode) to the group group.
void reset(void) override
Resets the graph.
bool isEdgeExists(size_t srcNode, size_t dstNode) const override
Checks whether the edge exists.
size_t getNumNodes(void) const override
Returns the number of nodes in the graph.
Definition: GraphPairwise.h:89
std::unique_ptr< Node > ptr_node_t
Definition: GraphPairwise.h:24
void getChildNodes(size_t node, vec_size_t &vNodes) const override
Returns the set of IDs of the child nodes of the argument node.
void getParentNodes(size_t node, vec_size_t &vNodes) const override
Returns the set of IDs of the parent nodes of the argument node.
void getNode(size_t node, Mat &pot) const override
Returns the node potential.
void setEdge(size_t srcNode, size_t dstNode, const Mat &pot) override
Sets or changes the potentional of directed edge.
std::unique_ptr< Edge > ptr_edge_t
Definition: GraphPairwise.h:55
void getEdge(size_t srcNode, size_t dstNode, Mat &pot) const override
Returns the edge potential.
size_t addNode(const Mat &pot=EmptyMat) override
Adds an additional node (with specified potentional)