Skip to content

Commit

Permalink
Update comment syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
b-studios committed Apr 26, 2024
1 parent 9a52708 commit 28ed63d
Showing 1 changed file with 72 additions and 58 deletions.
130 changes: 72 additions & 58 deletions examples/pos/probabilistic.effekt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ module examples/pos/probabilistic

import immutable/list

///
/// Bayesian inference for random variables (RVs) with boolean values
///

// Bayesian inference for random variables (RVs) with boolean values
// -----------------------------------------------------------------

// set up a heap for storing RVs
effect IndexOutOfBounds[A](): A
Expand Down Expand Up @@ -58,35 +58,36 @@ def heap[R] { prog: => R / Heap } = {
}


// effects for expressing some constructs on RVs

/// Cond expresses a RV which depends on a some other RVs listed in listRef.
/// The list listProbabilities contains the probabilities with which the
/// expressed RV is true given that the RVs in listRef are true/false:
/// if there are n RVs in listRef, then there are supposed to be 2^n
/// elements in listProbabilities, one for each combination of true/false
/// for the elements in listRef.
/// The order in listProbabilities goes from all RVs in listRef are false to
/// all of them are true in ascending order, when false is read
/// as 0 and true as 1 and the list is interpreted as binary number.
/// That is, if, e.g., there are 3 elements in listRef, then the first element
/// in listProbabilities corresponds to [false,false,false] (interpreted as 000),
/// the second to [false,false,true] (or 001) then [false,true,false]
/// (or 010) and so on up to [true,true,true] (or 111).
// Effects for expressing some constructs on RVs
// ---------------------------------------------

// Cond expresses a RV which depends on a some other RVs listed in listRef.
// The list listProbabilities contains the probabilities with which the
// expressed RV is true given that the RVs in listRef are true/false:
// if there are n RVs in listRef, then there are supposed to be 2^n
// elements in listProbabilities, one for each combination of true/false
// for the elements in listRef.
// The order in listProbabilities goes from all RVs in listRef are false to
// all of them are true in ascending order, when false is read
// as 0 and true as 1 and the list is interpreted as binary number.
// That is, if, e.g., there are 3 elements in listRef, then the first element
// in listProbabilities corresponds to [false,false,false] (interpreted as 000),
// the second to [false,false,true] (or 001) then [false,true,false]
// (or 010) and so on up to [true,true,true] (or 111).
effect Cond(listRef: List[Ref], listProbabilities: List[Double]): Ref

/// Conj and Disj express the conjunction and disjunction of
/// RVs x and y, i.e., Conj(x, y) is true iff x and y are both true,
/// where Disj(x, y) is false iff x and y are both false.
// Conj and Disj express the conjunction and disjunction of
// RVs x and y, i.e., Conj(x, y) is true iff x and y are both true,
// where Disj(x, y) is false iff x and y are both false.
effect Conj(x: Ref, y: Ref): Ref
effect Disj(x: Ref, y: Ref): Ref

/// Prior expresses that the prior belief that x is true is prob.
// Prior expresses that the prior belief that x is true is prob.
effect Prior(x: Ref, prob: Double): Unit

/// Flip expresses a RV which is true with probability prob.
/// It can be written as a special case of Cond with no dependencies,
/// so it is no additional effect but just a function using Cond.
// Flip expresses a RV which is true with probability prob.
// It can be written as a special case of Cond with no dependencies,
// so it is no additional effect but just a function using Cond.
def Flip(prob: Double) = do Cond([], [prob])


Expand All @@ -99,23 +100,24 @@ effect Fork(): Bool
effect Fail[A](): A


// some functions for handling the probabilistic constructs
// Some functions for handling the probabilistic constructs
// --------------------------------------------------------

def pow(base: Int, exp: Int): Int = {
if (exp < 0) { 0 }
else if (exp == 0) { 1 }
else { base * pow(base, exp - 1) }
}

/// Observe a RV, failing when the same RV
/// is observed again with a different result.
// Observe a RV, failing when the same RV
// is observed again with a different result.
def observe(ref: Ref, b: Bool) =
do get(ref) match {
case Unobserved() => do put(ref, Observed(b))
case Observed(y) => if (b == y) { () } else { do Fail() }
}

/// Observe each (if the Bool list is long enough) RV in a list.
// Observe each (if the Bool list is long enough) RV in a list.
def observeList(listRef: List[Ref], listBool: List[Bool]): Unit / { Heap, Fail } = {
listRef match {
case Nil() => ()
Expand All @@ -128,15 +130,17 @@ def observeList(listRef: List[Ref], listBool: List[Bool]): Unit / { Heap, Fail }
}
}

/// Convert a non-negative number to a list of booleans with specified length.
/// The conversion proceeds according to the interpretation of positions
/// in a list as described above for the Cond effect. If the number is too large
/// to fit into the list of the specified length, the higher bits are truncated.
/// Example: given that the length is 3, the correspondence is
/// decimal number binary number bool list
/// 0 000 [false,false,false]
/// 1 001 [false,false,true]
/// 5 101 [true,false,true]
/**
* Convert a non-negative number to a list of booleans with specified length.
* The conversion proceeds according to the interpretation of positions
* in a list as described above for the Cond effect. If the number is too large
* to fit into the list of the specified length, the higher bits are truncated.
* Example: given that the length is 3, the correspondence is
* decimal number binary number bool list
* 0 000 [false,false,false]
* 1 001 [false,false,true]
* 5 101 [true,false,true]
*/
def toBoolList(length: Int, number: Int): List[Bool] = try {
def toBoolListReverse(length: Int, number: Int): List[Bool] = {
if (number < 0) { do Fail() }
Expand All @@ -155,12 +159,14 @@ def toBoolList(length: Int, number: Int): List[Bool] = try {
reverse(toBoolListReverse(length, number))
} with Fail[A] { () => println("toBoolList: Unexpected negative number."); [] }

/// Observe the possibilities of true/false combinations for the RVs
/// in listRef corresponding to the above-described interpretation of
/// positions in a list up to position index, and score in each case
/// with the probability at the corresponding position in listProbabilities.
/// Usually this function is called with index = (2^n - 1) where n is the
/// length of listRef, to observe all possibilitites.
/**
* Observe the possibilities of true/false combinations for the RVs
* in listRef corresponding to the above-described interpretation of
* positions in a list up to position index, and score in each case
* with the probability at the corresponding position in listProbabilities.
* Usually this function is called with index = (2^n - 1) where n is the
* length of listRef, to observe all possibilitites.
*/
def observeAndScore(index: Int, listRef: List[Ref], listProbabilities: List[Double]): Unit / { IndexOutOfBounds, Heap, Fail, Fork, Score } = {
if (index < 0)
()
Expand All @@ -185,11 +191,13 @@ def choose3[R] { x: => R } { y: => R } { z: => R } : R / Fork =

def fresh(): Ref / Heap = do empty(Unobserved())

/// Handler for effects for probabilistic constructs:
/// run the program prog forwards collecting all effects for probabilistic
/// constructs, then observe the result RV in prog to be as expected and
/// then go backwards through the program enumerating all possible ways
/// how the result could have come about from the input RV.
/*
* Handler for effects for probabilistic constructs:
* run the program prog forwards collecting all effects for probabilistic
* constructs, then observe the result RV in prog to be as expected and
* then go backwards through the program enumerating all possible ways
* how the result could have come about from the input RV.
*/
def handleLang(expected: Bool) { prog: Ref => Ref / { Cond, Conj, Disj, Prior }}: Var / { IndexOutOfBounds, Score, Fail, Fork } = heap {
val input = fresh();
try { do put(prog(input), Observed(expected)) }
Expand Down Expand Up @@ -257,12 +265,14 @@ def handleLang(expected: Bool) { prog: Ref => Ref / { Cond, Conj, Disj, Prior }}

type Weighted[R] { MkWeighted(weight: Double, value: R) }

/// Handler for scoring, forking and failing:
/// start with current probability 1, run the program prog
/// and handle Score by updating the current probability
/// accordingly and handle Fork by resuming with both
/// possibilities false and true appending the results.
/// This yields a list of weighted ways through the program.
/*
* Handler for scoring, forking and failing:
* start with current probability 1, run the program prog
* and handle Score by updating the current probability
* accordingly and handle Fork by resuming with both
* possibilities false and true appending the results.
* This yields a list of weighted ways through the program.
*/
def handleProbabilities[R] { prog: => R / { Score, Fork, Fail } } = {
val empty: List[Weighted[R]] = Nil();
try {
Expand All @@ -275,8 +285,11 @@ def handleProbabilities[R] { prog: => R / { Score, Fork, Fail } } = {
with Fail[A] { () => empty }
}

// functions for calculating the normalized posterior from a

// Functions for calculating the normalized posterior from a
// list of weighted ways through a program


def collectProbabilities(b: Bool, l: List[Weighted[Var]]): Double = {
l match {
case Nil() => 0.0
Expand Down Expand Up @@ -305,8 +318,9 @@ def posterior(result: List[Weighted[Var]]): List[Weighted[Bool]] / Fail = {
}


// some examples, in particular three versions of
// the famous sprinkler-rain-grass example
// Some examples
// -------------
// In particular three versions of the famous sprinkler-rain-grass example

def test() = {
if (do Fork()) {
Expand Down

0 comments on commit 28ed63d

Please sign in to comment.