Feature/prior classes#91
Merged
Merged
Conversation
…riors
Replace hardcoded Cauchy/beta-prime priors with a BAS-inspired prior class
system. Users now specify priors via constructor functions:
bgm(x, interaction_prior = normal_prior(0.5),
threshold_prior = normal_threshold_prior(1),
edge_prior = beta_bernoulli_prior(2, 5))
R-level changes:
- R/priors.R: 7 prior constructors (cauchy_prior, normal_prior,
beta_prime_prior, normal_threshold_prior, bernoulli_prior,
beta_bernoulli_prior, sbm_prior) with print methods and unpackers
- bgm() and bgmCompare(): new interaction_prior, threshold_prior,
edge_prior object parameters; all old scalar params deprecated via
lifecycle with full backward compatibility
C++ changes:
- src/priors/interaction_prior.h: InteractionPriorType and
ThresholdPriorType enums with logp/grad inline functions
- All R::dcauchy() calls replaced with interaction_prior_logp() across
GGM, OMRF, MixedMRF, and bgmCompare model code (~50 call sites)
- All inline log_beta_prior lambdas replaced with threshold_prior_logp()
- Prior types flow from R -> spec -> C++ bridge -> model constructors
This enables Normal priors for SBC validation studies where Cauchy
priors generate degenerate data, and prepares the architecture for
future g-priors and other prior families.
sample_mixed.cpp checked for "interaction_prior" and "threshold_prior" keys in the R input list, but run_sampler.R sends them as "interaction_prior_type" and "threshold_prior_type". This mismatch caused the mixed model to silently ignore user-specified priors and always fall back to Cauchy/beta-prime defaults. Adds test-prior-interface.R with 54 tests covering all prior constructors × model types (ordinal, GGM, mixed, blume-capel, bgmCompare), edge selection, backward compatibility, and stored prior info.
…anup - Use n-1 effective degrees of freedom in GGM likelihood for centered data, fixing systematic overestimation of diagonal precision elements - Add sample_ggm_prior() NUTS-based prior sampler for SBC validation, supporting both full and constrained (sparse) graphs via RATTLE - Remove redundant Gamma(1,1) diagonal prior from edge parameter and edge indicator updates (cancels under constrained Cholesky parameterization) - Guard initialize_precision_from_mle() against n=0 (prior-only sampling) - Regenerate RcppExports (remove stale sample_mixed_prior binding) - Document interaction_prior and threshold_prior params in bgmCompare
…oxygen; update README; fix mixed MRF prior - Revert posterior_mean_associations back to posterior_mean_pairwise across all R code, man pages, and tests for consistency with other output and extractor naming conventions. - Trim detailed roxygen sections in bgm() and bgmCompare() to concise summaries with a pointer to the package website. - Update x parameter documentation to mention continuous variables and GGM column-centering. - Align README citation section with the website. - Fix mixed MRF interaction prior: evaluate on Kyy = -Omega/2 scale with chain-rule correction. - Update NEWS.md with acceptance rate fix.
…rior_mean_pairwise
- Merge bgms_interaction_prior and bgms_threshold_prior into a single bgms_parameter_prior S3 class. All prior families (Cauchy, Normal, Beta-Prime) are now valid for interactions, thresholds, and means. - Constructors use dual class vectors for backward compatibility: cauchy_prior/normal_prior inherit bgms_interaction_prior, beta_prime_prior inherits bgms_threshold_prior. - Remove normal_threshold_prior() (never released); use normal_prior(). - Add means_prior argument to bgm() for continuous variable means in mixed MRF (currently plumbed to C++ but not yet consumed). - Add unpack_parameter_prior() as unified unpacker; existing unpack functions become thin wrappers. - Convert test fixtures from deprecated string edge priors to S3 objects. - Add tests for string edge_prior deprecation warnings and class-based edge prior plumbing. - Apply package-wide styler formatting.
- New bgms_scale_prior S3 class for positive scale parameters (precision matrix diagonal). - gamma_prior(shape, rate) and exponential_prior(rate) constructors. - New precision_scale_prior argument in bgm() for GGM and mixed MRF. - Plumbed through bgm_spec and run_sampler to inputFromR (C++ not yet consuming the values). - Add prior constructors section to _pkgdown.yml.
New header src/priors/parameter_prior.h with: - BaseParameterPrior abstract base class (virtual logp, grad, clone) - CauchyPrior, NormalPrior, BetaPrimePrior for real-valued parameters - GammaScalePrior for positive parameters (precision diagonal) - Factory functions create_parameter_prior() and create_scale_prior() - All concrete classes marked final for devirtualization in hot loops Not yet wired into models (Phase 4).
Replace InteractionPriorType enum + pairwise_scale_ with unique_ptr<BaseParameterPrior> interaction_prior_ and diagonal_prior_ throughout the GGM model: - ggm_model.h: constructors, copy constructor, member declarations - ggm_model.cpp: all Metropolis acceptance ratio computations - ggm_gradient.h/cpp: rebuild() takes prior refs, logp/grad use virtual dispatch instead of switch statements - sample_ggm.cpp: construct priors from inputFromR via factories - ggm_gradient_interface.cpp: update all test interface functions
- Replace enum + scalar prior params with unique_ptr<BaseParameterPrior> for both interaction and threshold priors in OMRF model. - Add logp(x, scale_factor) and grad(x, scale_factor) virtual methods to BaseParameterPrior for OMRF's per-edge pairwise_scaling_factors. - Override in CauchyPrior and NormalPrior to apply multiplicative scale. - Update factory function and sample_omrf.cpp to construct priors from inputFromR.
Replace enum + scalar prior params with unique_ptr<BaseParameterPrior> for all four prior roles in the Mixed MRF model: - interaction_prior_: pairwise interactions (discrete-discrete, etc.) - threshold_prior_: main effects / thresholds (discrete variables) - means_prior_: continuous variable means (was hardcoded Normal(0,1)) - diagonal_prior_: precision diagonal (was hardcoded Gamma(1,1)) Updated: mixed_mrf_model.h/cpp (constructors, members, copy), mixed_mrf_metropolis.cpp (all MH acceptance ratios), mixed_mrf_gradient.cpp (log-posterior and gradient computations), sample_mixed.cpp (prior construction from inputFromR), mixed_gradient_interface.cpp (test interface functions).
Replace enum + scalar prior params with const BaseParameterPrior& references throughout the bgmCompare subsystem: - Three prior objects: interaction_prior (baseline pairwise), difference_prior (group differences), threshold_prior (main effects) - Updated all function signatures through the 6-deep call chain - bgmCompare_interface.cpp constructs priors via factories - Uses logp(x, scale_factor) for pairwise_scaling_factors
Delete src/priors/interaction_prior.h (InteractionPriorType and ThresholdPriorType enums, and the free logp/grad functions). All models now use the polymorphic BaseParameterPrior hierarchy from parameter_prior.h exclusively. Remove redundant #include "priors/interaction_prior.h" from all headers and source files that already include parameter_prior.h.
New test file test-parameter-prior-cpp.R (240 tests) covering: 1. C++ prior logp/grad correctness: each prior class (Cauchy, Normal, Beta-Prime, Gamma, Exponential) verified against R reference implementations at multiple parameter values. 2. Scaled variant correctness: logp(x, scale_factor) and grad(x, scale_factor) verified against reference at scaled parameters (used by OMRF/bgmCompare pairwise_scaling_factors). 3. Numerical gradient verification: GGM gradient engine tested with Normal, Beta-Prime, and non-default Gamma diagonal priors on both full and sparse graphs; analytic gradients match finite differences. Both active-theta (NUTS) and full-space (RATTLE) parameterizations. 4. Prior consumption tests: verify that non-default precision_scale_prior and means_prior produce different posteriors than defaults, confirming the C++ code actually uses the new prior objects. New C++ test interface: src/prior_test_interface.cpp exposing test_parameter_prior(), test_scale_prior(), and prior-parameterized gradient test functions.
Extend mixed_test_logp_and_gradient and mixed_test_logp_and_gradient_full C++ test interfaces to accept means_prior and diagonal_prior parameters (previously hardcoded as Normal(0,1) and Gamma(1,1)). Add three mixed MRF numerical gradient tests: - Normal interaction prior - Cauchy means prior + Gamma(2,1) diagonal prior - All non-default priors (Normal interaction, Normal threshold, Cauchy means, Gamma(0.5,2) diagonal) All analytic gradients match finite differences to < 1e-4.
Verify that edge selection (spike-and-slab) works correctly when
combined with non-default priors across all model types:
- GGM: normal_prior, beta_prime_prior, non-default diagonal prior
- OMRF: normal_prior interaction + cauchy threshold,
beta_prime_prior interaction
- Mixed MRF: all four non-default priors simultaneously
All tests verify inclusion indicators are in [0,1] and the sampler
runs without error.
Verify bgmCompare runs correctly with: - normal_prior interaction + cauchy threshold (no selection) - beta_prime_prior interaction + beta_prime_prior threshold (no selection) - normal_prior for both + difference selection enabled
Rename the edge prior class to bgms_indicator_prior since the same selection prior structure (Bernoulli, Beta-Bernoulli, SBM) applies to both edge inclusion in bgm() and difference selection in bgmCompare(). - Rename class, print method, and unpack function throughout - bgmCompare() now accepts indicator prior objects for difference_prior (bernoulli_prior, beta_bernoulli_prior, sbm_prior) - Deprecate string-valued difference_prior and loose difference_probability - Convert test fixture from deprecated string to prior object - SBM prior is now available for difference selection in bgmCompare
Replace <U+201C>/<U+201D> (smart quotes), <U+2013> (en-dash), <U+2014> (em-dash), and <U+2019> (smart apostrophe) with ASCII equivalents across all R source files. These were introduced by styler converting actual Unicode characters to escape sequences.
Rename roxygen titles and descriptions from "Edge Inclusion" to "Inclusion Indicators" for bernoulli_prior, beta_bernoulli_prior, and sbm_prior. These priors apply to both edge selection in bgm() and difference selection in bgmCompare().
- Replace <U+2192> (arrow) and <U+00D7> (multiplication) escape sequences with ASCII -> and x in comments. - Add explicit error when edge_prior receives a non-indicator, non-string object (e.g. cauchy_prior), instead of falling through to an unhelpful match.arg error. String values are still accepted via the deprecated legacy path.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #91 +/- ##
==========================================
- Coverage 87.14% 86.95% -0.19%
==========================================
Files 72 76 +4
Lines 12291 12929 +638
==========================================
+ Hits 10711 11243 +532
- Misses 1580 1686 +106 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
MaartenMarsman
commented
Apr 10, 2026
Brings in the pd-fix for random graph initialization and the JASP progress_callback plumbing. Conflicts were textual only: the deprecated prior arguments added on feature branch sat in the same argument lists where main added progress_callback; both sides preserved. Unicode-escape conflicts in bgm.R / test_compliance.R were already resolved on feature branch (commits f457435, 14fe873).
The top-level trajectory loop in nuts_step overwrote the Metropolis contribution (alpha, n_alpha) with the latest subtree's values each iteration instead of accumulating across the full trajectory. The reported accept_prob therefore reflected only the last built subtree, biasing the signal consumed by dual-averaging step-size adaptation. Match Stan's base_nuts.hpp semantics: accumulate sum_metro_prob and n_leapfrog across every subtree built (including ones that terminated early), outside the s_prime == 1 guard, since every leapfrog step contributes to the Metropolis diagnostic.
Adds the Claude Code settings directory to .Rbuildignore so it is not flagged as an unexpected hidden directory by --as-cran checks. The directory is also listed in .gitignore but R CMD check scans the working tree, not the git index.
Surface the per-iteration mean Metropolis acceptance probability in fit$nuts_diag$accept_prob (chains x iterations), paralleling Stan's accept_stat__ output. Adds a per-chain mean_accept_prob summary and threads the value through the bgm and bgmCompare output pipelines. The new field also serves as a direct regression guard for the accept_prob accumulation bug fixed previously: the test in test-reversibility-check.R asserts a well-tuned GGM produces mean accept_prob above the dual-averaging target.
The 'Geweke-style forward-sampling test' added in #86 was never a valid Geweke joint distribution test: it drew K from a Wishart(p+1, I) prior while bgms targets a Cauchy(0, 2.5) + Gamma(1, 1) prior, ran 50 warmup iterations (so the kernel kept changing during 'one transition'), and started NUTS from a data-driven init. A bug-free sampler could not satisfy the equality it was asserting; the test has been quietly failing on every nightly run since it was introduced. The NUTS-vs-MH moment comparison and the SBC test cover the same correctness territory properly. A future commit will add a proper SBC replacement (TODO noted in the file header).
The nightly workflow invoked 'devtools::test()', which returns a testthat result object with exit code 0 even when tests fail. As a result the job reported 'success' on every nightly run despite testthat printing 'FAIL 4' (the Geweke test, now removed). Switch to 'devtools::test(stop_on_failure = TRUE)' so a single test failure propagates to the job status and the nightly turns red.
Replace the Hoffman-Gelman slice sampler inside nuts_step with Stan's
multinomial variant. Candidates are now weighted by log w_i = H0 - h_i
(the Hamiltonian offset of each leaf from the initial state) and
combined with log-sum-exp in log space:
- Base case: log_sum_weight = H0 - h (or -inf on divergence); the
non-reversible early return runs BEFORE logp evaluation, so broken
states never hit the posterior cache.
- Sibling subtrees (within build_tree) are combined with symmetric
multinomial sampling: accept the final subtree with probability
exp(w_final - log_sum_exp(w_init, w_final)).
- Top-level (in nuts_step) uses biased progressive sampling:
accept the new subtree with probability min(1, w_subtree / w_traj),
so later subtrees are preferred on average.
- Divergence is detected by (h - H0) > Delta_max (= 1000), matching
Stan; no slice variable is needed.
The Metropolis diagnostic (alpha and n_leapfrog) is computed for every
leaf regardless of divergence or reversibility and accumulated outside
the s_prime guard, so the reported accept_prob still reflects the full
trajectory.
Drops the vestigial theta_0 and r0 parameters from build_tree's
signature. Adds a numerically stable log_sum_exp helper under src/math/.
n_alpha is renamed to n_leapfrog and n_prime is replaced by
log_sum_weight in BuildTreeResult, matching Stan's vocabulary.
Validation:
- Full testthat suite green (7362 pass / 43 expected skips).
- test-ggm-nuts.R (slow) passes including NUTS-vs-MH moment agreement,
edge-selection accuracy, gradient-near-PD-boundary, and diagnostics.
- test-rattle-edge-selection.R (slow) passes.
- test-mixed-nuts.R (slow) passes.
- test-sbc-ggm.R NUTS part passes; pre-existing MH SBC failure is
unaffected by this change.
- Step 0 regression test (accept_prob >= 0.75 on a well-tuned GGM)
still passes; mean accept_prob ~ 0.94.
- Mean tree depth: 2.9100 (pre-swap slice) -> 3.0025 (multinomial),
within MC noise. Divergence rate unchanged at 0.
References:
Betancourt, M. (2017). A Conceptual Introduction to Hamiltonian
Monte Carlo, section A.3.2. arXiv:1701.02434.
Stan Development Team. base_nuts.hpp.
https://github.com/stan-dev/stan/blob/develop/src/stan/mcmc/hmc/nuts/base_nuts.hpp
bgms's doubling-window loop produced one extra small trailing window
at the end of Stage-2 whenever warmup \geq 1000. Each window boundary
triggers a mass-matrix update and a step-size reinit (heuristic +
dual-averaging restart), so the spurious extra update disrupted
step-size convergence during the most important part of warmup.
For warmup=1000 the window boundaries now match Stan exactly:
bgms (before): 100, 150, 250, 450, 850, 950 (6 windows)
bgms (after): 100, 150, 250, 450, 950 (5 windows, same as Stan)
The rule: when the window AFTER the next would overshoot stage3a_start,
stretch the current next_end to stage3a_start instead of emitting a
smaller trailing window. Matches Stan's
windowed_adaptation::compute_next_window().
Measured improvement at matched settings (3-seed average):
p=5 tridiagonal GGM, warmup=1000, iter=2000:
ESS_MIN 2841 -> 3121 (+10%)
ESS/leapfrog 0.181 -> 0.200
2D standard normal, warmup=1000, iter=4000:
ESS_MIN 3306 -> 3466 (+5%)
This is a partial close of the ~30% ESS gap versus Stan; the remaining
gap is still under investigation (step-size reinit heuristic, build-tree
early-return bookkeeping).
This reverts commit aee662f.
The outer trajectory loop in nuts_step was tracking the four U-turn
boundary momenta (p_bck_bck / p_bck_fwd / p_fwd_bck / p_fwd_fwd and
their sharp counterparts) incorrectly:
1. Neither outer-end momentum (p_bck_bck for the leftmost end, p_fwd_fwd
for the rightmost) was maintained at all. Stan requires them so that
the 'save old outer end as new interior boundary' step can run
before each extension.
2. The backward branch assigned the subtree's BEG fields to the
'bck_bck' slot and the subtree's END fields to the 'bck_fwd' slot,
which is the opposite of what the names mean. For a backward
subtree, result.p_beg is the FIRST leaf (interior right, closest to
the rest of the trajectory) and result.p_end is the LAST leaf
(outer leftmost). The forward branch was correct; only the backward
branch had the asymmetry.
3. Neither branch saved the old outer end into the interior-boundary
slot before calling build_tree, so the extended U-turn checks
(checks 2 and 3) used stale momenta from whatever extension last
updated those variables — typically the initial r0 when the
sampler happened to extend in the same direction multiple times
in a row.
The combined effect: on targets where the trajectory's U-turn
geometry depends on the interior boundary (the higher the dimension
or the more non-isotropic the posterior, the stronger the effect),
bgms terminated trees at positions Stan would have continued past.
Trajectories were cut short, ESS was lost.
Fix: (1) declare p_bck_bck and p_fwd_fwd in nuts_step and keep them
updated; (2) save p_bck_bck -> p_fwd_bck before each backward
extension and p_fwd_fwd -> p_bck_fwd before each forward extension,
matching Stan's base_nuts.hpp; (3) normalize the backward-branch
post-call assignments so p_bck_bck holds the outer-leftmost momentum
(result.p_end) and p_bck_fwd holds the interior-right momentum
(result.p_beg).
Validation:
- 6 targets x 5 seeds (gauss_2d, ggm_p3/p5/p8/p12/p20): ESS_min up
on 6/6 targets, ranging +1.3% (p=8) to +95.1% (p=20). Treedepth
increases slightly (trees now run to real U-turns instead of
premature ones) but ESS/leapfrog also improves on 5/6.
- Posterior mean/sd differences <= 0.003 across all targets; sd
ratios in [0.97, 1.01]. Same target, same posterior.
- Zero divergences in every run.
- Full testthat suite: 7362/7362 fast tests pass; slow suite shows
zero new regressions (3 failing tests are pre-existing on HEAD,
unrelated to NUTS).
- External 65-D marginal-PL benchmark reports bgms/Stan ESS ratio
of 1.05 (up from 0.69) at matched settings; posterior-mean /
sd-ratio agreement preserved.
References:
Betancourt, M. (2017). A Conceptual Introduction to Hamiltonian
Monte Carlo. arXiv:1701.02434.
Stan Development Team. base_nuts.hpp. Verbatim reference checked in
under dev/stan_reference/.
Three changes, all verified by analytic tests and paired SBC against the mixedGM Stan reference. 1. Interaction prior on Kyy scale (pure GGM + mixed MRF continuous block). The `interaction_prior` now refers to off-diagonal entries on the K_yy = -K/2 association scale, matching the mixed-MRF convention. A `Normal(0, scale)` prior therefore constrains K_yy off-diagonals with standard deviation `scale`, equivalent to Normal(0, 2*scale) on the precision entries. 2. Mixed-MRF marginal pseudo-likelihood (`pseudolikelihood = "marginal"`): the off-diagonal cross-induced contribution to the effective interaction matrix M = A_xx + 2 A_xy Sigma_yy A_xy' was under-counted by a factor of 2 in the rest-score computation. Forward log-posterior and analytic gradient now match a direct Gaussian-integral reference and central finite differences to machine precision. The fix affects both the NUTS and adaptive-Metropolis paths. 3. NUTS Stage-2 warmup windowing: when the window after the next would overshoot the Stage-3a boundary, the current next window is now stretched to absorb the remaining Stage-2 budget instead of emitting a small trailing window. Each window boundary triggers a mass-matrix update and step-size reinitialization, so eliminating the disruptive trailing window improves dual-averaging convergence and matches Stan's windowed_adaptation::compute_next_window.
The user-facing wrapper now validates inputs, rejects beta_prime_prior() with a clear message, passes the scale_prior_type through to C++ via create_scale_prior(), and wires verbose to the progress manager. The return list is fully documented with examples. Adds tests/testthat/test-sample-ggm-prior.R covering return shape, edge_indicators constraint enforcement (algebraic vs RATTLE-projected zeros), interaction- and scale-prior plumbing, and error paths.
Brings the HMC removal (PR #93), conditional pseudolikelihood removal (PR #94), sampler rename/collapse (PR #95), NUTS Stan-compliance fixes (PR #96), and marginal-PL correctness fixes (PR #97) into the prior-classes branch. Conflict resolution rule: - HMC code → take main's deletion (drops update_hmc_bgmcompare, hamiltonian_mc enum branches, hmc_num_leapfrogs args, .Deprecated paths, HMC test fixtures) - if(use_marginal_pl_) { marginal } else { conditional } → keep marginal branch only; drop the use_marginal_pl_ field and pseudolikelihood string parameter from MixedMRFModel constructor and downstream test interfaces - Prior-class additions (interaction_prior_, threshold_prior_, means_prior_, diagonal_prior_) preserved everywhere Test helper updated to inject the prior-class C++ test functions (test_parameter_prior, test_scale_prior, ggm_test_logp_and_gradient_prior, ggm_test_logp_and_gradient_full_prior, ggm_test_leapfrog_constrained_checked, unpack_interaction_prior, unpack_threshold_prior) into globalenv when running outside R CMD check. test-mixed-mrf-likelihood.R reverted to main's version (the marginal-vs-conditional comparison test no longer applies after conditional PL removal). 6663 / 6732 tests pass, 0 fail, 0 error, 69 skip (slow/CRAN-gated).
Styler pass via inst/styler/bgms_style.R picked up the assignment-style violations introduced when keeping HEAD's prior-class additions in R/bgm.R, R/bgm_spec.R, R/run_sampler.R, R/sample_ggm_prior.R, and the auto-merged R/bgmCompare.R / tests/.
Both the CRAN release of easybgm and its in-development rewrite are stamped 0.4.0, so the previous version-based threshold (version < 0.4.0) returned FALSE for both, sending an S7 fit to old-API code that does class(fit) <- ... and fit$arguments$... and crashing it. Replace the version check with a source-code fingerprint: probe the easybgm namespace for bgm_extract.package_bgms and inspect its body for extract_category_thresholds (renamed to extract_main_effects in bgms 0.2.0). The CRAN body still calls the old name; the rewrite uses extract_main_effects. Verified: - easybgm CRAN main (0.4.0, old code): 182 pass, 0 fail (was 87 pass + 3 errors under the version-only threshold) - easybgm update_easybgm (0.4.0, new): 232 pass, 0 fail
Source-fingerprint detection was a workaround for the version collision between CRAN main and the in-development rewrite (both 0.4.0). Once update_easybgm bumps to 0.5.0, the version-based threshold is the cleaner discriminator. Status under the 0.5.0 threshold: - CRAN main 0.4.0: shim -> S3 list (still 182 pass) - update_easybgm 0.4.0: shim -> S3 list (still 232 pass; the new extractor API works on S3 too, so this is fine until the version is bumped to 0.5.0) - update_easybgm >= 0.5.0 (after bump): S7 path
The previous name was opaque: the function samples precision matrices $K$ from the GGM prior (n=0, S=0 makes the likelihood flat), so 'precision_prior' captures both *what* it draws and *where* it draws from. Also list it under "Simulation and prediction" in _pkgdown.yml — its absence was breaking the GitHub Pages build. Renamed: - R/sample_ggm_prior.R -> R/sample_precision_prior.R - tests/testthat/test-sample-ggm-prior.R -> test-sample-precision-prior.R - C++ entry point sample_ggm_prior() -> sample_precision_prior() - Rcpp export name sample_ggm_prior_cpp -> sample_precision_prior_cpp Tests: 6663/6732 pass, 0 fail, 0 error.
simulate_* = forward-generate data given known parameters (cheap, exact). sample_* = MCMC draws from a target distribution (NUTS/Metropolis). The two prefixes coexist on purpose; record that under the 'Simulation and prediction' section description so users browsing the reference don't read it as accidental inconsistency.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
...