https://github.com/armanbilge/schrodinger
Give your cats a set of dice
https://github.com/armanbilge/schrodinger
cats cats-effect probabilistic-programming
Last synced: 5 months ago
JSON representation
Give your cats a set of dice
- Host: GitHub
- URL: https://github.com/armanbilge/schrodinger
- Owner: armanbilge
- License: apache-2.0
- Created: 2021-04-29T09:29:23.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2025-04-21T19:18:13.000Z (6 months ago)
- Last Synced: 2025-05-07T13:06:42.805Z (5 months ago)
- Topics: cats, cats-effect, probabilistic-programming
- Language: Scala
- Homepage:
- Size: 898 KB
- Stars: 38
- Watchers: 2
- Forks: 4
- Open Issues: 19
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# Schrodinger
[](https://index.scala-lang.org/armanbilge/schrodinger/schrodinger)
Schrodinger is an (early-stage) project for probabilistic programming in Scala 3, built for the [Cats](https://github.com/typelevel/cats) ecosystem. At its heart is the `RVT` monad transformer for modeling pseudo-random effects that is designed to fully compose with asynchronous effects such as `IO`. The goal is that this construct will facilitate the implementation of high-performance, concurrent Monte Carlo algorithms for simulation and inference.
Furthermore, Schrodinger encodes the foundational probability distributions as a set of typeclasses to be used to write "universal" probabilistic programs, for which simulators and inference algorithms can be automatically derived by implementing interpreters in terms of these same typeclasses.
## Usage
```scala
libraryDependencies += "com.armanbilge" %% "schrodinger" % "0.3-193-ed9a8ba"
```## Modules
* `kernel`: essential typeclasses for writing probabilistic programs.
- `Random[F[_]]` encodes the primitive of generating random bits in the form of `Int` and `Long`.
- `PseudoRandom[F[_], G[_], S]`: encodes the ability to pseudo-randomly simulate ("compile") a `Random` effect `F` to another effect `G` via a seed `S`. Extends `Random[F]`.
- `Distribution[F[_], P, X]`: the Kleisli `P => F[X]`, encoding the mapping from parameters `P` (e.g., the mean and standard deviation of a Gaussian) for a distribution on `X` (e.g., the reals represented as `Double`) to an instance of an effect `F[X]` (e.g., an effect implementing the `Random` typeclass).
- Various `case class`es parameterizing different distribution families, to be used as arguments for `P` above, as well as convenient aliases that can be used with the usual typeclass syntax.
- `Density[F[_], X, R]`: the Kleisli `X => F[R]`, encoding the probability density (or probability mass) function in some effect `F`.
* `random`: samplers for the distribution families in `kernel`. These are implemented purely monadically, in terms of `Random[F]` or each other.
* `schrodinger`: the core module, also brings in `random`.
- `RVT[F[_], S, A]`: a monad transformer for pseudo-random effects. Use this to simulate your probabilistic programs. Externally it is pure, although internally it is implemented with a mutable RNG for performance. Notably, it implements all the Cats Effect typeclasses up to `Async` (given that `F` is equally capable) by utilizing the underlying RNG's capability to deterministically ["split"](https://docs.oracle.com/javase/8/docs/api/java/util/SplittableRandom.html) itself, such that each fiber has its own source of randomness. Not only does this avoid contention and synchronization, it makes it possible to write pseudo-random programs that are concurrent yet _deterministic_, and thus reproducible. Anyone who has debugged a complex Monte Carlo algorithm knows this is a big deal.
- `Rng[S]`: a mutable and thus unsafe random number generator with state `S`.
- `RngDispatcher[F[_], S]`: "dispatches" a mutable RNG that can be used to run pseudo-random imperative programs, for interop with unsafe lands. This also relies on the splitting capability described above.
* `stats`: `Density` implementations for the distribution families in `kernel`.
* `monte-carlo`: algorithms and datastructures for Monte Carlo inference.
- `Weighted` and `WeightedT`: encodes a sample from a distribution along with its weight and probability density. This is useful for implementing importance sampling-based algorithms.
- `ImportanceSampler`: derives a sampler for a distribution `P` in terms of a sampler for a distribution `Q`.
* `math`: assorted math stuff.
- `LogDouble` for [probability calculations in log space](https://en.wikipedia.org/wiki/Log_probability).
* `laws`: currently empty besides a silly law for `PseudoRandom`. Still figuring this one out in [#2](https://github.com/armanbilge/schrodinger/issues/2).
* `kernel-testkit`: currently mostly used to test `random`.
- the `PureRVT` monad, implemented in terms of Cats' `StateT`. It is completely pure, unlike `RVT` in core which is run with an unsafe mutable RNG.
- \*waves hands\* `Eq` for a pseudo-random effect `F`.
* `testkit`: used to test `RVT`.If not readily apparent, various aspects of the design are heavily influenced by [Cats Effect 3](https://github.com/typelevel/cats-effect).
* `monte-carlo` is like a "`std`" lib, and so-called middlewares can ideally be implemented only in terms of that and `kernel`. The implementations provided by the `random` and `stats` modules and `RVT` itself are only needed at runtime and indeed can be substituted with (more performant!) alternatives.
* The unsafe `Rng` that is used to simulate an `RVT` is kind of like the unsafe `IORuntime` that runs `IO`.
* `RngDispatcher` facilitates interop with "unsafe lands" inspired by the `Dispatcher` in CE3.