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

STTLA PR #414

Open
wants to merge 21 commits into
base: dev
Choose a base branch
from
Open

STTLA PR #414

wants to merge 21 commits into from

Conversation

andyElking
Copy link
Contributor

@andyElking andyElking commented May 8, 2024

This PR adds space-time-time Levy area to VirtualBrownianTree and UnsafeBrownianPath. The changes to the overall logic are minor, I mostly just added the math for the space-time-time case.

The additions to test_brownian.py are more extensive:

  • In test_conditional_statistics we test the pvals of the marginals for W, H, and K separately. This confirms that they are all Gaussian, so their joint distribution is exactly determined by their means and covariances, which we also test for. All of these are conditioned on the sample just before and the one just after the current sample (as it was before). I moved the code for computing the statistics into the conditional_statistics function.
  • Since the code of test_conditional_statistics itself is based on thm 3.7 from the Single-seed paper, I chose to test its correctness from a different angle in test_whk_interpolation. This test tries three things: a) just final interpolation with no halving (brownian bridge) steps, b) only one halving step followed by a final interpolation, c) 15 halving steps (i.e. tol = 2**-15) and no final interpolation (aka. "zero" spline). Since they all have the same distribution as predicted by thm 3.7, I conclude that indeed everything is as it should be. This still relies on the assumption that the halving steps are correct (i.e. thm 3.5), but that was computed by James in his thesis, so I suppose that's a fair assumption :).

In the third commit I added shape annotations to arrays in AbstractBrownianIncrement and its subclasses. This is optional, so if you prefer we can remove this commit.

In the fourth commit I just removed two unnecessary # pyright: ignore comments, so pyright doesn't complain. These have nothing to do with the rest of this PR.

I hope this PR is less challenging to review. No hurry though :)

@andyElking andyElking force-pushed the sttla_pr branch 2 times, most recently from 7b9b1e7 to a1f2e2a Compare May 9, 2024 14:07
abocquet and others added 21 commits May 19, 2024 09:07
**Major**

- Renamed "bar"->"meter" to reflect the fact that e.g. the text output isn't a bar.
- Added docstrings for all progress meter methods, the new `diffeqsolve(..., progress_meter=...)` argument, and added everything into the docs.
- Fixed bug with t0!=0 producing the wrong results.
- Fixed vmap'd diffeqsolves crashing progress bars. Making this work actually necessitated a fair bit of rewriting, with a gamut of different callbacks and unvmaps.

**Minor**

- Progress updates now move over `[0, 1]` rather than `[0, 100]`.
- Tidied up tqdm bar formatting.
- `TqdmProgressMeter` now checks at trace-time if `tqdm` is installed, rather than crashing at runtime.
- The progress bar state is now a `PyTree[Array]`
* Added parametric control types

* Demo of AbstractTerm change

* Correct initial parametric control type implementation.

* Parametric AbstractTerm initial implementation.

* Update tests and fix hinting

* Implement review comments.

* Add parametric control check to integrator.

* Update and test parametric control check

* Introduce new LevyArea types

* Updated Brownian path LevyArea types

* Replace Union types in isinstance checks

* Remove rogue comment

* Revert _brownian_arch to single assignment

* Revert _evaluate_leaf key splitting

* Rename variables in test_term

* Update isinstance and issubclass checks

* Safer handling in _denormalise_bm_inc

* Fix style in integrate control type check

* Add draft vector_field typing

* Add draft vector_field typing

* Fix term test

* Revert extemporaneous modifications in _tree

* Rename TimeLevyArea to BrownianIncrement and simplify diff

* Rename AbstractLevyReturn to AbstractBrownianReturn

* Rename _LevyArea to _BrownianReturn

* Enhance _term_compatiblity checks

* Fix merge issues

* Bump pre-commit and fix type hints

* Clean up from self-review

* Explicitly add typeguard to deps

* Bump ruff config to new syntax

* Parameterised terms: fixed term compatibility + spurious pyright errors

Phew, this ended up being a complicated one!

Let's start with the easy stuff:
- Disabled spurious pyright errors due to incompatible between pyright and `eqx.AbstractVar`.
- Now using ruff.lint and pinned exact typeguard version.

Now on to the hard stuff:
- Fixed term compatibibility missing some edge cases.

Edge cases? What edge cases? Well, what we had before was basically predicated around doing
```python
vf, contr = get_args(term_cls)
```
recalling that we may have e.g. `term_cls = AbstractTerm[SomeVectorField, SomeControl]`. So far so simple: get the arguments of a subscripted generic, no big deal.

What this failed to account for is that we may also have subclasses of this generic, e.g. `term_cls = ODETerm[SomeVectorField]`, such that some of the type variables have already been filled in when defining it:
```python
class ODETerm(AbstractTerm[_VF, RealScaleLike]): ...
```
so in this case, `get_args(term_cls)` simply returns a 1-tuple of `(SomeVectorField,)`. Oh no! Somehow we have to traverse both the filled-in type variables (to find that one of our type variables is `SomeVectorField` due to subscripting) *and* the type hierarchy (to figure out that the other type variable was filled in during the definition).

Once again, for clarity: given a subscriptable base class `AbstractTerm[_VF, _Control]` and some arbitrary possible-subscripted subclass, we need to find the values of `_VF` and `_Control`, regardless of whehther they have been passed in via subscripting the final class (and are `get_args`-able) or have been filled in during subclassing (and require traversing pseudo-type-hierarchies of `__orig_bases__`).

Any sane implementation would simply... not bother. There is no way that the hassle of figuring this out was going to be worth the small amount of type safety this brings...

So anyway, after a few hours working on this *far* past the point I should be going to sleep, this problem this is now solved. This PR introduces a new `get_args_of` function, called as `get_args_of(superclass, subclass, error_msg_if_necessary)`. This acts analogous to `get_args`, but instead of looking up both parameters (the type variables we want filled in) and the arguments (the values those type variables have been filled in with) on the same class, it looks up the parameters on the superclass, and their filled-in-values on the subclass. Pure madness.

(I'm also tagging @leycec here because this is exactly the kind of insane typing hackery that he seems to really enjoy.)

Does anyone else remember the days when this was a package primarily concerned about solving differential equations?

---------

Co-authored-by: Patrick Kidger <33688385+patrick-kidger@users.noreply.github.com>
- set reportUnnecessaryTypeIgnoreComment=true, as required by the
static type "tests" in `test_term`;

- remove now redundant, commented out, beatype based tests in
`test_term`;

- remove all unnecessary type ignore comments from across the
codebase.
* Fix complex casting and types issues

* Dependency version
* Fix complex tests

* Fix more complex tests

* New sde related fixes

* New sde related fixes
* Enable implicit solvers for complex inputs

* change version

* make pyright happy
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.

None yet

7 participants