diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..59c43457 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,140 @@ +# Contributing to Bijectors.jl + +Thank you for your interest in contributing to Bijectors.jl! This guide will help you set up your development environment and understand how to run tests locally. + +## Development Setup + + 1. **Clone the repository**: + + ```bash + git clone https://github.com/TuringLang/Bijectors.jl.git + cd Bijectors.jl + ``` + + 2. **Install dependencies**: + + ```bash + julia --project=. -e "using Pkg; Pkg.instantiate()" + ``` + 3. **Verify the package loads**: + + ```bash + julia --project=. -e "using Bijectors; println(\"Package loaded successfully\")" + ``` + +## Running Tests + +### Reproducing CI Test Failures + +When CI tests fail, the output often shows incomplete reproduction instructions. Here are the correct commands to reproduce different CI scenarios locally: + +#### Interface Tests + +```bash +julia --project=. -e "ENV[\"GROUP\"] = \"Interface\"; using Pkg; Pkg.test()" +``` + +#### AD Tests with Specific Backend + +Replace `BackendName` with the failing AD backend from the CI output: + +```bash +# ForwardDiff +julia --project=. -e "ENV[\"GROUP\"] = \"AD\"; ENV[\"AD\"] = \"ForwardDiff\"; using Pkg; Pkg.test()" + +# ReverseDiff +julia --project=. -e "ENV[\"GROUP\"] = \"AD\"; ENV[\"AD\"] = \"ReverseDiff\"; using Pkg; Pkg.test()" + +# Enzyme (may fail on some systems - this is expected) +julia --project=. -e "ENV[\"GROUP\"] = \"AD\"; ENV[\"AD\"] = \"Enzyme\"; using Pkg; Pkg.test()" + +# Mooncake +julia --project=. -e "ENV[\"GROUP\"] = \"AD\"; ENV[\"AD\"] = \"Mooncake\"; using Pkg; Pkg.test()" +``` + +#### Full Test Suite + +```bash +julia --project=. -e "using Pkg; Pkg.test()" +``` + +### CI Test Matrix + +Our CI runs tests with the following configurations: + + - **Interface tests**: Core functionality tests (GROUP=Interface) + - **AD tests**: Automatic differentiation tests with multiple backends (GROUP=AD, AD={ForwardDiff,ReverseDiff,Enzyme,Mooncake}) + +### Important Notes + + 1. **Always use `--project=.`**: This ensures Julia uses the correct project environment with the right dependencies. + + 2. **Environment variables matter**: The `GROUP` and `AD` environment variables control which tests run, matching the CI configuration. + 3. **Enzyme tests may fail**: Due to system compatibility issues, Enzyme tests may fail on some machines. This is expected and not a blocker for development. + 4. **Test timing**: + + + Interface tests: ~7.5 minutes + + AD tests (single backend): ~1.5 minutes + + Full test suite: 20+ minutes + +## Code Formatting + +We use JuliaFormatter.jl for consistent code formatting: + +```bash +# Install formatter (one-time setup) +julia --project=. -e "using Pkg; Pkg.add(PackageSpec(name=\"JuliaFormatter\", version=\"1\"))" + +# Format code +julia --project=. -e "using JuliaFormatter; format(\".\")" +``` + +## Documentation + +To build documentation locally: + +```bash +julia --project=docs -e "using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate(); include(\"docs/make.jl\")" +``` + +## Validation Checklist + +Before submitting a PR, please ensure: + + - [ ] Package loads without errors: `julia --project=. -e "using Bijectors"` + - [ ] Interface tests pass: `julia --project=. -e "ENV[\"GROUP\"] = \"Interface\"; using Pkg; Pkg.test()"` + - [ ] Code is formatted: `julia --project=. -e "using JuliaFormatter; format(\".\")"` + - [ ] Basic functionality works (see test scenarios below) + +### Basic Test Scenarios + +You can manually verify basic functionality: + +```julia +using Bijectors, Distributions + +# Test 1: Basic bijector for LogNormal +d = LogNormal() +b = bijector(d) +x = 1.0 +y = b(x) # Should return 0.0 + +# Test 2: Inverse transformation +x_reconstructed = inverse(b)(y) # Should return 1.0 + +# Test 3: Log absolute determinant of Jacobian +logjac = logabsdetjac(b, x) + +# Test 4: Combined transformation +z, logabsdet = with_logabsdet_jacobian(b, x) +``` + +## Getting Help + +If you need help: + + - Join the #turing channel on [Julia Slack](https://julialang.org/slack/) + - Ask questions on [Julia Discourse](https://discourse.julialang.org) + - Open a GitHub issue for bugs or feature requests + +Thank you for contributing to Bijectors.jl! diff --git a/Project.toml b/Project.toml index 6617caad..b78a1618 100644 --- a/Project.toml +++ b/Project.toml @@ -11,6 +11,7 @@ DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" Functors = "d9f16b24-f501-4c13-a1f2-28368ffc5196" InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112" IrrationalConstants = "92d709cd-6900-40b7-9082-c6be49f344b6" +JuliaFormatter = "98e50ef6-434e-11e9-1051-2b60c6c9e899" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" LogExpFunctions = "2ab3a3ac-af41-5b50-aa03-7779005ae688" MappedArrays = "dbb5928d-eab1-5f90-85c2-b9b0edb7c900" @@ -35,8 +36,8 @@ BijectorsEnzymeCoreExt = "EnzymeCore" BijectorsForwardDiffExt = "ForwardDiff" BijectorsLazyArraysExt = "LazyArrays" BijectorsMooncakeExt = "Mooncake" -BijectorsReverseDiffExt = "ReverseDiff" BijectorsReverseDiffChainRulesExt = ["ChainRules", "ReverseDiff"] +BijectorsReverseDiffExt = "ReverseDiff" [compat] ArgCheck = "1, 2" @@ -51,6 +52,7 @@ ForwardDiff = "0.10, 1.0.1" Functors = "0.1, 0.2, 0.3, 0.4, 0.5" InverseFunctions = "0.1" IrrationalConstants = "0.1, 0.2" +JuliaFormatter = "2.1.6" LazyArrays = "2" LogExpFunctions = "0.3.3" MappedArrays = "0.2.2, 0.3, 0.4" @@ -67,4 +69,4 @@ EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869" ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" LazyArrays = "5078a376-72f3-5289-bfd5-ec5146d43c02" Mooncake = "da2b9cff-9c12-43a0-ae48-6db2b0edb7d6" -ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" \ No newline at end of file +ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" diff --git a/README.md b/README.md index 7155a11e..3b8394fb 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,10 @@ This package is used heavily in the probabilistic programming language Turing.jl See the [documentation](https://turinglang.github.io/Bijectors.jl) for more. +## Development + +For development instructions, including how to reproduce CI test failures locally, see [CONTRIBUTING.md](CONTRIBUTING.md). + ## Do you want to contribute? If you feel you have some relevant skills and are interested in contributing, please get in touch! diff --git a/src/bijectors/named_bijector.jl b/src/bijectors/named_bijector.jl index 85e53e9b..4838a177 100644 --- a/src/bijectors/named_bijector.jl +++ b/src/bijectors/named_bijector.jl @@ -139,7 +139,7 @@ deps(b::NamedCoupling{<:Any,Deps}) where {Deps} = Deps return quote b = nc.f($([:(x.$d) for d in deps]...)) x_target, logjac = with_logabsdet_jacobian(b, x.$target) - return merge(x, ($target=x_target,)), logjac + return merge(x, (($target)=x_target,)), logjac end end @@ -149,6 +149,6 @@ end return quote ib = inverse(ni.orig.f($([:(x.$d) for d in deps]...))) x_target, logjac = with_logabsdet_jacobian(ib, x.$target) - return merge(x, ($target=x_target,)), logjac + return merge(x, (($target)=x_target,)), logjac end end diff --git a/test/bijectors/product_bijector.jl b/test/bijectors/product_bijector.jl index 818f89c0..73dbba08 100644 --- a/test/bijectors/product_bijector.jl +++ b/test/bijectors/product_bijector.jl @@ -39,7 +39,7 @@ has_square_jacobian(b, x) = Bijectors.output_size(b, x) == size(x) y, logjac, changes_of_variables_test=has_square_jacobian(b, xs[1]), - test_not_identity=!isidentity, + test_not_identity=(!isidentity), ) end @@ -63,7 +63,7 @@ has_square_jacobian(b, x) = Bijectors.output_size(b, x) == size(x) y, logjac, changes_of_variables_test=has_square_jacobian(b, xs[1]), - test_not_identity=!isidentity, + test_not_identity=(!isidentity), ) end end diff --git a/test/bijectors/rational_quadratic_spline.jl b/test/bijectors/rational_quadratic_spline.jl index a936c01c..cfb315d8 100644 --- a/test/bijectors/rational_quadratic_spline.jl +++ b/test/bijectors/rational_quadratic_spline.jl @@ -46,7 +46,7 @@ using LogExpFunctions # Outside of domain x = 5.0 - test_bijector(b, -x; y=-x, logjac=0) + test_bijector(b, -x; y=(-x), logjac=0) test_bijector(b, x; y=x, logjac=0) # multivariate