CMS 3D CMS Logo

GraphMap.cc
Go to the documentation of this file.
3 
4 #include <iostream>
5 #include <iomanip>
6 
7 using namespace reco;
8 
9 GraphMap::GraphMap(uint nNodes) : nNodes_(nNodes) {
10  // One entry for node in the edges_ list
11  edgesIn_.resize(nNodes);
12  edgesOut_.resize(nNodes);
13 }
14 
16  nodesCategories_[category].push_back(index);
17  nodesCount_[category] += 1;
18 }
19 
20 void GraphMap::addNodes(const std::vector<uint> &indices, const std::vector<NodeCategory> &categories) {
21  for (size_t i = 0; i < indices.size(); i++) {
23  }
24 }
25 
26 void GraphMap::addEdge(const uint i, const uint j) {
27  // The first index is the starting node of the outcoming edge.
28  edgesOut_.at(i).push_back(j);
29  edgesIn_.at(j).push_back(i);
30  // Adding a connection in the adjacency matrix only in one direction
31  adjMatrix_[{i, j}] = 1.;
32 }
33 
34 void GraphMap::setAdjMatrix(const uint i, const uint j, const float score) { adjMatrix_[{i, j}] = score; };
35 
36 void GraphMap::setAdjMatrixSym(const uint i, const uint j, const float score) {
37  adjMatrix_[{i, j}] = score;
38  adjMatrix_[{j, i}] = score;
39 };
40 
41 const std::vector<uint> &GraphMap::getOutEdges(const uint i) const { return edgesOut_.at(i); };
42 
43 const std::vector<uint> &GraphMap::getInEdges(const uint i) const { return edgesIn_.at(i); };
44 
45 uint GraphMap::getAdjMatrix(const uint i, const uint j) const { return adjMatrix_.at({i, j}); };
46 
47 std::vector<float> GraphMap::getAdjMatrixRow(const uint i) const {
48  std::vector<float> out;
49  for (const auto &j : getOutEdges(i)) {
50  out.push_back(adjMatrix_.at({i, j}));
51  }
52  return out;
53 };
54 
55 std::vector<float> GraphMap::getAdjMatrixCol(const uint j) const {
56  std::vector<float> out;
57  for (const auto &i : getInEdges(j)) {
58  out.push_back(adjMatrix_.at({i, j}));
59  }
60  return out;
61 };
62 
63 //=================================================
64 // Debugging info
66  edm::LogVerbatim("GraphMap") << "OUT edges" << std::endl;
67  uint seed = 0;
68  for (const auto &s : edgesOut_) {
69  edm::LogVerbatim("GraphMap") << "cl: " << seed << " --> ";
70  for (const auto &e : s) {
71  edm::LogVerbatim("GraphMap") << e << " (" << adjMatrix_[{seed, e}] << ") ";
72  }
73  edm::LogVerbatim("GraphMap") << std::endl;
74  seed++;
75  }
76  edm::LogVerbatim("GraphMap") << std::endl << "IN edges" << std::endl;
77  seed = 0;
78  for (const auto &s : edgesIn_) {
79  edm::LogVerbatim("GraphMap") << "cl: " << seed << " <-- ";
80  for (const auto &e : s) {
81  edm::LogVerbatim("GraphMap") << e << " (" << adjMatrix_[{e, seed}] << ") ";
82  }
83  edm::LogVerbatim("GraphMap") << std::endl;
84  seed++;
85  }
86  edm::LogVerbatim("GraphMap") << std::endl << "AdjMatrix" << std::endl;
87  for (const auto &s : nodesCategories_[NodeCategory::kSeed]) {
88  for (size_t n = 0; n < nNodes_; n++) {
89  edm::LogVerbatim("GraphMap") << std::setprecision(2) << adjMatrix_[{s, n}] << " ";
90  }
91  edm::LogVerbatim("GraphMap") << std::endl;
92  }
93 }
94 
95 //--------------------------------------------------------------
96 // Nodes collection algorithms
98  // Clear any stored graph output
99  graphOutput_.clear();
100 
101  if (strategy == GraphMap::CollectionStrategy::Cascade) {
102  // Starting from the highest energy seed, collect all the nodes.
103  // Other seeds collected by higher energy seeds are ignored
105  } else if (strategy == GraphMap::CollectionStrategy::CollectAndMerge) {
106  // First, for each simple node (no seed) keep only the edge with the highest score.
107  // Then collect all the simple nodes around the seeds.
108  // Edges between the seed are ignored.
109  // Finally, starting from the first seed (highest pt), look for linked secondary seed
110  // and if they pass the threshold, merge their noded.
112  const auto &[seedsGraph, simpleNodesMap] = collectSeparately(threshold);
113  mergeSubGraphs(threshold, seedsGraph, simpleNodesMap);
114  } else if (strategy == GraphMap::CollectionStrategy::SeedsFirst) {
115  // Like strategy D, but after solving the edges between the seeds,
116  // the simple nodes edges are cleaned to keep only the highest score link.
117  // Then proceed as strategy B.
121  } else if (strategy == GraphMap::CollectionStrategy::CascadeHighest) {
122  // First, for each simple node keep only the edge with the highest score.
123  // Then proceed as strategy A, from the first seed cascading to the others.
124  // Secondary seeds that are linked, are absorbed and ignored in the next iteration:
125  // this implies that nodes connected to these seeds are lost.
128  }
129 }
130 
131 //----------------------------------------
132 // Implementation of single actions
133 
135  // Starting from the highest energy seed, collect all the nodes.
136  // Other seeds collected by higher energy seeds are ignored
137  const auto &seeds = nodesCategories_[NodeCategory::kSeed];
138  // seeds are already included in order
139  LogDebug("GraphMap") << "Cascading...";
140  for (const auto &s : seeds) {
141  LogTrace("GraphMap") << "seed: " << s;
142  std::vector<uint> collectedNodes;
143  // Check if the seed if still available
144  if (adjMatrix_[{s, s}] < threshold)
145  continue;
146  // Loop on the out-coming edges
147  for (const auto &out : edgesOut_[s]) {
148  // Check the threshold for association
149  if (adjMatrix_[{s, out}] >= threshold) {
150  LogTrace("GraphMap") << "\tOut edge: " << s << " --> " << out;
151  // Save the node
152  collectedNodes.push_back(out);
153  // Remove all incoming edges to the selected node
154  // So that it cannot be taken from other SuperNodes
155  for (const auto &out_in : edgesIn_[out]) {
156  // There can be 4 cases:
157  // 1) out == s, out_in can be an incoming edge from other seed: to be removed
158  // 2) out == s, out_in==s (self-loop): zeroing will remove the current node from the available ones
159  // 3) out == r, out_in==s (current link): keep this
160  // 4) out == r, out_in==r (self-loop on other seeds): remove this making the other seed not accessible
161  if (out != s && out_in == s)
162  continue; // No need to remove the edge we are using
163  adjMatrix_[{out_in, out}] = 0.;
164  LogTrace("GraphMap") << "\t\t Deleted edge: " << out << " <-- " << out_in;
165  }
166  }
167  }
168  graphOutput_.push_back({s, collectedNodes});
169  }
170 }
171 
173  // First for each simple node (no seed) keep only the highest score link
174  // Then perform strategy A.
175  LogTrace("GraphMap") << "Keep only highest score edge";
176  for (const auto &cl : nodesCategories_[NodeCategory::kNode]) {
177  std::pair<uint, float> maxPair{0, 0};
178  bool found = false;
179  for (const auto &seed : edgesIn_[cl]) {
180  float score = adjMatrix_[{seed, cl}];
181  if (score > maxPair.second) {
182  maxPair = {seed, score};
183  found = true;
184  }
185  }
186  if (!found)
187  continue;
188  LogTrace("GraphMap") << "cluster: " << cl << " edge from " << maxPair.first;
189  // Second loop to remove all the edges apart from the max
190  for (const auto &seed : edgesIn_[cl]) {
191  if (seed != maxPair.first) {
192  adjMatrix_[{seed, cl}] = 0.;
193  }
194  }
195  }
196 }
197 
198 std::pair<GraphMap::GraphOutput, GraphMap::GraphOutputMap> GraphMap::collectSeparately(float threshold) {
199  // Save a subgraph of only seeds, without self-loops
200  GraphOutput seedsGraph;
201  // Collect all the nodes around seeds, but not other seeds
202  GraphOutputMap simpleNodesGraphMap;
203  LogDebug("GraphMap") << "Collecting separately each seed...";
204  // seeds are already included in order
205  for (const auto &s : nodesCategories_[NodeCategory::kSeed]) {
206  LogTrace("GraphMap") << "seed: " << s;
207  std::vector<uint> collectedNodes;
208  std::vector<uint> collectedSeeds;
209  // Check if the seed if still available
210  if (adjMatrix_[{s, s}] < threshold)
211  continue;
212  // Loop on the out-coming edges
213  for (const auto &out : edgesOut_[s]) {
214  // Check if it is another seed
215  // if out is a seed adjMatrix[self-loop] > 0
216  if (out != s && adjMatrix_[{out, out}] > 0) {
217  // DO NOT CHECK the score of the edge, it will be checked during the merging
218  collectedSeeds.push_back(out);
219  // No self-loops are saved in the seed graph output
220  // Then continue and do not work on this edgeOut
221  continue;
222  }
223  // Check the threshold for association
224  if (adjMatrix_[{s, out}] >= threshold) {
225  LogTrace("GraphMap") << "\tOut edge: " << s << " --> " << out << " (" << adjMatrix_[{s, out}] << " )";
226  // Save the node
227  collectedNodes.push_back(out);
228  // The links of the node to other seeds are not touched
229  // IF the function is called after assignHighestScoreEdge
230  // the other links have been already removed.
231  // IF not: the same node can be assigned to more subgraphs.
232  // The self-loop is included in this case in order to save the seed node
233  // in its own sub-graph.
234  }
235  }
236  simpleNodesGraphMap[s] = collectedNodes;
237  seedsGraph.push_back({s, collectedSeeds});
238  }
239  return std::make_pair(seedsGraph, simpleNodesGraphMap);
240 }
241 
242 void GraphMap::mergeSubGraphs(float threshold, GraphOutput seedsGraph, GraphOutputMap nodesGraphMap) {
243  // We have the graph between the seed and a map of
244  // simple nodes connected to each seed separately.
245  // Now we link them and build superGraphs starting from the first seed
246  LogTrace("GraphMap") << "Starting merging";
247  for (const auto &[s, other_seeds] : seedsGraph) {
248  LogTrace("GraphMap") << "seed: " << s;
249  // Check if the seed is still available
250  if (adjMatrix_[{s, s}] < threshold)
251  continue;
252  // If it is, we collect the final list of nodes
253  std::vector<uint> collectedNodes;
254  // Take the previously connected simple nodes to the current seed one
255  const auto &simpleNodes = nodesGraphMap[s];
256  collectedNodes.insert(std::end(collectedNodes), std::begin(simpleNodes), std::end(simpleNodes));
257  // Check connected seeds
258  for (const auto &out_s : other_seeds) {
259  // Check the score of the edge for the merging
260  // and check if the other seed has not been taken already
261  if (adjMatrix_[{out_s, out_s}] > threshold && adjMatrix_[{s, out_s}] > threshold) {
262  LogTrace("GraphMap") << "\tMerging nodes from seed: " << out_s;
263  // Take the nodes already linked to this seed
264  const auto &otherNodes = nodesGraphMap[out_s];
265  // We don't check for duplicates because assignHighestScoreEdge() should
266  // have been called already
267  collectedNodes.insert(std::end(collectedNodes), std::begin(otherNodes), std::end(otherNodes));
268  // Now let's disable the secondary seed
269  adjMatrix_[{out_s, out_s}] = 0.;
270  // This makes the strategy NOT RECURSIVE
271  // Other seeds linked to the disable seed won't be collected, but analyzed independently.
272  }
273  }
274  // Now remove the current seed from the available ones,
275  // if not other seeds could take it and we would have a double use of objects.
276  adjMatrix_[{s, s}] = 0;
277  graphOutput_.push_back({s, collectedNodes});
278  }
279 }
280 
282  LogTrace("GraphMap") << "Resolving seeds";
283  for (const auto &s : nodesCategories_[NodeCategory::kSeed]) {
284  LogTrace("GraphMap") << "seed: " << s;
285  // Check if the seed if still available
286  if (adjMatrix_[{s, s}] < threshold)
287  continue;
288  // Loop on the out-coming edges
289  for (const auto &out : edgesOut_[s]) {
290  if (out != s && adjMatrix_[{out, out}] > 0 && adjMatrix_[{s, out}] > threshold) {
291  // This is a link to another still available seed
292  // If the edge score is good the other seed node is not disabled --> remove it
293  LogTrace("GraphMap") << "\tdisable seed: " << out;
294  adjMatrix_[{out, out}] = 0.;
295  // Remove the edges from that seed
296  // This is needed in order to be able to use the
297  // assignHighestScoreEdge after this function correctly
298  for (const auto &c : edgesOut_[out]) {
299  adjMatrix_[{out, c}] = 0.;
300  // We don't touch the edgesIn and edgesOut collections but we zero the adjmatrix --> more efficient
301  }
302  }
303  }
304  }
305 }
Log< level::Info, true > LogVerbatim
void mergeSubGraphs(float threshold, GraphOutput seedsGraph, GraphOutputMap nodesGraphMap)
Definition: GraphMap.cc:242
uint getAdjMatrix(const uint i, const uint j) const
Definition: GraphMap.cc:45
std::map< uint, uint > nodesCount_
Definition: GraphMap.h:67
void addNode(const uint index, const NodeCategory category)
Definition: GraphMap.cc:15
void resolveSuperNodesEdges(float threshold)
Definition: GraphMap.cc:281
const std::vector< uint > & getInEdges(const uint i) const
Definition: GraphMap.cc:43
#define LogTrace(id)
void addNodes(const std::vector< uint > &indices, const std::vector< NodeCategory > &categories)
Definition: GraphMap.cc:20
const std::vector< uint > & getOutEdges(const uint i) const
Definition: GraphMap.cc:41
void collectNodes(GraphMap::CollectionStrategy strategy, float threshold)
Definition: GraphMap.cc:97
std::vector< std::pair< uint, std::vector< uint > > > GraphOutput
Definition: GraphMap.h:56
void setAdjMatrix(const uint i, const uint j, const float score)
Definition: GraphMap.cc:34
std::vector< float > getAdjMatrixCol(const uint j) const
Definition: GraphMap.cc:55
std::vector< float > getAdjMatrixRow(const uint i) const
Definition: GraphMap.cc:47
std::map< NodeCategory, std::vector< uint > > nodesCategories_
Definition: GraphMap.h:65
std::vector< std::vector< uint > > edgesOut_
Definition: GraphMap.h:71
void assignHighestScoreEdge()
Definition: GraphMap.cc:172
void printGraphMap()
Definition: GraphMap.cc:65
std::map< std::pair< uint, uint >, float > adjMatrix_
Definition: GraphMap.h:75
void addEdge(const uint i, const uint j)
Definition: GraphMap.cc:26
std::map< uint, std::vector< uint > > GraphOutputMap
Definition: GraphMap.h:57
void setAdjMatrixSym(const uint i, const uint j, const float score)
Definition: GraphMap.cc:36
fixed size matrix
uint nNodes_
Definition: GraphMap.h:60
GraphMap(uint nNodes)
Definition: GraphMap.cc:9
void collectCascading(float threshold)
Definition: GraphMap.cc:134
std::pair< GraphOutput, GraphOutputMap > collectSeparately(float threshold)
Definition: GraphMap.cc:198
std::vector< std::vector< uint > > edgesIn_
Definition: GraphMap.h:69
GraphOutput graphOutput_
Definition: GraphMap.h:78
#define LogDebug(id)