Delta rules
\[ \newcommand{\expr}[3]{\begin{array}{c} #1 \\ \bbox[lightblue,5px]{#2} \end{array} ⊢ #3} \newcommand{\ct}[1]{\bbox[font-size: 0.8em]{\mathsf{#1}}} \newcommand{\updct}[1]{\ct{upd\_#1}} \newcommand{\abbr}[1]{\bbox[transform: scale(0.95)]{\mathtt{#1}}} \newcommand{\pure}[1]{\bbox[border: 1px solid orange]{\bbox[border: 4px solid transparent]{#1}}} \newcommand{\return}[1]{\bbox[border: 1px solid black]{\bbox[border: 4px solid transparent]{#1}}} \def\P{\mathtt{P}} \def\Q{\mathtt{Q}} \def\True{\ct{T}} \def\False{\ct{F}} \def\ite{\ct{if\_then\_else}} \def\Do{\abbr{do}} \]
Now that we have constants, we would like to able to do things (i.e., compute) with them. For example, following the discussion here, we would like for the encoding of expressions such as
\[ \ct{CG}(\updct{CG}(cg)(s)) \]
to be able to be evaluated—in this case—to \(cg\). We implement computations involving constants in terms of what we call delta-rules.1 In Haskell, we encode these as the following type of function:
-- | The type of Delta rules.
type DeltaRule = Term -> Maybe Term
Thus a delta rule is a partial function taking terms onto terms. It is partial because any given rule may only apply to some constants. For example, a delta rule that performs arithmetic computations might be defined on constants representing real numbers—but not, for example, on constants representing truth values.
Here we list some example rules. For clarity of presentation, the rules are defined using Haskell’s PatternSynonyms
language extension. It should be fairly clear what the relevant synonyms abbreviate.
Arithmetic
-- | Performs some arithmetic simplifications.
arithmetic :: DeltaRule
= \case
arithmetic Add t u -> case t of
Zero -> Just u
@(DCon _) -> case u of
xZero -> Just x
@(DCon _) -> Just (x + y)
y-> Nothing
_ -> case u of
t' Zero -> Just t'
-> Nothing
_ Mult t u -> case t of
Zero -> Just Zero
One -> Just u
@(DCon _) -> case u of
xZero -> Just Zero
One -> Just x
@(DCon _) -> Just (x * y)
y-> case u of
t' Zero -> Just Zero
One -> Just t'
-> Nothing
_ Neg (DCon x) -> Just (dCon (-x))
-> Nothing _
Tidying up probabilistic programs
-- | Get rid of vacuous let-bindings.
cleanUp :: DeltaRule
= \case
cleanUp Let v m k | sampleOnly m && v `notElem` freeVars k -> Just k
-> Nothing _
The indicator function
-- | Computes the indicator function.
indicator :: DeltaRule
= \case
indicator Indi Tr -> Just 1
Indi Fa -> Just 0
-> Nothing _
Indices
-- | Computes functions on indices.
indices :: DeltaRule
= \case
indices Ling (UpdLing p _) -> Just p
Ling (UpdSocPla _ i) -> Just (Ling i)
SocPla (UpdSocPla p _) -> Just p
SocPla (UpdLing _ i) -> Just (SocPla i)
-> Nothing _
If then else
-- | Computes /if then else/.
ite :: DeltaRule
= \case
ite ITE Tr x y -> Just x
ITE Fa x y -> Just y
-> Nothing _
Logical operations
logical :: DeltaRule
= \case
logical And p Tr -> Just p
And Tr p -> Just p
And Fa _ -> Just Fa
And _ Fa -> Just Fa
Or p Fa -> Just p
Or Fa p -> Just p
Or Tr _ -> Just Tr
Or _ Tr -> Just Tr
-> Nothing _
Computing the max function
-- | Computes the /max/ function.
maxes :: DeltaRule
= \case
maxes Max (Lam y (GE x (Var y'))) | y' == y -> Just x
-> Nothing _
Making observations
-- | Observing @Tr@ is trivial, while observing @Fa@ yields an undefined
-- probability distribution.
observations :: DeltaRule
= \case
observations Let _ (Observe Tr) k -> Just k
Let _ (Observe Fa) k -> Just Undefined
-> Nothing _
Some ways of computing probabilities
-- | Computes probabilities for certain probabilitic programs.
probabilities :: DeltaRule
= \case
probabilities Pr (Return Tr) -> Just 1
Pr (Return Fa) -> Just 0
Pr (Bern x) -> Just x
-> Nothing _
States
-- | Computes functions on states.
states :: DeltaRule
= \case
states CG (UpdCG cg _) -> Just cg
CG (UpdQUD _ s) -> Just (CG s)
CG (UpdTauKnow _ s) -> Just (CG s)
QUD (UpdQUD q _) -> Just q
QUD (UpdCG _ s) -> Just (QUD s)
-> Nothing _
Combining delta-rules
Note that delta-rules can be combined just like signatures.
Footnotes
Named after δ-reduction.↩︎