add utilization
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
from dataclasses import asdict, dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
@@ -39,22 +39,36 @@ class Server(Process):
|
|||||||
|
|
||||||
|
|
||||||
class CustomerGenerator(Process):
|
class CustomerGenerator(Process):
|
||||||
|
def __init__(self, lam=40, servers=[]):
|
||||||
|
self.lam = lam
|
||||||
|
self.servers = servers
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
while True:
|
while True:
|
||||||
wait_for = float(max(0, (np.random.poisson(lam=40, size=1) / 10)[0]))
|
wait_for = float(max(0, (np.random.poisson(lam=self.lam, size=1) / 10)[0]))
|
||||||
customer = Customer(arrived_at=self.simulation.clock)
|
customer = Customer(arrived_at=self.simulation.clock)
|
||||||
customers_unhandled.append(customer)
|
customers_unhandled.append(customer)
|
||||||
for server in servers:
|
for server in self.servers:
|
||||||
server.resume()
|
server.resume()
|
||||||
yield from self.hold(wait_for)
|
yield from self.hold(wait_for)
|
||||||
|
|
||||||
|
|
||||||
servers = [Server() for _ in range(2)]
|
def run_simulation(n_servers=2, lam=40):
|
||||||
simulation = Simulation(processes=[CustomerGenerator(), *servers])
|
servers = [Server() for _ in range(n_servers)]
|
||||||
simulation.start()
|
simulation = Simulation(
|
||||||
|
processes=[CustomerGenerator(servers=servers, lam=lam), *servers]
|
||||||
|
)
|
||||||
|
simulation.start()
|
||||||
|
|
||||||
df = pd.DataFrame([asdict(customer) for customer in customers_handled]).assign(
|
df_customers = pd.DataFrame(
|
||||||
queue_time=lambda row: row["started_at"] - row["arrived_at"]
|
[customer.__dict__ for customer in customers_handled]
|
||||||
)
|
).assign(queue_time=lambda row: row["started_at"] - row["arrived_at"])
|
||||||
print(f"\nservers: {len(servers)}")
|
df_servers = pd.DataFrame([server.__dict__ for server in servers]).set_index("id")
|
||||||
print(df[["queue_time", "handling_time"]].mean())
|
print("\n")
|
||||||
|
print(df_customers[["queue_time", "handling_time"]].mean())
|
||||||
|
print(f"\nservers: {len(servers)}")
|
||||||
|
print(df_servers[["utilization"]])
|
||||||
|
|
||||||
|
|
||||||
|
run_simulation(n_servers=2, lam=30)
|
||||||
|
|||||||
@@ -17,19 +17,32 @@ class Process(BaseProcess):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.id: int = 1
|
self.id: int = 1
|
||||||
self.simulation = BaseSimulation()
|
self.simulation = BaseSimulation()
|
||||||
|
self.started_at: float = 0
|
||||||
self.resume_at: float = 0
|
self.resume_at: float = 0
|
||||||
|
self.time_active: float = 0
|
||||||
|
self.utilization: float = 0
|
||||||
self.suspended = False
|
self.suspended = False
|
||||||
self._gen = self.run()
|
self._gen = self.run()
|
||||||
|
|
||||||
@property
|
def start(self, simulation, id):
|
||||||
def name(self):
|
self.id = id
|
||||||
return f"{self.__class__.__name__} {self.id}"
|
self.started_at = simulation.clock
|
||||||
|
self.simulation = simulation
|
||||||
|
|
||||||
def hold(self, hold_for: float):
|
def hold(self, hold_for: float):
|
||||||
hold_for_formatted = "{:.2f}".format(hold_for)
|
hold_for_formatted = "{:.2f}".format(hold_for)
|
||||||
self.simulation.log(f"holding {self.name} for {hold_for_formatted} seconds")
|
self.simulation.log(f"holding {self.name} for {hold_for_formatted} seconds")
|
||||||
self.resume_at = self.simulation.clock + hold_for
|
self.resume_at = self.simulation.clock + hold_for
|
||||||
|
t_start = self.simulation.clock
|
||||||
yield
|
yield
|
||||||
|
t_end = self.simulation.clock
|
||||||
|
self.time_active += t_end - t_start
|
||||||
|
try:
|
||||||
|
self.utilization = self.time_active / (
|
||||||
|
self.simulation.clock - self.started_at
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
|
||||||
def suspend(self):
|
def suspend(self):
|
||||||
self.suspended = True
|
self.suspended = True
|
||||||
@@ -42,6 +55,10 @@ class Process(BaseProcess):
|
|||||||
self.suspended = False
|
self.suspended = False
|
||||||
next(self._gen)
|
next(self._gen)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return f"{self.__class__.__name__} {self.id}"
|
||||||
|
|
||||||
|
|
||||||
class Simulation(BaseSimulation):
|
class Simulation(BaseSimulation):
|
||||||
def __init__(self, processes: list[Process]):
|
def __init__(self, processes: list[Process]):
|
||||||
@@ -56,8 +73,7 @@ class Simulation(BaseSimulation):
|
|||||||
for p in self.processes
|
for p in self.processes
|
||||||
if p.__class__.__name__ == process.__class__.__name__
|
if p.__class__.__name__ == process.__class__.__name__
|
||||||
]
|
]
|
||||||
process.id = 1 + len(processes_with_same_class)
|
process.start(simulation=self, id=1 + len(processes_with_same_class))
|
||||||
process.simulation = self
|
|
||||||
self.processes.append(process)
|
self.processes.append(process)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|||||||
Reference in New Issue
Block a user