56#define CHECK_ASSERTION(LINE,ASSERTION,MSG) \
59#define CHECK_ASSERTION(LINE,ASSERTION,MSG) continue;
64 use iso_fortran_env,
only:
output_unit
68#define MAXDEN_ENABLED 1
69#define MINVOL_ENABLED 0
71 real(
RK) ,
parameter ::
POSINF = +huge(
0._RK)
/ 10
72 real(
RK) ,
parameter ::
NEGINF = -huge(
0._RK)
/ 10
75 integer(
IK) ,
allocatable :: EffectiveSize(:)
76 integer(
IK) ,
allocatable :: Membership(:)
77 integer(
IK) ,
allocatable :: CumSumSize(:)
78 integer(
IK) ,
allocatable ::
Size(:)
79 real(
RK) ,
allocatable :: Center(:,:)
80 real(
RK) ,
allocatable :: potential(:)
81 real(
RK) ,
allocatable :: MahalSq(:,:)
82 real(
RK) ,
allocatable :: InvCovMat(:,:,:)
83 real(
RK) ,
allocatable :: ChoLowCovUpp(:,:,:)
84 real(
RK) ,
allocatable :: ScaleFactorSq(:)
85 real(
RK) ,
allocatable :: ScaleFactor(:)
86 real(
RK) ,
allocatable :: LogVolRatio(:)
87 real(
RK) ,
allocatable :: LogVolNormed(:)
88 real(
RK) ,
allocatable :: LogLikeFitness(:)
100 logical(
LK) :: deallocated
= .true._LK
101 real(
RK) ,
allocatable :: SumLogLikeFitness(:)
102 logical(
LK) ,
allocatable :: SubclusteringWarranted(:)
106 real(
RK) ,
allocatable :: potential(:)
107 real(
RK) ,
allocatable :: Center(:,:)
108 integer(
IK) ,
allocatable :: Membership(:)
109 integer(
IK) ,
allocatable ::
Size(:)
120 integer(IK) :: minSize
121 integer(IK) :: kmeansNumFailMax
122 integer(IK) :: kmeansNumRecursionMax
123 integer(IK) :: kvolumeNumRecursionMax
124 logical(LK) :: scaleOptimizationEnabled
125 logical(LK) :: shapeOptimizationEnabled
126 logical(LK) :: shapeAdaptationEnabled
127 logical(LK) :: biasCorrectionEnabled
128 logical(LK) :: mahalSqWeightEnabled
129 logical(LK) :: optimizationEnabled
130 real(RK) :: mahalSqWeightExponent
131 real(RK) :: parentLogVolNormed
132 real(RK) :: pointLogVolNormed
134 real(RK) :: inclusionFraction
138 real(RK) :: logExpansion
139 real(RK) :: logShrinkage
140 real(RK) :: kmeansRelTol
143 integer(IK) :: numRecursiveCall
144 integer(IK) :: convergenceFailureCount
145 logical(LK) :: stanEnabled
147 integer(IK) ,
allocatable ::
Size(:)
148 integer(IK) ,
allocatable :: Final(:,:)
149 integer(IK) ,
allocatable :: CumSumSize(:)
150 integer(IK) ,
allocatable :: Membership(:)
151 integer(IK) ,
allocatable :: PointIndex(:)
152 integer(IK) ,
allocatable :: EffectiveSize(:)
153 real(RK) ,
allocatable :: LogLikeFitness(:)
154 real(RK) ,
allocatable :: LogVolNormed(:)
155 real(RK) ,
allocatable :: ChoLowCovUpp(:,:,:)
156 real(RK) ,
allocatable :: InvCovMat(:,:,:)
157 real(RK) ,
allocatable :: Center(:,:)
158 real(RK) ,
allocatable :: VolNormedCDF(:)
159 real(RK) ,
allocatable :: BiasCorrectionScaleFactorSq(:)
160 type(err_type) :: err
221 , nc,nt & ! LCOV_EXCL_LINE
222 , nsim & ! LCOV_EXCL_LINE
223 , nemax & ! LCOV_EXCL_LINE
224 , minSize & ! LCOV_EXCL_LINE
225 , stanEnabled & ! LCOV_EXCL_LINE
226 , trimEnabled & ! LCOV_EXCL_LINE
227 , kmeansRelTol & ! LCOV_EXCL_LINE
228 , logExpansion & ! LCOV_EXCL_LINE
229 , logShrinkage & ! LCOV_EXCL_LINE
231 , inclusionFraction & ! LCOV_EXCL_LINE
233 , parentLogVolNormed & ! LCOV_EXCL_LINE
234 , mahalSqWeightExponent & ! LCOV_EXCL_LINE
235 , kmeansNumFailMax & ! LCOV_EXCL_LINE
236 , kmeansNumRecursionMax & ! LCOV_EXCL_LINE
237 , kvolumeNumRecursionMax & ! LCOV_EXCL_LINE
238 , scaleOptimizationEnabled & ! LCOV_EXCL_LINE
239 , shapeOptimizationEnabled & ! LCOV_EXCL_LINE
240 , shapeAdaptationEnabled & ! LCOV_EXCL_LINE
241 , biasCorrectionEnabled & ! LCOV_EXCL_LINE
243#if INTEL_COMPILER_ENABLED && DLL_ENABLED && (WINDOWS_ENABLED || DARWIN_ENABLED)
246 real(RK) ,
intent(inout),
contiguous :: Point(:,:)
247 integer(IK) ,
intent(in) ,
optional :: nc,nt
248 integer(IK) ,
intent(in) ,
optional :: nsim
249 integer(IK) ,
intent(in) ,
optional :: nemax
250 integer(IK) ,
intent(in) ,
optional :: minSize
251 logical(LK) ,
intent(in) ,
optional :: stanEnabled
252 logical(LK) ,
intent(in) ,
optional :: trimEnabled
253 real(RK) ,
intent(in) ,
optional :: kmeansRelTol
254 real(RK) ,
intent(in) ,
optional :: logExpansion
255 real(RK) ,
intent(in) ,
optional :: logShrinkage
257 real(RK) ,
intent(in) ,
optional :: inclusionFraction
259 real(RK) ,
intent(in) ,
optional :: parentLogVolNormed
260 real(RK) ,
intent(in) ,
optional :: mahalSqWeightExponent
261 integer(IK) ,
intent(in) ,
optional :: kmeansNumFailMax
262 integer(IK) ,
intent(in) ,
optional :: kmeansNumRecursionMax
263 integer(IK) ,
intent(in) ,
optional :: kvolumeNumRecursionMax
264 logical(LK) ,
intent(in) ,
optional :: scaleOptimizationEnabled
265 logical(LK) ,
intent(in) ,
optional :: shapeOptimizationEnabled
266 logical(LK) ,
intent(in) ,
optional :: shapeAdaptationEnabled
267 logical(LK) ,
intent(in) ,
optional :: biasCorrectionEnabled
270 Partition
%nd
= size(Point(:,
1))
271 Partition
%np
= size(Point(
1,:))
273 Partition
%nc
= 2;
if (
present(nc)) Partition
%nc
= max(Partition
%nc, nc)
274 Partition
%nt
= 1;
if (
present(nt)) Partition
%nt
= max(Partition
%nt, nt)
275 Partition
%nsim
= 0;
if (
present(nsim)) Partition
%nsim
= max(Partition
%nsim, nsim)
276 Partition
%minSize
= 0;
if (
present(minSize)) Partition
%minSize
= minSize
277 Partition
%nemax
= Partition
%np
/ max(
1, Partition
%minSize);
if (
present(nemax)) Partition
%nemax
= max(
1, nemax)
278 if (Partition
%nemax
> Partition
%np) Partition
%nemax
= Partition
%np
279 Partition
%kvolumeNumRecursionMax
= 3;
if (
present(kvolumeNumRecursionMax)) Partition
%kvolumeNumRecursionMax
= kvolumeNumRecursionMax
280 Partition
%kmeansNumRecursionMax
= 300;
if (
present(kmeansNumRecursionMax)) Partition
%kmeansNumRecursionMax
= kmeansNumRecursionMax
281 Partition
%kmeansNumFailMax
= 10;
if (
present(kmeansNumFailMax)) Partition
%kmeansNumFailMax
= kmeansNumFailMax
282 Partition
%mahalSqWeightExponent
= 0._RK;
if (
present(mahalSqWeightExponent)) Partition
%mahalSqWeightExponent
= mahalSqWeightExponent
283 Partition
%mahalSqWeightEnabled
= abs(Partition
%mahalSqWeightExponent)
> 1.e-4_RK
285 Partition
%inclusionFraction
= 0._RK;
if (
present(inclusionFraction))
then;
if (abs(inclusionFraction)
>1.e-5_RK) Partition
%inclusionFraction
= inclusionFraction;
endif
289 Partition
%logShrinkage
= 0._RK;
if (
present(logExpansion)) Partition
%logExpansion
= logExpansion
290 Partition
%logShrinkage
= 0._RK;
if (
present(logShrinkage)) Partition
%logShrinkage
= logShrinkage
291 Partition
%kmeansRelTol
= 1.e-4_RK;
if (
present(kmeansRelTol)) Partition
%kmeansRelTol
= kmeansRelTol
292 Partition
%stanEnabled
= .true.;
if (
present(stanEnabled)) Partition
%stanEnabled
= stanEnabled
293 Partition
%nplog
= log(
real(Partition
%np,RK))
295 Partition
%scaleOptimizationEnabled
= .true.;
if (
present(scaleOptimizationEnabled)) Partition
%scaleOptimizationEnabled
= scaleOptimizationEnabled
296 Partition
%shapeOptimizationEnabled
= .true.;
if (
present(shapeOptimizationEnabled)) Partition
%shapeOptimizationEnabled
= shapeOptimizationEnabled
297 Partition
%shapeAdaptationEnabled
= .true.;
if (
present(shapeAdaptationEnabled)) Partition
%shapeAdaptationEnabled
= shapeAdaptationEnabled
298 Partition
%biasCorrectionEnabled
= .true.;
if (
present(biasCorrectionEnabled)) Partition
%biasCorrectionEnabled
= biasCorrectionEnabled
299 Partition
%optimizationEnabled
= Partition
%shapeAdaptationEnabled
.or. Partition
%scaleOptimizationEnabled
.or. Partition
%shapeOptimizationEnabled
302 if (Partition
%mahalSqWeightExponent
== 0._RK .and. .not. present(parentLogVolNormed))
then
303 Partition
%err
%msg
= "If `mahalSqWeightExponent` is given as input argument, then `parentLogVolNormed` must also be given as input."
304 Partition
%err
%occurred
= .true._LK
308 allocate( Partition
%Try(
0:Partition
%nemax)
&
309 , Partition
%Center(Partition
%nd, Partition
%nemax)
&
310 , Partition
%InvCovMat(Partition
%nd, Partition
%nd
+ 1, Partition
%nemax)
&
311 , Partition
%ChoLowCovUpp(Partition
%nd, Partition
%nd
+ 1, Partition
%nemax)
&
312 , Partition
%LogVolNormed(
1 : Partition
%nemax)
&
313 , Partition
%LogLikeFitness(
1 : Partition
%nemax)
&
314 , Partition
%EffectiveSize(
1 : Partition
%nemax)
&
315 , Partition
%VolNormedCDF(
1 : Partition
%nemax)
&
316 , Partition
%CumSumSize(
0:Partition
%nemax)
&
317 , Partition
%Final (
2,Partition
%nemax)
&
318 , Partition
%size (
1 : Partition
%nemax)
&
319 , Partition
%Membership(Partition
%np)
&
320 , Partition
%PointIndex(Partition
%np)
&
321 , Partition
%BiasCorrectionScaleFactorSq(Partition
%nd
+1 : Partition
%np)
&
324 Partition
%BiasCorrectionScaleFactorSq(Partition
%nd
+1 : Partition
%np)
= getBiasCorrectionScaleFactorSq(nd
= Partition
%nd, npmin
= Partition
%nd
+ 1, npmax
= Partition
%np)
326 Partition
%CumSumSize(
0)
= 0
327 call Partition
%run(Point, parentLogVolNormed)
329 if (
present(trimEnabled))
then
330 if (trimEnabled)
then
331 Partition
%Try
= Partition
%Try(
0 : Partition
%ne)
332 Partition
%Center
= Partition
%Center(
1 : Partition
%nd,
1 : Partition
%ne)
333 Partition
%InvCovMat
= Partition
%InvCovMat(
1 : Partition
%nd,
1 : Partition
%nd ,
1 : Partition
%ne)
334 Partition
%ChoLowCovUpp
= Partition
%ChoLowCovUpp(
1 : Partition
%nd,
1 : Partition
%nd
+ 1 ,
1 : Partition
%ne)
335 Partition
%LogVolNormed
= Partition
%LogVolNormed(
1 : Partition
%ne)
336 Partition
%LogLikeFitness
= Partition
%LogLikeFitness(
1 : Partition
%ne)
337 Partition
%EffectiveSize
= Partition
%EffectiveSize(
1 : Partition
%ne)
338 Partition
%CumSumSize
= Partition
%CumSumSize(
0 : Partition
%ne)
339 Partition
%Final = Partition
%Final (
1 :
2,
1 : Partition
%ne)
340 Partition
%size
= Partition
%size (
1 : Partition
%ne)
361#if INTEL_COMPILER_ENABLED && DLL_ENABLED && (WINDOWS_ENABLED || DARWIN_ENABLED)
376 real(RK) ,
intent(inout) ,
contiguous :: Point(:,:)
377 real(RK) ,
intent(in) ,
optional :: parentLogVolNormed
379 character(
*, SK),
parameter :: PROCEDURE_NAME
= MODULE_NAME
//SK_
"@runPartition()"
383 real(RK) :: ndInverse
384 real(RK) :: expanFactor
385 real(RK) :: scaleFactor
386 real(RK) :: scaleFactorSq
387 real(RK) :: ndHalfInverse
388 real(RK) :: sumPotentialNew
389 real(RK) :: sumPotentialOld
390 real(RK) :: logLikeFitnessGain
391 real(RK) :: scaleFactorSqInverse
392 real(RK) :: PointStd(Partition%nd)
393 real(RK) :: PointStdInv(Partition%nd)
394 real(RK) :: MinDistanceSq(Partition%np)
395 real(RK) :: CumSumMinDistanceSq(Partition%np)
396 real(RK) :: NormedPoint(Partition%nd, Partition%np)
401 integer(IK) :: ndPlusOne
402 integer(IK) :: minSizePartition
403 integer(IK) :: biasedEffectiveSize
404 integer(IK) :: PointIndex(Partition%np)
405 integer(IK) :: KmeansMemberCounter(Partition%nc)
406 integer(IK) :: i,j, ip, ic,ie,nd,kt,it,ktmin
407 integer(IK) :: ipstart,ipend
414 integer(IK) :: kvnew,kvopt,kvdum
415 integer(IK) :: kvolRecursionCounter
416 integer(IK) :: KvolPointIndex(Partition%np)
417 logical(LK) :: reassignmentOccurred
418 real(RK) :: MahalSqWeight(Partition%nc)
419 real(RK) :: logVolNormedExpected
420 real(RK) :: LogSumVolNormed(
2)
421 real(RK) :: maxLogVolNormed
426 real(RK) :: MahalSq(Partition%np)
427 real(RK) :: logVolRatio
428 real(RK) :: logExpanFactor
429 real(RK) :: logScaleFactorSq
430 real(RK) :: logLikeFitnessRef
431 real(RK) :: logLikeOccurrence
432 real(RK) :: PointNormed(Partition%nd)
433 real(RK),
allocatable :: SortedValue(:)
434 integer ,
allocatable :: SortedIndex(:)
435 integer(IK) :: MahalSqSortedIndex(Partition%np)
436 integer(IK) :: optimizationCounter
437 integer(IK) :: npc,nps,npe,je,jes
438 logical(LK) :: optimizationWarranted
439 logical(LK) :: shapeAdaptationEnabled
440 logical(LK) :: subclusteringWarranted
441 logical(LK) :: scaleOptimizationSucceeded
442 logical(LK) :: shapeOptimizationSucceeded
445 Partition
%mahalSqWeightEnabled
= mahalSqWeightExponent
/= 0._RK .and. parentLogVolNormed
> NEGINF
448 ndPlusOne
= nd
+ 1_IK
450 ndInverse
= 1._RK / nd
451 ndHalfInverse
= 1._RK / ndHalf
453 minSizePartition
= max(
1,Partition
%minSize)
455 Partition
%err
%occurred
= .false._LK
456 Partition
%numRecursiveCall
= 0_IK
457 Partition
%convergenceFailureCount
= 0_IK
458 Partition
%Membership(
1 : Partition
%np)
= 0_IK
459 if (
present(parentLogVolNormed)) Partition
%parentLogVolNormed
= parentLogVolNormed
+ Partition
%logExpansion
460 Partition
%pointLogVolNormed
= Partition
%parentLogVolNormed
- Partition
%nplog
463 do concurrent(ip
= 1_IK:Partition
%np)
464 Partition
%PointIndex(ip)
= ip
467 if (Partition
%nt
> 1_IK)
then
468 do kt
= 1_IK, Partition
%nt
469 allocate( KmeansTry(kt)
%size(Partition
%nc)
&
470 , KmeansTry(kt)
%potential(Partition
%nc)
&
471 , KmeansTry(kt)
%Center(nd, Partition
%nc)
&
472 , KmeansTry(kt)
%Membership(Partition
%np)
&
477 if (Partition
%kvolumeNumRecursionMax
> 0_IK)
then
479 allocate( KvolTry(kt)
%EffectiveSize(Partition
%nc)
&
480 , KvolTry(kt)
%Membership(Partition
%np)
&
481 , KvolTry(kt)
%CumSumSize(
0 : Partition
%nc)
&
482 , KvolTry(kt)
%size(Partition
%nc)
&
483 , KvolTry(kt)
%Center(nd, Partition
%nc)
&
484 , KvolTry(kt)
%MahalSq(Partition
%np,Partition
%nc)
&
485 , KvolTry(kt)
%InvCovMat(nd, nd, Partition
%nc)
&
486 , KvolTry(kt)
%ChoLowCovUpp(nd, nd
+ 1, Partition
%nc)
&
487 , KvolTry(kt)
%ScaleFactorSq(Partition
%nc)
&
488 , KvolTry(kt)
%ScaleFactor(Partition
%nc)
&
489 , KvolTry(kt)
%LogVolRatio(Partition
%nc)
&
490 , KvolTry(kt)
%LogVolNormed(Partition
%nc)
&
491 , KvolTry(kt)
%LogLikeFitness(Partition
%nc)
&
499 Partition
%Try(
0_IK)
%ic
= 0_IK
500 Partition
%Try(
0_IK)
%nc
= 1_IK
501 Partition
%Try(
0_IK)
%ne
= 0_IK
502 Partition
%Try(
0_IK)
%itp
= 0_IK
503 nemax
= Partition
%nemax
507 loopRecursivePartition:
do
509 Partition
%numRecursiveCall
= Partition
%numRecursiveCall
+ 1_IK
512 blockForwardBackwardStream:
if (Partition
%Try(it)
%ic
== 0_IK)
then
515 nemax
= nemax
- Partition
%Try(it)
%nc
+ 1_IK
516 if (Partition
%Try(it)
%deallocated)
then
517 allocate( Partition
%Try(it)
%size(Partition
%nc)
&
518 , Partition
%Try(it)
%CumSumSize(
0_IK:Partition
%nc)
&
519 , Partition
%Try(it)
%Center(nd, Partition
%nc)
&
520 , Partition
%Try(it)
%LogVolRatio(Partition
%nc)
&
521 , Partition
%Try(it)
%ScaleFactor(Partition
%nc)
&
522 , Partition
%Try(it)
%LogVolNormed(Partition
%nc)
&
523 , Partition
%Try(it)
%ScaleFactorSq(Partition
%nc)
&
524 , Partition
%Try(it)
%LogLikeFitness(Partition
%nc)
&
525 , Partition
%Try(it)
%InvCovMat(nd, nd, Partition
%nc)
&
526 , Partition
%Try(it)
%SumLogLikeFitness(Partition
%nc)
&
527 , Partition
%Try(it)
%ChoLowCovUpp(nd, nd
+ 1, Partition
%nc)
&
528 , Partition
%Try(it)
%MahalSq(Partition
%np,Partition
%nc)
&
529 , Partition
%Try(it)
%SubclusteringWarranted(Partition
%nc)
&
530 , Partition
%Try(it)
%EffectiveSize(Partition
%nc)
&
531 , Partition
%Try(it)
%Membership(Partition
%np)
&
533 Partition
%Try(it)
%deallocated
= .false._LK
535 Partition
%Try(it)
%SumLogLikeFitness(
1_IK:Partition
%Try(it)
%nc)
= 0._RK
542 blockKmeansOrSingularPartition:
if (Partition
%Try(it)
%nc
> 1_IK)
then
545 Partition
%Try(it)
%nps
= Partition
%Try(Partition
%Try(it)
%itp)
%CumSumSize(Partition
%Try(Partition
%Try(it)
%itp)
%ic
-1)
+ 1_IK
546 Partition
%Try(it)
%npe
= Partition
%Try(Partition
%Try(it)
%itp)
%CumSumSize(Partition
%Try(Partition
%Try(it)
%itp)
%ic)
547 Partition
%Try(it)
%np
= Partition
%Try(it)
%npe
- Partition
%Try(it)
%nps
+ 1_IK
549 blockStandardization:
if (Partition
%stanEnabled)
then
550#define STAN_ENABLED 1
551 if (Partition
%kvolumeNumRecursionMax
> 0_IK)
then
552#define KVOL_ENABLED 1
553#include "pm_clusDensity.inc.kmeans.inc.F90"
554#include "pm_clusDensity.inc.prop.inc.F90"
557#include "pm_clusDensity.inc.kmeans.inc.F90"
558#include "pm_clusDensity.inc.prop.inc.F90"
561 else blockStandardization
562 if (Partition
%kvolumeNumRecursionMax
> 0_IK)
then
563#define KVOL_ENABLED 1
564#include "pm_clusDensity.inc.kmeans.inc.F90"
565#include "pm_clusDensity.inc.prop.inc.F90"
568#include "pm_clusDensity.inc.kmeans.inc.F90"
569#include "pm_clusDensity.inc.prop.inc.F90"
571 end if blockStandardization
577 blockRecursiveKvolumeOptimization:
if (it
> 0_IK .and. Partition
%kvolumeNumRecursionMax
> 0_IK)
then
580 kvolRecursionCounter
= 0_IK
581 loopRecursivePartitionOptimization:
do
583 kvolRecursionCounter
= kvolRecursionCounter
+ 1_IK
585 KvolTry(kvnew)
%size(
1 : Partition
%Try(it)
%nc)
= KvolTry(kvopt)
%size(
1 : Partition
%Try(it)
%nc)
586 do concurrent(ic
= 1 : Partition
%Try(it)
%nc)
587 KvolTry(kvnew)
%Center(
1 : nd, ic)
= KvolTry(kvopt)
%Center(
1 : nd, ic)
* KvolTry(kvopt)
%size(ic)
592 blockReassignPoint:
if (Partition
%mahalSqWeightEnabled)
then
593#define MAHALSQ_WEIGHT_ENABLED 1
594#include "pm_clusDensity.inc.kvolume.inc.F90"
595#undef MAHALSQ_WEIGHT_ENABLED
596 else blockReassignPoint
597#include "pm_clusDensity.inc.kvolume.inc.F90"
598 end if blockReassignPoint
608 blockReclusteringNeeded:
if (reassignmentOccurred)
then
612 do ic
= 1, Partition
%Try(it)
%nc
613 if (KvolTry(kvnew)
%size(ic)
== Partition
%Try(it)
%np)
exit loopRecursivePartitionOptimization
623 do concurrent(ic
= 1 : Partition
%Try(it)
%nc)
624 if (KvolTry(kvnew)
%size(ic)
> 0_IK) KvolTry(kvnew)
%Center(
1 : nd, ic)
= KvolTry(kvnew)
%Center(
1 : nd, ic)
/ KvolTry(kvnew)
%size(ic)
629#define KVOL_ENABLED 2
630#include "pm_clusDensity.inc.prop.inc.F90"
635 if (LogSumVolNormed(kvnew)
> LogSumVolNormed(kvopt))
then
636 Point(
1 : nd, Partition
%Try(it)
%nps : Partition
%Try(it)
%npe)
= Point(
1 : nd,KvolPointIndex(Partition
%Try(it)
%nps : Partition
%Try(it)
%npe))
637 Partition
%PointIndex(Partition
%Try(it)
%nps : Partition
%Try(it)
%npe)
= Partition
%PointIndex(KvolPointIndex(Partition
%Try(it)
%nps : Partition
%Try(it)
%npe))
638 exit loopRecursivePartitionOptimization
672 if (kvolRecursionCounter
< Partition
%kvolumeNumRecursionMax)
cycle loopRecursivePartitionOptimization
702 end if blockReclusteringNeeded
704 exit loopRecursivePartitionOptimization
706 end do loopRecursivePartitionOptimization
713 Partition
%Try(it)
%EffectiveSize(
1 : Partition
%Try(it)
%nc)
= KvolTry(kvopt)
%EffectiveSize(
1 : Partition
%Try(it)
%nc)
714 Partition
%Try(it)
%Membership(Partition
%Try(it)
%nps : Partition
%Try(it)
%npe)
= KvolTry(kvopt)
%Membership(Partition
%Try(it)
%nps : Partition
%Try(it)
%npe)
715 Partition
%Try(it)
%CumSumSize(
0 : Partition
%Try(it)
%nc)
= KvolTry(kvopt)
%CumSumSize(
0 : Partition
%Try(it)
%nc)
716 Partition
%Try(it)
%size (
1 : Partition
%Try(it)
%nc)
= KvolTry(kvopt)
%size (
1 : Partition
%Try(it)
%nc)
717 Partition
%Try(it)
%Center(
1 : nd,
1 : Partition
%Try(it)
%nc)
= KvolTry(kvopt)
%Center(
1 : nd,
1 : Partition
%Try(it)
%nc)
718 Partition
%Try(it)
%MahalSq(
1 : Partition
%np,
1 : Partition
%Try(it)
%nc)
= KvolTry(kvopt)
%MahalSq(
1 : Partition
%np,
1 : Partition
%Try(it)
%nc)
719 Partition
%Try(it)
%InvCovMat(
1 : nd,
1 : nd,
1 : Partition
%Try(it)
%nc)
= KvolTry(kvopt)
%InvCovMat(
1 : nd,
1 : nd,
1 : Partition
%Try(it)
%nc)
720 Partition
%Try(it)
%ChoLowCovUpp(
1 : nd,
1 : nd
+ 1,
1 : Partition
%Try(it)
%nc)
= KvolTry(kvopt)
%ChoLowCovUpp(
1 : nd,
1 : nd
+ 1,
1 : Partition
%Try(it)
%nc)
721 Partition
%Try(it)
%ScaleFactorSq(
1 : Partition
%Try(it)
%nc)
= KvolTry(kvopt)
%ScaleFactorSq(
1 : Partition
%Try(it)
%nc)
722 Partition
%Try(it)
%ScaleFactor(
1 : Partition
%Try(it)
%nc)
= KvolTry(kvopt)
%ScaleFactor(
1 : Partition
%Try(it)
%nc)
723 Partition
%Try(it)
%LogVolRatio(
1 : Partition
%Try(it)
%nc)
= KvolTry(kvopt)
%LogVolRatio(
1 : Partition
%Try(it)
%nc)
724 Partition
%Try(it)
%LogVolNormed(
1 : Partition
%Try(it)
%nc)
= KvolTry(kvopt)
%LogVolNormed(
1 : Partition
%Try(it)
%nc)
725 Partition
%Try(it)
%LogLikeFitness(
1 : Partition
%Try(it)
%nc)
= KvolTry(kvopt)
%LogLikeFitness(
1 : Partition
%Try(it)
%nc)
727 end if blockRecursiveKvolumeOptimization
730 else blockKmeansOrSingularPartition
733 CHECK_ASSERTION(__LINE__, it
== 0, SK_
": The condition `it == 0` must hold. \todo: this must be fixed. This condition happens when Partition%nemax ~ Partition%nc. it = "//getStr(it))
734 Partition
%Try(it)
%npe
= Partition
%np
735 Partition
%Try(it)
%nps
= Partition
%CumSumSize(Partition
%ne)
+ 1_IK
736 Partition
%Try(it)
%np
= Partition
%Try(it)
%npe
- Partition
%Try(it)
%nps
+ 1_IK
737 Partition
%Try(it)
%size(
1)
= Partition
%Try(it)
%np
738 Partition
%Try(it)
%Membership(Partition
%Try(it)
%nps : Partition
%Try(it)
%npe)
= 1_IK
739 Partition
%Try(it)
%Center(
1 : nd,
1)
= 0._RK
740 do ip
= Partition
%Try(it)
%nps, Partition
%Try(it)
%npe
741 Partition
%Try(it)
%Center(
1 : nd,
1)
= Partition
%Try(it)
%Center(
1 : nd,
1)
+ Point(
1 : nd, ip)
743 Partition
%Try(it)
%Center(
1 : nd,
1)
= Partition
%Try(it)
%Center(
1 : nd,
1)
/ Partition
%Try(it)
%np
749#include "pm_clusDensity.inc.prop.inc.F90"
752 end if blockKmeansOrSingularPartition
758 real(RK) :: CenterDum(nd)
759 do ic
= 1, Partition
%Try(it)
%nc
762 do ip
= Partition
%Try(it)
%CumSumSize(ic
-1)
+ 1, Partition
%Try(it)
%CumSumSize(ic)
763 CenterDum(
1 : nd)
= CenterDum(
1 : nd)
+ Point(
1 : nd, ip)
764 sizeDum
= sizeDum
+ 1_IK
766 if (sizeDum
> 0)
then
767 CenterDum(
1 : nd)
= CenterDum(
1 : nd)
/ sizeDum
768 if (
any(abs(CenterDum(
1 : nd)
- Partition
%Try(it)
%Center(
1 : nd, ic))
> 1.e-6_RK))
then
769 if (sizeDum
/= Partition
%Try(it)
%size(ic))
then;
write(
*,
*)
"sizeDum, Kmeans%size = ", sizeDum, Partition
%Try(it)
%size;
error stop;
endif
770 write(
*,
*)
"nd,minSize, ic,nc,it = ", nd, Partition
%minSize, ic, Partition
%Try(it)
%nc, it
771 write(
*,
*)
"Partition%Try(it)%Center(:) = ", Partition
%Try(it)
%Center(
1 : nd, ic)
772 write(
*,
*)
"CenterDum(:) = ", CenterDum(
1 : nd)
773 write(
*,
*)
"Partition%Try(it)%size(:) = ", Partition
%Try(it)
%size
774 write(
*,
*)
"Partition%err%stat = ", Partition
%err
%stat
775 write(
*,
*)
"Partition%err%occurred = ", Partition
%err
%occurred
784 elseif (Partition
%err
%occurred)
then blockForwardBackwardStream
788 nemax
= nemax
+ Partition
%Try(Partition
%Try(it)
%its)
%nc
- 1_IK
789 Partition
%ne
= Partition
%Try(it)
%ne
+ 1
790 Partition
%err
%occurred
= .false._LK
792 CHECK_ASSERTION(__LINE__, Partition
%Try(it)
%size(Partition
%Try(it)
%ic)
> 0, SK_
": The condition `Partition%Try(it)%size(Partition%Try(it)%ic) > 0` must hold. it, ic, Partition%Try(it)%ic, Partition%Try(it)%size(Partition%Try(it)%ic) = "//getStr([it, ic, Partition
%Try(it)
%ic, Partition
%Try(it)
%size(Partition
%Try(it)
%ic)]))
793#include "pm_clusDensity.inc.terminal.inc.F90"
796 end if blockForwardBackwardStream
803 loopOverSubclusters:
do
805 blockForwardBackwardDecision:
if (Partition
%Try(it)
%ic
< Partition
%Try(it)
%nc)
then
807 Partition
%Try(it)
%ic
= Partition
%Try(it)
%ic
+ 1_IK
809 blockComputeLikelihoodForNonEmptyCluster:
if (Partition
%Try(it)
%size(Partition
%Try(it)
%ic)
> 0_IK)
then
816 Partition
%Try(it)
%SubclusteringWarranted(Partition
%Try(it)
%ic)
= Partition
%Try(it)
%LogVolRatio(Partition
%Try(it)
%ic)
> 0._RK .and. Partition
%Try(it)
%size(Partition
%Try(it)
%ic)
> nd
.and. nemax
> 1
817 if (Partition
%Try(it)
%SubclusteringWarranted(Partition
%Try(it)
%ic))
then
818 call random_number(unifrnd)
819 if (unifrnd
> 0._RK)
then; unifrnd
= log(unifrnd);
else; unifrnd
= -huge(unifrnd);
end if
821 if (Partition
%Try(it)
%LogLikeFitness(Partition
%Try(it)
%ic)
< NEGINF .or. Partition
%Try(it)
%LogLikeFitness(Partition
%Try(it)
%ic)
> 0._RK)
then
822 write(
*,
*)
.or."Internal error occurred: Partition%Try(it)%LogLikeFitness(Partition%Try(it)%ic) < NEGINF Partition%Try(it)%LogLikeFitness(Partition%Try(it)%ic) > 0._RK"
823 write(
*,
*)
"Partition%Try(it)%LogLikeFitness(Partition%Try(it)%ic):", Partition
%Try(it)
%LogLikeFitness(Partition
%Try(it)
%ic)
824 write(
*,
*)
"Partition%Try(it)%EffectiveSize(Partition%Try(it)%ic):", Partition
%Try(it)
%EffectiveSize(Partition
%Try(it)
%ic)
825 write(
*,
*)
"Partition%Try(it)%LogVolRatio(Partition%Try(it)%ic):", Partition
%Try(it)
%LogVolRatio(Partition
%Try(it)
%ic)
829 Partition
%Try(it)
%SubclusteringWarranted(Partition
%Try(it)
%ic)
= Partition
%Try(it)
%LogLikeFitness(Partition
%Try(it)
%ic)
< unifrnd
836 if (Partition
%Try(it)
%size(Partition
%Try(it)
%ic)
> nd)
then
837 associate(ic
=> Partition
%Try(it)
%ic)
838#include "pm_clusDensity.inc.biasCorrection.inc.F90"
846 if (Partition
%Try(it)
%SubclusteringWarranted(Partition
%Try(it)
%ic))
then
850 Partition
%Try(it)
%ic
= 0_IK
851 Partition
%Try(it)
%itp
= itp
852 Partition
%Try(itp)
%its
= it
853 Partition
%Try(itp)
%ne
= Partition
%ne
854 Partition
%Try(it)
%nc
= min(Partition
%nc, nemax)
855 cycle loopRecursivePartition
857 Partition
%ne
= Partition
%ne
+ 1_IK
858#include "pm_clusDensity.inc.terminal.inc.F90"
859 cycle loopOverSubclusters
862 else blockComputeLikelihoodForNonEmptyCluster
864 cycle loopOverSubclusters
866 end if blockComputeLikelihoodForNonEmptyCluster
868 else blockForwardBackwardDecision
871 it
= Partition
%Try(it)
%itp
872 Partition
%Try(it)
%SumLogLikeFitness(Partition
%Try(it)
%ic)
= sum(Partition
%Try(Partition
%Try(it)
%its)
%SumLogLikeFitness(
1 : Partition
%Try(Partition
%Try(it)
%its)
%nc))
873 if (Partition
%Try(it)
%LogLikeFitness(Partition
%Try(it)
%ic)
> Partition
%Try(it)
%SumLogLikeFitness(Partition
%Try(it)
%ic)
+ Partition
%logShrinkage)
then
875 Partition
%Try(Partition
%Try(it)
%its)
%SumLogLikeFitness(
1 : Partition
%Try(Partition
%Try(it)
%its)
%nc)
= 0._RK
876 nemax
= nemax
+ Partition
%Try(Partition
%Try(it)
%its)
%nc
- 1_IK
877 Partition
%ne
= Partition
%Try(it)
%ne
+ 1_IK
880 if (Partition
%Try(it)
%size(Partition
%Try(it)
%ic)
<= 0_IK)
error stop
882#include "pm_clusDensity.inc.terminal.inc.F90"
884 cycle loopRecursivePartition
886 exit loopRecursivePartition
889 end if blockForwardBackwardDecision
891 end do loopOverSubclusters
893 end do loopRecursivePartition
899#include "pm_clusDensity.inc.optimize.inc.F90"
901 if(Partition
%err
%occurred)
error stop
908#if INTEL_COMPILER_ENABLED && DLL_ENABLED && (WINDOWS_ENABLED || DARWIN_ENABLED)
911 integer(IK) ,
intent(in) :: count
912 real(RK) ,
intent(in) :: logVolRatio
913 real(RK) :: logLikeFitness
914 logLikeFitness
= count
* (
1._RK + logVolRatio
- exp(logVolRatio))
916 if (logLikeFitness
< NEGINF .or. logLikeFitness
> 0._RK)
then
917 write(
*,
*)
.or."Internal error occurred: logLikeFitness < NEGINF logLikeFitness > 0._RK"
918 write(
*,
*)
"count, logVolRatio, logLikeFitness:", count, logVolRatio, logLikeFitness
929#if INTEL_COMPILER_ENABLED && DLL_ENABLED && (WINDOWS_ENABLED || DARWIN_ENABLED)
932 integer(IK) ,
intent(in) :: nd
933 integer(IK) ,
intent(in) :: npmin
934 integer(IK) ,
intent(in) :: npmax
935 real(RK) :: BiasCorrectionScaleFactorSq(npmin:npmax)
936 integer(IK) :: ip, ndim
937 real(RK) :: LogCount(npmin:npmax)
940 real(RK),
allocatable :: LogNumPointInSpheroid(:)
941 real(RK),
allocatable :: LogMeanLogScaleFactor(:)
943#include "pm_clusDensity.inc.scaleFactor.inc.F90"
946 if (npmin
< nd
+ 1_IK)
then
947 write(
output_unit,
"(*(g0,:,' '))")
"Internal error occurred. npmin < nd + 1_IK :", npmin, nd
+ 1_IK
950 if (ndim
< lbound(Case,
dim = 1))
then
951 write(
output_unit,
"(*(g0,:,' '))")
"Internal error occurred. ndim < lbound(Case, dim = 1) :", ndim,
lbound(Case,
dim = 1)
954 if (ndim
> ubound(Case,
dim = 1)) ndim
= ubound(Case,
dim = 1)
956 LogCount(npmin:npmax)
= [(
log(
real(ip,RK)), ip
= npmin, npmax )]
959 use InterpLinear_mod,
only: InterpLinear_type
960 type(InterpLinear_type) :: Interp
961 Interp
= InterpLinear_type(SortedX
= Case(ndim)
%LogNumPointInSpheroid, SortedY
= Case(ndim)
%LogMeanLogScaleFactor)
962 BiasCorrectionScaleFactorSq(npmin:npmax)
= exp(
2_IK*exp(Interp
%predict(QueryX
= LogCount)))
965 BiasCorrectionScaleFactorSq
= 0
969 if (
any(BiasCorrectionScaleFactorSq
< 1._RK))
error stop
971 where (BiasCorrectionScaleFactorSq
< 1._RK); BiasCorrectionScaleFactorSq
= 1._RK;
end where
979 , fileUnit & ! LCOV_EXCL_LINE
980 , Point & ! LCOV_EXCL_LINE
982#if INTEL_COMPILER_ENABLED && DLL_ENABLED && (WINDOWS_ENABLED || DARWIN_ENABLED)
986 integer(IK) ,
intent(in) :: fileUnit
987 real(RK) ,
intent(in) :: Point(Partition%nd, Partition%np)
988 character(
*,SK) ,
parameter :: fileFormat
= "(*(g0,:,','))"
991 write(fileUnit,
"(*(g0,:,'"//new_line(
"a")
//"'))")
"nd", Partition
%nd,
"np", Partition
%np,
"nc", Partition
%ne
993 write(fileUnit,
"(A)")
"numRecursiveCall"
994 write(fileUnit, fileFormat) Partition
%numRecursiveCall
996 write(fileUnit,
"(A)")
"pointLogVolNormed"
997 write(fileUnit, fileFormat) Partition
%pointLogVolNormed
999 write(fileUnit,
"(A)")
"parentLogVolNormed"
1000 write(fileUnit, fileFormat) Partition
%parentLogVolNormed
1002 write(fileUnit,
"(A)")
"Size"
1003 write(fileUnit, fileFormat) Partition
%size(
1 : Partition
%ne)
1005 write(fileUnit,
"(A)")
"Center"
1006 write(fileUnit, fileFormat) Partition
%Center(
1 : Partition
%nd,
1 : Partition
%ne)
1008 write(fileUnit,
"(A)")
"LogVolNormed"
1009 write(fileUnit, fileFormat) Partition
%LogVolNormed(
1 : Partition
%ne)
1011 write(fileUnit,
"(A)")
"ChoLow"
1012 write(fileUnit, fileFormat) ((Partition
%ChoLowCovUpp(j : Partition
%nd, j, ic), j
= 1, Partition
%nd), ic
= 1, Partition
%ne)
1014 write(fileUnit,
"(A)")
"Point"
1015 write(fileUnit, fileFormat) Point
1017 write(fileUnit,
"(A)")
"LogLikeFitness"
1018 write(fileUnit, fileFormat) Partition
%LogLikeFitness(
1 : Partition
%ne)
1020 write(fileUnit,
"(A)")
"Membership"
1021 write(fileUnit, fileFormat) Partition
%Membership(
1 : Partition
%np)
1027end module pm_clusDensity
Sort the input scalar string or contiguous vector in ascending order, or return the sorted indices of...
Compute and return an iteratively-refined set of cluster centers given the input sample using the k-m...
Generate and return a decorated string resulting from the concatenation of getFile(FILE) and getLine(...
Verify the input assertion holds and if it does not, print the (optional) input message on stdout and...
Return the cumulative sum of the proportions of the exponential of the input array,...
Generate and return the natural logarithm of the sum of the exponential of the input array robustly (...
Compute and return the lower/upper-triangle of the Cholesky factorization of the input Symmetric/Her...
Generate and return the full inverse of a general or triangular matrix or a subset of the inverse of ...
Return the covariance matrix corresponding to the input (potentially weighted) correlation matrix or ...
Generate and return the conversion of the input value to an output Fortran string,...
This module contains procedures and generic interfaces for various sorting tasks.
This module contains procedures and routines for finding the minimum-volume bounding ellipsoid partit...
real(RK), parameter POSINF
function partition_typer(Point, nc, nt, nsim, nemax, minSize, stanEnabled, trimEnabled, kmeansRelTol, logExpansion, logShrinkage if MINVOL_ENABLED
This function can serve as the constructor for partition_type while also performing the partitioning ...
subroutine runPartition(Partition, Point, parentLogVolNormed)
This procedure is a method of the class partition_type. Perform recursive clustering of the input Poi...
real(RK), parameter NEGINF
PURE real(RK) function getLogLikeFitness(count, logVolRatio)
subroutine writePartition(Partition, fileUnit, Point)
character(*, SK), parameter MODULE_NAME
real(RK) function, dimension(npmin:npmax) getBiasCorrectionScaleFactorSq(nd, npmin, npmax)
This module contains procedures and routines for the computing the Kmeans clustering of a given set o...
This module contains classes and procedures for reporting and handling errors.
This module defines the relevant Fortran kind type-parameters frequently used in the ParaMonte librar...
integer, parameter RK
The default real kind in the ParaMonte library: real64 in Fortran, c_double in C-Fortran Interoperati...
integer, parameter LK
The default logical kind in the ParaMonte library: kind(.true.) in Fortran, kind(....
integer, parameter IK
The default integer kind in the ParaMonte library: int32 in Fortran, c_int32_t in C-Fortran Interoper...
integer, parameter SK
The default character kind in the ParaMonte library: kind("a") in Fortran, c_char in C-Fortran Intero...
This module contains the procedures and interfaces for computing the cumulative sum of the exponentia...
This module contains the procedures and interfaces for computing the natural logarithm of the sum of ...
This module contains procedures and generic interfaces for computing the Cholesky factorization of po...
This module contains abstract and concrete derived types and procedures related to the inversion of s...
This module contains classes and procedures for computing the properties related to the covariance ma...
This module contains the generic procedures for converting values of different types and kinds to For...
The partition_type class. Partitions an input array Point(nd,np) with nd attributes and np observatio...
This is the derived type for generating objects to gracefully and verbosely handle runtime unexpected...