votca 2024.2-dev
Loading...
Searching...
No Matches
reducedgraph.cc
Go to the documentation of this file.
1/*
2 * Copyright 2009-2020 The VOTCA Development Team
3 * (http://www.votca.org)
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License")
6 *
7 * You may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
20// Standard includes
21#include <algorithm>
22#include <cassert>
23
24// Local VOTCA includes
25#include "votca/tools/edge.h"
27
28using namespace std;
29
30namespace votca {
31namespace tools {
32
33class GraphNode;
34
35/******************************************************************************
36 * Internal Private Functions
37 ******************************************************************************/
38
47bool compareChainWithChains_(const vector<Index>& chain,
48 const vector<vector<Index>>& chains) {
49 bool match = false;
50 for (const vector<Index>& chain2 : chains) {
51 if (chain2.size() == chain.size()) {
52 match = true;
53 for (size_t index = 0; index < chain.size(); ++index) {
54 if (chain2.at(index) != chain.at(index)) {
55 match = false;
56 break;
57 }
58 } // Cycle vertices in each chain
59 if (match) {
60 return true;
61 }
62 } // Chains same size
63 }
64 return false;
65}
66
97set<Index> getVertexJunctions_(const vector<ReducedEdge>& reduced_edges) {
98 unordered_map<Index, Index> vertex_count;
99 for (ReducedEdge reduced_edge : reduced_edges) {
100 // if loop, increment value is double and the first index is skipped to
101 // prevent over counting of the first number
102 Index increment = 1;
103 size_t index = 0;
104 if (reduced_edge.loop()) {
105 ++index;
106 increment = 2;
107 }
108 vector<Index> chain = reduced_edge.getChain();
109 for (; index < chain.size(); ++index) {
110 if (vertex_count.count(chain.at(index))) {
111 vertex_count[chain.at(index)] += increment;
112 } else {
113 vertex_count[chain.at(index)] = increment;
114 }
115 }
116 }
117 set<Index> junctions;
118 for (pair<Index, Index> vertex_and_count : vertex_count) {
119 if (vertex_and_count.second > 2) {
120 junctions.insert(vertex_and_count.first);
121 }
122 }
123 return junctions;
124}
125
155 vector<Edge>& edges, const ReducedEdge reduced_edge,
156 unordered_map<Edge, vector<vector<Index>>>& expanded_edges) {
157
158 Edge edge(reduced_edge.getEndPoint1(), reduced_edge.getEndPoint2());
159 if (expanded_edges.count(edge)) {
160 bool match =
161 compareChainWithChains_(reduced_edge.getChain(), expanded_edges[edge]);
162 if (!match) {
163 expanded_edges[edge].push_back(reduced_edge.getChain());
164 }
165 } else {
166 expanded_edges[edge].push_back(reduced_edge.getChain());
167 }
168 edges.push_back(edge);
169}
170
195void orderChainAfterInitialVertex_(vector<Index>& chain) {
196 size_t ignore_first_and_last_vertex = 2;
197 size_t total_number_to_parse =
198 (chain.size() - ignore_first_and_last_vertex) / 2;
199 bool reverse_vector = false;
200 for (size_t count = 0; count < (total_number_to_parse); ++count) {
201 if (chain.at(chain.size() - count - 1) < chain.at(count + 1)) {
202 reverse_vector = true;
203 break;
204 }
205 }
206
207 if (reverse_vector) {
208 reverse(chain.begin(), chain.end());
209 }
210}
211
213 vector<Edge>& edges,
214 unordered_map<Edge, vector<vector<Index>>>& expanded_edges,
215 vector<Index> chain, Index vertex, size_t& chain_index) {
216
217 Edge edge(vertex, vertex);
218 edges.push_back(edge);
219 vector<Index> new_chain;
220 for (size_t index = 0; index < chain.size(); ++index) {
221 if (((chain_index + index) % chain.size()) == 0) {
222 ++chain_index;
223 }
224 Index new_chain_index = (chain_index + index) % chain.size();
225 new_chain.push_back(chain.at(new_chain_index));
226 }
227 // Ensure that the new_chain is sorted so after the first vertex they are
228 // ordered from smallest to largest
230 bool match = compareChainWithChains_(new_chain, expanded_edges[edge]);
231 if (!match) {
232 expanded_edges[edge].push_back(new_chain);
233 return true;
234 }
235 return false;
236}
237
238set<Index> getAllVertices_(const std::vector<ReducedEdge>& reduced_edges) {
239 set<Index> vertices;
240 for (const ReducedEdge& reduced_edge : reduced_edges) {
241 vector<Index> chain = reduced_edge.getChain();
242 for (const Index vertex : chain) {
243 vertices.insert(vertex);
244 }
245 }
246 return vertices;
247}
248
250 const unordered_map<Edge, vector<vector<Index>>>& expanded_edges) {
251 set<Index> all_vertices;
252
253 for (const auto& edge_and_chains : expanded_edges) {
254 for (vector<Index> chain : edge_and_chains.second) {
255 all_vertices.insert(chain.begin(), chain.end());
256 }
257 }
258 return all_vertices;
259}
260/******************************************************************************
261 * Private Class Methods
262 ******************************************************************************/
263
264void ReducedGraph::init_(vector<ReducedEdge> reduced_edges,
265 unordered_map<Index, GraphNode> nodes) {
266 vector<Edge> edges;
267 nodes_ = nodes;
268
269 junctions_ = getVertexJunctions_(reduced_edges);
270
271 for (const ReducedEdge& reduced_edge : reduced_edges) {
272
273 if (reduced_edge.loop() &&
274 junctions_.count(reduced_edge.getEndPoint1()) == 0) {
275 vector<Index> chain = reduced_edge.getChain();
276 size_t chain_index = 0;
277 bool edge_added = false;
278 for (Index vertex : chain) {
279 if (junctions_.count(vertex)) {
281 edges, expanded_edges_, chain, vertex, chain_index);
282 break;
283 }
284 ++chain_index;
285 }
286 if (!edge_added) {
287 addEdgeIfNotLoop_(edges, reduced_edge, expanded_edges_);
288 }
289 } else {
290 addEdgeIfNotLoop_(edges, reduced_edge, expanded_edges_);
291 }
292 }
293
295
296 calcId_();
297}
298
299/******************************************************************************
300 * Public Class Methods
301 ******************************************************************************/
302
303ReducedGraph::ReducedGraph(std::vector<ReducedEdge> reduced_edges) {
304
305 set<Index> vertices = getAllVertices_(reduced_edges);
306 unordered_map<Index, GraphNode> nodes;
307 for (const Index vertex : vertices) {
308 GraphNode gn;
309 nodes[vertex] = gn;
310 }
311 init_(reduced_edges, nodes);
312}
313
314ReducedGraph::ReducedGraph(std::vector<ReducedEdge> reduced_edges,
315 unordered_map<Index, GraphNode> nodes) {
316
317 set<Index> vertices = getAllVertices_(reduced_edges);
318 if (nodes.size() < vertices.size()) {
319 throw invalid_argument(
320 "The number of nodes passed into a reduced graph "
321 "must be greater or equivalent to the number of vertices");
322 }
323 for (const Index vertex : vertices) {
324 if (nodes.count(vertex) == 0) {
325 throw invalid_argument("A vertex is missing its corresponding node.");
326 }
327 }
328 init_(reduced_edges, nodes);
329
330 // Add all the nodes that are isolated
331 for (pair<const Index, GraphNode>& id_and_node : nodes) {
332 if (vertices.count(id_and_node.first) == 0) {
333 edge_container_.addVertex(id_and_node.first);
334 }
335 }
336}
337
339 vector<Edge> all_expanded_edges;
340 for (const pair<Edge, vector<vector<Index>>> edge_and_vertices :
342 vector<vector<Edge>> edges_local = expandEdge(edge_and_vertices.first);
343 for (vector<Edge>& edges : edges_local) {
344 all_expanded_edges.insert(all_expanded_edges.end(), edges.begin(),
345 edges.end());
346 }
347 }
348 return Graph(all_expanded_edges, nodes_);
349}
350
351vector<vector<Edge>> ReducedGraph::expandEdge(const Edge& edge) const {
352 vector<vector<Edge>> all_edges;
353 vector<vector<Index>> chains = expanded_edges_.at(edge);
354 for (vector<Index> vertices : chains) {
355 vector<Edge> edges;
356 for (size_t index = 0; index < (vertices.size() - 1); ++index) {
357 Edge edge_temp(vertices.at(index), vertices.at(index + 1));
358 edges.push_back(edge_temp);
359 }
360 all_edges.push_back(edges);
361 }
362 return all_edges;
363}
364
365vector<pair<Index, GraphNode>> ReducedGraph::getNodes() const {
366 vector<Index> vertices = edge_container_.getVertices();
367 vector<pair<Index, GraphNode>> nodes;
368 for (const Index vertex : vertices) {
369 pair<Index, GraphNode> id_and_node(vertex, nodes_.at(vertex));
370 nodes.push_back(id_and_node);
371 }
372
373 set<Index> all_connected_vertices = getAllConnectedVertices_(expanded_edges_);
374 // Grab the nodes that are not attached to any edges
375 for (pair<Index, GraphNode> id_and_node : nodes_) {
376 if (!all_connected_vertices.count(id_and_node.first)) {
377 nodes.push_back(id_and_node);
378 }
379 }
380 return nodes;
381}
382
383vector<Index> ReducedGraph::getVerticesDegree(Index degree) const {
384 if (degree == 0) {
385 set<Index> all_connected_vertices =
387 vector<Index> vertices;
388 for (const pair<Index, GraphNode> id_and_node : nodes_) {
389 if (all_connected_vertices.count(id_and_node.first) == false) {
390 vertices.push_back(id_and_node.first);
391 }
392 return vertices;
393 }
394 }
395 return edge_container_.getVerticesDegree(degree);
396}
397
398ostream& operator<<(ostream& os, const ReducedGraph graph) {
399 os << "Graph" << endl;
400 for (const pair<const Index, GraphNode>& id_and_node : graph.nodes_) {
401 os << "Node " << id_and_node.first << endl;
402 os << id_and_node.second << endl;
403 }
404
405 os << endl;
406 os << graph.edge_container_ << endl;
407
408 os << endl;
409 os << "Expanded Edge Chains" << endl;
410
411 for (const pair<const Edge, vector<vector<Index>>>& edge_and_chains :
412 graph.expanded_edges_) {
413 for (const vector<Index>& chain : edge_and_chains.second) {
414 for (const Index vertex : chain) {
415 os << vertex << " ";
416 }
417 os << endl;
418 }
419 os << endl;
420 }
421
422 return os;
423}
424
425} // namespace tools
426} // namespace votca
EdgeContainer is responsible for operations on groups of edges.
std::vector< Index > getVerticesDegree(Index degree) const
Contains vector of all vertices with degree.
void addVertex(Index vertex)
Add a lone vertex.
std::vector< Index > getVertices() const
Get all the vertices in vector form.
Connects to vertices.
Definition edge.h:42
Index getEndPoint1() const
grab the smaller integer
Definition edge.h:55
Index getEndPoint2() const
grab the larger integer
Definition edge.h:57
A graph node that will take a variety of different values.
Definition graphnode.h:46
std::unordered_map< Index, GraphNode > nodes_
Definition graph.h:47
EdgeContainer edge_container_
Definition graph.h:45
void calcId_()
Calculate the id of the graph.
Definition graph.cc:129
Connects two vertices, also stores the vertices between the endpoints.
Definition reducededge.h:49
std::vector< Index > getChain() const
Returns a vector of vertices that constitute the edge.
Definition reducededge.h:61
Contains a graph that consits of vertices with degree of 1 or greater than 3.
Graph expandGraph() const
This method will return a copy of the full graph.
std::vector< std::vector< Edge > > expandEdge(const Edge &edge) const
Allows one to return all edges connecting two vertices of the reduced graph.
void init_(std::vector< ReducedEdge > reduced_edges, std::unordered_map< Index, GraphNode > nodes)
std::set< Index > junctions_
std::unordered_map< Edge, std::vector< std::vector< Index > > > expanded_edges_
std::vector< std::pair< Index, GraphNode > > getNodes(void) const override
Gets the junctions in the graph.
std::vector< Index > getVerticesDegree(Index degree) const override
Returns all the vertices with degree specified by degree
STL namespace.
void orderChainAfterInitialVertex_(vector< Index > &chain)
This is a helper function used to help store the vertex chain in a reproducable order.
set< Index > getVertexJunctions_(const vector< ReducedEdge > &reduced_edges)
Given a vector of Reduced Edges will find and return junctions if any exist.
std::ostream & operator<<(std::ostream &out, const Correlate &c)
Definition correlate.h:53
set< Index > getAllConnectedVertices_(const unordered_map< Edge, vector< vector< Index > > > &expanded_edges)
bool compareChainWithChains_(const vector< Index > &chain, const vector< vector< Index > > &chains)
Function will compare a chain with a vector of chains.
set< Index > getAllVertices_(const std::vector< ReducedEdge > &reduced_edges)
void addEdgeIfNotLoop_(vector< Edge > &edges, const ReducedEdge reduced_edge, unordered_map< Edge, vector< vector< Index > > > &expanded_edges)
function adds an edge to an unordered_map and a vector if it is found to not be a loop
bool reorderAndStoreChainIfDoesNotExist_(vector< Edge > &edges, unordered_map< Edge, vector< vector< Index > > > &expanded_edges, vector< Index > chain, Index vertex, size_t &chain_index)
base class for all analysis tools
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26