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 +21 -0
- parismc-0.1.0/MANIFEST.in +38 -0
- parismc-0.1.0/PKG-INFO +233 -0
- parismc-0.1.0/README.md +177 -0
- parismc-0.1.0/examples/basic_example.py +141 -0
- parismc-0.1.0/examples/multimodal_example.py +469 -0
- parismc-0.1.0/examples/multimodal_results/analysis_summary.txt +10 -0
- parismc-0.1.0/parismc/__init__.py +39 -0
- parismc-0.1.0/parismc/clustering.py +203 -0
- parismc-0.1.0/parismc/optimization.py +77 -0
- parismc-0.1.0/parismc/sampler.py +775 -0
- parismc-0.1.0/parismc/utils.py +41 -0
- parismc-0.1.0/parismc.egg-info/SOURCES.txt +14 -0
- parismc-0.1.0/pyproject.toml +105 -0
- parismc-0.1.0/requirements.txt +15 -0
- parismc-0.1.0/setup.cfg +4 -0
- parismc-0.1.0/setup.py +72 -0
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
|
+
|
parismc-0.1.0/README.md
ADDED
|
@@ -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()
|