Skip to content

Commit

Permalink
Merge branch 'dev' of github.com:probmods/webppl into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
longouyang committed Nov 13, 2015
2 parents 8aef1f2 + 11cd4ec commit 55e342a
Show file tree
Hide file tree
Showing 9 changed files with 90 additions and 5 deletions.
12 changes: 12 additions & 0 deletions docs/packages.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@ You can automatically prepend WebPPL files to your code by added a
}
}

The use of some inference algorithms causes a caching transform to be
applied to each ``wppl`` file. It is possible to skip the application
of this transform on a per-file basis by placing the ``no caching``
directive at the beginning of the file. For example::

'no caching';

// Rest of WebPPL program

This is expected to be useful in only a limited number of cases and
shouldn't be applied routinely.

Macros
------

Expand Down
16 changes: 16 additions & 0 deletions src/erp.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ var _ = require('underscore');
var util = require('./util');
var assert = require('assert');

var LOG_PI = 1.1447298858494002;
var LOG_2PI = 1.8378770664093453;

function ERP(obj) {
Expand Down Expand Up @@ -227,6 +228,20 @@ var multivariateGaussianERP = new ERP({
score: multivariateGaussianScore
});

var cauchyERP = new ERP({
sample: function(params) {
var location = params[0];
var scale = params[1];
var u = util.random();
return location + scale * Math.tan(180 * (u - 0.5));
},
score: function(params, x) {
var location = params[0];
var scale = params[1];
return -LOG_PI - Math.log(scale) - Math.log(1 + Math.pow((x - location) / scale, 2));
}
});

var discreteERP = new ERP({
sample: function(params) {
return multinomialSample(params[0]);
Expand Down Expand Up @@ -695,6 +710,7 @@ module.exports = setErpNames({
gaussianERP: gaussianERP,
multinomialSample: multinomialSample,
multivariateGaussianERP: multivariateGaussianERP,
cauchyERP: cauchyERP,
poissonERP: poissonERP,
randomIntegerERP: randomIntegerERP,
uniformERP: uniformERP,
Expand Down
6 changes: 6 additions & 0 deletions src/header.wppl
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'no caching';

// ERPs

var flip = function(theta) {
Expand Down Expand Up @@ -25,6 +27,10 @@ var multivariateGaussian = function(mu, cov) {
return sample(multivariateGaussianERP, [mu, cov]);
};

var cauchy = function(location, scale) {
return sample(cauchyERP, [location, scale]);
};

var uniform = function(a, b) {
return sample(uniformERP, [a, b]);
};
Expand Down
5 changes: 2 additions & 3 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,8 @@ function parsePackageCode(packages, verbose) {
}

function applyCaching(asts) {
// This assume that asts[0] is the header.
return asts.map(function(ast, i) {
return i > 0 ? caching.transform(ast) : ast;
return asts.map(function(ast) {
return caching.hasNoCachingDirective(ast) ? ast : caching.transform(ast);
});
}

Expand Down
10 changes: 9 additions & 1 deletion src/transforms/caching.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,15 @@ function transformRequired(programAST) {
return flag;
}

function hasNoCachingDirective(ast) {
return ast.body.length > 0 &&
ast.body[0].type === Syntax.ExpressionStatement &&
ast.body[0].expression.type === Syntax.Literal &&
ast.body[0].expression.value === 'no caching';
}

module.exports = {
transform: cachingMain,
transformRequired: transformRequired
transformRequired: transformRequired,
hasNoCachingDirective: hasNoCachingDirective
};
33 changes: 33 additions & 0 deletions tests/test-caching.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
'use strict';

var _ = require('underscore');
var parse = require('esprima').parse;
var caching = require('../src/transforms/caching');

var hasCachingDirectiveTests = {
test1: { code: "'no caching'", expected: true },
test2: { code: '"no caching";\n', expected: true },
test3: { code: '\n"no caching";\n1+1', expected: true },
test4: { code: '1 + 1', expected: false },
test5: { code: "1 + 1;\n'no caching'", expected: false },
test6: { code: '', expected: false }
};

var transformRequiredTests = {
test1: { code: 'IncrementalMH(model, 0);', expected: true },
test2: { code: 'Enumerate(model);', expected: false }
};

function generateTests(cases, testFn) {
return _.mapObject(cases, function(caseDef) {
return function(test) {
test.strictEqual(testFn(parse(caseDef.code)), caseDef.expected);
test.done();
};
});
}

module.exports = {
hasNoCachingDirective: generateTests(hasCachingDirectiveTests, caching.hasNoCachingDirective),
transformRequired: generateTests(transformRequiredTests, caching.transformRequired)
};
6 changes: 6 additions & 0 deletions tests/test-data/stochastic/expected/cauchy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"hist": {
"true": 0.3743,
"false": 0.6257
}
}
4 changes: 4 additions & 0 deletions tests/test-data/stochastic/models/cauchy.wppl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
var model = function() {
var x = cauchy(2, 1.5);
return 1 < x && x <= 3;
};
3 changes: 2 additions & 1 deletion tests/test-inference.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ var tests = [
beta: true,
exponential: true,
binomial: true,
poisson: true
poisson: true,
cauchy: true
}
},
{
Expand Down

0 comments on commit 55e342a

Please sign in to comment.