ProSHADE  0.6.5 (NOV 2018)
Protein Shape Descriptors and Symmetry Detection
ProSHADE_legendre.h
Go to the documentation of this file.
1 
24 #ifndef __LEGENDRE_PROSHADE__
25 #define __LEGENDRE_PROSHADE__
26 
27 //============================================ Standard Library
28 #include <iostream>
29 #include <cmath>
30 #include <vector>
31 
32 //============================================ RVAPI
33 #include <rvapi_interface.h>
34 
42 {
55  inline void getPolyAtZero ( unsigned int order,
56  double *polyValue,
57  double *deriValue )
58  {
59  //==================================== Initialise
60  double hlpVal = 0.0;
61  double prevPoly = 1.0;
62  double prevPrevPoly = 0.0;
63  double prevDeri = 0.0;
64  double prevPrevDeri = 0.0;
65 
66  for ( unsigned int ordIt = 0; ordIt < order; ordIt++ )
67  {
68  hlpVal = static_cast<double> ( ordIt );
69  *polyValue = -hlpVal * prevPrevPoly / ( hlpVal + 1.0 );
70  *deriValue = ( ( 2.0 * hlpVal + 1.0 ) * prevPoly - hlpVal * prevPrevDeri ) / ( hlpVal + 1.0 );
71  prevPrevPoly = prevPoly;
72  prevPoly = *polyValue;
73  prevPrevDeri = prevDeri;
74  prevDeri = *deriValue;
75  }
76 
77  //==================================== Done
78  return ;
79 
80  }
81 
95  inline double advancePolyValue ( double from,
96  double to,
97  double valAtFrom,
98  unsigned int noSteps )
99  {
100  //==================================== Initialise
101  double hlpVal = 0.0;
102  double stepSize = 0.0;
103  double valChange = 0.0;
104  double valSecChange = 0.0;
105  double squareSteps = 0.0;
106  double curVal = 0.0;
107  unsigned int taylorSeriesCap = 10;
108 
109  stepSize = ( to - from ) / static_cast<double> ( taylorSeriesCap );
110  squareSteps = sqrt ( static_cast<double> ( noSteps * ( noSteps + 1 ) ) );
111  curVal = from;
112 
113  for ( unsigned int iter = 0; iter < taylorSeriesCap; iter++ )
114  {
115  hlpVal = ( 1.0 - valAtFrom ) * ( 1.0 + valAtFrom );
116  valChange = - stepSize * hlpVal / ( squareSteps * sqrt ( hlpVal ) - 0.5 * valAtFrom * sin ( 2.0 * curVal ) );
117  valAtFrom = valAtFrom + valChange;
118 
119  curVal = curVal + stepSize;
120 
121  hlpVal = ( 1.0 - valAtFrom ) * ( 1.0 + valAtFrom );
122  valSecChange = - stepSize * hlpVal / ( squareSteps * sqrt ( hlpVal ) - 0.5 * valAtFrom * sin ( 2.0 * curVal ) );
123  valAtFrom = valAtFrom + 0.5 * ( valSecChange - valChange );
124  }
125 
126  //==================================== Done
127  return valAtFrom;
128 
129  }
130 
144  inline double evaluateSeries ( double *series,
145  double target,
146  unsigned int terms )
147  {
148  //==================================== Initalise
149  double factorialValue = 1.0;
150  double value = 0.0;
151 
152  for ( unsigned int iter = 1; iter <= terms; iter++ )
153  {
154  value = value + series[iter] * factorialValue;
155  factorialValue = factorialValue * target;
156  }
157 
158  //==================================== Done
159  return ( value );
160 
161  }
162 
176  inline void getFirstEvenRoot ( double polyAtZero,
177  unsigned int order,
178  double *abscAtZero,
179  double *weighAtZero )
180  {
181  //==================================== Initialise
182  *abscAtZero = advancePolyValue ( 0.0, -M_PI / 2.0, 0.0, order );
183  double hlp = 0.0;
184  double hlpVal = static_cast<double> ( order );
185  unsigned int taylorSeriesCap = 30;
186  double *abscSteps;
187  double *weightSteps;
188 
189  //==================================== Allocate memory
190  abscSteps = new double [taylorSeriesCap+2];
191  weightSteps = new double [taylorSeriesCap+1];
192 
193  //==================================== Pre-set values
194  abscSteps[0] = 0.0;
195  abscSteps[1] = polyAtZero;
196  weightSteps[0] = 0.0;
197 
198  //==================================== Fill in abscissa and weight steps
199  for ( unsigned int iter = 0; iter <= taylorSeriesCap - 2; iter = iter + 2 )
200  {
201  hlp = static_cast<double> ( iter );
202 
203  abscSteps[iter+2] = 0.0;
204  abscSteps[iter+3] = ( hlp * ( hlp + 1.0 ) - hlpVal * ( hlpVal + 1.0 ) ) * abscSteps[iter+1] / (hlp + 1.0) / (hlp + 2.0 );
205 
206  weightSteps[iter+1] = 0.0;
207  weightSteps[iter+2] = ( hlp + 2.0 ) * abscSteps[iter+3];
208  }
209 
210  //==================================== Find abscissa and weights
211  for ( unsigned int iter = 0; iter < 5; iter++ )
212  {
213  *abscAtZero = *abscAtZero - evaluateSeries ( abscSteps, *abscAtZero, taylorSeriesCap ) / evaluateSeries ( weightSteps, *abscAtZero, taylorSeriesCap-1 );
214  }
215  *weighAtZero = evaluateSeries ( weightSteps,
216  *abscAtZero,
217  taylorSeriesCap-1 );
218 
219  //==================================== Free memory
220  delete abscSteps;
221  delete weightSteps;
222 
223  //==================================== Done
224  return ;
225 
226  }
227 
239  inline void completeLegendreSeries ( unsigned int order,
240  std::vector<double>* abscissa,
241  std::vector<double>* weights )
242  {
243  //==================================== Initialise
244  double hlpTaylorVal = 0.0;
245  double hlpOrderVal = static_cast<double> ( order );
246  double abscValueChange = 0.0;
247  double prevAbsc = 0.0;
248  double *hlpAbscSeries;
249  double *hlpWeightSeries;
250  unsigned int taylorSeriesCap = 30;
251  unsigned int noSeriesElems = 0;
252  unsigned int oddEvenSwitch = 0;
253 
254  //==================================== Pre-set values
255  if ( order % 2 == 1 )
256  {
257  noSeriesElems = ( order - 1 ) / 2 - 1;
258  oddEvenSwitch = 1;
259  }
260  else
261  {
262  noSeriesElems = order / 2 - 1;
263  oddEvenSwitch = 0;
264  }
265 
266  //==================================== Allocate memory
267  hlpAbscSeries = new double[taylorSeriesCap+2];
268  hlpWeightSeries = new double[taylorSeriesCap+1];
269 
270  //==================================== For each series element
271  for ( unsigned int serIt = noSeriesElems + 1; serIt < order - 1; serIt++ )
272  {
273  //================================ Init loop
274  prevAbsc = abscissa->at(serIt);
275  abscValueChange = advancePolyValue ( M_PI/2.0, -M_PI/2.0, prevAbsc, order ) - prevAbsc;
276 
277  //================================ Init abscissas
278  hlpAbscSeries[0] = 0.0;
279  hlpAbscSeries[1] = 0.0;
280  hlpAbscSeries[2] = weights->at(serIt);
281 
282  //================================ Init weights
283  hlpWeightSeries[0] = 0.0;
284  hlpWeightSeries[1] = hlpAbscSeries[2];
285 
286  //================================ Taylor expansion
287  for ( unsigned int tayIt = 0; tayIt <= taylorSeriesCap - 2; tayIt++ )
288  {
289  hlpTaylorVal = static_cast<double> ( tayIt );
290 
291  hlpAbscSeries[tayIt+3] = ( 2.0 * prevAbsc * ( hlpTaylorVal + 1.0 ) * hlpAbscSeries[tayIt+2]
292  + ( hlpTaylorVal * ( hlpTaylorVal + 1.0 ) - hlpOrderVal * ( hlpOrderVal + 1.0 ) ) * hlpAbscSeries[tayIt+1] /
293  ( hlpTaylorVal + 1.0 ) ) / ( 1.0 - prevAbsc ) / ( 1.0 + prevAbsc ) / ( hlpTaylorVal + 2.0 );
294 
295  hlpWeightSeries[tayIt+2] = ( hlpTaylorVal + 2.0 ) * hlpAbscSeries[tayIt+3];
296  }
297 
298  //================================ Sum over results
299  for ( unsigned int iter = 0; iter < 5; iter++ )
300  {
301  abscValueChange = abscValueChange - evaluateSeries ( hlpAbscSeries, abscValueChange, taylorSeriesCap ) /
302  evaluateSeries ( hlpWeightSeries, abscValueChange, taylorSeriesCap-1 );
303  }
304 
305  //================================ Save results
306  abscissa->at(serIt+1) = prevAbsc + abscValueChange;
307  weights->at(serIt+1) = evaluateSeries ( hlpWeightSeries, abscValueChange, taylorSeriesCap - 1 );
308  }
309 
310  for ( unsigned int serIt = 0; serIt <= noSeriesElems + oddEvenSwitch; serIt++ )
311  {
312  abscissa->at(serIt) = - abscissa->at(order-serIt-1);
313  weights->at(serIt) = weights->at(order-serIt-1);
314  }
315 
316  //==================================== Free memory
317  delete hlpAbscSeries;
318  delete hlpWeightSeries;
319 
320  //==================================== Done
321  return ;
322 
323  }
324 
337  inline void getLegendreAbscAndWeights ( unsigned int order,
338  std::vector<double>* abscissa,
339  std::vector<double>* weights,
340  ProSHADE::ProSHADE_settings* settings )
341  {
342  //==================================== Sanity check
343  if ( order < 1 )
344  {
345  std::cerr << "!!! ProSHADE ERROR !!! Trying to compute legendre quadrature with order " << order << " which seems too low!" << std::endl;
346 
347  if ( settings->htmlReport )
348  {
349  std::stringstream hlpSS;
350  hlpSS << "<font color=\"red\">" << "The automatic determination of the Gauss-Legendre integration order has determined the optimal order to be less than 1. This may happen for very small maps, if this is the case, please manually set the integration value to 10-ish and re-run. If the map is reasonably large, please report this as a bug." << "</font>";
351  rvapi_set_text ( hlpSS.str().c_str(),
352  "ProgressSection",
353  settings->htmlReportLineProgress,
354  1,
355  1,
356  1 );
357  settings->htmlReportLineProgress += 1;
358  rvapi_flush ( );
359  }
360 
361  exit ( -1 );
362  }
363 
364  //==================================== Initialise
365  double polyValue = 0.0;
366  double deriValue = 0.0;
367  double weightSum = 0.0;
368 
369  //==================================== Find the polynomial and derivative values at 0
370  getPolyAtZero ( order,
371  &polyValue,
372  &deriValue );
373 
374  //==================================== If the order is odd, then 0 is a root ...
375  if ( order % 2 == 1 )
376  {
377  abscissa->at((order-1)/2) = polyValue;
378  weights->at((order-1)/2) = deriValue;
379  }
380  else
381  {
382  // ... and if order is even, find the first root
383  getFirstEvenRoot ( polyValue, order, &abscissa->at(order/2), &weights->at(order/2) );
384  }
385 
386  //==================================== Now, having computed the first roots, complete the series
387  completeLegendreSeries ( order,
388  abscissa,
389  weights );
390 
391  //==================================== Correct weights by anscissa values
392  for ( unsigned int iter = 0; iter < order; iter++ )
393  {
394  weights->at(iter) = 2.0 / ( 1.0 - abscissa->at(iter) ) / ( 1.0 + abscissa->at(iter) ) / weights->at(iter) / weights->at(iter);
395  weightSum = weightSum + weights->at(iter);
396  }
397 
398  //==================================== Normalise weights
399  for ( unsigned int iter = 0; iter < order; iter++ )
400  {
401  weights->at(iter) = 2.0 * weights->at(iter) / weightSum;
402  }
403 
404  //==================================== Done
405  return ;
406 
407  }
408 }
409 
410 #endif
double advancePolyValue(double from, double to, double valAtFrom, unsigned int noSteps)
This function finds the next value of the polynomial.
bool htmlReport
Should HTML report for the run be created?
Definition: ProSHADE.h:186
int htmlReportLineProgress
Iterator for current HTML line in the progress bar.
Definition: ProSHADE.h:188
void completeLegendreSeries(unsigned int order, std::vector< double > *abscissa, std::vector< double > *weights)
This function completes the Legendre polynomial series assuming you have obtained the first values...
void getPolyAtZero(unsigned int order, double *polyValue, double *deriValue)
This function obtains the Legendre polynomial values and its derivative at zero for any positive inte...
void getFirstEvenRoot(double polyAtZero, unsigned int order, double *abscAtZero, double *weighAtZero)
This function finds the first root for Legendre polynomials of odd order.
This class stores all the settings and is passed to the executive classes instead of multitude of par...
Definition: ProSHADE.h:74
void getLegendreAbscAndWeights(unsigned int order, std::vector< double > *abscissa, std::vector< double > *weights, ProSHADE::ProSHADE_settings *settings)
This function takes everytging together and computes the abscissas and weights for the Gauss-Legendre...
double evaluateSeries(double *series, double target, unsigned int terms)
This function evaluates the Taylor expansion.