Car
A single car, a driver, and red traffic light in the middle of the night.

Red Light, Matthias Ripp (CC BY 2.0)
Let’s start with a very simple model. The example demonstrates the main mode of operation, the core API and the component process model implemented in kalasim. We want to build a simulation where a single car is driving around for a some time before stopping in front of a red traffic light.
////Cars.kts
import org.kalasim.*
import kotlin.time.Duration.Companion.hours
import kotlin.time.Duration.Companion.minutes
class Driver : Resource()
class TrafficLight : State<String>("red")
class Car : Component() {
val trafficLight = get<TrafficLight>()
val driver = get<Driver>()
override fun process() = sequence {
request(driver) {
hold(30.minutes, description = "driving")
wait(trafficLight, "green")
}
}
}
createSimulation {
enableComponentLogger()
dependency { TrafficLight() }
dependency { Driver() }
Car()
}.run(5.hours)
For each (active) component we (can) define a type such as:
class Car : Component()
The class inherits from org.kalasim.Component.
Our car depends on a state TrafficLight and resource Driver for operation. To implement that, we first declare these dependencies with dependency{} in the main body of the simulation, and secondly inject them into our car with get<T>. Note, we could also directly inject states and resources with dependency {State("red")} without sub-classing.
Although it is possible to define other processes within a class,
the standard way is to define a generator function called process in the class.
A generator is a function that returns Sequence<Component>. Within these process definitions we use suspendable interaction function calls as a signal to give control to the centralized event loop.
In this example,
hold(1.hour)
suspends execution control and comes back after 1 hour (of simulated time). Apart from hold, kalasim supports a rich vocabulary of interaction methods including passivate, request, wait and component.
The main body of every kalasim model usually starts with:
createSimulation{
...
}
Car(). It automatically is assigned the name Car.0.
As there is a generator function called process in Car, this process description will be activated (by default at time now, which is 0 by default at the beginning of a simulation). It is possible to start a process later, but this is by far the most common way to start a process.
With
run(5.minutes)
we start the simulation and get back control after 5 simulated minutes. A component called main is defined under the hood to get access to the main process.
When we run this program, we get the following output (displayed as table for convenience):
time current receiver action info
------ -------- --------- ---------------------------------- -------------------
.00 main Created
.00 main
.00 Driver.1 Created capacity=1
.00 Car.1 Created
.00 activate scheduled for .00
.00 main run +5.00 scheduled for 5.00
.00 Car.1 Car.1
.00 Requesting 1.0 from Driver.1
.00 Claimed 1.0 from 'Car.1'
.00 Request honor Driver.1 scheduled for .00
.00
.00 hold +1.00 scheduled for 1.00
1.00
1.00 entering waiters of TrafficLight.1
1.00 wait scheduled for <inf>
5.00 main main
Process finished with exit code 0
There are plenty of other more advanced (that is more fun!) examples listed in examples chapter.