Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-15 08:59:24

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] = std::move(avec);
0117   }
0118 
0119   // std::vector< G4double > avec ( numberOfVariable , 0.0 );
0120   std::vector<G4double> avec(numberOfVariable, 1);
0121   currentSimplex[numberOfVariable] = std::move(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   G4double sum =
0204     std::accumulate(currentHeights.begin(), currentHeights.end(), 0.0);
0205   G4double average = sum / (numberOfVariable + 1);
0206 
0207   G4double delta = 0.0;
0208   for(G4int i = 0; i <= numberOfVariable; ++i)
0209   {
0210     delta += std::abs(currentHeights[i] - average);
0211   }
0212 
0213   G4bool result = false;
0214   if (average > 0.0)
0215   {
0216     result = ((delta / (numberOfVariable + 1) / average) < max_ratio);
0217   }
0218   return result;
0219 }
0220 
0221 template <class T>
0222 void G4SimplexDownhill<T>::doDownhill()
0223 {
0224   G4int nth_trial = 0;
0225 
0226   while(nth_trial < maximum_no_trial)
0227   {
0228     calHeights();
0229 
0230     if(isItGoodEnough())
0231     {
0232       break;
0233     }
0234 
0235     auto it_maxh = std::max_element(currentHeights.cbegin(), currentHeights.cend());
0236     auto it_minh = std::min_element(currentHeights.cbegin(), currentHeights.cend());
0237 
0238     G4double h_H = *it_maxh;
0239     G4double h_L = *it_minh;
0240 
0241     G4int ih      = 0;
0242     G4int il      = 0;
0243     G4double h_H2 = 0.0;
0244     G4int i       = 0;
0245     for(auto it = currentHeights.cbegin(); it != currentHeights.cend(); ++it)
0246     {
0247       if(it == it_maxh)
0248       {
0249         ih = i;
0250       }
0251       else
0252       {
0253         h_H2 = std::max(h_H2, *it);
0254       }
0255 
0256       if(it == it_minh)
0257       {
0258         il = i;
0259       }
0260       ++i;
0261     }
0262 
0263     std::vector<G4double> centroidPoint = calCentroid(ih);
0264 
0265     // REFLECTION
0266     std::vector<G4double> reflectionPoint =
0267       getReflectionPoint(currentSimplex[ih], centroidPoint);
0268 
0269     G4double h = getValue(reflectionPoint);
0270 
0271     if(h <= h_L)
0272     {
0273       // EXPANSION
0274       std::vector<G4double> expansionPoint =
0275         getExpansionPoint(reflectionPoint, std::move(centroidPoint));
0276       G4double hh = getValue(expansionPoint);
0277 
0278       if(hh <= h_L)
0279       {
0280         // Replace
0281         currentSimplex[ih] = std::move(expansionPoint);
0282         // G4cout << "A" << G4endl;
0283       }
0284       else
0285       {
0286         // Replace
0287         currentSimplex[ih] = std::move(reflectionPoint);
0288         // G4cout << "B1" << G4endl;
0289       }
0290     }
0291     else
0292     {
0293       if(h <= h_H2)
0294       {
0295         // Replace
0296         currentSimplex[ih] = std::move(reflectionPoint);
0297         // G4cout << "B2" << G4endl;
0298       }
0299       else
0300       {
0301         if(h <= h_H)
0302         {
0303           // Replace
0304           currentSimplex[ih] = std::move(reflectionPoint);
0305           // G4cout << "BC" << G4endl;
0306         }
0307         // CONTRACTION
0308         std::vector<G4double> contractionPoint =
0309           getContractionPoint(currentSimplex[ih], std::move(centroidPoint));
0310         G4double hh = getValue(contractionPoint);
0311         if(hh <= h_H)
0312         {
0313           // Replace
0314           currentSimplex[ih] = std::move(contractionPoint);
0315           // G4cout << "C" << G4endl;
0316         }
0317         else
0318         {
0319           // Replace
0320           for(G4int j = 0; j <= numberOfVariable; ++j)
0321           {
0322             std::vector<G4double> vec(numberOfVariable, 0.0);
0323             for(G4int k = 0; k < numberOfVariable; ++k)
0324             {
0325               vec[k] = (currentSimplex[j][k] + currentSimplex[il][k]) / 2.0;
0326             }
0327             currentSimplex[j] = std::move(vec);
0328           }
0329         }
0330       }
0331     }
0332 
0333     ++nth_trial;
0334   }
0335 }
0336 
0337 template <class T>
0338 std::vector<G4double> G4SimplexDownhill<T>::GetMinimumPoint()
0339 {
0340   if(!minimized)
0341   {
0342     GetMinimum();
0343   }
0344 
0345   auto it_minh = std::min_element(currentHeights.cbegin(), currentHeights.cend());
0346 
0347   G4int imin = 0;
0348   G4int i    = 0;
0349   for(auto it = currentHeights.cbegin(); it != currentHeights.cend(); ++it)
0350   {
0351     if(it == it_minh)
0352     {
0353       imin = i;
0354     }
0355     ++i;
0356   }
0357   minimumPoint = currentSimplex[imin];
0358 
0359   return minimumPoint;
0360 }