mirror of
https://github.com/maciej-bendkowski/generic-boltzmann-brain.git
synced 2024-09-11 12:48:09 +03:00
Initial README
This commit is contained in:
parent
6c908da3f9
commit
15ba2fd199
193
README.md
193
README.md
@ -1,10 +1,187 @@
|
|||||||
# generic-boltzmann-brain
|
# Generic Boltzmann Brain
|
||||||
|
-------------------------
|
||||||
|
|
||||||
*Generic-boltzmann-brain* is a framework which allows one to automatically
|
`generic-boltzmann-brain` is a template Haskell library which allows its users
|
||||||
derive multiparametric *analytic* (Boltzmann) samplers for algebraic data types
|
to automatically generate efficient multi-parametric analytic *Boltzmann
|
||||||
in Haskell. As such, *generic-boltzmann-brain* is a twin project of
|
samplers* for algebraic data types.
|
||||||
[Boltzmann-brain](https://github.com/maciej-bendkowski/boltzmann-brain).
|
|
||||||
|
|
||||||
Please bear in mind that the current project is still under active development.
|
**Disclaimer**
|
||||||
Usage instractions, documentation, and tooling will be delivered in the near future.
|
|
||||||
In the meantime, you're welcome to explore the current codebase for yourself.
|
Please bear in mind that the current project is still under active development
|
||||||
|
and should therefore be treated as a working prototype. Comments, critique, and
|
||||||
|
feature requests are most welcome.
|
||||||
|
|
||||||
|
### Quick overview
|
||||||
|
|
||||||
|
`generic-boltzmann-brain` constructs [Boltzmann
|
||||||
|
samplers](https://en.wikipedia.org/wiki/Boltzmann_sampler) generating random
|
||||||
|
inhabitants of user-declared algebraic data types. For instance, given the
|
||||||
|
following `BinTree` data type
|
||||||
|
|
||||||
|
```hs
|
||||||
|
data BinTree
|
||||||
|
= Leaf
|
||||||
|
| Node BinTree BinTree
|
||||||
|
deriving (Generic, Show)
|
||||||
|
```
|
||||||
|
|
||||||
|
one can construct a corresponding Boltzmann sampler in a single line of code
|
||||||
|
|
||||||
|
``` hs
|
||||||
|
mkDefBoltzmannSampler ''Tree 1000
|
||||||
|
```
|
||||||
|
|
||||||
|
which makes `BinTree` an instance of the `BoltzmannSampler` type class:
|
||||||
|
|
||||||
|
``` hs
|
||||||
|
class BoltzmannSampler a where
|
||||||
|
-- |
|
||||||
|
-- Samples a random object of type @a@. If the object size is larger than
|
||||||
|
-- the given upper bound parameter, @Nothing@ is returned instead.
|
||||||
|
sample :: RandomGen g => Int -> MaybeT (BuffonMachine g) (a, Int)
|
||||||
|
```
|
||||||
|
|
||||||
|
The so created `sample` function implements a Boltzmann sampler for `BinTree`.
|
||||||
|
The sampler outcomes follow a distribution in which *all* binary trees of equal
|
||||||
|
size have the *exact same* (uniform) probability of being sampled. The *size* of
|
||||||
|
the outcomes is itself a random variable with the user-declared mean value of
|
||||||
|
`1000`.
|
||||||
|
|
||||||
|
Further control over the outcome size distribution can be achieved through
|
||||||
|
*rejection sampling* discarding objects falling outside of the admissible lower
|
||||||
|
and upper size bounds.
|
||||||
|
|
||||||
|
``` hs
|
||||||
|
rejectionSampler ::
|
||||||
|
(RandomGen g, BoltzmannSampler a) => LowerBound -> UpperBound -> BuffonMachine g a
|
||||||
|
```
|
||||||
|
|
||||||
|
The `BuffonMachine g a` type encapsulates computations using random bits and is
|
||||||
|
in that respect closely related to QuickCheck's generator type `Gen a` to which
|
||||||
|
it can be converted through, e.g.:
|
||||||
|
|
||||||
|
``` hs
|
||||||
|
hoistRejectionSampler ::
|
||||||
|
BoltzmannSampler a => (Int -> (LowerBound, UpperBound)) -> Gen a
|
||||||
|
```
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
#### Multiparametric samplers
|
||||||
|
|
||||||
|
In a more advanced setting, `generic-boltzmann-brain` supports *inter allia*:
|
||||||
|
- systems of, possibly mutually recursive, algebraic data types,
|
||||||
|
- custom size definitions through user-declared constructor weights,
|
||||||
|
- outcome distribution tuning through constructors with user-prescribed frequencies.
|
||||||
|
|
||||||
|
Consider the following example of lambda terms in [DeBruijn notation](https://en.wikipedia.org/wiki/De_Bruijn_notation):
|
||||||
|
|
||||||
|
``` hs
|
||||||
|
data DeBruijn
|
||||||
|
= Z
|
||||||
|
| S DeBruijn
|
||||||
|
deriving (Generic, Show)
|
||||||
|
|
||||||
|
data Lambda
|
||||||
|
= Index DeBruijn
|
||||||
|
| App Lambda Lambda
|
||||||
|
| Abs Lambda
|
||||||
|
deriving (Generic, Show)
|
||||||
|
```
|
||||||
|
|
||||||
|
Suppose that we want a size notion where all constructors have weight
|
||||||
|
`1` (*i.e.* contribute one to the overall term size) *except* for `Index` which,
|
||||||
|
as a simple type converter, should contribute no size. Furthermore, suppose that
|
||||||
|
we want to *skew* the default uniform distribution, and increase the expected number
|
||||||
|
of abstractions in a random lambda term while retaining the sampler's *fairness*, *i.e.*
|
||||||
|
lambda terms of equal size *and* equal number of abstractions should have the same
|
||||||
|
probability of being sampled. With `generic-boltzmann-brain` we can generate such
|
||||||
|
a sampler as follows:
|
||||||
|
|
||||||
|
``` hs
|
||||||
|
mkBoltzmannSampler
|
||||||
|
System
|
||||||
|
{ targetType = ''Lambda
|
||||||
|
, meanSize = 10_000
|
||||||
|
, frequencies = ('Abs, 4_000) <:> def
|
||||||
|
, weights =
|
||||||
|
('Index, 0)
|
||||||
|
<:> $(mkDefWeights ''Lambda)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that `mkDefWeights` generates default constructor weights, whereas `<:>`
|
||||||
|
*overrides* the default value of `('Index, 1)` to be `('Index, 0)`. Likewise,
|
||||||
|
`def` defines the default (empty) set of frequencies and `<:>` includes
|
||||||
|
the custom frequency for the `Abs` constructor.
|
||||||
|
|
||||||
|
Using constructor tuning, it is therefore possible to distort the natural
|
||||||
|
frequency of each constructor in the given system. However, such an additional
|
||||||
|
non-trivial tuning procedure causes a not insignificant change in the underlying
|
||||||
|
probability model. In extreme cases, such as for instance requiring *80%* of
|
||||||
|
internal nodes in plane binary trees, the sampler might be unavailable or
|
||||||
|
virtually ineffective due to the sparsity of tuned structures.
|
||||||
|
|
||||||
|
**Please tune with caution!**
|
||||||
|
|
||||||
|
#### Multiple samplers for the same types
|
||||||
|
|
||||||
|
It is possible to have multiple samplers for the same underlying type, for
|
||||||
|
instance if different constructor frequencies are needed or different size
|
||||||
|
notions are required. Simply create a `newtype` wrapper and generate a let
|
||||||
|
`generic-boltzmann-brain` generate a new instance of `BoltzmannSampler`:
|
||||||
|
|
||||||
|
``` hs
|
||||||
|
newtype BinLambda = MkBinLambda Lambda
|
||||||
|
deriving (Generic, Show)
|
||||||
|
|
||||||
|
mkBoltzmannSampler
|
||||||
|
System
|
||||||
|
{ targetType = ''BinLambda
|
||||||
|
, meanSize = 6_000
|
||||||
|
, frequencies = ('Abs, 2340) <:> def
|
||||||
|
, weights =
|
||||||
|
('Index, 0)
|
||||||
|
<:> ('App, 2)
|
||||||
|
<:> ('Abs, 2)
|
||||||
|
<:> $(mkDefWeights ''Lambda)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
Currently, no pre-compiled binaries are available.
|
||||||
|
|
||||||
|
`generic-boltzmann-brain` uses an external [Python](https://www.python.org/) library
|
||||||
|
called [Paganini](https://github.com/maciej-bendkowski/paganini) to the construction
|
||||||
|
of Boltzmann samplers. `Python` with available `paganini` are expected to be executable
|
||||||
|
and present in the `PATH`.
|
||||||
|
|
||||||
|
We recommend using `stack` for compiling `generic-boltzmann-brain` sources.
|
||||||
|
|
||||||
|
### Known limitations
|
||||||
|
|
||||||
|
- Polymorphic data types are *not* supported.
|
||||||
|
- Non-algebraic data type specification are currently *not* supported, though
|
||||||
|
some of their extensions, such as some *Pólya structures* are *feasible*.
|
||||||
|
- Nested lists such as `[[Lambda]]` are *not* supported, even though lists such
|
||||||
|
as `[Lambda]` are. Note however that this is not a conceptual limitation, and
|
||||||
|
could be supported in future versions of `generic-boltzmann-brain`.
|
||||||
|
|
||||||
|
### Related work
|
||||||
|
|
||||||
|
As such, *generic-boltzmann-brain* is a twin project of
|
||||||
|
[Boltzmann-brain](https://github.com/maciej-bendkowski/boltzmann-brain). If you
|
||||||
|
are interested in generating standalone samplers out of a textual
|
||||||
|
representation, consider using *boltzmann-brain* instead.
|
||||||
|
|
||||||
|
`generic-boltzmann-brain` heavily relies on published work of numerous excellent
|
||||||
|
authors. Below, you can find a short (and definitely inexhaustive) list of
|
||||||
|
papers on the subject:
|
||||||
|
|
||||||
|
- [P. Duchon, P. Flajolet, G. Louchard. G. Schaeffer: Boltzmann Samplers for
|
||||||
|
the random generation of combinatorial
|
||||||
|
structures](http://algo.inria.fr/flajolet/Publications/DuFlLoSc04.pdf)
|
||||||
|
- [O.Bodini, J. Lumbroso, N. Rolin: Analytic samplers and the combinatorial rejection method](https://dl.acm.org/citation.cfm?id=2790220&dl=ACM&coll=DL)
|
||||||
|
- [F. Saad, C. Freer, M. Rinard, V. Mansinghka : Optimal Approximate Sampling from Discrete Probability Distributions](https://arxiv.org/pdf/2001.04555.pdf)
|
||||||
|
- [M. Bendkowski, S. Dovgal, O. Bodini : Polynomial tuning of multiparametric combinatorial
|
||||||
|
samplers](https://epubs.siam.org/doi/10.1137/1.9781611975062.9)
|
||||||
|
Loading…
Reference in New Issue
Block a user