The following is an implementation of the machine shop example from the Simpy documentation using Ciw. Parts of this implementation came from this post.
"""Machine shop implementation."""
from __future__ import annotations
import ciw
import pandas as pd
class CiwMachineShop:
"""A class to simulate a machine shop using Ciw."""
def __init__(
self,
mfft: float = 300.0,
repair_time: float = 30.0,
job_duration: float = 30.0,
num_machines: int = 10,
) -> None:
self.mfft = mfft
self.break_mean = 1.0 / mfft
self.repair_time = repair_time
self.network = ciw.create_network(
arrival_distributions=[ciw.dists.Sequential([0.0, float("inf")]), None],
service_distributions=[
ciw.dists.Exponential(rate=self.break_mean),
ciw.dists.Deterministic(value=float(repair_time)),
],
routing=[[0.0, 1.0], [1.0, 0.0]],
batching_distributions=[ciw.dists.Deterministic(num_machines), None],
number_of_servers=[float("inf"), 1],
)
def run(self, sim_time: float = 4 * 7 * 24 * 60) -> pd.Series:
sim = ciw.Simulation(self.network)
sim.simulate_until_max_time(sim_time)
recs = sim.get_all_records()
df = pd.DataFrame(recs)
parts = (
df[df["node"] == 1]
.groupby(by="id_number")["service_time"]
.sum()
.apply(self.sample_parts_made)
)
return parts
def sample_parts_made(
self, uptime: float, part_mean: float = 10.0, part_sigma: float = 2.0
) -> int:
count = 0
parts_time = 0.0
while True:
parts_time += ciw.dists.Normal(part_mean, part_sigma).sample()
if parts_time >= uptime:
return count
count += 1When we use the run method on an instance of the CiwMachineShop we obtain similar counts as the SimPy machine shop.
>>> CiwMachineShop().run()
id_number
1 3304
2 3208
3 3317
4 3276
5 3277
6 3376
7 3267
8 3254
9 3356
10 3262
Name: service_time, dtype: int64