diff --git a/.gitignore b/.gitignore index 16c4bc5..19135d1 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.jl.cov *.jl.*.cov *.jl.mem +lcov.info # Ignore the root package lockfile and the formatter tool lockfile. # Keep docs/Manifest.toml trackable for reproducible documentation builds. @@ -41,4 +42,4 @@ benchmark/results/ # Developer-specific files sc_* -lcov.info + diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index c2a4b95..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,82 +0,0 @@ -# Changelog - -All notable changes to QMC.jl will be documented in this file. - -The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## [0.1.0] - 2026-05-29 - -Initial release — a full Julia port of QMCPy v2.3. - -### Discrete Distributions - -- `IIDStdUniform` — i.i.d. uniform sampling (pure Julia) -- `Lattice` — rank-1 lattice with Kuo generating vectors, shift randomization, radical-inverse/Gray-code ordering, replications -- `DigitalNetB2` — Sobol digital nets with LMS, DS, NUS, Owen scrambling, replications -- `Halton` — Halton sequence with Owen scrambling -- `Kronecker` — Kronecker/golden-ratio low-discrepancy sequence -- `DigitalNetAnyBases` / `Faure` — generalized digital nets -- Windowed sampling (`n_start` parameter) for all generators - -### True Measures - -- `Uniform`, `Gaussian`, `BrownianMotion`, `Lebesgue`, `GeometricBrownianMotion` -- `StudentT`, `Triangular`, `Kumaraswamy`, `JohnsonsSU`, `BernoulliCont` -- `AcceptanceRejection` — rejection sampling with custom PDF -- `DistributionsWrapper` — bridge to Distributions.jl marginals -- `MaternGP`, `UniformTriangle`, `ZeroInflatedExpUniform` - -### Integrands - -- `Keister`, `Genz`, `BoxIntegral`, `Linear0`, `Sin1D` -- `Ishigami`, `Hartmann6D`, `Multimodal2D`, `FourBranch2D` -- `AsianOption`, `FinancialOption` (European, Asian, lookback, digital, barrier) -- `FinancialOptionML` — multilevel financial option -- `SensitivityIndices` — Sobol sensitivity indices via pick-freeze -- `BayesianLRCoeffs` — Bayesian logistic regression posterior -- `UMBridgeWrapper` — UMBridge.jl model integration -- `CustomFun` — user-defined integrand - -### Stopping Criteria - -- `CubMCCLT` — MC with CLT confidence interval -- `CubMCCLTVec` — vectorized MC with CLT, resume/checkpoint support -- `CubMCG` — MC with guaranteed error (kurtosis-based) -- `CubQMCLatticeG` / `CubQMCNetG` — QMC with guaranteed error -- `CubQMCBayesLatticeG` / `CubQMCBayesNetG` — Bayesian QMC -- `CubQMCRepStudentT` — replicated QMC with Student-t CI -- `CubMLMC` / `CubMLMCCont` — multilevel MC -- `CubMLQMC` / `CubMLQMCCont` — multilevel QMC -- `PFGPCI` — stub (requires AbstractGPs.jl backend) -- `rel_tol` support across all criteria -- Resume/checkpoint support for iterative criteria -- `IterationLog` diagnostics framework - -### Kernels - -- `KernelShiftInvar`, `KernelDigShiftInvar` -- `KernelMatern12`, `KernelMatern32`, `KernelMatern52`, `KernelGaussian` -- `KernelMultiTask`, `SumKernel`, `ProductKernel` - -### Utilities - -- Fast Walsh-Hadamard transform (`fwht!`, `ifwht!`) -- BRO-FFT transform -- Periodization transforms (Baker, C1, C2, C3, C2SIN) -- Bernoulli polynomials -- LatNetBuilder linker -- `mlmc_test` multilevel diagnostic utility -- GPU backend stub - -### Demos - -- 26 Jupyter notebooks covering: quickstart, sampling, lattices, digital nets, Halton, Kronecker, financial options, multilevel QMC, sensitivity analysis, Bayesian optimization, ray tracing, UMBridge, and more - -### Infrastructure - -- Documenter.jl documentation with full API reference -- CI/CD: fast Linux CI, cross-platform full sweep, nightly compatibility, docs build -- JuliaFormatter configuration -- Benchmark suite with BenchmarkTools.jl -- Concurrency cancellation on all CI workflows diff --git a/Makefile b/Makefile index c76e49e..3e8c929 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,8 @@ -.PHONY: test coverage doc format format-check lint clean bench bench-compare bench-compare-py bench-compare-py-label bench-all-label bench-compare-labels check-qmcpy-python +.PHONY: test coverage doc format format-check lint clean bench bench-compare bench-compare-py bench-compare-py-label bench-all bench-compare-labels bench-coverage bench-compare-coverage bench-compare-py-coverage bench-all-coverage local-ci check-qmcpy-python + +# ============================================================================ +# Configuration and helpers +# ============================================================================ FORMATTER_PROJECT=devtools/formatter DOC_DEPOT ?= $(if $(TMPDIR),$(TMPDIR),/tmp/)qmcju-doc-depot @@ -10,6 +14,18 @@ QMCPY_PYTHON_AUTO := $(shell \ fi; \ done) PYTHON ?= $(if $(QMCPY_PYTHON_AUTO),$(QMCPY_PYTHON_AUTO),python) +BENCH_COVERAGE ?= 0 +JULIA_BENCH_COVERAGE_FLAG := $(if $(filter 1,$(BENCH_COVERAGE)),--code-coverage=user,) + +define RUN_TIMED + @start=$$(date +%s); \ + $(1); \ + exit_code=$$?; \ + end=$$(date +%s); \ + elapsed=$$((end - start)); \ + printf '\n[%s] total runtime: %ss\n' "$(2)" "$$elapsed"; \ + exit $$exit_code +endef # Allow `make bench gaus` / `make bench-compare gaus` / `make bench-compare-py gaus` # as shorthand for `LABEL=gaus`. `make` treats `gaus` as an extra goal, so consume @@ -33,15 +49,33 @@ ifneq ($(filter bench-compare-labels,$(firstword $(MAKECMDGOALS))),) LABEL_B ?= $(word 2,$(EXTRA_LABEL_COMPARE_GOALS)) OUT_LABEL ?= $(word 3,$(EXTRA_LABEL_COMPARE_GOALS)) .PHONY: $(EXTRA_LABEL_COMPARE_GOALS) - $(EXTRA_LABEL_COMPARE_GOALS): + $(EXTRA_LABEL_COMPARE_GOALS): @: endif endif +# ============================================================================ +# Project maintenance and setup +# ============================================================================ + # Update packages and resolve dependencies update: julia --project=. -e 'using Pkg; Pkg.update(); Pkg.resolve' +# Instantiate project dependencies (includes Plots and all other deps). Download what Manifest.toml says. +setup: + julia --project=. -e 'using Pkg; Pkg.instantiate()' + +# Clean build artifacts +clean: + rm -rf docs/build + rm -rf *.jl.cov *.jl.*.cov *.jl.mem lcov.info + find src benchmark test -name '*.cov' -delete + +# ============================================================================ +# Testing and coverage +# ============================================================================ + # Run all tests test: julia --project=. -e 'using Pkg; Pkg.instantiate(); Pkg.test()' @@ -52,16 +86,23 @@ coverage: rm -f lcov.info julia --project=. -e 'using Pkg; Pkg.instantiate(); Pkg.test(coverage=true)' julia --project=. devtools/process_coverage.jl + find src test -name '*.cov' -delete # Run specific test file test-%: julia --project=. -e 'include("test/$*.jl")' +# ============================================================================ +# Documentation +# ============================================================================ + # Build documentation doc: - rm -rf docs/build - JULIA_DEPOT_PATH="$(DOC_DEPOT):$(HOME)/.julia" julia --project=docs -e 'using Pkg; Pkg.instantiate(); Pkg.resolve()' - JULIA_DEPOT_PATH="$(DOC_DEPOT):$(HOME)/.julia" julia --project=docs docs/make.jl + $(call RUN_TIMED,rm -rf docs/build && JULIA_DEPOT_PATH="$(DOC_DEPOT):$(HOME)/.julia" julia --project=docs -e 'using Pkg; Pkg.instantiate(); Pkg.resolve()' && JULIA_DEPOT_PATH="$(DOC_DEPOT):$(HOME)/.julia" julia --project=docs docs/make.jl,doc) + +# ============================================================================ +# Formatting +# ============================================================================ # Format code with JuliaFormatter (uses the repo .JuliaFormatter.toml for all paths) format: @@ -71,14 +112,9 @@ format: format-check: julia --project=$(FORMATTER_PROJECT) -e 'using Pkg; Pkg.instantiate(); using JuliaFormatter; @assert format(["src/", "test/", "benchmark/"], overwrite=false)' -# Clean build artifacts -clean: - rm -rf docs/build - rm -rf *.jl.cov *.jl.*.cov *.jl.mem lcov.info - -# Instantiate project dependencies (includes Plots and all other deps). Download what Manifest.toml says. -setup: - julia --project=. -e 'using Pkg; Pkg.instantiate()' +# ============================================================================ +# Smoke checks and notebooks +# ============================================================================ # Run a quick smoke test smoke: @@ -92,11 +128,15 @@ notebook: notebook-%: julia --project=. test/run_notebooks.jl $* +# ============================================================================ +# Benchmarking +# ============================================================================ + # Run the benchmark suite (uses its own environment in benchmark/, set up on first run) # Override output label with: make bench LABEL=gaus or make bench gaus # Saves results to benchmark/results/latest.json (default) or