In-memory reference compiler
CompiledModelScript model =
ModelScript.compile(source, data);Portable and usually sufficient.
Data to posterior · language 0.8
Fit the same normal-mean posterior from a CSV file through the Java builder and a Stan-inspired .jdm script, then choose among in-memory, cached, and ahead-of-time compilation.
Step 1
The checked-in examples/data/normal-observations.csv begins with a y header followed by one numeric observation per row. The executable companion provides a small reader:
Path csv = Paths.get("examples/data/normal-observations.csv");
double[] y = McmcDataIngestionExamples.readNumericColumn(csv, "y");
That reader is dependency-free and rejects missing or nonnumeric cells. It is not a general RFC-style CSV parser: use a dedicated CSV library for quoted delimiters and then pass the resulting primitive arrays to JDistlib.
Step 2 · script frontend
.jdm file with dataPath modelFile = Paths.get(
"examples/models/41-normal-csv-mean.jdm");
String source = new String(
Files.readAllBytes(modelFile), StandardCharsets.UTF_8);
Map<String, double[]> data =
new LinkedHashMap<String, double[]>();
data.put("N", new double[] {y.length});
data.put("y", y);
CompiledModelScript compiled =
ModelScript.compile(source, data);
BayesianModel scriptedModel = compiled.model();
ModelScript.compile parses the source, validates names, dimensions, integer values and bounds, binds a defensive copy of the supplied data, lowers the program to a BayesianModel, and creates the generated-quantities evaluator. Scalars use one-element arrays because the data boundary has one uniform Java type.
Step 3 · Java frontend
ModelBuilderBayesianModel javaModel = new ModelBuilder()
.data("y", y)
.parameter("mu", Constraints.real(), 0.0)
.factor("mu prior", new String[] {"mu"},
ModelFactors.normalPrior("mu", 0.0, 10.0))
.factor("observations", new String[] {"y", "mu"},
ModelFactors.normalObservations("y", "mu", 1.0))
.build();
The Java and script routes produce the same model abstraction. Use Java for custom likelihood code or APIs outside the script subset; use scripts when a compact textual model is easier to review or deploy.
Step 4
GradientCheckResult check = Gradients.check(
scriptedModel, scriptedModel.initialState(), 1e-5, 1e-5);
if (!check.passed()) throw new IllegalStateException(check.message());
SamplingOptions options = SamplingOptions.builder()
.warmupIterations(500)
.sampleIterations(1000)
.targetAcceptance(0.85)
.build();
double[][] initial = {{-1}, {-0.25}, {0.25}, {1}};
ChainResult[] chains = Chains.parallel(
new NoUTurnSampler(), scriptedModel, initial,
options, 2026082701L, 4);
McmcDiagnosticReport report = McmcDiagnostics.analyze(
new String[] {"mu"}, chains);
Diagnostics, graphs, checkpoints, and exports do not care which frontend created the model. Generate a posterior prediction with compiled.generate(draw, random).
Step 5
CompiledModelScript model =
ModelScript.compile(source, data);Portable and usually sufficient.
try (LoadedGeneratedModel loaded =
ModelCompilationCache.compile(source,
Paths.get("build/model-cache"))) {
CompiledModelScript model =
loaded.factory().compile(data);
}Generates, invokes javac, hashes, caches, and loads an isolated wrapper. A JDK is required.
gradlew.bat jar
java -cp build\libs\* ^
jdistlib.inference.lang.ModelScriptCli ^
examples\models\41-normal-csv-mean.jdm ^
com.example.NormalCsvMean ^
build\generated\com\example\NormalCsvMean.java
javac -cp build\libs\* ^
-d build\generated-classes ^
build\generated\com\example\NormalCsvMean.java
ModelScriptCli validates the script and writes a Java class implementing GeneratedModelFactory. It does not invoke javac, bind data, or sample. Instantiate com.example.NormalCsvMean and call compile(data) after placing the library and generated classes on the runtime classpath.
Language additions
model {
real total = 0;
for (n in 1:N) {
if (y[n] >= 0)
total += normal_lpdf(y[n] | mu, 1);
else
total += normal_lpdf(y[n] | mu, 2);
}
int pass = 0;
while (pass < 2) {
total += 0;
pass += 1;
}
target += total;
}
The model block supports initialized scalar locals, scoped blocks, assignments, comparisons and boolean expressions, if/else, integer-range for, and guarded while. The language also provides a broad scalar math catalog and more than thirty scalar probability families. Consult the supported-surface reference before porting a model.
Complete examples
See McmcDataIngestionExamples.java, ModelScriptCompilationExamples.java, the sample CSV, all fifty-one JDistlib scripts, and forty-one ordinary Stan fixtures. Continue with the v0.8.3 containers tutorial.