Quick Start Guide

Learn how to use SimASM for discrete event simulation in just a few minutes.

1. Installation

Install SimASM using pip:

pip install simasm

2. Your First Model

SimASM models consist of domains (entity types), variables, rules, and an initialization block. Here's a simple counter example:

// counter.simasm - A simple counter model
domain Object

var counter: Nat
var max_value: Nat

main rule step =
    if counter < max_value then
        counter := counter + 1
        print counter
    endif
endrule

init:
    counter := 0
    max_value := 10
endinit

3. Running in Python

Use the SimASM Python API to run your model:

import simasm

# Define the model source
model_source = """
domain Object

var counter: Nat
var max_value: Nat

main rule step =
    if counter < max_value then
        counter := counter + 1
    endif
endrule

init:
    counter := 0
    max_value := 10
endinit
"""

# Register and run the model
simasm.register_model("counter", model_source)
result = simasm.run_model(model_source, steps=15)
print(result)

4. Using Jupyter Notebooks

SimASM provides cell magic for Jupyter notebooks:

# First cell - import SimASM (registers magic automatically)
import simasm
# Second cell - define a model using cell magic
%%simasm model --name mm1_queue

import Random as rnd
import Stdlib as lib

domain Object
domain Customer <: Object

var queue: List<Customer>
var server_busy: Bool
var total_served: Nat

var interarrival: rnd.exponential(1.0) as "arrivals"
var service_time: rnd.exponential(0.8) as "service"

main rule step =
    // Arrivals handled by event scheduler
    if not server_busy and lib.length(queue) > 0 then
        server_busy := true
    endif
endrule

init:
    queue := []
    server_busy := false
    total_served := 0
endinit
# Third cell - run an experiment
%%simasm experiment

experiment QueueTest:
    model := "mm1_queue"

    replication:
        count: 5
        warm_up_time: 100
        run_length: 1000
        seed_strategy: "incremental"
        base_seed: 42
    endreplication

    statistics:
        stat avg_queue:
            expression: "lib.length(queue)"
            aggregation: time_average
        endstat
    endstatistics

    output:
        format: "json"
        file_path: "results.json"
    endoutput
endexperiment

5. Queue Model Example

Here's a more complete M/M/1 queue model demonstrating key SimASM features:

// mm1_queue.simasm - M/M/1 Queueing Model
import Random as rnd
import Stdlib as lib

// Define entity types
domain Object
domain Customer <: Object

// State variables
var queue: List<Customer>
var server_busy: Bool
var customers_served: Nat
var sim_time: Real

// Random streams
var interarrival: rnd.exponential(1.0) as "arrivals"
var service: rnd.exponential(0.8) as "service"

// Derived function for queue length
derived function queue_length(): Nat =
    lib.length(queue)

// Rule for customer arrival
rule arrive(c: Customer) =
    queue := lib.add(queue, c)
endrule

// Rule for starting service
rule start_service() =
    if not server_busy and queue_length() > 0 then
        server_busy := true
        queue := lib.remove(queue, lib.first(queue))
    endif
endrule

// Rule for completing service
rule complete_service() =
    server_busy := false
    customers_served := customers_served + 1
endrule

// Main simulation step
main rule step =
    // Process events in priority order
    start_service()
endrule

// Initialize the model
init:
    queue := []
    server_busy := false
    customers_served := 0
    sim_time := 0.0
endinit

6. Model Verification

SimASM can verify behavioral equivalence between two models using W-stutter equivalence:

// verification_spec.simasm
verification QueueEquivalence:
    models:
        import ModelA from "queue_eg.simasm"
        import ModelB from "queue_acd.simasm"
    endmodels

    seed: 42

    labels:
        label queue_empty for ModelA: "queue_length() == 0"
        label queue_empty for ModelB: "marking == 0"
        label server_busy for ModelA: "server_busy == true"
        label server_busy for ModelB: "server_state == BUSY"
    endlabels

    observables:
        observable queue_state:
            ModelA -> queue_empty
            ModelB -> queue_empty
        endobservable
        observable server_state:
            ModelA -> server_busy
            ModelB -> server_busy
        endobservable
    endobservables

    check:
        type: stutter_equivalence
        run_length: 1000
        timeout: 60
    endcheck

    output:
        format: "json"
        file_path: "verification_result.json"
        include_counterexample: true
    endoutput
endverification

7. Key Concepts

Domains define entity types. Use <: for inheritance: domain Customer <: Object
Variables hold mutable state: var name: Type
Rules define state transitions. The main rule is executed each simulation step.
Random Streams use rnd.distribution(params) as "name" for reproducible randomness.
Library Functions are accessed via lib.* (e.g., lib.length(), lib.add()).

Next Steps