https://www.cdslab.org/paramonte/fortran/2
Current view: top level - main - pm_sampleACT@routines.inc.F90 (source / functions) Hit Total Coverage
Test: ParaMonte 2.0.0 :: Serial Fortran - Code Coverage Report Lines: 78 96 81.2 %
Date: 2024-04-08 03:18:57 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       2             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       3             : !!!!                                                                                                                            !!!!
       4             : !!!!    ParaMonte: Parallel Monte Carlo and Machine Learning Library.                                                           !!!!
       5             : !!!!                                                                                                                            !!!!
       6             : !!!!    Copyright (C) 2012-present, The Computational Data Science Lab                                                          !!!!
       7             : !!!!                                                                                                                            !!!!
       8             : !!!!    This file is part of the ParaMonte library.                                                                             !!!!
       9             : !!!!                                                                                                                            !!!!
      10             : !!!!    LICENSE                                                                                                                 !!!!
      11             : !!!!                                                                                                                            !!!!
      12             : !!!!       https://github.com/cdslaborg/paramonte/blob/main/LICENSE.md                                                          !!!!
      13             : !!!!                                                                                                                            !!!!
      14             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      15             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      16             : 
      17             : !>  \brief
      18             : !>  This file contains the implementation details of the 2D routines under the generic interface [pm_sampleACT](@ref pm_sampleACT).
      19             : !>
      20             : !>  \finmain
      21             : !>
      22             : !>  \author
      23             : !>  \FatemehBagheri, Saturday 4:40 PM, August 21, 2021, Dallas, TX
      24             : 
      25             : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      26             : 
      27             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      28             : #if     getACT_ENABLED && D1_ENABLED && DEF_ENABLED
      29             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      30             : 
      31           1 :         act = getACT(seq, batchMeans)
      32             : 
      33             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      34             : #elif   getACT_ENABLED && D1_ENABLED && BMM_ENABLED
      35             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      36             : 
      37             :         integer(IK) :: smin, smax, step, isize, lenseq
      38           2 :         smin = method%smin
      39           2 :         step = method%step
      40           2 :         smax = method%smax
      41           2 :         lenseq = size(seq, 1, IK)
      42           2 :         CHECK_ASSERTION(__LINE__, 0 < lenseq, SK_"@getACT(): The condition `0 < size(seq)` must hold. size(seq) = "//getStr(lenseq))
      43           2 :         CHECK_ASSERTION(__LINE__, 1_IK < smin, SK_"@getACT(): The condition `1 < method%smin` must hold. method%smin = "//getStr(smin))
      44           6 :         CHECK_ASSERTION(__LINE__, smax == huge(0_IK) .or. (smax <= smin .and. smax <= lenseq / 2_IK), SK_"@getACT(): The condition `method%smin <= method%smax <= size(seq, 1) / 2` must hold. method%smax, size(seq) = "//getStr([smax, lenseq]))
      45           2 :         CHECK_ASSERTION(__LINE__, 0_IK < step, SK_"@getACT(): The condition `0 < method%step` must hold. method%step = "//getStr(step))
      46           2 :         if (1_IK < lenseq) then
      47           2 :             smax = min(smax, lenseq / 2_IK)
      48           0 :             act = -huge(act)
      49           2 :             do isize = smin, smax, step
      50             : #if             ONE_ENABLED
      51        5085 :                 act = max(act, getACT(seq, batchMeans_type(isize)))
      52             : #elif           WTI_ENABLED
      53           0 :                 act = max(act, getACT(seq, weight, batchMeans_type(isize)))
      54             : #else
      55             : #error          "Unrecognized interface."
      56             : #endif
      57             :             end do
      58             :         else
      59           0 :             act = lenseq
      60             :         end if
      61             : 
      62             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      63             : #elif   getACT_ENABLED && D1_ENABLED && BMD_ENABLED
      64             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      65             : 
      66             :         integer(IK) :: batchSize, lenseq, weisum
      67             :         real(TKC), allocatable :: batchMean(:)
      68             :         real(TKC) :: batchSizeInv, avgSeq, sumDiffSq, varBatchMean, avgBatchMean
      69             :         integer(IK) :: nbatch, ibatch, seqLenEffective
      70             : #if     WTI_ENABLED
      71             :         real(TKC) :: diffSq
      72         104 :         integer(IK) :: cumSumWei(size(seq, 1, IK)), currentBatchEndLoc, iseq, iseqVerbose
      73          52 :         lenseq = size(seq, 1, IK)
      74          52 :         call setCumSum(cumSumWei, weight)
      75         156 :         CHECK_ASSERTION(__LINE__, size(weight, 1, IK) == lenseq, SK_"@getACT(): The condition `size(weight) == size(seq)` must hold. size(weight), size(seq) = "//getStr([size(weight, 1, IK), lenseq]))
      76          52 :         weisum = cumSumWei(lenseq)
      77             : #elif   ONE_ENABLED
      78             :         integer(IK) :: iseqBeg, iseqEnd
      79        9822 :         lenseq = size(seq, 1, IK)
      80             :         weisum = lenseq
      81             : #else
      82             : #error  "Unrecognized interface."
      83             : #endif
      84        9874 :         CHECK_ASSERTION(__LINE__, 0 < lenseq, SK_"@getACT(): The condition `0 < size(seq)` must hold. size(seq) = "//getStr(lenseq))
      85        9874 :         if (lenseq < 2_IK) then
      86           0 :             act = lenseq
      87           0 :             return
      88             :         end if
      89             : 
      90             :         ! Compute batch size and count.
      91             : 
      92           0 :         act = 1._TKC
      93        9874 :         batchSize = method%size
      94        9874 :         if (batchSize == 0_IK) batchSize = int(real(weisum)**real(2./3.), IK)
      95        9874 :         batchSizeInv = 1._TKC / real(batchSize, TKC)
      96        9874 :         nbatch = weisum / batchSize
      97        9874 :         CHECK_ASSERTION(__LINE__, 0_IK < batchSize, SK_"@getACT(): The condition `0 < method%size` must hold. method%size = "//getStr(batchSize))
      98        9874 :         if (nbatch < 2_IK) then
      99             :             !check_assertion(__LINE__, method%size == 0_IK, SK_"@getACT(): The condition `method%size * 2 < sum(weight)` must hold (there must be more than one batches to compute ACT). method%size, sum(weight) = "//getStr([batchSize, weisum]))
     100           0 :             act = weisum
     101           0 :             return
     102             :         end if
     103        9874 :         seqLenEffective = nbatch * batchSize
     104             :         ! xxx: here goes another GFortran 7.3 bug: `batchMean` is assumed already allocated, despite the first appearance here.
     105        9874 :         if (allocated(batchMean)) deallocate(batchMean)
     106        9874 :         allocate(batchMean(nbatch))
     107             : 
     108             :         ! \todo
     109             :         ! iterate from the end to the beginning of the chain to ignore initial points instead of the last points.
     110             :         ! This would be beneficial for MCMC samples.
     111             : 
     112             :         ! Compute the Batch means vector and mean of the whole (weighted) sequence.
     113             : 
     114           0 :         sumDiffSq = 0._TKC
     115           0 :         avgSeq = 0._TKC
     116             : #if     WTI_ENABLED
     117             :         iseq = 1
     118             :         ibatch = 1
     119             :         iseqVerbose = 0
     120             :         currentBatchEndLoc = batchSize
     121          52 :         batchMean(ibatch) = 0._TKC
     122      381479 :         loopOverWeight: do
     123      381531 :             iseqVerbose = iseqVerbose + 1
     124      381531 :             if (cumSumWei(iseq) < iseqVerbose) iseq = iseq + 1
     125      381531 :             if (currentBatchEndLoc < iseqVerbose) then ! we are done with the current batch
     126         712 :                 avgSeq = avgSeq + batchMean(ibatch)
     127         712 :                 if (seqLenEffective < iseqVerbose) exit loopOverWeight  ! condition equivalent to currentBatchEndLoc == seqLenEffective.
     128         660 :                 currentBatchEndLoc = currentBatchEndLoc + batchSize
     129         660 :                 ibatch = ibatch + 1
     130         660 :                 batchMean(ibatch) = 0._TKC
     131             :             end if
     132      381531 :             batchMean(ibatch) = batchMean(ibatch) + seq(iseq)
     133             :         end do loopOverWeight
     134         764 :         batchMean = batchMean * batchSizeInv
     135          52 :         avgSeq = avgSeq / real(seqLenEffective, TKC) ! whole sequence mean.
     136             :         ! compute whole sequence variance.
     137             :         iseq = 1
     138             :         iseqVerbose = 0
     139          52 :         diffSq = (seq(iseq) - avgSeq)**2
     140      381479 :         loopComputeVariance: do
     141      381531 :             iseqVerbose = iseqVerbose + 1
     142      381531 :             if (seqLenEffective < iseqVerbose) exit loopComputeVariance
     143      381479 :             if (cumSumWei(iseq) < iseqVerbose) then
     144      365418 :                 iseq = iseq + 1 ! by definition, iseq never become > lenseq, otherwise it leads to disastrous errors
     145      365418 :                 diffSq = (seq(iseq) - avgSeq)**2
     146             :             end if
     147      381531 :             sumDiffSq = sumDiffSq + diffSq ! whole sequence variance.
     148             :         end do loopComputeVariance
     149             : #elif   ONE_ENABLED
     150             :         iseqBeg = 1
     151             :         iseqEnd = 0
     152      166727 :         do ibatch = 1, nbatch
     153      156905 :             iseqEnd = iseqEnd + batchSize
     154    82887268 :             batchMean(ibatch) = sum(seq(iseqBeg : iseqEnd))
     155      156905 :             avgSeq = avgSeq + batchMean(ibatch)
     156      156905 :             batchMean(ibatch) = batchMean(ibatch) * batchSizeInv
     157      166727 :             iseqBeg = iseqEnd + 1_IK
     158             :         end do
     159        9822 :         avgSeq = avgSeq / real(seqLenEffective, TKC) ! whole sequence mean.
     160    82740185 :         sumDiffSq = sum((seq(1 : seqLenEffective) - avgSeq)**2) ! whole sequence variance.
     161             : 
     162             : #else
     163             : #error  "Unrecognized interface."
     164             : #endif
     165      167491 :         avgBatchMean = sum(batchMean) / real(nbatch, TKC) ! batch means
     166      167491 :         varBatchMean = sum((batchMean - avgBatchMean)**2) / real(nbatch - 1, TKC) ! batch variances
     167             :         !act = varBatchMean * seqLenEffective * (seqLenEffective - 1) / sumDiffSq
     168             :         !act = batchSize * varBatchMean * (seqLenEffective - 1) / sumDiffSq
     169        9874 :         act = varBatchMean * seqLenEffective * (seqLenEffective - 1) / sumDiffSq / real(nbatch, TKC)
     170             :         !print *, avgSeq, sumDiffSq
     171             :         !print *, sum(batchMean) / real(nbatch, TKC), varBatchMean
     172             :         !print *, nbatch, batchSize
     173             :         !print *, act
     174             : 
     175             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     176             : #elif   getACT_ENABLED && D1_ENABLED && (CSD_ENABLED || CSM_ENABLED)
     177             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     178             : 
     179           8 :         real(TKC) :: mean, sample(size(seq, 1, IK))
     180             :         integer(IK) :: lenseq, weisum
     181           4 :         lenseq = size(seq, 1, IK)
     182           4 :         CHECK_ASSERTION(__LINE__, 1 < lenseq, SK_"@getACT(): The condition `0 < size(seq)` must hold. size(seq) = "//getStr(lenseq))
     183           4 :         if (lenseq < 2_IK) then
     184           0 :             act = lenseq
     185           0 :             return
     186             :         end if
     187             : #if     WTI_ENABLED
     188           0 :         CHECK_ASSERTION(__LINE__, size(weight, 1, IK) == size(seq, 1, IK), SK_"@getACT(): The condition `size(weight) == size(seq)` must hold. size(weight), size(seq) = "//getStr([size(weight, 1, IK), size(seq, 1, IK)]))
     189           0 :         weisum = sum(weight)
     190           0 :         sample = getVerbose(seq, weight, weisum)
     191           0 :         mean = sum(sample * weight) / real(weisum, TKC)
     192           0 :         sample = sample - mean
     193             : #elif   ONE_ENABLED
     194             :         weisum = size(seq, 1, IK)
     195       36992 :         mean = sum(seq) / real(weisum, TKC)
     196       36992 :         sample = seq - mean
     197             : #else
     198             : #error  "Unrecognized interface."
     199             : #endif
     200             : #if     CSD_ENABLED
     201             :         block
     202             :             integer(IK) :: i
     203             :             real(TKC) :: signif
     204           3 :             signif = real(method%signif, TKC)
     205           3 :             CHECK_ASSERTION(__LINE__, 0 <= method%signif, SK_"@getACT(): The condition `0 <= method%signif` must hold. method%signif = "//getStr(signif))
     206       27744 :             sample = getACF(sample, norm = stdscale)
     207             :             ! For autocorrelation, under the assumption of a completely random series, the ACF standard error reduces to `sqrt(1 / ndata)`.
     208           0 :             act = 0._TKC
     209           3 :             signif = signif * sqrt(1._TKC / weisum)
     210         275 :             do i = 1, size(sample, 1, IK)
     211         275 :                 if (sample(i) < signif) exit
     212         275 :                 act = act + sample(i)
     213             :             end do
     214           3 :             act = 2 * act - 1
     215             :         end block
     216             : #elif   CSM_ENABLED
     217        9248 :         sample = getACF(sample, norm = stdscale)
     218        9249 :         act = 2 * maxval(getCumSum(sample)) - 1
     219             : #else
     220             : #error  "Unrecognized interface."
     221             : #endif
     222             : 
     223             : #else
     224             :         !%%%%%%%%%%%%%%%%%%%%%%%%
     225             : #error  "Unrecognized interface."
     226             :         !%%%%%%%%%%%%%%%%%%%%%%%%
     227             : #endif
     228             : #undef  TYPE_OF_SEQ
     229             : #undef  GET_ABSQ
     230             : #undef  GET_RE

ParaMonte: Parallel Monte Carlo and Machine Learning Library 
The Computational Data Science Lab
© Copyright 2012 - 2024