Skip to content

Add mixed distribution support to TrueMeasure - #615

Open
Laasya-73 wants to merge 9 commits into
developfrom
feature/mixed-distribution
Open

Laasya-73 wants to merge 9 commits into
developfrom
feature/mixed-distribution

Conversation

@Laasya-73

Copy link
Copy Markdown
Collaborator

Summary

This PR adds support for finite mixed distributions through a new Mixture TrueMeasure.

Given component distributions with densities

$$\rho_0(x), \rho_1(x), \ldots, \rho_{s-1}(x)$$

and probabilities

$$p_0, p_1, \ldots, p_{s-1}, \qquad p_j > 0, \qquad \sum_{j=0}^{s-1} p_j = 1,$$

the resulting mixed distribution has density

$$\rho(x) = \sum_{j=0}^{s-1} p_j \rho_j(x).$$

To sample from the mixture, Mixture uses one additional uniform coordinate. For a component dimension d, the outer sampler therefore has dimension d + 1.

For

$$u = (u_0, u_1, \ldots, u_d) \in [0,1]^{d+1},$$

the first coordinate $u_0$ selects a component according to the cumulative probabilities, and the remaining coordinates $(u_1, \ldots, u_d)$ are passed through the selected component's existing TrueMeasure transform. The resulting sample is in dimension d.

Implementation

  • Adds a general Mixture TrueMeasure that can combine different compatible TrueMeasure components.
  • Requires all components to have the same output dimension.
  • Validates component types, probabilities, and the required d + 1 sampler dimension.
  • Uses each selected component's recursive transform, so composed TrueMeasures are preserved.
  • Computes mixture weights as the probability-weighted sum of the component weights.
  • Supports replicated samples and same-dimension spawning.
  • Exposes Mixture through the public qmcpy API.

A new demo notebook shows the selection mechanism as well as mixtures involving different component types, including Gaussian, zero-inflated, bounded, heavy-tailed, composed, and multidimensional examples.

Tests

Added focused tests for component selection, cumulative-probability boundaries, validation, mixture weights, composed transforms, spawning, and replicated samples.

@Laasya-73 Laasya-73 self-assigned this Sep 1, 2026
@Laasya-73 Laasya-73 added the enhancement New feature or request label Sep 1, 2026

@fjhickernell fjhickernell left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for doing this Laasya.

We talked and I requested an example showing the advantage of mixture sampling over non-mixture sampling. Let me know when you have added that.

@Laasya-73

Copy link
Copy Markdown
Collaborator Author

Thanks for doing this Laasya.

We talked and I requested an example showing the advantage of mixture sampling over non-mixture sampling. Let me know when you have added that.

Sure!!

@sou-cheng-choi sou-cheng-choi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Laasya-73

  1. Remove unnecessary line breaks and add "Open in Colab" badge to the demo by running terminal command, make format. The badge will work once this PR is merged into develop branch.

  2. Do you plan to add mean, variance, standard deviation, and covariance to Mixture in this PR?

  3. Why is weight value being 1 outside bounded support at 1.5 in the following example? Also, at any point in the bounded support, shouldn't the weight just be 0.5?

mb = Mixture(DigitalNetB2(2), [Uniform(DigitalNetB2(1), 0, 1), Uniform(DigitalNetB2(1), 2, 3)], [0.5, 0.5])
w = mb._weight(np.array([[0.5], [2.5], [1.5]]))   # currently prints [1, 1, 1]
  1. Should we use right instead of left for line 125 (self._cumulative_probabilities, flat_x[:, 0], side="left") in mixture.py?

  2. In abstract_true_measure.py:84, measure.d == measure.discrete_distrib.d by construction. However, line 75 of mixture essentially validates measure.discrete_distrib.d == measure.d + 1. The mismatch of dimensions result in exception as in the following example:

m = Mixture(DigitalNetB2(2, seed=7), [Gaussian(DigitalNetB2(1), mean=-2, covariance=1), Gaussian(DigitalNetB2(1), mean=2, covariance=1)], [0.3, 0.7])
g = CustomFun(m, lambda t: t[..., 0] ** 2)
CubQMCNetG(g).integrate() 
# ValueError: all the input array dimensions except for the concatenation axis must match exactly, but along dimension 1, the array at index 0 has size 1 and the array at index 1 has size 2

@Laasya-73

Copy link
Copy Markdown
Collaborator Author

@sou-cheng-choi

Thank you. I’ll run make format for the demo formatting and Colab badge. And yes, I’m planning to add mean, variance, standard_deviation, and covariance support to Mixture.

@Laasya-73

Copy link
Copy Markdown
Collaborator Author

@sou-cheng-choi

Thanks for the feedback. I’ve pushed updates:

  1. Formatted the demo and added the "Open in Colab" badge.
  2. Added mean, variance, standard_deviation, and covariance to Mixture.
  3. Fixed _weight so bounded-support mixtures return the correct weighted density, including 0 outside the component supports.
  4. Changed the selector boundary handling to side="right" and added boundary tests.
  5. I investigated the d+1 sampler vs. d output dimension issue further. I have not modified AbstractIntegrand yet because the selector introduces a discontinuity that can hurt QMC performance. The updated notebook now compares selector-based sampling with componentwise QMC and documents the current limitation.

For #5, I’d appreciate guidance on whether you’d prefer support for the d+1 -> d transform in the existing integration pipeline, or a componentwise mixture-integration approach.

Comment thread test/test_tm_mixed_distributions.py Fixed

@sou-cheng-choi sou-cheng-choi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Laasya-73

I have made a few commits to accomplish the following goals. Please review and revise if necessary.

  • Merge with latest develop branch code
  • Preserve sampler dimensions in integration, resume, and GP
  • Add regression tests
  • Enhance DigitalNetB2 error message for invalid sample counts

Since it has been a while since @alegresor and @fjhickernell commented or reviewed, may I suggest that you seek (re-)review from both of them whenever you feel ready?

BTW, are you using Python 3.12? It should work but a while ago, we have started to encourage QMCPy developers to move to Python 3.13.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants