hoppMCMC 2.2.0__tar.gz → 2.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/NEWS.txt +1 -2
  2. {hoppmcmc-2.2.0/src/hoppMCMC.egg-info → hoppmcmc-2.2.2}/PKG-INFO +1 -1
  3. {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/pyproject.toml +1 -1
  4. {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/setup.cfg +1 -1
  5. {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC/__init__.py +1 -1
  6. {hoppmcmc-2.2.0 → hoppmcmc-2.2.2/src/hoppMCMC.egg-info}/PKG-INFO +1 -1
  7. {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/inferFun/__init__.py +128 -9
  8. {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/LICENSE +0 -0
  9. {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/MANIFEST.in +0 -0
  10. {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/README.txt +0 -0
  11. {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/setup.py +0 -0
  12. {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC/doc/hoppMCMC_manual.pdf +0 -0
  13. {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC/examples/example1.py +0 -0
  14. {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC/examples/example2.py +0 -0
  15. {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC/examples/example3.py +0 -0
  16. {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC/examples/example4.py +0 -0
  17. {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC/examples/example5.py +0 -0
  18. {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC.egg-info/SOURCES.txt +0 -0
  19. {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC.egg-info/dependency_links.txt +0 -0
  20. {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC.egg-info/not-zip-safe +0 -0
  21. {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC.egg-info/requires.txt +0 -0
  22. {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/hoppMCMC.egg-info/top_level.txt +0 -0
  23. {hoppmcmc-2.2.0 → hoppmcmc-2.2.2}/src/myMPI/__init__.py +0 -0
@@ -1,14 +1,13 @@
1
1
  News
2
2
  ====
3
3
 
4
- 2.2.0
4
+ 2.2.2
5
5
  -----
6
6
 
7
7
  *Release date: 13-Jul-2026*
8
8
 
9
9
  inferFun is now updated to include ABCModel and inferABCModels as the main ABC-SMC inference tools
10
10
 
11
- 2.1.0
12
11
  1.2.1
13
12
  1.2
14
13
  1.1 *13-Sep-2018*
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hoppMCMC
3
- Version: 2.2.0
3
+ Version: 2.2.2
4
4
  Summary: An adaptive basin-hopping Markov-chain Monte Carlo algorithm for Bayesian optimisation
5
5
  Author: Kamil Erguler
6
6
  Author-email: Kamil Erguler <kerguler@gmail.com>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "hoppMCMC"
7
- version = "2.2.0"
7
+ version = "2.2.2"
8
8
  description = "An adaptive basin-hopping Markov-chain Monte Carlo algorithm for Bayesian optimisation"
9
9
  authors = [{ name = "Kamil Erguler", email = "kerguler@gmail.com" }]
10
10
  license = { text = "GPLv3" }
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = hoppMCMC
3
- version = 2.2.0
3
+ version = 2.2.2
4
4
  description = Adaptive basin-hopping MCMC and ABC inference with MPI support
5
5
  author = Kamil Erguler
6
6
  author_email = k.erguler@cyi.ac.cy
@@ -6,7 +6,7 @@ This is the python (v2.7) implementation of the hoppMCMC algorithm aiming to ide
6
6
 
7
7
  """
8
8
 
9
- __version__ = '2.2.0'
9
+ __version__ = '2.2.2'
10
10
 
11
11
  import os
12
12
  import sys
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hoppMCMC
3
- Version: 2.2.0
3
+ Version: 2.2.2
4
4
  Summary: An adaptive basin-hopping Markov-chain Monte Carlo algorithm for Bayesian optimisation
5
5
  Author: Kamil Erguler
6
6
  Author-email: Kamil Erguler <kerguler@gmail.com>
@@ -477,18 +477,137 @@ class inferABCModels:
477
477
 
478
478
  def log_kernel_density(self, model_id, x, mean, kernel):
479
479
  inferpar = self.inferpars[model_id]
480
-
481
- x_inf = x[inferpar]
482
- mean_inf = mean[inferpar]
480
+ x_inf = numpy.asarray(x[inferpar], dtype=float)
481
+ mean_inf = numpy.asarray(mean[inferpar], dtype=float)
482
+ d = len(inferpar)
483
483
 
484
484
  kernel = numpy.asarray(kernel, dtype=float)
485
485
  if kernel.ndim == 0:
486
- kernel = numpy.array([[kernel]])
487
-
488
- # Add small jitter to avoid singular covariance problems.
489
- kernel = kernel + numpy.eye(kernel.shape[0]) * self.jitter
490
-
491
- return multivariate_normal.logpdf(x_inf, mean=mean_inf, cov=kernel, allow_singular=False)
486
+ kernel = numpy.array([[float(kernel)]], dtype=float)
487
+ elif kernel.ndim == 1:
488
+ kernel = numpy.diag(kernel)
489
+ elif kernel.ndim != 2:
490
+ raise ValueError(
491
+ f"Kernel for model {model_id} ({self.model_names[model_id]}) "
492
+ f"must be scalar, 1D, or 2D. Got shape {kernel.shape}."
493
+ )
494
+ if kernel.shape != (d, d):
495
+ raise ValueError(
496
+ f"Kernel dimension mismatch for model {model_id} "
497
+ f"({self.model_names[model_id]}). "
498
+ f"Expected {(d, d)}, got {kernel.shape}. "
499
+ f"inferpar={inferpar}"
500
+ )
501
+ if not numpy.all(numpy.isfinite(x_inf)):
502
+ raise ValueError(
503
+ f"Non-finite x values for model {model_id} "
504
+ f"({self.model_names[model_id]}): {x_inf}"
505
+ )
506
+ if not numpy.all(numpy.isfinite(mean_inf)):
507
+ raise ValueError(
508
+ f"Non-finite kernel mean for model {model_id} "
509
+ f"({self.model_names[model_id]}): {mean_inf}"
510
+ )
511
+ if not numpy.all(numpy.isfinite(kernel)):
512
+ raise ValueError(
513
+ f"Non-finite kernel entries for model {model_id} "
514
+ f"({self.model_names[model_id]}):\n{kernel}"
515
+ )
516
+ # Symmetrise, just in case floating-point noise introduced asymmetry.
517
+ kernel = 0.5 * (kernel + kernel.T)
518
+ diag = numpy.diag(kernel)
519
+ if numpy.any(diag < 0):
520
+ raise ValueError(
521
+ f"Negative diagonal variance in kernel for model {model_id} "
522
+ f"({self.model_names[model_id]}).\n"
523
+ f"Diagonal={diag}\n"
524
+ f"Kernel=\n{kernel}"
525
+ )
526
+ eigvals, eigvecs = numpy.linalg.eigh(kernel)
527
+ max_eig = numpy.max(eigvals)
528
+ # A purely absolute jitter may be too small if the largest variance is large.
529
+ # This floor is both absolute and relative.
530
+ eig_floor = max(self.jitter, self.jitter * max(1.0, max_eig))
531
+ if numpy.any(eigvals <= eig_floor):
532
+ bad = numpy.where(eigvals <= eig_floor)[0]
533
+ if self.verbose:
534
+ print(
535
+ f"Warning: regularising near-singular kernel for model {model_id} "
536
+ f"({self.model_names[model_id]}).",
537
+ flush=True
538
+ )
539
+ print(f" parameter indices: {inferpar}", flush=True)
540
+ print(f" diagonal variances: {diag}", flush=True)
541
+ print(f" eigenvalues before regularisation: {eigvals}", flush=True)
542
+ print(f" eigenvalue floor: {eig_floor:g}", flush=True)
543
+ #
544
+ for b in bad:
545
+ direction = eigvecs[:, b]
546
+ order = numpy.argsort(numpy.abs(direction))[::-1]
547
+ print(
548
+ f" problematic eigenvalue {b}: {eigvals[b]:g}",
549
+ flush=True
550
+ )
551
+ print(" strongest dimensions in this direction:", flush=True)
552
+ for k in order[:min(5, len(order))]:
553
+ print(
554
+ f" kernel dim {k}, parameter index {inferpar[k]}, "
555
+ f"loading={direction[k]:g}, "
556
+ f"variance={diag[k]:g}",
557
+ flush=True
558
+ )
559
+ # Regularise eigenvalues, not only diagonal entries.
560
+ eigvals = numpy.maximum(eigvals, eig_floor)
561
+ kernel = eigvecs @ numpy.diag(eigvals) @ eigvecs.T
562
+ kernel = 0.5 * (kernel + kernel.T)
563
+ # Final check by Cholesky. This is stricter and clearer than waiting for SciPy.
564
+ try:
565
+ numpy.linalg.cholesky(kernel)
566
+ except numpy.linalg.LinAlgError as err:
567
+ eigvals_final = numpy.linalg.eigvalsh(kernel)
568
+ raise ValueError(
569
+ f"Kernel is still not positive definite for model {model_id} "
570
+ f"({self.model_names[model_id]}).\n"
571
+ f"parameter indices={inferpar}\n"
572
+ f"x={x_inf}\n"
573
+ f"mean={mean_inf}\n"
574
+ f"diagonal variances={numpy.diag(kernel)}\n"
575
+ f"eigenvalues={eigvals_final}\n"
576
+ f"kernel=\n{kernel}"
577
+ ) from err
578
+ try:
579
+ value = multivariate_normal.logpdf(
580
+ x_inf,
581
+ mean=mean_inf,
582
+ cov=kernel,
583
+ allow_singular=False
584
+ )
585
+ except Exception as err:
586
+ eigvals_final = numpy.linalg.eigvalsh(kernel)
587
+ raise ValueError(
588
+ f"multivariate_normal.logpdf failed for model {model_id} "
589
+ f"({self.model_names[model_id]}).\n"
590
+ f"parameter indices={inferpar}\n"
591
+ f"x={x_inf}\n"
592
+ f"mean={mean_inf}\n"
593
+ f"diagonal variances={numpy.diag(kernel)}\n"
594
+ f"eigenvalues={eigvals_final}\n"
595
+ f"kernel=\n{kernel}"
596
+ ) from err
597
+ if not numpy.isfinite(value):
598
+ eigvals_final = numpy.linalg.eigvalsh(kernel)
599
+ raise ValueError(
600
+ f"Non-finite kernel log density for model {model_id} "
601
+ f"({self.model_names[model_id]}).\n"
602
+ f"logpdf={value}\n"
603
+ f"parameter indices={inferpar}\n"
604
+ f"x={x_inf}\n"
605
+ f"mean={mean_inf}\n"
606
+ f"diagonal variances={numpy.diag(kernel)}\n"
607
+ f"eigenvalues={eigvals_final}\n"
608
+ f"kernel=\n{kernel}"
609
+ )
610
+ return value
492
611
 
493
612
  def calc_weights(self, mat_new, mat_old, kernels):
494
613
  """
File without changes
File without changes
File without changes
File without changes
File without changes