source: src/Fragmentation/Evaluation/StabilityEvaluator.cpp@ 13e5be

stable v1.7.0
Last change on this file since 13e5be was 999eaf, checked in by Frederik Heber <frederik.heber@…>, 5 years ago

Added EvaluateStabilityAction to estimate a molecule's stability.

  • removes every bond and checks the energies of the products against the educt equipped with enough hydrogen molecules to compensate for the cut bond times its degree.
  • outputs a CSV file with entries per bond.
  • extended HomologyGraph to allow direct use of AtomIdSet, i.e. atomic ids coming from a selection in the World or from the molecule.
  • DOCU: Added subsection on this action to section homology.
  • TEST: Added regression test case.
  • Property mode set to 100644
File size: 7.3 KB
RevLine 
[999eaf]1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2021 Frederik Heber. All rights reserved.
5 *
6 *
7 * This file is part of MoleCuilder.
8 *
9 * MoleCuilder is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * MoleCuilder is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with MoleCuilder. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23/*
24 * StabilityEvaluator.cpp
25 *
26 * Created on: Apr 18, 2021
27 * Author: heber
28 */
29
30
31// include config.h
32#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35
36//#include "CodePatterns/MemDebug.hpp"
37
38#include "CodePatterns/Log.hpp"
39
40#include "StabilityEvaluator.hpp"
41
42#include <iostream>
43
44#include "Atom/atom.hpp"
45#include "Bond/bond.hpp"
46#include "Fragmentation/Homology/HomologyContainer.hpp"
47#include "Fragmentation/Homology/HomologyGraph.hpp"
48#include "Fragmentation/KeySet.hpp"
49#include "molecule.hpp"
50#include "World.hpp"
51
52
53StabilityEvaluator::StabilityEvaluator(const molecule * _mol):
54 mol(_mol),
55 container(World::getInstance().getHomologies())
56{
57
58}
59
60
61/**
62 * Graph discovery to find the keyset if we exclude a bond from a connected
63 * graph.
64 */
65KeySet discoverKeySetsFromAtomOnExcludedBond(
66 const atom *_startatom,
67 const bond::ptr &_bond) {
68 KeySet result;
69
70 std::stack<const atom *> atoms_to_visit;
71 atoms_to_visit.push(_startatom);
72
73 result.insert(_startatom->getId());
74 while (!atoms_to_visit.empty()) {
75 const atom * Walker = atoms_to_visit.top();
76 atoms_to_visit.pop();
77 const BondList& ListOfBonds = Walker->getListOfBonds();
78 for (BondList::const_iterator bonditer = ListOfBonds.begin();
79 bonditer != ListOfBonds.end(); ++bonditer) {
80 // exclude the given bond
81 if (*bonditer != _bond) {
82 const atom * OtherAtom = (*bonditer)->GetOtherAtom(Walker);
83 // have we seen the atom already_
84 if (result.count(OtherAtom->getId()) == 0) {
85 result.insert(OtherAtom->getId());
86 atoms_to_visit.push(OtherAtom);
87 }
88 }
89 }
90 }
91
92 return result;
93}
94
95
96template <class N, class G>
97void insertInto(const N &item, G &_list) {
98 std::pair<typename G::iterator, bool> inserter = _list.insert(std::make_pair(item, (size_t)1));
99 if (!inserter.second) {
100 ++(inserter.first->second);
101 }
102}
103
104std::string getFormulaFrom(const HomologyGraph &graph) {
105 Formula formula;
106 for (HomologyGraph::nodes_t::const_iterator iter = graph.getNodes().begin();
107 iter != graph.getNodes().end(); ++iter)
108 for (size_t i=0;i<(*iter).second;++i)
109 formula += (*iter).first.getAtomicNumber();
110 return formula.toString();
111}
112
113HomologyGraph createHydrogenMoleculeHomologyGraph() {
114 HomologyGraph::nodes_t nodes;
115 // two hydrogen atoms
116 const FragmentNode node = FragmentNode((atomicNumber_t)1, 1);
117 insertInto(node, nodes);
118 insertInto(node, nodes);
119 // one hydrogen bond/edge
120 HomologyGraph::edges_t edges;
121 const FragmentEdge edge = FragmentEdge((atomicNumber_t)1, (atomicNumber_t)1);
122 insertInto(edge, edges);
123 // and return
124 return HomologyGraph(nodes, edges);
125
126}
127
128StabilityEvaluator::stabilities_t StabilityEvaluator::operator()() const {
129 stabilities_t stabilities;
130
131 // gather all non-hydrogen bonds of the molecule
132 typedef std::set<bond::ptr> bondset_t;
133 bondset_t non_hydrogen_bonds;
134 for (molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) {
135 const BondList& ListOfBonds = (*iter)->getListOfBonds();
136 for (BondList::const_iterator bonditer = ListOfBonds.begin();
137 bonditer != ListOfBonds.end(); ++bonditer) {
138 if ((*bonditer)->HydrogenBond == 0)
139 non_hydrogen_bonds.insert(*bonditer );
140 }
141 }
142 stabilities.reserve(non_hydrogen_bonds.size());
143
144 // create homology graph for full molecule
145 const HomologyGraph fullgraph(mol->getAtomIds());
146 const std::string fullgraph_formula = mol->getFormula().toString();
147 const HomologyGraph hydrogengraph = createHydrogenMoleculeHomologyGraph();
148
149 // get the energy of the educts
150 const double energy_fullgraph = getLowestEnergyFromHomologyContainer(fullgraph);
151 const double energy_hydrogen_molecule = getLowestEnergyFromHomologyContainer(hydrogengraph);
152
153 // go through every discovered non-hydrogen bond
154 for (bondset_t::iterator bonditer = non_hydrogen_bonds.begin();
155 bonditer != non_hydrogen_bonds.end(); ++bonditer) {
156 const bond::ptr &bondptr = (*bonditer);
157
158 // create stability criterion structure to fill
159 StabilityCriterion criterion;
160 criterion.energy_educts = energy_fullgraph + bondptr->getDegree() * energy_hydrogen_molecule;
161 criterion.formula_educt1 = fullgraph_formula;
162 criterion.formula_educt2 = "H"+toString(bondptr->getDegree()*2);
163
164 // create graphs for each set
165 const HomologyGraph leftgraph(
166 discoverKeySetsFromAtomOnExcludedBond(bondptr->leftatom, *bonditer)
167 );
168 const HomologyGraph rightgraph(
169 discoverKeySetsFromAtomOnExcludedBond(bondptr->rightatom, *bonditer)
170 );
171
172 // look up energy for each graph in the homology container
173 criterion.energy_products =
174 getLowestEnergyFromHomologyContainer(leftgraph)
175 + getLowestEnergyFromHomologyContainer(rightgraph);
176 criterion.formula_product1 = getFormulaFrom(leftgraph);
177 criterion.formula_product2 = getFormulaFrom(rightgraph);
178 criterion.isStable = criterion.energy_educts < criterion.energy_products;
179 stabilities.push_back(criterion);
180 }
181
182 return stabilities;
183}
184
185double StabilityEvaluator::getLowestEnergyFromHomologyContainer(const HomologyGraph &nodes_graph) const {
186 HomologyContainer::range_t range = container.getHomologousGraphs(nodes_graph);
187
188 if (range.first == range.second) {
189 // range is empty, the fragment is unknown
190 ELOG(1, "Cannot find fragment graph " << nodes_graph << " .");
191 return 0.;
192 } else {
193 // list lowest energy
194 const HomologyContainer::const_iterator lowest_contribution_graph =
195 std::min_element(range.first, range.second, HomologyContainer::compareEnergy);
196 const HomologyContainer::const_iterator highest_contribution_graph =
197 std::max_element(range.first, range.second, HomologyContainer::compareEnergy);
198 LOG(2, "INFO: Fragment graph " << nodes_graph << " has energy contributions from "
199 << lowest_contribution_graph->second.fragmentenergy << " Ht till "
200 << highest_contribution_graph->second.fragmentenergy << " Ht, picking lowest.");
201 return lowest_contribution_graph->second.fragmentenergy;
202 }
203}
204
205void createHomologyGraphFromMolecule() {
206 HomologyGraph::nodes_t graph_nodes;
207 HomologyGraph::edges_t graph_edges;
208}
209
210std::ostream& operator<<(std::ostream &ost, const StabilityEvaluator::StabilityCriterion &_stability) {
211 ost << _stability.formula_educt1 << " + " << _stability.formula_educt2
212 << " (" << _stability.energy_educts << " Ht) < "
213 << _stability.formula_product1 << " + " << _stability.formula_product2
214 << " (" << _stability.energy_products << " Ht) ? "
215 << _stability.isStable;
216 return ost;
217}
Note: See TracBrowser for help on using the repository browser.