All examples
Generative models

Generate conditional scientific series

Train a small native conditional model and inspect bounded scientific outputs.

generative_scientific.aner
// Uses Philox addressed sampling with explicit seed and draw identities.
// Native scientific generation workflow. Fresh checkpoint paths are required.
// This short run demonstrates mechanics; quantitative research gates live in
// tests/gen_scientific_validation.cpp and docs/benchmarks/scientific_validation_20261014.json.
// Values below are deliberately nondimensional and order one.
import aner.gen
import aner.nn
import aner.tensor
import aner.math
import aner.parallel
import aner.dev
import aner.random

nn.configure("cpu", "Float64", "preserve")

// Independent trajectories from a conditional AR(1) simulator.
fn trajectories(records: Int64, length: Int64, seed: Int64, role: String) -> ScientificData {
    let values = DynamicArray<Float64>(capacity: records * length)
    let conditions = DynamicArray<Float64>(capacity: records)
    var record = 0
    while record < records {
        let condition = (Float64(record % 5) - 2.0) * 0.5
        conditions.append(condition)
        let equilibrium = 0.5 * condition + 0.2
        var state = equilibrium
        var time = 0
        while time < length {
            state = 0.65 * state + 0.35 * equilibrium + 0.08 * random.normal(mean: 0.0, stddev: 1.0, seed: seed, draw: record * length + time)
            values.append(state)
            time = time + 1
        }
        record = record + 1
    }
    let observations = tensor.reshape(values.to_tensor(rows: records, cols: length), List(records, length, 1))
    return gen.series_data(observations, conditions.to_tensor(rows: records, cols: 1), role)
}
let training = trajectories(20, 48, 901, "training")
let heldout = trajectories(10, 48, 902, "test")
let model = gen.series_model(channels: 1, history: 1, condition_size: 1,
    width: 16, innovation_sigma: 0.08, seed: 41)
let partial = model.train(training, steps: 250, batch: 32, rate: 0.001, seed: 17)
partial.save("series-partial.anersci")
let trained = gen.load_scientific("series-partial.anersci").resume(training, steps: 250)
print(trained.summary())
print(trained.loss(heldout))
// A condition between the five training levels.
let condition = [[0.25]]
let prefix = tensor.reshape([[0.325]], List(1, 1, 1))
let generated = trained.sample_series(condition, prefix, new_steps: 192, seed: 7)
let retained = tensor.slice(generated, axis: 1, start: 64, length: 128)
print(gen.series_statistics(retained, lag: 1))
dev.capture("Generated trajectory", retained)

// Simulated zero-Dirichlet fields, with random amplitude in a second mode.
let field_values = DynamicArray<Float64>(capacity: 80 * 25)
let field_conditions = DynamicArray<Float64>(capacity: 80)
var record = 0
while record < 80 {
    let amplitude = (Float64(record % 5) - 2.0) * 0.35
    field_conditions.append(amplitude)
    let fluctuation = 0.05 * random.normal(mean: 0.0, stddev: 1.0, seed: 903, draw: record)
    var row = 0
    while row < 5 {
        var col = 0
        while col < 5 {
            var value = 0.0
            if row > 0 && row < 4 && col > 0 && col < 4 {
                let x = Float64(col) / 4.0
                let y = Float64(row) / 4.0
                value = amplitude * math.sin(3.141592653589793 * x) * math.sin(3.141592653589793 * y)
                    + fluctuation * math.sin(2.0 * 3.141592653589793 * x) * math.sin(3.141592653589793 * y)
            }
            field_values.append(value)
            col = col + 1
        }
        row = row + 1
    }
    record = record + 1
}
let fields = tensor.reshape(field_values.to_tensor(rows: 80, cols: 25), List(80, 5, 5))
let field_training = gen.field_data(fields, field_conditions.to_tensor(rows: 80, cols: 1), role: "training")
let denoiser = gen.diffusion_model(rows: 5, cols: 5, condition_size: 1, width: 32,
    diffusion_steps: 128, beta_start: 0.00001, beta_end: 0.1, seed: 19)
print(gen.scientific_memory(denoiser, batch: 32, training: true))
let fitted = denoiser.train(field_training, steps: 500, batch: 32, rate: 0.001, seed: 37)
let sampled = fitted.sample_fields([[0.175]], seed: 11)
print(gen.field_statistics(sampled, dx: 0.25, dy: 0.25))
dev.capture("Generated field", sampled)
// Boundary_max is exactly zero. PDE and distribution quality need the held-out
// ensemble experiment and its baselines; this short run makes no fidelity claim.

Make it your experiment.

With Aner 0.0.3 or newer installed, save this program as examples/generative_scientific.aner inside a folder for your experiment. Open a terminal in that folder, then check and run the program.

Terminal
aner check examples/generative_scientific.aner
aner run examples/generative_scientific.aner

The aner command must be on your PATH. Follow the installation guide if your terminal cannot find it.

Use Aner 0.0.3 or newer with aner.token, aner.gen and sequence primitives. CPU supports Float64 and Float32; native Metal/MPS sequence kernels require Float32 and a compatible build. CUDA sequence kernels support Float64 and Float32 with a CUDA enabled build and compatible NVIDIA hardware. Run checkpoint examples from a fresh working directory because existing artifacts are never replaced. These local synthetic examples require no model provider, credentials or network connection. Use matching editor integration for these APIs.

Bundled datasets retain their own source attribution and license notices. Example outcomes are not comparative benchmarks or evidence of clinical validity.

Dataset sources & attribution
Install Aner