source: src/Fragmentation/Exporters/SaturationDistanceMaximizer.cpp

Candidate_v1.6.1
Last change on this file was 9eb71b3, checked in by Frederik Heber <frederik.heber@…>, 8 years ago

Commented out MemDebug include and Memory::ignore.

  • MemDebug clashes with various allocation operators that use a specific placement in memory. It is so far not possible to wrap new/delete fully. Hence, we stop this effort which so far has forced us to put ever more includes (with clashes) into MemDebug and thereby bloat compilation time.
  • MemDebug does not add that much usefulness which is not also provided by valgrind.
  • Property mode set to 100644
File size: 10.1 KB
Line 
1/*
2 * Project: MoleCuilder
3 * Description: creates and alters molecular systems
4 * Copyright (C) 2014 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 * SaturationDistanceMaximizer.cpp
25 *
26 * Created on: Jul 27, 2014
27 * Author: heber
28 */
29
30// include config.h
31#ifdef HAVE_CONFIG_H
32#include <config.h>
33#endif
34
35//#include "CodePatterns/MemDebug.hpp"
36
37#include "SaturationDistanceMaximizer.hpp"
38
39#include <cmath>
40#include <gsl/gsl_multimin.h>
41#include <gsl/gsl_vector.h>
42
43#include "CodePatterns/Log.hpp"
44
45double
46func(const gsl_vector *x, void *adata)
47{
48 // get the object whose functions we call
49 SaturationDistanceMaximizer::Advocate *maximizer =
50 static_cast<SaturationDistanceMaximizer::Advocate *>(adata);
51 // set alphas
52 maximizer->setAlphas(x);
53 // calculate function value and return
54 return maximizer->calculatePenality();
55}
56
57void
58jacf(const gsl_vector *x, void *adata, gsl_vector *g)
59{
60 // get the object whose functions we call
61 SaturationDistanceMaximizer::Advocate *maximizer =
62 static_cast<SaturationDistanceMaximizer::Advocate *>(adata);
63 // set alphas
64 maximizer->setAlphas(x);
65 // calculate function gradient and return
66 std::vector<double> gradient = maximizer->calculatePenalityGradient();
67 for (unsigned int i=0;i<gradient.size();++i)
68 gsl_vector_set(g,i,gradient[i]);
69}
70
71void
72funcjacf(const gsl_vector *x, void *adata, double *f, gsl_vector *g)
73{
74 // get the object whose functions we call
75 SaturationDistanceMaximizer::Advocate *maximizer =
76 static_cast<SaturationDistanceMaximizer::Advocate *>(adata);
77 // set alphas
78 maximizer->setAlphas(x);
79 // calculate function value and return
80 *f = maximizer->calculatePenality();
81 std::vector<double> gradient = maximizer->calculatePenalityGradient();
82 for (unsigned int i=0;i<gradient.size();++i)
83 gsl_vector_set(g,i,gradient[i]);
84}
85
86std::vector<double> SaturationDistanceMaximizer::getAlphas() const
87{
88 std::vector<double> alphas;
89 PositionContainers_t::iterator containeriter = PositionContainers.begin();
90 for (unsigned int i=0; i<PositionContainers.size(); ++i, ++containeriter)
91 alphas.push_back( (*containeriter)->alpha );
92 return alphas;
93}
94
95void SaturationDistanceMaximizer::setAlphas(const gsl_vector *x)
96{
97 PositionContainers_t::iterator containeriter = PositionContainers.begin();
98 for (unsigned int i=0; i<PositionContainers.size(); ++i, ++containeriter)
99 (*containeriter)->alpha = gsl_vector_get(x,i);
100}
101
102void SaturationDistanceMaximizer::operator()()
103{
104 // some control constants
105 const double tolerance = 1e-6;
106 const unsigned int MAXITERATIONS = 100;
107
108 const gsl_multimin_fdfminimizer_type *T;
109 gsl_multimin_fdfminimizer *s;
110
111 gsl_vector *x;
112 gsl_multimin_function_fdf my_func;
113
114 const unsigned int N = PositionContainers.size();
115 my_func.n = N;
116 my_func.f = &func;
117 my_func.df = &jacf;
118 my_func.fdf = &funcjacf;
119 SaturationDistanceMaximizer::Advocate* const advocate = getAdvocate();
120 my_func.params = advocate;
121
122 // allocate argument and set to zero
123 x = gsl_vector_alloc(N);
124 for (unsigned int i=0;i<N;++i)
125 gsl_vector_set(x, i, 0.);
126
127 // set minimizer and allocate workspace
128 T = gsl_multimin_fdfminimizer_vector_bfgs;
129 s = gsl_multimin_fdfminimizer_alloc (T, N);
130
131 // initialize minimizer
132 gsl_multimin_fdfminimizer_set(s, &my_func, x, 0.1, tolerance); /* tolerance */
133
134 size_t iter = 0;
135 int status = 0;
136 do {
137 ++iter;
138 status = gsl_multimin_fdfminimizer_iterate(s);
139
140 if (status)
141 break;
142
143 status = gsl_multimin_test_gradient(s->gradient, tolerance);
144
145 } while ((status = GSL_CONTINUE) && (iter < MAXITERATIONS));
146
147 // set to solution
148 setAlphas(s->x);
149
150 // print solution
151 if (DoLog(4)) {
152 std::stringstream sstream;
153 sstream << "DEBUG: Minimal alphas are ";
154 for (unsigned int i=0;i<N;++i)
155 sstream << gsl_vector_get(s->x,i) << ((i!= N-1) ? "," : "");
156 LOG(4, sstream.str());
157 }
158
159 // free memory
160 gsl_multimin_fdfminimizer_free(s);
161 my_func.params = NULL;
162 delete advocate;
163 gsl_vector_free(x);
164}
165
166SaturationDistanceMaximizer::Advocate* SaturationDistanceMaximizer::getAdvocate()
167{
168 return new Advocate(*this);
169}
170
171SaturationDistanceMaximizer::position_bins_t
172SaturationDistanceMaximizer::getAllPositionBins() const
173{
174 position_bins_t position_bins;
175 position_bins.reserve(PositionContainers.size());
176 for (PositionContainers_t::const_iterator containeriter = PositionContainers.begin();
177 containeriter != PositionContainers.end(); ++containeriter)
178 position_bins.push_back( (*containeriter)->getPositions() );
179
180 return position_bins;
181}
182
183double SaturationDistanceMaximizer::calculatePenality() const
184{
185 double penalty = 0.;
186
187 LOG(6, "DEBUG: Current alphas are " << getAlphas());
188
189 // gather all positions
190 position_bins_t position_bins = getAllPositionBins();
191
192 // go through both bins (but with i<j)
193 for (position_bins_t::const_iterator firstbiniter = position_bins.begin();
194 firstbiniter != position_bins.end(); ++firstbiniter) {
195 for (position_bins_t::const_iterator secondbiniter = firstbiniter;
196 secondbiniter != position_bins.end(); ++secondbiniter) {
197 if (firstbiniter == secondbiniter)
198 continue;
199
200 // then in each bin take each position
201 for (SaturatedBond::positions_t::const_iterator firstpositioniter = firstbiniter->begin();
202 firstpositioniter != firstbiniter->end(); ++firstpositioniter) {
203 for (SaturatedBond::positions_t::const_iterator secondpositioniter = secondbiniter->begin();
204 secondpositioniter != secondbiniter->end(); ++secondpositioniter) {
205 // Both iters are from different bins, can never be the same.
206 // We do not penalize over positions from same bin as their positions
207 // are fixed.
208
209 // We penalize by one over the squared distance
210 penalty += 1./(firstpositioniter->DistanceSquared(*secondpositioniter));
211 }
212 }
213 }
214 }
215
216 LOG(4, "DEBUG: Penalty is " << penalty);
217
218 return penalty;
219}
220
221#ifdef HAVE_INLINE
222inline
223#else
224static
225#endif
226size_t calculateHydrogenNo(
227 const SaturatedBond::positions_t::const_iterator &_start,
228 const SaturatedBond::positions_t::const_iterator &_current)
229{
230 const size_t HydrogenNo = std::distance(_start, _current);
231 ASSERT( (HydrogenNo >= 0) && (HydrogenNo <= 2),
232 "calculatePenalityGradient() - hydrogen no not in [0,2].");
233 return HydrogenNo;
234}
235
236std::vector<double> SaturationDistanceMaximizer::calculatePenalityGradient() const
237{
238 // gather all positions
239 const position_bins_t position_bins = getAllPositionBins();
240 LOG(6, "DEBUG: Current alphas are " << getAlphas());
241
242 std::vector<double> gradient(position_bins.size(), 0.);
243
244 std::vector<double>::iterator biniter = gradient.begin();
245 PositionContainers_t::const_iterator bonditer = PositionContainers.begin();
246 position_bins_t::const_iterator firstbiniter = position_bins.begin();
247 // go through each bond/gradient component/alpha
248 for(; biniter != gradient.end(); ++biniter, ++bonditer, ++firstbiniter) {
249 LOG(5, "DEBUG: Current bond is " << **bonditer << ", current bin is #"
250 << std::distance(gradient.begin(), biniter) << ", set of positions are "
251 << *firstbiniter);
252 // skip bin if it belongs to a degree-1 bond (no alpha dependency here)
253 if ((*bonditer)->saturated_bond.getDegree() == 1) {
254 LOG(6, "DEBUG: Skipping due to degree 1.");
255 continue;
256 }
257
258 // in the bin go through each position
259 for (SaturatedBond::positions_t::const_iterator firstpositioniter = firstbiniter->begin();
260 firstpositioniter != firstbiniter->end(); ++firstpositioniter) {
261 LOG(6, "DEBUG: Current position is " << *firstpositioniter);
262
263 // count the hydrogen we are looking at: Each is placed at a different position!
264 const size_t HydrogenNo =
265 calculateHydrogenNo(firstbiniter->begin(), firstpositioniter);
266 const double alpha = (*bonditer)->alpha
267 + (double)HydrogenNo * 2.*M_PI/(double)(*bonditer)->saturated_bond.getDegree();
268 LOG(6, "DEBUG: HydrogenNo is " << HydrogenNo << ", alpha is " << alpha);
269
270 // and go through each other bin
271 for (position_bins_t::const_iterator secondbiniter = position_bins.begin();
272 secondbiniter != position_bins.end(); ++secondbiniter) {
273 // distance between hydrogens in same bin is not affected by the angle
274// if (firstbiniter == secondbiniter)
275// continue;
276
277 // in the other bin go through each position
278 for (SaturatedBond::positions_t::const_iterator secondpositioniter = secondbiniter->begin();
279 secondpositioniter != secondbiniter->end(); ++secondpositioniter) {
280 if (firstpositioniter == secondpositioniter) {
281 LOG(7, "DEBUG: Skipping due to same positions.");
282 continue;
283 }
284 LOG(7, "DEBUG: Second position is " << *secondpositioniter);
285
286 // iters are from different bins, can never be the same
287 const Vector distance = *firstpositioniter - *secondpositioniter;
288 const double temp = -2./pow(distance.NormSquared(), 2);
289 const Vector tempVector =
290 (-sin(alpha)*(*bonditer)->vector_a)
291 +(cos(alpha)*(*bonditer)->vector_b);
292 const double result = temp * (distance.ScalarProduct(tempVector));
293 *biniter += 2.*result; //for x_i and x_j
294 LOG(7, "DEBUG: Total is " << result << ", temp is " << temp << ", tempVector is " << tempVector
295 << ", and bondVector is " << distance << ": bin = " << *biniter);
296 }
297 }
298 }
299 }
300
301 LOG(4, "DEBUG: Gradient of penalty is " << gradient);
302
303 return gradient;
304}
305
Note: See TracBrowser for help on using the repository browser.