def checkAAAParticleWeights(sp, seed): if inParallel() and "make_suff_stat_bernoulli" in sp and backend_name( ) == "puma": raise SkipTest( "The Lite SPs in Puma interface is not thread-safe, and make_suff_stat_bernoulli comes from Lite." ) if "dir_cat" in sp and backend_name() == 'puma': raise SkipTest( "Dirichlet categorical in Puma does not accept objects parameter. Issue #340" ) ripl = get_ripl(seed=seed) ripl.assume("a", "1.0") # bogus labelled directives, so the infer step can forget them ripl.predict("nil", label="f") ripl.predict("nil", label="pid") predictions = collectSamples(ripl, "pid", infer="""\ (do (resample 10) (forget 'pid) (forget 'f) (assume f %s f) (predict (f) pid) (observe (f) true obs1) (observe (f) true obs2) (resample 1) (forget 'obs2) (forget 'obs1))""" % sp) ans = [(False, .25), (True, .75)] return reportKnownDiscrete(ans, predictions)
def checkSliceStudentT2(slice_method, seed): # Simple program involving simulating from a student_t if (backend_name() != "lite") and (slice_method == 'slice_doubling'): raise SkipTest( "Slice sampling with doubling only implemented in Lite.") ripl = get_ripl(seed=seed) ripl.assume("a", "(student_t 1.0)") ripl.observe("(normal a 1.0)", 3.0) ripl.predict("(normal a 1.0)", label="pid") predictions = myCollectSamples(ripl, slice_method) # Posterior of a is proprtional to def postprop(a): return stats.t(1).pdf(a) * stats.norm(loc=3).pdf(a) import scipy.integrate as integrate (normalize, _) = integrate.quad(postprop, -10, 10) def posterior(a): return postprop(a) / normalize (meana, _) = integrate.quad(lambda x: x * posterior(x), -10, 10) (meanasq, _) = integrate.quad(lambda x: x * x * posterior(x), -10, 10) vara = meanasq - meana * meana # TODO Test agreement with the whole shape of the distribution, not # just the mean return reportKnownMean(meana, predictions, variance=vara + 1.0)
def testForeignInterfaceSimulate(): for (name, sp) in relevantSPs(): if name in [ "scope_include", # Because scope_include is # misannotated as to the true # permissible types of scopes and # blocks "tag", "get_current_environment", # Because MockArgs gives a bogus environment "extend_environment", # Because MockArgs gives a bogus environment ]: continue if backend_name() != "lite" and name in [ ## Expected failures "dict", # Because keys and values must be the same length "matrix", # Because rows must be the same length "get_empty_environment", # Environments can't be rendered to stack dicts ]: continue if name.startswith('gp_cov_') or name.startswith('gp_mean_'): # XXX Can't compare equivalent functions for equality without # false negatives. continue if not sp.outputPSP.isRandom(): yield checkForeignInterfaceAgreesWithDeterministicSimulate, name, sp
def posterior_inference_action(): # Work around the fact that Puma doesn't have rejection sampling # by asking for a bunch of MH. if backend_name() == 'lite': return "(rejection default all 1)" else: return "(resimulation_mh default one %d)" % ( default_num_transitions_per_sample(), )
def checkSliceBasic1(slice_method, seed): # Basic sanity test for slice if (backend_name() != "lite") and (slice_method == 'slice_doubling'): raise SkipTest( "Slice sampling with doubling only implemented in Lite.") ripl = get_ripl(seed=seed) ripl.assume("a", "(normal 10.0 1.0)", label="pid") predictions = myCollectSamples(ripl, slice_method) return reportKnownGaussian(10, 1, predictions)
def testConstrainWithAPredict1(): if backend_name() != "lite": raise SkipTest("assert(false) crashes NoseTests") for p in [ "(resimulation_mh default one 50)", "(rejection default all 50)", "(func_pgibbs default ordered 3 50 false)", "(pgibbs default ordered 3 50 false)", "(meanfield default one 50)", ]: yield checkConstrainWithAPredict1, p
def testRandomScopeIdSmoke(): # Test that scope membership maintenance works even if the scope id # changes under inference r = get_ripl() if backend_name() == "puma": # Puma doesn't have the invariant check that Lite does r.define("checkInvariants", "(lambda () pass)") r.execute_program(""" (predict (tag (flip) "frob" (flip))) (repeat 50 (do (mh default one 1) (checkInvariants)))""")
def testInvWishartPrior4(seed): # Confirm that as dof increases, the elements of a Wishart obey the # central limit theorem. if inParallel() and backend_name() == "puma": raise SkipTest("The Lite SPs in Puma interface is not thread-safe, and wishart comes from Lite.") ripl = get_ripl(seed=seed) ripl.assume("s", "(scale_matrix 10000 (id_matrix 3))") ripl.assume("m", "(inv_wishart s 10000)") ripl.predict("(lookup m (pair 0 1))", label="prediction") predictions = collectSamples(ripl, "prediction") return reportKnownGaussian(0, 0.01, predictions)
def checkSliceNormalWithObserve1(slice_method, seed): # Checks the posterior distribution on a Gaussian given an unlikely # observation if (backend_name() != "lite") and (slice_method == 'slice_doubling'): raise SkipTest( "Slice sampling with doubling only implemented in Lite.") ripl = get_ripl(seed=seed) ripl.assume("a", "(normal 10.0 1.0)", label="pid") ripl.observe("(normal a 1.0)", 14.0) # Posterior for a is normal with mean 12, precision 2 # ripl.predict("(normal a 1.0)") predictions = myCollectSamples(ripl, slice_method) return reportKnownGaussian(12, math.sqrt(0.5), predictions)
def checkSliceL(slice_method, seed): # Checks slice sampling on an L-shaped distribution. if (backend_name() != "lite") and (slice_method == 'slice_doubling'): raise SkipTest( "Slice sampling with doubling only implemented in Lite.") ripl = get_ripl(seed=seed) ripl.assume("a", "(uniform_continuous 0.0 1.0)") ripl.assume("b", "(< a 0.2)") ripl.observe("(flip (biplex b 0.8 0.2))", True) # Posterior for b is 0.5 true, 0.5 false ripl.predict("b", label="pid") predictions = myCollectSamples(ripl, slice_method) return reportKnownDiscrete([[True, 0.5], [False, 0.5]], predictions)
def testInvWishartPrior2(seed): # Confirm that the diagonal elements of an inverse Wishart are an # inverse Gamma distribution. if inParallel() and backend_name() == "puma": raise SkipTest("The Lite SPs in Puma interface is not thread-safe, and wishart comes from Lite.") ripl = get_ripl(seed=seed) ripl.assume("s", "(matrix (array (array 2 -1) (array -1 3)))") ripl.assume("m", "(inv_wishart s 4.2)") ripl.predict("(lookup m (pair 1 1))", label="prediction") predictions = collectSamples(ripl, "prediction") cdf = scipy.stats.invgamma(a=1.6, scale=1.5).cdf return reportKnownContinuous(cdf, predictions)
def testWishartPrior1(seed): # Confirm that the diagonal elements of a Wishart are a chi-squared # distribution. if inParallel() and backend_name() == "puma": raise SkipTest("The Lite SPs in Puma interface is not thread-safe, and wishart comes from Lite.") ripl = get_ripl(seed=seed) ripl.assume("s", "(matrix (array (array 2 -1) (array -1 3)))") ripl.assume("m", "(wishart s 5)") ripl.predict("(lookup m (pair 0 0))", label="prediction") predictions = collectSamples(ripl, "prediction") cdf = scipy.stats.chi2(df=5, scale=2).cdf return reportKnownContinuous(cdf, predictions)
def testCMVN2D_mu1(seed): if backend_name() != "lite": raise SkipTest("CMVN in lite only") ripl = get_ripl(seed=seed) ripl.assume("m0", "(array 5.0 5.0)") ripl.assume("k0", "7.0") ripl.assume("v0", "11.0") ripl.assume("S0", "(matrix (array (array 13.0 0.0) (array 0.0 13.0)))") ripl.assume("f", "(make_niw_normal m0 k0 v0 S0)") ripl.predict("(f)", label="pid") predictions = collectSamples(ripl, "pid") mu1 = [p[0] for p in predictions] return reportKnownMean(5, mu1)
def checkRiplAgreesWithDeterministicSimulate(name, sp): if backend_name() != "lite" and name in [ ## Incompatibilities with Puma "apply", # Not implemented, and can't seem to import it as a foreign from Python "arange", # Not the same return type (elements boxed in Puma?) "vector_dot", # Numerical inconsistency between Eigen and Numpy "matrix_times_vector", # Numerical inconsistency between Eigen and Numpy "vector_times_matrix", # Numerical inconsistency between Eigen and Numpy "int_div", # Discrpancy on negative divisor between C++ and Python "int_mod", # Discrpancy on negative modulus between C++ and Python "vector_add", # Size-mismatched vectors crash Puma "matrix_add", # Size-mismatched matrices crash Puma ]: raise SkipTest("%s in Puma not implemented compatibly with Lite" % name) checkTypedProperty(propRiplAgreesWithDeterministicSimulate, fully_uncurried_sp_type(sp.venture_type()), name, sp)
def testLogCategoricalAbsorb(seed): # A simple test that checks the interface of log categorical and its # simulate and log density methods ripl = get_ripl(seed=seed) if backend_name() == "puma": # XXX Puma's log_categorical demands a simplex argument, as that's # the best representation the backend has for an array of numbers. # Lite's simplex, however, checks boundary conditions, so can't be # used here. ripl.assume("x", "(simplex (log .1) (log .9))") ripl.assume("y", "(simplex (log .55) (log .45))") else: ripl.assume("x", "(array (log .1) (log .9))") ripl.assume("y", "(array (log .55) (log .45))") ripl.assume("b", "(flip)", label="b") ripl.observe("(log_categorical (if b x y) (array 10 100))", "100") predictions = collectSamples(ripl, "b") ans = [(False, 0.333), (True, 0.667)] return reportKnownDiscrete(ans, predictions)
def checkMakeBetaBernoulli1(maker, hyper, seed): if rejectionSampling() and hyper == "(normal 10.0 1.0)": raise SkipTest( "Too slow. Tightening the rejection bound is Issue #468.") if inParallel() and "make_suff_stat_bernoulli" in maker and backend_name( ) == "puma": raise SkipTest( "The Lite SPs in Puma interface is not thread-safe, and make_suff_stat_bernoulli comes from Lite." ) ripl = get_ripl(seed=seed) ripl.assume("a", hyper) ripl.assume("f", "(%s a a)" % maker) ripl.predict("(f)", label="pid") for _ in range(20): ripl.observe("(f)", "true") predictions = collectSamples(ripl, "pid") ans = [(False, .25), (True, .75)] return reportKnownDiscrete(ans, predictions)
def testRandomScopeIdExclusionSmoke(): # Test that scope membership maintenance works even if the scope id # excluded by tag_exclude changes under inference r = get_ripl() if backend_name() == "puma": # Puma doesn't have the invariant check that Lite does r.define("checkInvariants", "(lambda () pass)") r.execute_program(""" (assume which_exclude (flip)) ; Outside the alice and bob scopes (predict (tag "alice" 0 (tag "bob" 0 (tag_exclude (if which_exclude "alice" "bob") (flip)))))""") for _ in range(50): alice = count_nodes_2(r, "alice") bob = count_nodes_2(r, "bob") eq_(1, alice + bob) r.infer(""" (do (mh default one 1) (checkInvariants))""")
def checkMakeBetaBernoulli4(maker, seed): if inParallel() and "make_suff_stat_bernoulli" in maker and backend_name( ) == "puma": raise SkipTest( "The Lite SPs in Puma interface is not thread-safe, and make_suff_stat_bernoulli comes from Lite." ) ripl = get_ripl(seed=seed) ripl.assume("a", "(normal 10.0 1.0)") ripl.assume("f", """ (if (lt a 10.0) ({0} a a) ({0} a a))""".format(maker)) ripl.predict("(f)", label="pid") for _ in range(20): ripl.observe("(f)", "true") predictions = collectSamples(ripl, "pid") ans = [(False, .25), (True, .75)] return reportKnownDiscrete(ans, predictions)
def testRiplSimulate(): for (name, sp) in relevantSPs(): if name in [ # Because tag is misannotated as to the true # permissible types of scopes and blocks "tag", "tag_exclude", "get_current_environment", # Because MockArgs gives a bogus environment "extend_environment", # Because MockArgs gives a bogus environment ]: continue if backend_name() != "lite" and name in [ ## Expected failures "dict", # Because keys and values must be the same length "matrix", # Because rows must be the same length "lookup", # Because the key must be an integer for sequence lookups "get_empty_environment", # Environments can't be rendered to stack dicts ]: continue if name.startswith('gp_cov_') or name.startswith('gp_mean_'): # XXX Printable representation of equivalent covariance kernels # or mean functions don't necessarily match. continue if not sp.outputPSP.isRandom(): yield checkRiplAgreesWithDeterministicSimulate, name, sp
def testCMVNSmoke(seed): if backend_name() != "lite": raise SkipTest("CMVN in lite only") get_ripl(seed=seed).predict( "((make_niw_normal (array 1.0 1.0) 2 2 (matrix (array (array 1.0 0.0) (array 0.0 1.0)))))" )