Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Stratonovich adjoint #21

Merged
merged 41 commits into from
Aug 20, 2020
Merged

Add support for Stratonovich adjoint #21

merged 41 commits into from
Aug 20, 2020

Conversation

lxuechen
Copy link
Collaborator

@lxuechen lxuechen commented Aug 16, 2020

Opening this up is mainly to let you know this is in progress.

The remaining stuff:

  • Write new adjoint selection function
  • Write new check contract.
  • Fix broken test for sdeint.
  • Fix broken tests for adjoint.
  • Fix broken tests for adjoint logqp.
  • Make BrownianPath support space-time, davie, foster Levy area.
  • Add gdg_jvp support. (Do this in another PR)
  • Example for gradient compute with adjoint for Strat SDE. (this shows adjoint is working for Stratonovich SDEs)

Update: It's all done. Would appreciate comments in getting the code in better shape, as although I tried to think through carefully about most code, some parts were done hastily. Now all tests pass. @patrick-kidger

This PR is really long, I'd prefer not to block/be blocked by others' work. So I'm leaving gdg_jvp for adjoint in another PR.

A couple of random things that playing around with the new code has make me think about:

  • Type check for scalar: We might want to think more carefully about the interface being supported; it seems that scalar noise matches better with diagonal noise in terms of functionality, but its current interface matches up with general/additive
  • Type check slowing down sdeint and sdeint_adjoint for small problems. I noticed this after running on some small examples with the new code.
  • Unifying some of the code in brownian.
  • From now on, whenever we plan to change something, we should always run the test suite and make sure everything there passes. If anything gets broken while modifying the codebase, we should fix it according to the test (or modify the test; less preferable).

Update: Additional caveats:

  • BrownianPath is currently not optimized; I could do these optimization in another PR. The main problems are:
    • search over t is global, whereas it could be made local
    • cholesky and matinv slow things down and might not be the most numerically stable

@patrick-kidger
Copy link
Collaborator

patrick-kidger commented Aug 16, 2020

Excellent, thanks. If this in still in-progress then ping me when you want me to go over it.

@lxuechen lxuechen mentioned this pull request Aug 16, 2020
47 tasks
@patrick-kidger
Copy link
Collaborator

patrick-kidger commented Aug 20, 2020

Thinking about strategy, something like this? (In order)

  • Merge this PR
  • Merge Tweaked to not hang on adaptive solvers. #33
  • Change the return_U/A stuff as in the previous comment.
  • Leave Milstein (Strat), Milstein grad-free (Ito + Strat) #31 until we've figured out what's going on with it, and in particular because it introduces prod which you say is a bit more difficult for the adjoint.
  • Remove logqp: I can see that maintaining this is an absolute hassle. I think eventually it would be nice to go back in (it's a very neat idea), but hopefully in a somewhat neater way. I'm thinking that it should be possible to factor it into some kind of wrapper SDE. (Doing it efficiently, without needlessly reevaluating f and g, is probably the difficult bit.)
  • Tuple-to-tensor rewrite
  • BTree levy area

I can adjust the return_U/A stuff, tear out logqp and try and make some free time to do tuple-to-tensor. Meanwhile you could look at BTree levy area and/or BPath optimisation? (Or whatever else you think is most important and won't clash.)

logqp and tuple-to-tensor should simplify the code dramatically, which will make going forward ten times easier.

@patrick-kidger
Copy link
Collaborator

Leaving another comment to keep points organised: I'm guessing the reason for implementing the adjoint SDE with custom g_prod, gdg_prod (rather than those derived in the forward SDE) is for efficiency reasons? How much is gained/lost? (Could we put the derivations from the forward SDE in as a fallback?)

@lxuechen
Copy link
Collaborator Author

(Copy from above since you comment on it down here, for clarity)
I agree the return_U stuff is a bit of a hassle. The reason I arranged it like this was so:

  • the same BM can be used with multiple schemes (as in the diagnostics)
  • the default behaviour is still to return the increment.

I'm not sure what else would satisfy those two conditions.

EDIT: Thinking about it - we could remove return_U and return_A. Then in the diagnostic BM, set levy_area_approximation='space-time' and just wrap it as e.g. sdeint(..., bm=lambda ta, tb: bm(ta, tb)[0]) for the non-SRK solvers. Sound good?

I think this is a good idea. The only concern is that I'd prefer not to have another wrapper. I think we could make bm always return a tuple (even a singleton one!) when we do interval based queries, and just let the solvers index the things needed. So it's like rather delegate the indexing to bm, we let the solver choose. WDYT?

@lxuechen
Copy link
Collaborator Author

Thinking about strategy, something like this? (In order)

  • Merge this PR
  • Merge Tweaked to not hang on adaptive solvers. #33
  • Change the return_U/A stuff as in the previous comment.
  • Leave Milstein (Strat), Milstein grad-free (Ito + Strat) #31 until we've figured out what's going on with it, and in particular because it introduces prod which you say is a bit more difficult for the adjoint.
  • Remove logqp: I can see that maintaining this is an absolute hassle. I think eventually it would be nice to go back in (it's a very neat idea), but hopefully in a somewhat neater way. I'm thinking that it should be possible to factor it into some kind of wrapper SDE. (Doing it efficiently, without needlessly reevaluating f and g, is probably the difficult bit.)
  • Tuple-to-tensor rewrite
  • BTree levy area

I can adjust the return_U/A stuff, tear out logqp and try and make some free time to do tuple-to-tensor. Meanwhile you could look at BTree levy area and/or BPath optimisation? (Or whatever else you think is most important and won't clash.)

logqp and tuple-to-tensor should simplify the code dramatically, which will make going forward ten times easier.

I agree with the overall plan. Two concerns I have:

  • About Tweaked to not hang on adaptive solvers. #33: I'm not entirely convinced that this will work always, but feel free to prove me wrong if you can. The fix seems like to target the specific test as opposed to providing a fail-safe general solution. I still think stepping over the predefined region is not that bad an idea. Another way to restructure the checks is to put the time check in check_contract, where it is checked whether any part of ts lay outside of t0 and t1 of bm, so that now we don't always get a warning when we call sdeint.

  • logqp: There's a simple way to do this by augmenting the state, but the code is likely to run slower without hacking the adjoint. The initial concern was that this would provide more strain on the user if they wanted to use this model, but I guess we could live with that once we have other optimizations in place. So I think at some point we could remove this entirely, and I'm happy to do the work just case something goes wrong.

@patrick-kidger
Copy link
Collaborator

I think this is a good idea. The only concern is that I'd prefer not to have another wrapper. I think we could make bm always return a tuple (even a singleton one!) when we do interval based queries, and just let the solvers index the things needed. So it's like rather delegate the indexing to bm, we let the solver choose. WDYT?

So the lambda wrapper is only used in our internal diagnostics, where I think we can accept bit more ugliness than in the public library.
That said, I think the tuple solution is also a fine one; specifically I'd use a namedtuple for clearer lookup in the solvers. No strong feelings either way.

I agree with the overall plan. Two concerns I have:

* About #33: I'm not entirely convinced that this will work always, but feel free to prove me wrong if you can. The fix seems like to target the specific test as opposed to providing a fail-safe general solution. I still think stepping over the predefined region is not that bad an idea. Another way to restructure the checks is to put the time check in `check_contract`, where it is checked whether any part of `ts` lay outside of `t0` and `t1` of `bm`, so that now we don't always get a warning when we call `sdeint`.

* logqp: There's a simple way to do this by augmenting the state, but the code is likely to run slower without hacking the adjoint. The initial concern was that this would provide more strain on the user if they wanted to use this model, but I guess we could live with that once we have other optimizations in place. So I think at some point we could remove this entirely, and I'm happy to do the work just case something goes wrong.

Regarding #33, I think it should always work. I'm not sure what you mean about checking times in check_contract as this was about fixing a floating point issue; the inputs were completely valid.

Regarding g_prod btw - right, I just hadn't clocked that this was a vjp. That makes total sense.

@lxuechen
Copy link
Collaborator Author

On another note, I think BrownianPath needs a partial rewrite due to the conditioning problem of levy area A. I will take those files down from this PR and send in another PR at a later time.

@patrick-kidger
Copy link
Collaborator

Makes sense. Let me know once you want me to review this PR again.

@lxuechen
Copy link
Collaborator Author

@patrick-kidger Made some minor fixes. Placed todos at places where I think would require some additional work to get the Levy area working.

@lxuechen
Copy link
Collaborator Author

That said, I think the tuple solution is also a fine one; specifically I'd use a namedtuple for clearer lookup in the solvers. No strong feelings either way.

Namedtuple would be much slower than tuple though.

I'm not sure what you mean about checking times in check_contract as this was about fixing a floating point issue; the inputs were completely valid.

I'm saying that I don't see a problem in letting the solve query times that are slightly outside the prespecified range. If you're worried about the bm always spitting out warnings for that in call, we could remove that and only do a time check in check_contract. And in that case, it wouldn't be producing warnings if the user does everything correctly.

@patrick-kidger
Copy link
Collaborator

I'll start going over it.

Fair enough that namedtuple may be too slow. (Although idk how much it matters in the grand scheme of things.) I'd suggest a custom class with __slots__ then.

So the reason that the BM spits out warnings in __call__ is that querying outside the specified range simply isn't defined for BrownianInterval; the data structure just isn't set up to handle that. (I suspect you could make a similar argument for BrownianTree? I've not looked too closely at exactly what you've done for that.) I don't see a way around that. Regardless, I'm more confident in #33 than you seem to be! I think it does the right thing in all scenarios.

torchsde/_brownian/brownian_path.py Outdated Show resolved Hide resolved
torchsde/_brownian/utils.py Show resolved Hide resolved
torchsde/_core/adjoint_sde.py Outdated Show resolved Hide resolved
torchsde/_core/adjoint.py Outdated Show resolved Hide resolved
torchsde/_core/adjoint_sde.py Outdated Show resolved Hide resolved
torchsde/_core/adjoint_sde.py Outdated Show resolved Hide resolved
torchsde/_core/sdeint.py Show resolved Hide resolved
@patrick-kidger
Copy link
Collaborator

patrick-kidger commented Aug 20, 2020

So I'm trying to figure out why Strat for all noise types isn't supported.
That's what I had in my head + what we've discussed but I can no longer find where in adjoint_sde.py things go wrong? Maybe I'm just tired.

(Except for gdg_prod_default not yet being implemetned, which I think only excludes using the derivative-using Milstein method for now.)

@lxuechen
Copy link
Collaborator Author

So I'm trying to figure out why Strat for all noise types isn't supported.
That's what I had in my head + what we've discussed but I can no longer find where in adjoint_sde.py things go wrong? Maybe I'm just tired.

(Except for gdg_prod_default not yet being implemetned, which I think only excludes using the derivative-using Milstein method for now.)

Let's do general noise for now. And it should be sufficient if you want to run certain experiments. I can do the small fixes for other noise types in another PR, but it would require quite some work, mostly regarding testing.

At this moment, I'm more interesting in getting the basic ingredients working for the methods you guys proposed, as opposed to adding features just for completeness.

@patrick-kidger
Copy link
Collaborator

So I'm trying to figure out why Strat for all noise types isn't supported.
That's what I had in my head + what we've discussed but I can no longer find where in adjoint_sde.py things go wrong? Maybe I'm just tired.
(Except for gdg_prod_default not yet being implemetned, which I think only excludes using the derivative-using Milstein method for now.)

Let's do general noise for now. And it should be sufficient if you want to run certain experiments. I can do the small fixes for other noise types in another PR, but it would require quite some work, mostly regarding testing.

At this moment, I'm more interesting in getting the basic ingredients working for the methods you guys proposed, as opposed to adding features just for completeness.

I'm not asking for them, dw. I just mean - I'm confused; what part of the code doesn't already support that? I had it in my head that we couldn't, and now I can't see why I thought that.

@lxuechen
Copy link
Collaborator Author

This PR is ready in my opinion. Remaining things on my list include

  • Fix Levy area problem in new BrownianPath + optimize performance (point-based storage + remove cholesky + matinv)
  • Add jvp_column_sum for adjoint
  • Add adjoint support for scalar/diagonal/additive noise Strat SDEs
  • Scalar noise type shape check + underlying impl consistency

It might be nice if you could check out BrownianInterval again for these things

  • docstring
  • use of utils.check_tensor_info
  • U_to_H

I'm now convinced that the min(..., ts[-1]) sol'n could work, if there's no arithmetic operation in min, which I don't think there would be. But there might be float -> torch.tensor conversions (or the other way around), which might lead to loss of numerical precision. But if ts is always a tensor, which we enforce now, I don't think there'd be an issue.

@lxuechen
Copy link
Collaborator Author

So I'm trying to figure out why Strat for all noise types isn't supported.
That's what I had in my head + what we've discussed but I can no longer find where in adjoint_sde.py things go wrong? Maybe I'm just tired.
(Except for gdg_prod_default not yet being implemetned, which I think only excludes using the derivative-using Milstein method for now.)

Let's do general noise for now. And it should be sufficient if you want to run certain experiments. I can do the small fixes for other noise types in another PR, but it would require quite some work, mostly regarding testing.
At this moment, I'm more interesting in getting the basic ingredients working for the methods you guys proposed, as opposed to adding features just for completeness.

I'm not asking for them, dw. I just mean - I'm confused; what part of the code doesn't already support that? I had it in my head that we couldn't, and now I can't see why I thought that.

I think the set of methods in adjoint_sde.py already supports additive and scalar; diagonal might need a little more thinking, but should be straightforward after I spend some time. The bulky thing that I want to leave to another PR is fixes to the tests and test problems. I would like to eventually have adjoint for Strat SDEs for different noise types numerically checked, and I'm a little worried that it might take quite some time. Atm, I don't want to block other people's work, if that make sense.

@lxuechen
Copy link
Collaborator Author

lxuechen commented Aug 20, 2020

(Except for gdg_prod_default not yet being implemetned, which I think only excludes using the derivative-using Milstein method for now.)

Without the function for computing the dg g A term, you wouldn't be able to use adjoints with the new log-ODE scheme. So this will also be on the top of my priority list.

@patrick-kidger
Copy link
Collaborator

Alright, looks good to me. I'll hit the merge button.

Everything you've said makes sense, in particular the to-do list. I'll get my part of that done. (One extra thing for whichever of us gets to it first: BrownianTree also needs Levy area support.)

@patrick-kidger patrick-kidger merged commit 572dc57 into dev Aug 20, 2020
@patrick-kidger patrick-kidger deleted the dev-strat-adjoint branch August 20, 2020 22:05
lxuechen added a commit that referenced this pull request Oct 22, 2020
* Added BrownianInterval

* Unified base solvers

* Updated solvers to use interval interface

* Unified solvers.

* Required Python 3.6. Bumped version.

* Updated benchmarks. Fixed several bugs.

* Tweaked BrownianInterval to accept queries outside its range

* tweaked benchmark

* Added midpoint. Tweaked and fixed things.

* Tided up adjoint.

* Bye bye Python 2; fixes #14.

* tweaks from feedback

* Fix typing.

* changed version

* Rename.

* refactored settings up a level. Fixed bug in BTree.

* fixed bug with non-srk methods

* Fixed? srk noise

* Fixed SRK properly, hopefully

* fixed mistake in adjoint

* Fix broken tests and refresh documentation.

* Output type annotation.

* Rename to reverse bm.

* Fix typo.

* minor refactors in response to feedback

* Tided solvers a little further.

* Fixed strong order for midpoint

* removed unused code

* Dev kidger2 (#19)

* Many fixes.

Updated diagnostics.
Removed trapezoidal_approx
Fixed error messages for wrong methods etc.
Can now call BrownianInterval with a single value.
Fixed bug in BrownianInterval that it was always returning 0!
There's now a 2-part way of getting levy area: it has to be set as
available during __init__, and then specified that it's wanted during
__call__. This allows one to create general Brownian motions that can be
used in multiple solvers, and have each solver call just the bits it
wants.
Bugfix spacetime -> space-time
Improved checking in check_contract
Various minor tidy-ups
Can use Brownian* with any Levy area sufficient for the solver, rather
than just the minimum the solver needs.
Fixed using bm=None in sdeint and sdeint_adjoint, so that it creates an
appropriate BrownianInterval. This also makes method='srk' easy.

* Fixed ReverseBrownian

* bugfix for midpoint

* Tided base SDE classes slightly.

* spacetime->space-time; small tidy up; fix latent_sde.py example

* Add efficient gdg_jvp term for log-ODE schemes. (#20)

* Add efficient jvp for general noise and refactor surrounding.

* Add test for gdg_jvp.

* Simplify requires grad logic.

* Add more rigorous numerical tests.

* Fix all issues

* Heun's method (#24)

* Implemented Heun method

* Refactor after review

* Added docstring

* Updated heun docstring

* BrownianInterval tests + bugfixes (#28)

* In progress commit on branch dev-kidger3.

* Added tests+bugfixes for BrownianInterval

* fixed typo in docstring

* Corrections from review

* Refactor tests for

* Refactor tests for BrownianInterval.

* Refactor tests for Brownian path and Brownian tree.

* use default CPU

* Remove loop.

Co-authored-by: Xuechen Li <12689993+lxuechen@users.noreply.github.com>

* bumped numpy version (#32)

* Milstein (Strat), Milstein grad-free (Ito + Strat) (#31)

* Added milstein_grad_free, milstein_strat and milstein_strat_grad_free

* Refactor after first review

* Changes after second review

* Formatted imports

* Changed used Ex. Reversed g_prod

* Add support for Stratonovich adjoint (#21)

* Add efficient jvp for general noise and refactor surrounding.

* Add test for gdg_jvp.

* Simplify requires grad logic.

* Add more rigorous numerical tests.

* Minor refactor.

* Simplify adjoints.

* Add general noise version.

* Refactor adjoint code.

* Fix new interface.

* Add adjoint method checking.

* Fix bug in not indexing the dict.

* Fix broken tests for sdeint.

* Fix bug in selection.

* Fix flatten bug in adjoint.

* Fix zero filling bug in jvp.

* Fix bug.

* Refactor.

* Simplify tuple logic in modified Brownian.

* Remove np.searchsorted in BrownianPath.

* Make init more consistent.

* Replace np.searchsorted with bisect for speed; also fixes #29.

* Prepare levy area support for BrownianPath.

* Use torch.Generator to move to torch 1.6.0.

* Prepare space-time Levy area support for BrownianPath.

* Enable all levy area approximations for BrownianPath.

* Fix for test_sdeint.

* Fix all broken tests; all tests pass.

* Add numerical test for gradient using midpoint method for Strat.

* Support float/int time list.

* Fixes from comments.

* Additional fixes from comments.

* Fix documentation.

* Remove to for BrownianPath.

* Fix insert.

* Use none for default levy area.

* Refactor check tensor info to reduce boilerplate.

* Add a todo regarding get noise.

* Remove type checks in adjoint.

* Fixes from comments.

* Added BrownianReturn (#34)

* Added BrownianReturn

* Update utils.py

* Binterval improvements (#35)

* Tweaked to not hang on adaptive solvers.

* Updated adaptive fix

* Several fixes for tests and adjoint.

Removed some broken tests.
Added error-raising `g` to the adjoint SDE.
Fixed Milstein for adjoint.
Fixed running adjoint at all.

* fixed bug in SRK

* tided up BInterval

* variable name tweak

* Improved heuristic for BrownianInterval's dependency tree. (#40)

* [On dev branch] Tuple rewrite (#37)

* Rename plot folders from diagnostics.

* Complete tuple rewrite.

* Remove inaccurate comments.

* Minor fixes.

* Fixes.

* Remove comment.

* Fix docstring.

* Fix noise type for problem.

* Binterval recursion fix (#42)

* Improved heuristic for BrownianInterval's dependency tree.

* Inlined the recursive code to reduce number of stack frames

* Add version number.

Co-authored-by: Xuechen <12689993+lxuechen@users.noreply.github.com>

* Refactor.

* Euler-Heun method (#39)

* Implemented euler-heun

* After refactor

* Applied refactor. Added more diagnostics

* Refactor after review

* Corrected order

* Formatting

* Formatting

* BInterval - U fix (#44)

* Improved heuristic for BrownianInterval's dependency tree.

* fixed H aggregation

* Added consistency test

* test fixes

* put seed back

* from comments

* Add log-ODE scheme and simplify typing. (#43)

* Add log-ODE scheme and simplify typing.

* Register log-ODE method.

* Refactor diagnostics and examples.

* Refactor plotting.

* Move btree profile to benchmarks.

* Refactor all ito diagnostics.

* Refactor.

* Split imports.

* Refactor the Stratonovich diagnostics.

* Fix documentation.

* Minor typing fix.

* Remove redundant imports.

* Fixes from comment.

* Simplify.

* Simplify.

* Fix typo caused bug.

* Fix directory issue.

* Fix order issue.

* Change back weak order.

* Fix test problem.

* Add weak order inspection.

* Bugfixes for log-ODE (#45)

* fixed rate diagnostics

* tweak

* adjusted test_strat

* fixed logODE default.

* Fix typo.

Co-authored-by: Xuechen Li <12689993+lxuechen@users.noreply.github.com>

* Default to loop-based. Fixes #46.

* Minor tweak of settings.

* Fix directory structure.

* Speed up experiments.

* Cycle through the possible line styles.

Co-authored-by: Patrick Kidger <33688385+patrick-kidger@users.noreply.github.com>

* Simplify and fix documentation.

* Minor fixes.

- Simplify strong order assignment for euler.
- Fix bug with "space_time".

* Simplify strong order assignment for euler.

* Fix bug with space-time naming.

* Make tensors for grad for adjoint specifiable. (#52)

* Copy of #55 | Created pyproject.toml (#56)

* Skip tests if the optional C++ implementations don't compile; fixes #51.

* Create pyproject.toml

* Version add 1.6.0 and up

Co-authored-by: Xuechen <12689993+lxuechen@users.noreply.github.com>

* Latent experiment (#48)

* Latent experiment

* Refactor after review

* Fixed y0

* Added stable div

* Minor refactor

* Simplify latent sde even further.

* Added double adjoint (#49)

* Added double adjoint

* tweaks

* Updated adjoint tests

* Dev adjoint double test (#57)

* Add gradgrad check for adjoint.

* Relax tolerance.

* Refactor numerical tests.

* Remove unused import.

* Fix bug.

* Fixes from comments.

* Rename for consistency.

* Refactor comment.

* Minor refactor.

* Add adjoint support for general/scalar noise in the Ito case. (#58)

* adjusted requires_grad

Co-authored-by: Xuechen Li <12689993+lxuechen@users.noreply.github.com>

* Dev minor (#63)

* Add requirements and update latent sde.

* Fix requirements.

* Fix.

* Update documentation.

* Use split to speed things up slightly.

* Remove jit standalone.

* Enable no value arguments.

* Fix bug in args.

* Dev adjoint strat (#67)

* Remove logqp test.

* Tide examples.

* Refactor to class attribute.

* Fix gradcheck.

* Reenable adjoints.

* Typo.

* Simplify tests

* Deprecate this test.

* Add back f ito and strat.

* Simplify.

* Skip more.

* Simplify.

* Disable adaptive.

* Refactor due to change of problems.

* Reduce problem size to prevent general noise test case run for ever.

* Continuous Integration.  (#68)

* Skip tests if the optional C++ implementations don't compile; fixes #51.

* Continuous integration.

* Fix os.

* Install package before test.

* Add torch to dependency list.

* Reduce trials.

* Restrict max number of parallel runs.

* Add scipy.

* Fixes from comment.

* Reduce frequency.

* Fixes.

* Make sure run installed package.

* Add check version on pr towards master.

* Separate with blank lines.

* Loosen tolerance.

* Add badge.

* Brownian unification (#61)

* Added tol. Reduced number of generator creations. Spawn keys now of
finite length. Tidied code.

* Added BrownianPath and BrownianTree as BrownianInterval wrappers

* added trampolining

* Made Path and Tree wrappers on Interval.

* Updated tests. Fixed BrownianTree determinism. Allowed cache_size=0

* done benchmarks. Fixed adjoint bug. Removed C++ from setup.py

* fixes for benchmark

* added base brownian

* BrownianPath/Tree now with the same interface as before

* BInterval(shape->size), changed BPath and BTree to composition-over-inheritance.

* tweaks

* Fixes for CI. (#69)

* Fixes for CI.

* Tweaks to support windows.

* Patch for windows.

* Update patch for windows.

* Fix flaky tests of BInterval.

* Add fail-fast: false (#72)

* Dev methods fixes (#73)

* Fixed adaptivity checks. Improved default method selection.

* Fixes+updated sdeint tests

* adjoint method fixes

* Fixed for Py3.6

* assert->ValueError; tweaks

* Dev logqp (#75)

* Simplify.

* Add stable div utility.

* Deprecate.

* Refactor problems.

* Sync adjoint tests.

* Fix style.

* Fix import style.

* Add h to test problems.

* Add logqp.

* Logqp backwards compatibility.

* Add type annotation.

* Better documentation.

* Fixes.

* Fix notebook. (#74)

* Fix notebook.

* Remove trivial stuff.

* Fixes from comments.

* Fixes.

* More fixes.

* Outputs.

* Clean up.

* Fixes.

* fixed BInterval flakiness+slowness (#76)

* Added documentation (#71)

* Added documentation

* tweaks

* Fix significance level.

* Fix check version.

* Skip confirmation.

* Fix indentation errors.

* Update README.md

Co-authored-by: Patrick Kidger <33688385+patrick-kidger@users.noreply.github.com>
Co-authored-by: Mateusz Sokół <8431159+mtsokol@users.noreply.github.com>
Co-authored-by: Sayantan Das <36279638+ucalyptus@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants