parismc 0.1.0__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.
parismc-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Miaoxin Liu, Alvin J. K. Chua
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,38 @@
1
+ # Include the README
2
+ include README.md
3
+
4
+ # Include the license
5
+ include LICENSE
6
+
7
+ # Include requirements
8
+ include requirements.txt
9
+
10
+ # Include all example files
11
+ recursive-include examples *.py
12
+ recursive-include examples *.md
13
+
14
+ # Include any data files if you have them
15
+ # recursive-include parismc/data *
16
+
17
+ # Exclude unnecessary files
18
+ recursive-exclude * __pycache__
19
+ recursive-exclude * *.py[co]
20
+ recursive-exclude * *.so
21
+ recursive-exclude * .DS_Store
22
+ exclude .gitignore
23
+ exclude .git
24
+ recursive-exclude .git *
25
+
26
+ # Include any additional documentation
27
+ include *.rst
28
+ include *.txt
29
+ include *.md
30
+
31
+ # Include setup files
32
+ include setup.py
33
+ include setup.cfg
34
+
35
+ # Exclude build artifacts
36
+ prune build
37
+ prune dist
38
+ prune *.egg-info
parismc-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,233 @@
1
+ Metadata-Version: 2.4
2
+ Name: parismc
3
+ Version: 0.1.0
4
+ Summary: PARIS: Parallel Adaptive Reweighting Importance Sampling for high-dimensional multi-modal Bayesian inference
5
+ Home-page: https://github.com/mx-Liu123/parismc
6
+ Author: Alvin J. K. Chua
7
+ Author-email: Miaoxin Liu <mx.liu123@outlook.com>
8
+ License: MIT
9
+ Project-URL: Homepage, https://github.com/mx-Liu123/parismc
10
+ Project-URL: Repository, https://github.com/mx-Liu123/parismc
11
+ Project-URL: Documentation, https://github.com/mx-Liu123/parismc/blob/main/README.md
12
+ Project-URL: Bug Reports, https://github.com/mx-Liu123/parismc/issues
13
+ Keywords: monte carlo,bayesian inference,importance sampling,multimodal,adaptive sampling,MCMC
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
18
+ Classifier: Topic :: Scientific/Engineering :: Physics
19
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
20
+ Classifier: License :: OSI Approved :: MIT License
21
+ Classifier: Programming Language :: Python :: 3
22
+ Classifier: Programming Language :: Python :: 3.8
23
+ Classifier: Programming Language :: Python :: 3.9
24
+ Classifier: Programming Language :: Python :: 3.10
25
+ Classifier: Programming Language :: Python :: 3.11
26
+ Classifier: Programming Language :: Python :: 3.12
27
+ Classifier: Operating System :: OS Independent
28
+ Requires-Python: >=3.8
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENSE
31
+ Requires-Dist: numpy>=1.20.0
32
+ Requires-Dist: scipy>=1.7.0
33
+ Requires-Dist: scikit-learn>=1.0.0
34
+ Requires-Dist: smt>=2.0.0
35
+ Requires-Dist: tqdm>=4.62.0
36
+ Provides-Extra: dev
37
+ Requires-Dist: pytest>=6.0; extra == "dev"
38
+ Requires-Dist: pytest-cov>=2.0; extra == "dev"
39
+ Requires-Dist: black>=22.0; extra == "dev"
40
+ Requires-Dist: flake8>=4.0; extra == "dev"
41
+ Requires-Dist: isort>=5.0; extra == "dev"
42
+ Provides-Extra: plotting
43
+ Requires-Dist: matplotlib>=3.5.0; extra == "plotting"
44
+ Requires-Dist: seaborn>=0.11.0; extra == "plotting"
45
+ Provides-Extra: notebook
46
+ Requires-Dist: jupyter>=1.0.0; extra == "notebook"
47
+ Requires-Dist: ipython>=7.0.0; extra == "notebook"
48
+ Provides-Extra: full
49
+ Requires-Dist: matplotlib>=3.5.0; extra == "full"
50
+ Requires-Dist: seaborn>=0.11.0; extra == "full"
51
+ Requires-Dist: jupyter>=1.0.0; extra == "full"
52
+ Requires-Dist: ipython>=7.0.0; extra == "full"
53
+ Dynamic: home-page
54
+ Dynamic: license-file
55
+ Dynamic: requires-python
56
+
57
+ # PARIS Monte Carlo Sampler
58
+
59
+ **An efficient adaptive importance sampler for high-dimensional multi-modal Bayesian inference.**
60
+
61
+ PARIS (**Parallel Adaptive Reweighting Importance Sampling**) combines global exploration with local adaptation to tackle complex posteriors. The workflow is simple:
62
+
63
+ 1. **Global Initialization**: Start with a space-filling design (e.g. Latin Hypercube Sampling) to seed promising regions.
64
+ 2. **Adaptive Proposals**: Each seed runs its own importance sampling process, where the proposal is a Gaussian mixture centered on past weighted samples with covariance estimated from the local sample set.
65
+ 3. **Dynamic Reweighting**: All samples are reweighted against the evolving proposal mixture, ensuring unbiased estimates and self-correcting any early overweights.
66
+ 4. **Mode Clustering**: Parallel processes that converge to the same region are merged to avoid redundancy, while distinct modes are preserved.
67
+ 5. **Posterior & Evidence**: The collected weighted samples directly reconstruct the posterior and yield accurate Bayesian evidence estimates.
68
+
69
+ This adaptive–parallel design allows PARIS to efficiently discover, refine, and integrate over complex multi-modal landscapes with minimal tuning and far fewer likelihood calls than conventional approaches.
70
+
71
+ ## Features
72
+
73
+ * **Adaptive Proposals per Seed** – Each process maintains its own proposal, evolving a local Gaussian mixture that adapts to past samples.
74
+ * **Auto-balanced Exploration** – High-weight discoveries automatically attract more samples, while overweights self-correct over time.
75
+ * **Accurate Evidence Estimation** – Bayesian evidence is computed directly from importance weights, no extra machinery needed.
76
+ * **Parallel Mode Discovery** – Multiple seeds explore independently, merging only when they converge to the same mode.
77
+ * **Intuitive Hyperparameters** – Settings like number of seeds, initial covariance, and merge thresholds map directly to prior knowledge.
78
+ * **Efficiency at Scale** – Handles high-dimensional, multi-modal targets with substantially fewer likelihood calls.
79
+ * **Boundary-safe** – Automatically respects \[0,1]^d priors.
80
+ * **Multiprocessing Ready** – Runs smoothly across CPU cores for large inference tasks.
81
+
82
+ ## Installation
83
+
84
+ ### From PyPI (when available)
85
+ ```bash
86
+ pip install parismc
87
+ ```
88
+
89
+ ### From Source
90
+ ```bash
91
+ git clone https://github.com/yourusername/parismc.git
92
+ cd parismc
93
+ pip install -e .
94
+ ```
95
+
96
+ ### Development Installation
97
+ ```bash
98
+ git clone https://github.com/yourusername/parismc.git
99
+ cd parismc
100
+ pip install -e .[dev]
101
+ ```
102
+
103
+ ## Quick Start
104
+
105
+ ```python
106
+ import numpy as np
107
+ from parismc import Sampler, SamplerConfig
108
+
109
+ # Define your log-likelihood function
110
+ def log_likelihood(x):
111
+ """Example: multivariate Gaussian log-likelihood"""
112
+ return -0.5 * np.sum(x**2, axis=1)
113
+
114
+ # Create sampler configuration
115
+ config = SamplerConfig(
116
+ alpha=1000,
117
+ latest_prob_index=1000,
118
+ boundary_limiting=True,
119
+ use_pool=False # Set to True for multiprocessing
120
+ )
121
+
122
+ # Initialize sampler
123
+ ndim = 2
124
+ n_walkers = 5
125
+ init_cov_list = [np.eye(ndim) * 0.1] * n_walkers
126
+
127
+ sampler = Sampler(
128
+ ndim=ndim,
129
+ n_seed=n_walkers,
130
+ log_reward_func=log_likelihood,
131
+ init_cov_list=init_cov_list,
132
+ config=config
133
+ )
134
+
135
+ # Prepare initial samples
136
+ sampler.prepare_lhs_samples(lhs_num=1000, batch_size=100)
137
+
138
+ # Run sampling
139
+ sampler.run_sampling(num_iterations=500, savepath='./results')
140
+
141
+ # Get results
142
+ samples, weights = sampler.get_samples_with_weights(flatten=True)
143
+ ```
144
+
145
+ ## Advanced Usage
146
+
147
+ ### Custom Prior Transform
148
+
149
+ ```python
150
+ def uniform_to_normal(x):
151
+ """Transform from [0,1]^d to unbounded space"""
152
+ from scipy.stats import norm
153
+ return norm.ppf(x)
154
+
155
+ sampler = Sampler(
156
+ ndim=ndim,
157
+ n_seed=n_walkers,
158
+ log_reward_func=log_likelihood,
159
+ init_cov_list=init_cov_list,
160
+ prior_transform=uniform_to_normal
161
+ )
162
+ ```
163
+
164
+ ### Configuration Options
165
+
166
+ ```python
167
+ config = SamplerConfig(
168
+ proc_merge_prob=0.9, # Probability threshold for merging clusters
169
+ alpha=1000, # Importance sampling parameter
170
+ latest_prob_index=1000, # Number of recent samples for weighting
171
+ trail_size=1000, # Maximum trial samples per iteration
172
+ boundary_limiting=True, # Enable boundary constraint handling
173
+ use_beta=True, # Use beta correction for boundaries
174
+ integral_num=100000, # Monte Carlo samples for beta estimation
175
+ gamma=100, # Covariance update frequency
176
+ use_pool=True, # Enable multiprocessing
177
+ n_pool=4 # Number of processes
178
+ )
179
+ ```
180
+
181
+ ## API Reference
182
+
183
+ ### Main Classes
184
+
185
+ - `Sampler`: Main sampling class
186
+ - `SamplerConfig`: Configuration dataclass
187
+
188
+ ### Key Methods
189
+
190
+ - `prepare_lhs_samples()`: Initialize with Latin Hypercube Sampling
191
+ - `run_sampling()`: Execute the sampling process
192
+ - `get_samples_with_weights()`: Retrieve samples and importance weights
193
+ - `save_state()` / `load_state()`: State persistence
194
+
195
+ ### Utility Functions
196
+
197
+ - `find_sigma_level()`: Compute confidence level thresholds
198
+ - `oracle_approximating_shrinkage()`: Covariance regularization
199
+ - Various weighting and clustering utilities
200
+
201
+ ## Requirements
202
+
203
+ - Python >= 3.8
204
+ - NumPy >= 1.20.0
205
+ - SciPy >= 1.7.0
206
+ - scikit-learn >= 1.0.0
207
+ - smt >= 2.0.0
208
+ - tqdm >= 4.62.0
209
+
210
+ ## License
211
+
212
+ MIT License - see LICENSE file for details.
213
+
214
+ ## Contributing
215
+
216
+ Contributions are welcome! Please feel free to submit pull requests or open issues.
217
+
218
+ ## Citation
219
+
220
+ If you use this software in your research, please cite:
221
+
222
+ ```bibtex
223
+ @software{parismc,
224
+ title={Parallel Adaptive Reweighting Importance Sampling (PARIS)},
225
+ author={Miaoxin Liu, Alvin J. K. Chua},
226
+ year={2025},
227
+ url={https://github.com/mx-Liu123/parismc}
228
+ }
229
+
230
+ ```
231
+
232
+
233
+
@@ -0,0 +1,177 @@
1
+ # PARIS Monte Carlo Sampler
2
+
3
+ **An efficient adaptive importance sampler for high-dimensional multi-modal Bayesian inference.**
4
+
5
+ PARIS (**Parallel Adaptive Reweighting Importance Sampling**) combines global exploration with local adaptation to tackle complex posteriors. The workflow is simple:
6
+
7
+ 1. **Global Initialization**: Start with a space-filling design (e.g. Latin Hypercube Sampling) to seed promising regions.
8
+ 2. **Adaptive Proposals**: Each seed runs its own importance sampling process, where the proposal is a Gaussian mixture centered on past weighted samples with covariance estimated from the local sample set.
9
+ 3. **Dynamic Reweighting**: All samples are reweighted against the evolving proposal mixture, ensuring unbiased estimates and self-correcting any early overweights.
10
+ 4. **Mode Clustering**: Parallel processes that converge to the same region are merged to avoid redundancy, while distinct modes are preserved.
11
+ 5. **Posterior & Evidence**: The collected weighted samples directly reconstruct the posterior and yield accurate Bayesian evidence estimates.
12
+
13
+ This adaptive–parallel design allows PARIS to efficiently discover, refine, and integrate over complex multi-modal landscapes with minimal tuning and far fewer likelihood calls than conventional approaches.
14
+
15
+ ## Features
16
+
17
+ * **Adaptive Proposals per Seed** – Each process maintains its own proposal, evolving a local Gaussian mixture that adapts to past samples.
18
+ * **Auto-balanced Exploration** – High-weight discoveries automatically attract more samples, while overweights self-correct over time.
19
+ * **Accurate Evidence Estimation** – Bayesian evidence is computed directly from importance weights, no extra machinery needed.
20
+ * **Parallel Mode Discovery** – Multiple seeds explore independently, merging only when they converge to the same mode.
21
+ * **Intuitive Hyperparameters** – Settings like number of seeds, initial covariance, and merge thresholds map directly to prior knowledge.
22
+ * **Efficiency at Scale** – Handles high-dimensional, multi-modal targets with substantially fewer likelihood calls.
23
+ * **Boundary-safe** – Automatically respects \[0,1]^d priors.
24
+ * **Multiprocessing Ready** – Runs smoothly across CPU cores for large inference tasks.
25
+
26
+ ## Installation
27
+
28
+ ### From PyPI (when available)
29
+ ```bash
30
+ pip install parismc
31
+ ```
32
+
33
+ ### From Source
34
+ ```bash
35
+ git clone https://github.com/yourusername/parismc.git
36
+ cd parismc
37
+ pip install -e .
38
+ ```
39
+
40
+ ### Development Installation
41
+ ```bash
42
+ git clone https://github.com/yourusername/parismc.git
43
+ cd parismc
44
+ pip install -e .[dev]
45
+ ```
46
+
47
+ ## Quick Start
48
+
49
+ ```python
50
+ import numpy as np
51
+ from parismc import Sampler, SamplerConfig
52
+
53
+ # Define your log-likelihood function
54
+ def log_likelihood(x):
55
+ """Example: multivariate Gaussian log-likelihood"""
56
+ return -0.5 * np.sum(x**2, axis=1)
57
+
58
+ # Create sampler configuration
59
+ config = SamplerConfig(
60
+ alpha=1000,
61
+ latest_prob_index=1000,
62
+ boundary_limiting=True,
63
+ use_pool=False # Set to True for multiprocessing
64
+ )
65
+
66
+ # Initialize sampler
67
+ ndim = 2
68
+ n_walkers = 5
69
+ init_cov_list = [np.eye(ndim) * 0.1] * n_walkers
70
+
71
+ sampler = Sampler(
72
+ ndim=ndim,
73
+ n_seed=n_walkers,
74
+ log_reward_func=log_likelihood,
75
+ init_cov_list=init_cov_list,
76
+ config=config
77
+ )
78
+
79
+ # Prepare initial samples
80
+ sampler.prepare_lhs_samples(lhs_num=1000, batch_size=100)
81
+
82
+ # Run sampling
83
+ sampler.run_sampling(num_iterations=500, savepath='./results')
84
+
85
+ # Get results
86
+ samples, weights = sampler.get_samples_with_weights(flatten=True)
87
+ ```
88
+
89
+ ## Advanced Usage
90
+
91
+ ### Custom Prior Transform
92
+
93
+ ```python
94
+ def uniform_to_normal(x):
95
+ """Transform from [0,1]^d to unbounded space"""
96
+ from scipy.stats import norm
97
+ return norm.ppf(x)
98
+
99
+ sampler = Sampler(
100
+ ndim=ndim,
101
+ n_seed=n_walkers,
102
+ log_reward_func=log_likelihood,
103
+ init_cov_list=init_cov_list,
104
+ prior_transform=uniform_to_normal
105
+ )
106
+ ```
107
+
108
+ ### Configuration Options
109
+
110
+ ```python
111
+ config = SamplerConfig(
112
+ proc_merge_prob=0.9, # Probability threshold for merging clusters
113
+ alpha=1000, # Importance sampling parameter
114
+ latest_prob_index=1000, # Number of recent samples for weighting
115
+ trail_size=1000, # Maximum trial samples per iteration
116
+ boundary_limiting=True, # Enable boundary constraint handling
117
+ use_beta=True, # Use beta correction for boundaries
118
+ integral_num=100000, # Monte Carlo samples for beta estimation
119
+ gamma=100, # Covariance update frequency
120
+ use_pool=True, # Enable multiprocessing
121
+ n_pool=4 # Number of processes
122
+ )
123
+ ```
124
+
125
+ ## API Reference
126
+
127
+ ### Main Classes
128
+
129
+ - `Sampler`: Main sampling class
130
+ - `SamplerConfig`: Configuration dataclass
131
+
132
+ ### Key Methods
133
+
134
+ - `prepare_lhs_samples()`: Initialize with Latin Hypercube Sampling
135
+ - `run_sampling()`: Execute the sampling process
136
+ - `get_samples_with_weights()`: Retrieve samples and importance weights
137
+ - `save_state()` / `load_state()`: State persistence
138
+
139
+ ### Utility Functions
140
+
141
+ - `find_sigma_level()`: Compute confidence level thresholds
142
+ - `oracle_approximating_shrinkage()`: Covariance regularization
143
+ - Various weighting and clustering utilities
144
+
145
+ ## Requirements
146
+
147
+ - Python >= 3.8
148
+ - NumPy >= 1.20.0
149
+ - SciPy >= 1.7.0
150
+ - scikit-learn >= 1.0.0
151
+ - smt >= 2.0.0
152
+ - tqdm >= 4.62.0
153
+
154
+ ## License
155
+
156
+ MIT License - see LICENSE file for details.
157
+
158
+ ## Contributing
159
+
160
+ Contributions are welcome! Please feel free to submit pull requests or open issues.
161
+
162
+ ## Citation
163
+
164
+ If you use this software in your research, please cite:
165
+
166
+ ```bibtex
167
+ @software{parismc,
168
+ title={Parallel Adaptive Reweighting Importance Sampling (PARIS)},
169
+ author={Miaoxin Liu, Alvin J. K. Chua},
170
+ year={2025},
171
+ url={https://github.com/mx-Liu123/parismc}
172
+ }
173
+
174
+ ```
175
+
176
+
177
+
@@ -0,0 +1,141 @@
1
+ """
2
+ Basic example of using the Paris Monte Carlo Sampler.
3
+
4
+ This example demonstrates:
5
+ 1. Setting up a simple multivariate Gaussian target distribution
6
+ 2. Configuring the sampler with minimal parameters
7
+ 3. Running a short sampling process
8
+ 4. Analyzing basic results
9
+ """
10
+
11
+ import numpy as np
12
+ from parismc import Sampler, SamplerConfig
13
+
14
+ # Define target distribution parameters at module level
15
+ TRUE_MEAN = np.array([0.3, 0.7])
16
+ TRUE_COV = np.array([[0.01, 0.005], [0.005, 0.02]])
17
+ INV_COV = np.linalg.inv(TRUE_COV)
18
+
19
+ def log_likelihood(x):
20
+ """
21
+ Log-likelihood for multivariate Gaussian in [0,1]^2 space.
22
+
23
+ Parameters:
24
+ ----------
25
+ x : array-like, shape (n_samples, 2)
26
+ Sample points in [0,1]^2
27
+
28
+ Returns:
29
+ -------
30
+ array-like, shape (n_samples,)
31
+ Log-likelihood values
32
+ """
33
+ if x.ndim == 1:
34
+ x = x.reshape(1, -1)
35
+
36
+ # Compute Mahalanobis distance
37
+ diff = x - TRUE_MEAN
38
+ mahal_dist = np.einsum('ij,jk,ik->i', diff, INV_COV, diff)
39
+
40
+ # Return log-likelihood (without normalization constant)
41
+ return -0.5 * mahal_dist
42
+
43
+ def main():
44
+
45
+ # Configure sampler with minimal settings
46
+ config = SamplerConfig() # Use all default values
47
+
48
+ # Initialize sampler
49
+ ndim = 2
50
+ n_walkers = 3
51
+ init_cov_list = [np.eye(ndim) * 0.05] * n_walkers
52
+
53
+ print("Initializing sampler...")
54
+ sampler = Sampler(
55
+ ndim=ndim,
56
+ n_seed=n_walkers,
57
+ log_reward_func=log_likelihood,
58
+ init_cov_list=init_cov_list
59
+ # No prior_transform needed for this simple example
60
+ )
61
+
62
+ # Prepare initial LHS samples
63
+ print("Preparing LHS samples...")
64
+ sampler.prepare_lhs_samples(lhs_num=1000, batch_size=100)
65
+
66
+ # Run sampling
67
+ print("Running sampling...")
68
+ sampler.run_sampling(num_iterations=100, savepath='./basic_results', print_iter=20)
69
+
70
+ # Get results
71
+ print("Extracting results...")
72
+ samples, weights = sampler.get_samples_with_weights(flatten=True)
73
+
74
+ # Basic analysis
75
+ print(f"\nResults Summary:")
76
+ print(f"Total samples: {len(samples)}")
77
+ print(f"Effective sample size: {1/np.sum(weights**2):.1f}")
78
+
79
+ # Weighted statistics
80
+ weighted_mean = np.average(samples, weights=weights, axis=0)
81
+ weighted_cov = np.cov(samples.T, aweights=weights)
82
+
83
+ print(f"\nTrue mean: {TRUE_MEAN}")
84
+ print(f"Estimated mean: {weighted_mean}")
85
+ print(f"Mean error: {np.linalg.norm(weighted_mean - TRUE_MEAN):.6f}")
86
+
87
+ print(f"\nTrue covariance diagonal: {np.diag(TRUE_COV)}")
88
+ print(f"Estimated covariance diagonal: {np.diag(weighted_cov)}")
89
+
90
+ # Optional plotting
91
+ try:
92
+ import matplotlib.pyplot as plt
93
+
94
+ plt.figure(figsize=(10, 4))
95
+
96
+ # Plot 1: Sample scatter plot
97
+ plt.subplot(1, 2, 1)
98
+ # Color samples by their weights
99
+ scatter = plt.scatter(samples[:, 0], samples[:, 1],
100
+ c=weights, s=30, alpha=0.7, cmap='viridis')
101
+ plt.colorbar(scatter, label='Sample Weight')
102
+ plt.scatter(TRUE_MEAN[0], TRUE_MEAN[1], color='red', s=100,
103
+ marker='x', label='True mean', linewidth=3)
104
+ plt.scatter(weighted_mean[0], weighted_mean[1], color='orange', s=100,
105
+ marker='+', label='Estimated mean', linewidth=3)
106
+ plt.xlim(0, 1)
107
+ plt.ylim(0, 1)
108
+ plt.xlabel('X1')
109
+ plt.ylabel('X2')
110
+ plt.title('Weighted Samples')
111
+ plt.legend()
112
+ plt.grid(True, alpha=0.3)
113
+
114
+ # Plot 2: Weight distribution
115
+ plt.subplot(1, 2, 2)
116
+ plt.hist(weights, bins=30, alpha=0.7, density=True, edgecolor='black')
117
+ plt.xlabel('Weight')
118
+ plt.ylabel('Density')
119
+ plt.title('Weight Distribution')
120
+ plt.grid(True, alpha=0.3)
121
+
122
+ plt.tight_layout()
123
+ plt.savefig('basic_results/sampling_results.png', dpi=150, bbox_inches='tight')
124
+ print(f"\nPlot saved to: basic_results/sampling_results.png")
125
+
126
+ # Show plot if in interactive environment
127
+ try:
128
+ plt.show()
129
+ except:
130
+ pass
131
+
132
+ except ImportError:
133
+ print("\nMatplotlib not available. Skipping plots.")
134
+ except Exception as e:
135
+ print(f"\nPlotting failed: {e}")
136
+
137
+ print("\nBasic example completed successfully!")
138
+ print("For more complex examples, see multimodal_example.py")
139
+
140
+ if __name__ == "__main__":
141
+ main()