Intro Chapter 1: The Core Language Chapter 2: Forward Models Chapter 3: Conditioning Chapter 4: Inference Algorithms

Examples

Poll example, taken from Probmods Chapter 7


// observed data
var k = 1 // number of people who support candidate A
var n = 20  // number of people asked

var model = function() {

    // true population proportion who support candidate A
    var p = uniform(0, 1);

    // Observed k people support "A"
    // Assuming each person's response is independent of each other
    observe(Binomial({p : p, n: n}), k);

    // predict what the next n will say
    var posteriorPredictive = binomial(p, n);

    // recreate model structure, without observe
    var prior_p = uniform(0, 1);
    var priorPredictive = binomial(prior_p, n);

    return {
        prior: prior_p, priorPredictive : priorPredictive,
        posterior : p, posteriorPredictive : posteriorPredictive
    };
}

var posterior = Infer(model);

viz.marginals(posterior)

A very simple case of linear regression.


//Observed data
var observedData = [{"x":0,"y":0},{"x":1,"y":5.2},{"x":2,"y":9.4},{"x":3,"y":15},{"x":4,"y":20.5},{"x":5,"y":24.3}]
    
    
var myDraw = Draw(500, 500, true)
    
//Intermediate functions to draw

//Scale a point to the image
var scale = function(p) {
      var newX = 20 + p.x * 75
      var newY = 480 - p.y * 15
      return{"x":newX,"y":newY}
}
    
// Draw a list of data points
var drawData = function(img,obs) {
    var scaleData = map(scale,obs)
    map(function(p) {
      img.circle(p.x, p.y, 3, 'black', 'white')
    }, scaleData)
}
    
// Draw a linear function 
var drawLinFun = function(img,f) { 
      var a = scale({"x":0, "y":f(0)})
      var b = scale({"x":5.5, "y":f(5.5)})
      img.line(a.x,a.y,b.x,b.y,1,0.01,"red")
}
    
// Make a function from a coefficient
var makeFun = function(a) {
    return ( function(x) {
        return(a * x)
      })
}
    
//Compute a Random Line, and observe data
var randomLine = function() {
    var a = uniform(0,10)
    var f = makeFun(a)
      
    var obsFn = function(datum){
        observe(Gaussian({mu: f(datum.x), sigma: 2}), datum.y)
    }
    mapData({data: observedData}, obsFn)
      
    return a      
}

// Infer the distribution on coefficients
var post = Infer(randomLine)
    
// Draw samples from the inferred distribution, to have some visual intuition about the distribution
var randomDraw = function() {
    var a = sample(post)
    drawLinFun(myDraw,makeFun(a))
}

//Visualize the distribution on coefficients
viz(post)
    
drawData(myDraw,observedData)
repeat(1000,randomDraw)
    
print("The value should be around 5")

The Core Language : A functional Javascript

Basic Arithmetics

//Usual operators. With only float division
(((1 + 2) - 1) * 3) / 4

// Modulo 
5 % 2 

// You can concatenate strings with +, and you can use both "" and ''
'Hello ' + "World"

//Automatic Cast
"Today is the " + 9

true + true 
    

Equality and Booleans

// Abstract Equality, attempts to type cast    
2 == "2"

// Strict Equality    
2 === "2"

// Some Boolean Operators    
!(true && (true || false))

Conditionals

if (5 > 1) {1} else {2}

// You can use the ternary operator to gain space and time  
(5 > 1) ? 1 : 2

Variable Declaration

 
// Always declare using var, no other way to do a variable declaration in webPPL 
var a = 5 
var b = 6, c = 7
print(b)

Objects and Functions

// Objects are standard, and you can call them by using point or bracket
var a = {"name" : "ficus", "length" : 50}
print(a.name)
print(a["name"]) 
print(a.length)
print(a["length"])

// Be careful with Object Equality, it compares references and not actual content. 
// Intuitively, you should never use equality between objects. 
var a = {"name" : "ficus", "length" : 50}
var b = {"name" : "ficus", "length" : 50} 
print("Tests:")
print(a == b)
print(a === b)
print(a == a)

// Arrays 
var a = [1,2,3,4,9,8]
print(a[0])
print(a[4])	

// You can only define function using this syntax
var f = function(a,b,x) {
	return (a*x + b)
}
f(3,5,4)

WebPPL is not an imperative language !

Everything is immutable, try the examples below:

var a = 5 
a = 6 
var a = [1,2,3,4]
a[0] = 0
var a = {"name" : "ficus", "length" : 50}
a.length = 40 
// But you can still do this:
var a = [1,2,3,4]
a.pop() 
a.push(1)
print(a)

Some Other Available Methods

var str = "Hello"
print("We test some methods:")

// You can access elements
print("Second element: " + str[1])

//Get the length
print("Length: " + str.length)

// Slice from beginning (included) to end (excluded). Also useful to create a copy of an array for example
print("Slicing: " + str.slice(1,3))

//Replace one occurence, you can also use regular expressions and replaceAll
print("Replace One Occurence: " + str.replace("l","r"))

// Some other useful functions includes operations on the alhabet
print("Upper Case: " + str.toUpperCase())

// You can use the standard string concatenation as a method instead of using + 
print("Concat: " + str.concat(" World"))

Functional Programming

Simple Recursion

var factorial = function(n) {
  if (n==1) {
    return 1
  }
  else {
    return n * factorial(n-1)
  }
}

factorial(5)

Iterative Recursion

var factorial = function(n) {
  var factorial_iter = function(i,r) {
    if (i > n) {
      return r  	
    }
    else {
      factorial_iter(i+1,i * r)	
    }  	
  }
  factorial_iter(1,1)	
}

factorial(5)    

Other tail recursive example

var factorial = function(n) {
  var factorialTR= function(n,r) {
    (n == 0) ? r : factorialTR(n-1,n * r) 
  }
  factorialTR(n,1)
}

factorial(5)

Higher-Order Functions

var myMap = function(l,f) {
  if (l.length == 0) {
    return []
  }
  else {
    var hd = l.pop()
    var tl = myMap(l,f)
    tl.push(f(hd))
    return tl
  }
}

myMap(_.range(1,11),function(x) {x * x})

print("Some Examples of Uses of Higher-Order Operators")

// Compute the square from 0 to 10
print(map(function(x) {x * x},_.range(0,11)))

// Compute the logs from 0 to 10 using mapN
print(mapN(function(x) {Math.log(x)},11))

//Compute the sums of the two list
print(map2(function(x,y) {x + y},[10,15,5,3,6],[4,7,9,0,13]))

//Compute the factorial by taking the product of the list of numbers from 1 to 5
print(reduce(function(x,r) {x * r},1,_.range(1,6)))

//Filter a list to keep only the even numbers
print(filter(function(x) {return (x % 2 == 0)},_.range(0,11)))