Julia bindings for using
spplacross PythonCall.jl.
Allows the usage of direct string macros:
spn = sppl"""
Nationality ~= choice({'India': 0.5, 'USA': 0.5})
if (Nationality == 'India'):
Perfect ~= bernoulli(p=0.10)
if (Perfect == 1):
GPA ~= atomic(loc=10)
else:
GPA ~= uniform(loc=0, scale=10)
else:
Perfect ~= bernoulli(p=0.15)
if (Perfect == 1):
GPA ~= atomic(loc=4)
else:
GPA ~= uniform(loc=0, scale=4)
"""as well as the usage of a native macro with native structures:
spn = @sppl begin
nationality ~ SPPL.Choice([:India => 0.5, :USA => 0.5])
perfect ~ SPPL.Bernoulli(0.1)
gpa ~ SPPL.Atomic(4)
end
println(spn)(nationality = <py Identity('nationality')>,
perfect = <py Identity('perfect')>,
gpa = <py Identity('gpa')>,
model = <py sppl.spe.ProductSPE object at 0x1e6ce3d60>)
Of course, you can use native abstractions:
@sppl function foo(x::Float64)
nationality ~ SPPL.Choice([:India => x, :USA => 1 - x])
perfect ~ SPPL.Bernoulli(0.1)
gpa ~ SPPL.Atomic(4)
endwhich expands to produce a generator:
:(function foo(x::Float64)
gpa = Main.IndianGPA.SPPL.Id(:gpa)
nationality = Main.IndianGPA.SPPL.Id(:nationality)
perfect = Main.IndianGPA.SPPL.Id(:perfect)
command = Main.IndianGPA.SPPL.Sequence(
Main.IndianGPA.SPPL.Sample(nationality,
SPPL.Choice([:India => x, :USA => 1 - x])),
Main.IndianGPA.SPPL.Sample(perfect, SPPL.Bernoulli(0.1)),
Main.IndianGPA.SPPL.Sample(gpa, SPPL.Atomic(4))
)
model = command.interpret()
namespace = (nationality = Main.IndianGPA.SPPL.Id(:nationality),
perfect = Main.IndianGPA.SPPL.Id(:perfect),
gpa = Main.IndianGPA.SPPL.Id(:gpa),
model = model)
namespace
end)
There are a few special pieces of syntax which the user should keep in mind. Some of these points make the macro parsing unambiguous, others are more for convenience.
Samplestatements are expressed using~syntax.Transformexpressions (a polynomial for example, expressed in Python asX[1] ~ 8 * W[2]**2 + 5) are specified a "special" operator.>.- The Julia ternary expression
foo ? b1 : b2is allowed - this desugars intoIfElse. - Array declarations are performed using the library-provided
arrayfunction interface. Array declarations must be made (!) before indexing/use - or else macro parsing will return an error. ==desugars to<<on the Python side (this creates anevent- a condition).- The
forexpression is allowed - but you are restricted to only supplyUnitRange{Int64}instances for the parsing/semantics to work properly.
Examples of each of these points can be found in the examples directory. These examples come directly from the sppl Jupyter notebooks. If you'd like to help port these over, just setup a PR!
