votca 2024.2-dev
Loading...
Searching...
No Matches
beadmotifalgorithms.cc
Go to the documentation of this file.
1/*
2 * Copyright 2009-2020 The VOTCA Development Team (http://www.votca.org)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16/ */
17
18// Standard includes
19#include <cassert>
20#include <cstddef>
21#include <utility>
22
23// VOTCA includes
26
27// Local VOTCA includes
30
31namespace votca {
32namespace csg {
33class BeadMotif;
34} // namespace csg
35namespace tools {
36class Graph;
37} // namespace tools
38} // namespace votca
39
40using namespace votca::tools;
41using namespace std;
42
43namespace votca {
44namespace csg {
45
46/******************************************************************************
47 * Locally Global Variables
48 ******************************************************************************/
49
50typedef std::pair<Index, BeadMotif> IdMotif;
51
53
54static Index motif_index = 0;
55
56/******************************************************************************
57 * Internal Private Functions
58 ******************************************************************************/
59
64void removeAllEdgesConnectedToVertex_(Index junction, Graph& full_graph,
65 unordered_map<Edge, bool>& remove_edges) {
66
67 vector<Edge> neigh_edges = full_graph.getNeighEdges(junction);
68 for (Edge& edge : neigh_edges) {
69 remove_edges[edge] = true;
70 }
71}
79 Index junction, ReducedGraph& reduced_graph,
80 unordered_map<Edge, bool>& remove_edges,
81 unordered_map<Index, vector<Edge>>
82 contracted_branch_edges_connected_to_junction) {
83
84 Index number_branches_with_more_than_one_bond = 0;
85 // Cycle the branches
86 for (pair<Index, vector<Edge>> branch_and_contracted_edges :
87 contracted_branch_edges_connected_to_junction) {
88 bool edge_is_single_connection_to_junction = false;
89 if (branch_and_contracted_edges.second.size() == 1) {
90 // Make sure the branch is not a loop as well
91 Edge contracted_edge = branch_and_contracted_edges.second.at(0);
92 if (contracted_edge.loop() == false) {
93 vector<vector<Edge>> expanded_edges =
94 reduced_graph.expandEdge(contracted_edge);
95 // Determine which of these edges are conneted to the vertex
96 if (expanded_edges.size() == 1) {
97 for (Edge& edge : expanded_edges.at(0)) {
98 if (edge.contains(junction)) {
99 remove_edges[edge] = true;
100 edge_is_single_connection_to_junction = true;
101 break;
102 }
103 }
104 }
105 }
106 }
107 if (edge_is_single_connection_to_junction == false) {
108 ++number_branches_with_more_than_one_bond;
109 }
110 }
111
112 return number_branches_with_more_than_one_bond;
113}
114
123 unordered_map<Edge, bool>& remove_edges) {
124
125 ReducedGraph reduced_graph = reduceGraph(full_graph);
126
127 vector<Index> junctions = reduced_graph.getJunctions();
128
129 for (Index& junction : junctions) {
130 vector<Edge> neighboring_edges = reduced_graph.getNeighEdges(junction);
131 unordered_map<Edge, bool> contracted_edge_explored;
132 for (Edge& edge : neighboring_edges) {
133 contracted_edge_explored[edge] = false;
134 }
135
136 Index branch_index = 0;
137 unordered_map<Index, vector<Edge>>
138 contracted_branch_edges_connected_to_junction;
139 for (Edge& branch_starting_edge : neighboring_edges) {
140 if (contracted_edge_explored[branch_starting_edge] == false) {
141 // The starting edge could be redundant but I guess it doesn't matter
142 // redundant edges would mean they are part of the same branch anyway
143 set<Edge> branch_edges =
144 exploreBranch(reduced_graph, junction, branch_starting_edge);
145
146 vector<Edge> starting_edges_explored_by_branch;
147 for (Edge& branch_starting_edge2 : neighboring_edges) {
148 if (branch_edges.count(branch_starting_edge2)) {
149 contracted_edge_explored[branch_starting_edge2] = true;
150 starting_edges_explored_by_branch.push_back(branch_starting_edge2);
151 }
152 }
153 contracted_branch_edges_connected_to_junction[branch_index] =
154 starting_edges_explored_by_branch;
155 ++branch_index;
156 }
157 } // for(Edge & brach_starting_edge : neighboring_edges)
158
159 // If there is more than one branch
160 if (branch_index > 1) {
161 // We now know how many edges are connected to the starting node from each
162 // branch We can use the full graph to decouple the edges we can begin by
163 // snipping branches with only a single edge connecting them to starting
164 // nodes.
165 Index number_branches_with_more_than_one_bond =
167 junction, reduced_graph, remove_edges,
168 contracted_branch_edges_connected_to_junction);
169
170 // If more than one branch claims the junction, and each branch has more
171 // than one connetion to the junction neigther branch can claim the
172 // junction, in this case all connections to the junction will be cut.
173 if (number_branches_with_more_than_one_bond > 1) {
174 removeAllEdgesConnectedToVertex_(junction, full_graph, remove_edges);
175 }
176 }
177 } // for(Index & junction : junctions)
178}
179
180/******************************************************************************
181 * Internal Private Class
182 ******************************************************************************/
183
195 public:
197 void AddMotif(IdMotif id_and_motif);
198
253
256 size_t CountComplexMotifs() const;
257
260 bool ConnectionsCompleted() const { return bead_edges_removed_.size() == 0; }
261
263 unordered_map<Index, BeadMotif> getSimpleMotifs();
264
265 private:
266 list<IdMotif> motifs_simple_;
270
271 // Returns the ids of the simple motifs that were assigned ids
272 void sortMotifsAndAssignIdsToSimpleMotifs_(list<BeadMotif>& bead_motifs);
274};
275
276unordered_map<Index, BeadMotif> MotifDeconstructor_::getSimpleMotifs() {
277 unordered_map<Index, BeadMotif> simple_motifs;
278 for (IdMotif& id_and_motif : motifs_simple_) {
279 simple_motifs.insert(id_and_motif);
280 }
281 return simple_motifs;
282}
283
288
290 if (id_and_motif.second.getType() ==
292 motifs_multiple_structures_.push_back(id_and_motif);
293 } else if (id_and_motif.second.getType() ==
295 motifs_complex_single_structure_.push_back(id_and_motif);
296 } else if (id_and_motif.second.isMotifSimple()) {
297 motifs_simple_.push_back(id_and_motif);
298 } else {
299 assert(false && "Error the motif type must be a simple or complex type.");
300 }
301}
302
304 BeadMotifConnector& connector) {
305 list<BeadMotif> split_motifs;
306 for (IdMotif& id_and_bead_motif : motifs_complex_single_structure_) {
307 Graph full_graph = id_and_bead_motif.second.getGraph();
308 vector<Edge> all_edges = full_graph.getEdges();
309 unordered_map<Edge, bool> remove_edges;
310 for (Edge& edge : all_edges) {
311 remove_edges[edge] = false;
312 }
313
314 calculateEdgesToRemove_(full_graph, remove_edges);
315
316 vector<Index> all_vertices = full_graph.getVertices();
317
318 std::vector<Edge> new_beadstructure_edges;
319 for (pair<const Edge, bool>& edge_and_remove : remove_edges) {
320 if (edge_and_remove.second == false) {
321
322 new_beadstructure_edges.push_back(edge_and_remove.first);
323 } else {
324 bead_edges_removed_.push_back(edge_and_remove.first);
325 }
326 }
327 BeadStructure new_beadstructure = id_and_bead_motif.second.getSubStructure(
328 all_vertices, new_beadstructure_edges);
329
330 list<BeadMotif> split_motifs_temp =
331 breakIntoMotifs<list<BeadMotif>>(new_beadstructure);
332
333 split_motifs.splice(split_motifs.end(), split_motifs_temp);
334 }
335
339}
340
342 BeadMotifConnector& connector) {
343
344 // Cycle the edges
345 list<Edge>::iterator edge_iterator = bead_edges_removed_.begin();
346 while (edge_iterator != bead_edges_removed_.end()) {
347 assert(edge_iterator->loop() == false);
348 Index bead_id1 = edge_iterator->getEndPoint1();
349 Index bead_id2 = edge_iterator->getEndPoint2();
350 // Cycle the motifs
351 list<IdMotif>::iterator motif_bead1_iterator;
352 for (motif_bead1_iterator = motifs_simple_.begin();
353 motif_bead1_iterator != motifs_simple_.end(); ++motif_bead1_iterator) {
354
355 if (motif_bead1_iterator->second.BeadExist(bead_id1)) {
356 break;
357 }
358 }
359
360 list<IdMotif>::iterator motif_bead2_iterator;
361 for (motif_bead2_iterator = motifs_simple_.begin();
362 motif_bead2_iterator != motifs_simple_.end(); ++motif_bead2_iterator) {
363
364 if (motif_bead2_iterator->second.BeadExist(bead_id2)) {
365 break;
366 }
367 }
368
369 // We remove the edge from the list and add it as a connection
370 if (motif_bead2_iterator != motifs_simple_.end() &&
371 motif_bead1_iterator != motifs_simple_.end()) {
372 Edge motif_edge(motif_bead1_iterator->first, motif_bead2_iterator->first);
373 connector.AddMotifAndBeadEdge(motif_edge, *edge_iterator);
374 edge_iterator = bead_edges_removed_.erase(edge_iterator);
375 } else {
376 ++edge_iterator;
377 }
378 } // while( edge_iterator != bead_edges.end() )
379}
380
382 list<BeadMotif>& bead_motifs) {
383
384 list<BeadMotif>::iterator bead_motif_iter = bead_motifs.begin();
385 while (bead_motif_iter != bead_motifs.end()) {
386
387 Index new_motif_id = unassigned_id;
388 if (bead_motif_iter->isMotifSimple()) {
389 new_motif_id = motif_index;
390 ++motif_index;
391 }
392 pair<Index, BeadMotif> id_and_motif(new_motif_id,
393 std::move(*bead_motif_iter));
394 AddMotif(id_and_motif);
395 bead_motif_iter = bead_motifs.erase(bead_motif_iter);
396 }
397}
398
399/******************************************************************************
400 * Public Functions
401 ******************************************************************************/
402
403pair<unordered_map<Index, BeadMotif>, BeadMotifConnector> breakIntoSimpleMotifs(
404 BeadMotif bead_motif) {
405
406 MotifDeconstructor_ motif_manipulator;
407 motif_manipulator.AddMotif(IdMotif(unassigned_id, bead_motif));
408
409 BeadMotifConnector connector;
410
411 do {
412 motif_manipulator.deconstructComplexSingleStructures(connector);
413 } while (motif_manipulator.CountComplexMotifs());
414
415 assert(motif_manipulator.ConnectionsCompleted());
416 unordered_map<Index, BeadMotif> motifs_simple_map =
417 motif_manipulator.getSimpleMotifs();
418 auto simple_motifs_and_connector =
419 pair<unordered_map<Index, BeadMotif>, BeadMotifConnector>(
420 motifs_simple_map, connector);
421 return simple_motifs_and_connector;
422}
423
424} // namespace csg
425} // namespace votca
Simple class for storing the connections between motifs and the underlying beads that are part of the...
void AddMotifAndBeadEdge(const tools::Edge &motif_edge, const tools::Edge &bead_edge)
Designed determine what kind of structure a beadstructure has.
Definition beadmotif.h:111
Designed to determine if the structure beads passed in.
BeadStructure getSubStructure(const std::vector< Index > &idx, const std::vector< tools::Edge > &edges) const
Given indices and edges that exist are a subset of beadstructure, return the sub-beadstructure.
This is an internal class meant to deconstruct bead motifs into their simple forms.
unordered_map< Index, BeadMotif > getSimpleMotifs()
Returns a map of all the simple motifs with their ids.
void sortMotifsAndAssignIdsToSimpleMotifs_(list< BeadMotif > &bead_motifs)
void AddMotif(IdMotif id_and_motif)
Adds a motif with its corresponding id.
void deconstructComplexSingleStructures(BeadMotifConnector &connector)
Takes a bead motif of type single structure and deconstructs it into smaller components.
void determineMotifConnections_(BeadMotifConnector &connector)
Connects to vertices.
Definition edge.h:42
bool loop() const
Checks to see if an edge loops back on itself.
Definition edge.h:65
virtual std::vector< Edge > getEdges()
Returns all the edges in the graph.
Definition graph.h:103
std::vector< Index > getJunctions() const
Gets all vertices with degree of 3 or greater.
Definition graph.cc:110
std::vector< Index > getVertices() const
Returns all the vertices in the graph.
Definition graph.cc:166
std::vector< Edge > getNeighEdges(Index vertex) const
Returns all the edges in the graph connected to vertex vertex
Definition graph.h:106
Contains a graph that consits of vertices with degree of 1 or greater than 3.
std::vector< std::vector< Edge > > expandEdge(const Edge &edge) const
Allows one to return all edges connecting two vertices of the reduced graph.
STL namespace.
const Index unassigned_id
T breakIntoMotifs(BeadStructure &beadstructure)
breaks a beadstructure into individual motifs.
std::pair< Index, BeadMotif > IdMotif
void calculateEdgesToRemove_(Graph &full_graph, unordered_map< Edge, bool > &remove_edges)
Calculates which edges to remove from a graph, in order to split it up correctly into simple motif ty...
void removeAllEdgesConnectedToVertex_(Index junction, Graph &full_graph, unordered_map< Edge, bool > &remove_edges)
Determines which edges are connected to the junction and stored them in the remove_edges map.
Index determineEdgesOfBranchesWithSingleConnectionToJunction_(Index junction, ReducedGraph &reduced_graph, unordered_map< Edge, bool > &remove_edges, unordered_map< Index, vector< Edge > > contracted_branch_edges_connected_to_junction)
std::pair< std::unordered_map< Index, BeadMotif >, BeadMotifConnector > breakIntoSimpleMotifs(BeadMotif bead_motif)
This function will take a beadmotif and break it into its simple motifs.
static Index motif_index
ReducedGraph reduceGraph(Graph graph)
Will take a graph and reduce it, by removing all vertices with degree of 2.
std::set< Edge > exploreBranch(Graph g, Index starting_vertex, const Edge &edge)
Explore one of the branches if exploration is initiated at vertex starting_vertex.
base class for all analysis tools
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26