From 5c070732c8aeff20aa3813db0090128a5d8abe22 Mon Sep 17 00:00:00 2001 From: Johannes Buchner Date: Mon, 18 Aug 2025 10:59:19 +0200 Subject: [PATCH 1/2] Increase sampling diversity by RedBlue one-to-one mapping Currently, the stretch move resamples again. Instead of finding a one-to-one mapping of red and blue, this can reuse points, decreasing proposal diversity. This commit favors a one-to-one mapping. --- src/emcee/moves/stretch.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/emcee/moves/stretch.py b/src/emcee/moves/stretch.py index 40d8e537..3ee05aa7 100644 --- a/src/emcee/moves/stretch.py +++ b/src/emcee/moves/stretch.py @@ -30,4 +30,17 @@ def get_proposal(self, s, c, random): zz = ((self.a - 1.0) * random.rand(Ns) + 1) ** 2.0 / self.a factors = (ndim - 1.0) * np.log(zz) rint = random.randint(Nc, size=(Ns,)) - return c[rint] - (c[rint] - s) * zz[:, None], factors + # deterministic matching of c to s + # they should be the same size +- 1. + if Nc == Ns: + cc = c + elif Nc == Ns + 1: # s is one shorter + cc = c[:Ns] + elif Nc == Ns - 1: # s is one longer, reuse one + # RedBlueMove's permutation means the first element is not special + cc = np.append(c, c[0]) + else: + # old resampling behaviour; this should not occur + rint = random.randint(Nc, size=(Ns,)) + cc = c[rint] + return proposal = cc - (cc - s) * zz[:, None], factors From 9e9ea81eb4ae2ba3c30fba52bfe837b5e691ea02 Mon Sep 17 00:00:00 2001 From: Johannes Buchner Date: Mon, 18 Aug 2025 11:08:19 +0200 Subject: [PATCH 2/2] use indices instead of arrays this avoids complex append/concatenate code on multi-dimensional arrays --- src/emcee/moves/stretch.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/emcee/moves/stretch.py b/src/emcee/moves/stretch.py index 3ee05aa7..6903212b 100644 --- a/src/emcee/moves/stretch.py +++ b/src/emcee/moves/stretch.py @@ -33,14 +33,15 @@ def get_proposal(self, s, c, random): # deterministic matching of c to s # they should be the same size +- 1. if Nc == Ns: - cc = c + rint = Ellipsis elif Nc == Ns + 1: # s is one shorter - cc = c[:Ns] + rint = slice(0, Ns) elif Nc == Ns - 1: # s is one longer, reuse one + rint = np.arange(Ns) # RedBlueMove's permutation means the first element is not special - cc = np.append(c, c[0]) + rint[-1] = 0 else: # old resampling behaviour; this should not occur rint = random.randint(Nc, size=(Ns,)) - cc = c[rint] - return proposal = cc - (cc - s) * zz[:, None], factors + cc = c[rint] + return cc - (cc - s) * zz[:, None], factors