/*
* Project: MoleCuilder
* Description: creates and alters molecular systems
* Copyright (C) 2017 Frederik Heber. All rights reserved.
*
*
* This file is part of MoleCuilder.
*
* MoleCuilder is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MoleCuilder is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MoleCuilder. If not, see .
*/
/*
* BoostGraphCreator.cpp
*
* Created on: May 17, 2017
* Author: heber
*/
// include config.h
#ifdef HAVE_CONFIG_H
#include
#endif
//#include "CodePatterns/MemDebug.hpp"
#include "BoostGraphCreator.hpp"
#include
#include "CodePatterns/Assert.hpp"
#include "Atom/atom.hpp"
#include "Graph/Graph6Reader.hpp"
#include "molecule.hpp"
void BoostGraphCreator::createFromMolecule(
const molecule &_mol,
const predicate_t &_pred)
{
createFromRange(_mol.begin(), _mol.end(), _mol.getAtomCount(), _pred);
}
static bool predicateAnd(
const BoostGraphCreator::predicate_t &_pred1,
const BoostGraphCreator::predicate_t &_pred2,
const bond &_bond)
{ return (_pred1(_bond) && _pred2(_bond)); }
static atomId_t getAtomId(
const atom *_atom
)
{ return _atom->getId(); }
static bool inSetPredicate(
const std::vector &_atomids,
const bond &_bond)
{
const atomId_t leftid = _bond.leftatom->getId();
const atomId_t rightid = _bond.rightatom->getId();
return std::binary_search(_atomids.begin(), _atomids.end(), leftid)
&& std::binary_search(_atomids.begin(), _atomids.end(), rightid);
}
void BoostGraphCreator::createFromAtoms(
const std::vector &_atoms,
const predicate_t &_pred)
{
// sort makes binary_search possible
std::vector atomids;
std::transform(_atoms.begin(), _atoms.end(),
std::back_inserter(atomids), getAtomId);
ASSERT( _atoms.size() == atomids.size(),
"BoostGraphCreator::createFromAtom() - atomids "
+toString(atomids.size())+" and atoms "+toString(_atoms.size())
+" differ in size?");
std::sort(atomids.begin(), atomids.end());
const predicate_t predicate = boost::bind(inSetPredicate, boost::ref(atomids), _1);
createFromRange::const_iterator>(
const_cast &>(_atoms).begin(),
const_cast &>(_atoms).end(),
_atoms.size(),
boost::bind(predicateAnd, _pred, predicate, _1));
}
void BoostGraphCreator::createFromGraph6String(
const std::string &_graph_string)
{
Graph6Reader reader;
{
std::stringstream inputstream(_graph_string);
reader(inputstream);
}
graph = UndirectedGraph();
// add nodes
for(int numbers = 0; numbers < reader.get_num_nodes(); ++numbers) {
const atomId_t atomid = numbers;
Vertex v = boost::add_vertex(atomid, graph);
const atomId_t vertexname = boost::get(boost::get(boost::vertex_name, graph), v);
const nodeId_t vertexindex = boost::get(boost::get(boost::vertex_index, graph), v);
LOG(2, "DEBUG: Adding node " << vertexindex << " associated to atom #" << vertexname);
ASSERT( vertexname == atomid,
"BoostGraphCreator::createFromRange() - atomid "+toString(atomid)
+" is not name of vertex "+toString(vertexname)+".");
atomids_nodeids.insert( std::make_pair(vertexname, vertexindex) );
}
LOG(1, "INFO: Added " << reader.get_num_nodes() << " nodes.");
// add edges
const Graph6Reader::edges_t &edges = reader.get_edges();
for(Graph6Reader::edges_t::const_iterator iter = edges.begin();
iter != edges.end(); ++iter) {
// graph6 contains only upper triangle of adjacency matrix, hence add only once
const nodeId_t leftnodeid = iter->first;
const nodeId_t rightnodeid = iter->second;
boost::add_edge(leftnodeid, rightnodeid, graph);
}
LOG(1, "INFO: Added " << reader.get_edges().size() << " edges.");
}
BoostGraphCreator::nodeId_t BoostGraphCreator::getNodeId(
const atomId_t &_atomid) const
{
atomids_nodeids_t::const_iterator iter =
atomids_nodeids.find(_atomid);
return (iter == atomids_nodeids.end()) ? (nodeId_t)-1 : iter->second;
}
BoostGraphCreator::Edge BoostGraphCreator::findEdge(const atomId_t &_firstid, const atomId_t &_secondid)
{
edge_iter i, end;
const name_map_t name_map = boost::get(boost::vertex_name, graph);
for (boost::tie(i, end) = boost::edges(graph); i != end; ++i) {
const BoostGraphCreator::Edge &e = *i;
const Vertex u = source(e, graph);
const Vertex v = target(e, graph);
const atomId_t atomid_u = boost::get(name_map, u);
const atomId_t atomid_v = boost::get(name_map, v);
if (atomid_u == _firstid) {
if (atomid_v == _secondid)
break;
} else if (atomid_u == _secondid) {
if (atomid_v == _firstid)
break;
}
}
if (i != end) {
BoostGraphCreator::Edge e = *i;
return e;
}
return BoostGraphCreator::Edge();
}
bool BoostGraphCreator::removeEdge(const atomId_t &_firstid, const atomId_t &_secondid)
{
// look through all edges
BoostGraphCreator::Edge e = findEdge(_firstid, _secondid);
// edge was found
if (e != BoostGraphCreator::Edge()) {
const Vertex u = source(e, graph);
const Vertex v = target(e, graph);
if (DoLog(3)) {
const name_map_t name_map = boost::get(boost::vertex_name, graph);
LOG(3, "DEBUG: Found edge " << boost::get(name_map, u) << " <-> "
<< boost::get(name_map, v) << ", removing.");
}
boost::remove_edge(e, graph);
return true;
}
return false;
}
bool BoostGraphCreator::addEdge(const atomId_t &_firstid, const atomId_t &_secondid)
{
// look through all edges
BoostGraphCreator::Edge e = findEdge(_firstid, _secondid);
if (e != BoostGraphCreator::Edge()) {
return false;
} else {
const nodeId_t leftnodeid = getNodeId(_firstid);
const nodeId_t rightnodeid = getNodeId(_secondid);
boost::add_edge(leftnodeid, rightnodeid, graph);
return true;
}
}