Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:59:05

0001 //
0002 // ********************************************************************
0003 // * License and Disclaimer                                           *
0004 // *                                                                  *
0005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
0006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
0007 // * conditions of the Geant4 Software License,  included in the file *
0008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
0009 // * include a list of copyright holders.                             *
0010 // *                                                                  *
0011 // * Neither the authors of this software system, nor their employing *
0012 // * institutes,nor the agencies providing financial support for this *
0013 // * work  make  any representation or  warranty, express or implied, *
0014 // * regarding  this  software system or assume any liability for its *
0015 // * use.  Please see the license in the file  LICENSE  and URL above *
0016 // * for the full disclaimer and the limitation of liability.         *
0017 // *                                                                  *
0018 // * This  code  implementation is the result of  the  scientific and *
0019 // * technical work of the GEANT4 collaboration.                      *
0020 // * By using,  copying,  modifying or  distributing the software (or *
0021 // * any work based  on the software)  you  agree  to acknowledge its *
0022 // * use  in  resulting  scientific  publications,  and indicate your *
0023 // * acceptance of all terms of the Geant4 Software license.          *
0024 // ********************************************************************
0025 //
0026 // G4SimplexDownhill inline methods implementation
0027 //
0028 // Author: Tatsumi Koi (SLAC/SCCS), 2007
0029 // --------------------------------------------------------------------------
0030 
0031 #include <cfloat>
0032 #include <iostream>
0033 #include <numeric>
0034 
0035 template <class T>
0036 void G4SimplexDownhill<T>::init()
0037 {
0038   alpha = 2.0;  // refrection coefficient:  0 < alpha
0039   beta  = 0.5;  // contraction coefficient:   0 < beta < 1
0040   gamma = 2.0;  // expantion coefficient:  1 < gamma
0041 
0042   maximum_no_trial = 10000;
0043   max_se           = FLT_MIN;
0044   // max_ratio = FLT_EPSILON/1;
0045   max_ratio = DBL_EPSILON / 1;
0046   minimized = false;
0047 }
0048 
0049 /*
0050 
0051 void G4SimplexDownhill<class T>::
0052 SetFunction( G4int n , G4double( *afunc )( std::vector < G4double > ) )
0053 {
0054    numberOfVariable = n;
0055    theFunction = afunc;
0056    minimized = false;
0057 }
0058 
0059 */
0060 
0061 template <class T>
0062 G4double G4SimplexDownhill<T>::GetMinimum()
0063 {
0064   initialize();
0065 
0066   // First Tryal;
0067 
0068   // G4cout << "Begin First Trials" << G4endl;
0069   doDownhill();
0070   // G4cout << "End First Trials" << G4endl;
0071 
0072   auto it_minh = std::min_element(currentHeights.cbegin(), currentHeights.cend());
0073   G4int imin = 0;
0074   G4int i    = 0;
0075   for(auto it = currentHeights.cbegin(); it != currentHeights.cend(); ++it)
0076   {
0077     if(it == it_minh)
0078     {
0079       imin = i;
0080     }
0081     ++i;
0082   }
0083   minimumPoint = currentSimplex[imin];
0084 
0085   // Second Trial
0086 
0087   // std::vector< G4double > minimumPoint = currentSimplex[ 0 ];
0088   initialize();
0089 
0090   currentSimplex[numberOfVariable] = minimumPoint;
0091 
0092   // G4cout << "Begin Second Trials" << G4endl;
0093   doDownhill();
0094   // G4cout << "End Second Trials" << G4endl;
0095 
0096   G4double sum =
0097     std::accumulate(currentHeights.begin(), currentHeights.end(), 0.0);
0098   G4double average = sum / (numberOfVariable + 1);
0099   G4double minimum = average;
0100 
0101   minimized = true;
0102 
0103   return minimum;
0104 }
0105 
0106 template <class T>
0107 void G4SimplexDownhill<T>::initialize()
0108 {
0109   currentSimplex.resize(numberOfVariable + 1);
0110   currentHeights.resize(numberOfVariable + 1);
0111 
0112   for(G4int i = 0; i < numberOfVariable; ++i)
0113   {
0114     std::vector<G4double> avec(numberOfVariable, 0.0);
0115     avec[i]           = 1.0;
0116     currentSimplex[i] = avec;
0117   }
0118 
0119   // std::vector< G4double > avec ( numberOfVariable , 0.0 );
0120   std::vector<G4double> avec(numberOfVariable, 1);
0121   currentSimplex[numberOfVariable] = avec;
0122 }
0123 
0124 template <class T>
0125 void G4SimplexDownhill<T>::calHeights()
0126 {
0127   for(G4int i = 0; i <= numberOfVariable; ++i)
0128   {
0129     currentHeights[i] = getValue(currentSimplex[i]);
0130   }
0131 }
0132 
0133 template <class T>
0134 std::vector<G4double> G4SimplexDownhill<T>::calCentroid(G4int ih)
0135 {
0136   std::vector<G4double> centroid(numberOfVariable, 0.0);
0137 
0138   G4int i = 0;
0139   for(const auto & it : currentSimplex)
0140   {
0141     if(i != ih)
0142     {
0143       for(G4int j = 0; j < numberOfVariable; ++j)
0144       {
0145         centroid[j] += it[j] / numberOfVariable;
0146       }
0147     }
0148     ++i;
0149   }
0150 
0151   return centroid;
0152 }
0153 
0154 template <class T>
0155 std::vector<G4double> G4SimplexDownhill<T>::getReflectionPoint(
0156   std::vector<G4double> p, std::vector<G4double> centroid)
0157 {
0158   // G4cout << "Reflection" << G4endl;
0159 
0160   std::vector<G4double> reflectionP(numberOfVariable, 0.0);
0161 
0162   for(G4int i = 0; i < numberOfVariable; ++i)
0163   {
0164     reflectionP[i] = (1 + alpha) * centroid[i] - alpha * p[i];
0165   }
0166 
0167   return reflectionP;
0168 }
0169 
0170 template <class T>
0171 std::vector<G4double> G4SimplexDownhill<T>::getExpansionPoint(
0172   std::vector<G4double> p, std::vector<G4double> centroid)
0173 {
0174   // G4cout << "Expantion" << G4endl;
0175 
0176   std::vector<G4double> expansionP(numberOfVariable, 0.0);
0177 
0178   for(G4int i = 0; i < numberOfVariable; ++i)
0179   {
0180     expansionP[i] = (1 - gamma) * centroid[i] + gamma * p[i];
0181   }
0182 
0183   return expansionP;
0184 }
0185 
0186 template <class T>
0187 std::vector<G4double> G4SimplexDownhill<T>::getContractionPoint(
0188   std::vector<G4double> p, std::vector<G4double> centroid)
0189 {
0190   std::vector<G4double> contractionP(numberOfVariable, 0.0);
0191 
0192   for(G4int i = 0; i < numberOfVariable; ++i)
0193   {
0194     contractionP[i] = (1 - beta) * centroid[i] + beta * p[i];
0195   }
0196 
0197   return contractionP;
0198 }
0199 
0200 template <class T>
0201 G4bool G4SimplexDownhill<T>::isItGoodEnough()
0202 {
0203   G4bool result = false;
0204 
0205   G4double sum =
0206     std::accumulate(currentHeights.begin(), currentHeights.end(), 0.0);
0207   G4double average = sum / (numberOfVariable + 1);
0208 
0209   G4double delta = 0.0;
0210   for(G4int i = 0; i <= numberOfVariable; ++i)
0211   {
0212     delta += std::abs(currentHeights[i] - average);
0213   }
0214 
0215   if(delta / (numberOfVariable + 1) / average < max_ratio)
0216   {
0217     result = true;
0218   }
0219 
0220   return result;
0221 }
0222 
0223 template <class T>
0224 void G4SimplexDownhill<T>::doDownhill()
0225 {
0226   G4int nth_trial = 0;
0227 
0228   while(nth_trial < maximum_no_trial)
0229   {
0230     calHeights();
0231 
0232     if(isItGoodEnough())
0233     {
0234       break;
0235     }
0236 
0237     auto it_maxh = std::max_element(currentHeights.cbegin(), currentHeights.cend());
0238     auto it_minh = std::min_element(currentHeights.cbegin(), currentHeights.cend());
0239 
0240     G4double h_H = *it_maxh;
0241     G4double h_L = *it_minh;
0242 
0243     G4int ih      = 0;
0244     G4int il      = 0;
0245     G4double h_H2 = 0.0;
0246     G4int i       = 0;
0247     for(auto it = currentHeights.cbegin(); it != currentHeights.cend(); ++it)
0248     {
0249       if(it == it_maxh)
0250       {
0251         ih = i;
0252       }
0253       else
0254       {
0255         h_H2 = std::max(h_H2, *it);
0256       }
0257 
0258       if(it == it_minh)
0259       {
0260         il = i;
0261       }
0262       ++i;
0263     }
0264 
0265     std::vector<G4double> centroidPoint = calCentroid(ih);
0266 
0267     // REFLECTION
0268     std::vector<G4double> reflectionPoint =
0269       getReflectionPoint(currentSimplex[ih], centroidPoint);
0270 
0271     G4double h = getValue(reflectionPoint);
0272 
0273     if(h <= h_L)
0274     {
0275       // EXPANSION
0276       std::vector<G4double> expansionPoint =
0277         getExpansionPoint(reflectionPoint, centroidPoint);
0278       G4double hh = getValue(expansionPoint);
0279 
0280       if(hh <= h_L)
0281       {
0282         // Replace
0283         currentSimplex[ih] = expansionPoint;
0284         // G4cout << "A" << G4endl;
0285       }
0286       else
0287       {
0288         // Replace
0289         currentSimplex[ih] = reflectionPoint;
0290         // G4cout << "B1" << G4endl;
0291       }
0292     }
0293     else
0294     {
0295       if(h <= h_H2)
0296       {
0297         // Replace
0298         currentSimplex[ih] = reflectionPoint;
0299         // G4cout << "B2" << G4endl;
0300       }
0301       else
0302       {
0303         if(h <= h_H)
0304         {
0305           // Replace
0306           currentSimplex[ih] = reflectionPoint;
0307           // G4cout << "BC" << G4endl;
0308         }
0309         // CONTRACTION
0310         std::vector<G4double> contractionPoint =
0311           getContractionPoint(currentSimplex[ih], centroidPoint);
0312         G4double hh = getValue(contractionPoint);
0313         if(hh <= h_H)
0314         {
0315           // Replace
0316           currentSimplex[ih] = contractionPoint;
0317           // G4cout << "C" << G4endl;
0318         }
0319         else
0320         {
0321           // Replace
0322           for(G4int j = 0; j <= numberOfVariable; ++j)
0323           {
0324             std::vector<G4double> vec(numberOfVariable, 0.0);
0325             for(G4int k = 0; k < numberOfVariable; ++k)
0326             {
0327               vec[k] = (currentSimplex[j][k] + currentSimplex[il][k]) / 2.0;
0328             }
0329             currentSimplex[j] = vec;
0330           }
0331         }
0332       }
0333     }
0334 
0335     ++nth_trial;
0336   }
0337 }
0338 
0339 template <class T>
0340 std::vector<G4double> G4SimplexDownhill<T>::GetMinimumPoint()
0341 {
0342   if(!minimized)
0343   {
0344     GetMinimum();
0345   }
0346 
0347   auto it_minh = std::min_element(currentHeights.cbegin(), currentHeights.cend());
0348 
0349   G4int imin = 0;
0350   G4int i    = 0;
0351   for(auto it = currentHeights.cbegin(); it != currentHeights.cend(); ++it)
0352   {
0353     if(it == it_minh)
0354     {
0355       imin = i;
0356     }
0357     ++i;
0358   }
0359   minimumPoint = currentSimplex[imin];
0360 
0361   return minimumPoint;
0362 }