Skip to content

Commit

Permalink
Reformatted with black
Browse files Browse the repository at this point in the history
  • Loading branch information
galenseilis committed Feb 7, 2024
1 parent 0a05a20 commit 1e3ed50
Show file tree
Hide file tree
Showing 22 changed files with 1,850 additions and 1,143 deletions.
39 changes: 28 additions & 11 deletions ciw/arrival_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

class ArrivalNode(object):
"""Class for the arrival node of the network.
See Also
--------
ciw.Simulation : Main simulation class.
Expand All @@ -25,12 +25,17 @@ def __init__(self, simulation):
"""
self.simulation = simulation
self.number_of_individuals = 0
self.number_of_individuals_per_class = {clss: 0 for clss in self.simulation.network.customer_class_names}
self.number_of_individuals_per_class = {
clss: 0 for clss in self.simulation.network.customer_class_names
}
self.number_accepted_individuals = 0
self.number_accepted_individuals_per_class = {clss: 0 for clss in self.simulation.network.customer_class_names}
self.number_accepted_individuals_per_class = {
clss: 0 for clss in self.simulation.network.customer_class_names
}
self.event_dates_dict = {
nd + 1: {clss: False for clss in self.simulation.network.customer_class_names
} for nd in range(self.simulation.network.number_of_nodes)
nd
+ 1: {clss: False for clss in self.simulation.network.customer_class_names}
for nd in range(self.simulation.network.number_of_nodes)
}

def initialise(self):
Expand All @@ -52,7 +57,9 @@ def decide_baulk(self, next_node, next_individual):
self.send_individual(next_node, next_individual)
else:
rnd_num = random()
if rnd_num < next_node.baulking_functions[self.next_class](next_node.number_of_individuals):
if rnd_num < next_node.baulking_functions[self.next_class](
next_node.number_of_individuals
):
self.record_baulk(next_node, next_individual)
self.simulation.nodes[-1].accept(next_individual, completed=False)
else:
Expand Down Expand Up @@ -84,15 +91,19 @@ def have_event(self):
for _ in range(batch):
self.number_of_individuals += 1
self.number_of_individuals_per_class[self.next_class] += 1
priority_class = self.simulation.network.priority_class_mapping[self.next_class]
priority_class = self.simulation.network.priority_class_mapping[
self.next_class
]
next_individual = self.simulation.IndividualType(
self.number_of_individuals,
self.next_class,
priority_class,
simulation=self.simulation,
)
if self.simulation.network.process_based:
next_individual.route = self.simulation.network.customer_classes[next_individual.customer_class].routing[self.next_node - 1](next_individual)
next_individual.route = self.simulation.network.customer_classes[
next_individual.customer_class
].routing[self.next_node - 1](next_individual)
next_node = self.simulation.transitive_nodes[self.next_node - 1]
self.release_individual(next_node, next_individual)

Expand Down Expand Up @@ -124,14 +135,18 @@ def inter_arrival(self, nd, clss):
"""
Samples the inter-arrival time for next class and node.
"""
return self.simulation.inter_arrival_times[nd][clss]._sample(t=self.simulation.current_time)
return self.simulation.inter_arrival_times[nd][clss]._sample(
t=self.simulation.current_time
)

def batch_size(self, nd, clss):
"""
Samples the batch size for next class and node.
Raises error if a positive integer is not sampled.
"""
batch = self.simulation.batch_sizes[nd][clss]._sample(t=self.simulation.current_time)
batch = self.simulation.batch_sizes[nd][clss]._sample(
t=self.simulation.current_time
)
if isinstance(batch, int) and batch >= 0:
return batch
raise ValueError("Batch sizes must be positive integers.")
Expand All @@ -146,7 +161,9 @@ def record_rejection(self, next_node, individual):
"""
Adds an individual to the rejection dictionary.
"""
next_node.write_baulking_or_rejection_record(individual, record_type="rejection")
next_node.write_baulking_or_rejection_record(
individual, record_type="rejection"
)

def release_individual(self, next_node, next_individual):
"""
Expand Down
3 changes: 2 additions & 1 deletion ciw/deadlock/deadlock_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ def action_at_attach_server(self, node, server, individual):
"""
for blq in node.blocked_queue:
inds = [
ind for ind in node.simulation.nodes[blq[0]].all_individuals
ind
for ind in node.simulation.nodes[blq[0]].all_individuals
if ind.id_number == blq[1]
]
ind = inds[0]
Expand Down
2 changes: 1 addition & 1 deletion ciw/disciplines.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ def LIFO(individuals):
LIFO: Last in first out / Last come first served
Returns the individual who joined the queue most recently
"""
return individuals[-1]
return individuals[-1]
2 changes: 1 addition & 1 deletion ciw/exactnode.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class ExactNode(Node):
precise version of addition to fix discrepencies
with floating point numbers.
"""

@property
def now(self):
"""
Expand Down
97 changes: 63 additions & 34 deletions ciw/import_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,20 +92,25 @@ def create_network_from_dictionary(params_input):
"class_change_matrices",
[None for nd in range(number_of_nodes)],
)
class_change_time_distributions = {clss2: {clss1: None for clss1 in params['customer_class_names']} for clss2 in params['customer_class_names']}
if 'class_change_time_distributions' in params:
for clss1 in params['customer_class_names']:
for clss2 in params['customer_class_names']:
class_change_time_distributions = {
clss2: {clss1: None for clss1 in params["customer_class_names"]}
for clss2 in params["customer_class_names"]
}
if "class_change_time_distributions" in params:
for clss1 in params["customer_class_names"]:
for clss2 in params["customer_class_names"]:
try:
class_change_time_distributions[clss1][clss2] = params['class_change_time_distributions'][clss1][clss2]
class_change_time_distributions[clss1][clss2] = params[
"class_change_time_distributions"
][clss1][clss2]
except:
pass

nodes, classes = [], {}
for nd in range(number_of_nodes):
nodes.append(
ServiceCentre(
params['number_of_servers'][nd],
params["number_of_servers"][nd],
params["queue_capacities"][nd],
class_change_matrices[nd],
preempt_priorities[nd],
Expand All @@ -114,12 +119,12 @@ def create_network_from_dictionary(params_input):
params["service_disciplines"][nd],
)
)
for clss_name in params['customer_class_names']:
for clss_name in params["customer_class_names"]:
if all(isinstance(f, types.FunctionType) for f in params["routing"]):
classes[clss_name] = CustomerClass(
params['arrival_distributions'][clss_name],
params['service_distributions'][clss_name],
params['routing'],
params["arrival_distributions"][clss_name],
params["service_distributions"][clss_name],
params["routing"],
params["priority_classes"][clss_name],
params["baulking_functions"][clss_name],
params["batching_distributions"][clss_name],
Expand All @@ -129,9 +134,9 @@ def create_network_from_dictionary(params_input):
)
else:
classes[clss_name] = CustomerClass(
params['arrival_distributions'][clss_name],
params['service_distributions'][clss_name],
params['routing'][clss_name],
params["arrival_distributions"][clss_name],
params["service_distributions"][clss_name],
params["routing"][clss_name],
params["priority_classes"][clss_name],
params["baulking_functions"][clss_name],
params["batching_distributions"][clss_name],
Expand Down Expand Up @@ -187,12 +192,21 @@ def fill_out_dictionary(params):
"routing": {class_name: [[0.0]] for class_name in class_names},
"number_of_nodes": len(params["number_of_servers"]),
"number_of_classes": len(class_names),
"queue_capacities": [float("inf") for _ in range(len(params["number_of_servers"]))],
"queue_capacities": [
float("inf") for _ in range(len(params["number_of_servers"]))
],
"priority_classes": {class_name: 0 for class_name in class_names},
"baulking_functions": {class_name: [None for _ in range(len(params["number_of_servers"]))]for class_name in class_names},
"batching_distributions": {class_name: [
ciw.dists.Deterministic(1) for _ in range(len(params["number_of_servers"]))
] for class_name in class_names},
"baulking_functions": {
class_name: [None for _ in range(len(params["number_of_servers"]))]
for class_name in class_names
},
"batching_distributions": {
class_name: [
ciw.dists.Deterministic(1)
for _ in range(len(params["number_of_servers"]))
]
for class_name in class_names
},
"ps_thresholds": [1 for _ in range(len(params["number_of_servers"]))],
"server_priority_functions": [
None for _ in range(len(params["number_of_servers"]))
Expand Down Expand Up @@ -313,34 +327,49 @@ def validify_dictionary(params):
if neg_numservers:
raise ValueError("Number of servers must be positive integers.")
for c in params["number_of_servers"]:
if not (isinstance(c, int) or isinstance(c, Schedule) or c == float('inf')):
raise ValueError("Number of servers must be positive integers or instances of ciw.schedules.Schedule.")
if not (isinstance(c, int) or isinstance(c, Schedule) or c == float("inf")):
raise ValueError(
"Number of servers must be positive integers or instances of ciw.schedules.Schedule."
)
if not valid_capacities:
raise ValueError("Queue capacities must be positive integers or zero.")

if "class_change_matrices" in params:
if not isinstance(params['class_change_matrices'], list):
raise ValueError("class_change_matrices should be a list of dictionaries for each node in the network.")
if not isinstance(params["class_change_matrices"], list):
raise ValueError(
"class_change_matrices should be a list of dictionaries for each node in the network."
)
num_nodes = len(params["class_change_matrices"]) == params["number_of_nodes"]
if not num_nodes:
raise ValueError("Ensure correct nodes used in class_change_matrices.")
for nd in params["class_change_matrices"]:
for row in nd.values():
if sum(row.values()) > 1.0 or min(row.values()) < 0.0 or max(row.values()) > 1.0:
if (
sum(row.values()) > 1.0
or min(row.values()) < 0.0
or max(row.values()) > 1.0
):
raise ValueError("Ensure that class change matrix is valid.")
class_change_names = set([k for matrix in params['class_change_matrices'] for k in matrix.keys()])
if not class_change_names.issubset(set(params['arrival_distributions'])):
class_change_names = set(
[k for matrix in params["class_change_matrices"] for k in matrix.keys()]
)
if not class_change_names.issubset(set(params["arrival_distributions"])):
raise ValueError("Ensure consistant names for customer classes.")

if "class_change_time_distributions" in params:
class_change_from_names = set(list(params['class_change_time_distributions'].keys()))
class_change_to_names = set([clss for row in params['class_change_time_distributions'].values() for clss in row.keys()])
wrong_class_names = (
not class_change_from_names.issubset(set(params['customer_class_names']))
) or (

not class_change_to_names.issubset(set(params['customer_class_names']))
class_change_from_names = set(
list(params["class_change_time_distributions"].keys())
)
class_change_to_names = set(
[
clss
for row in params["class_change_time_distributions"].values()
for clss in row.keys()
]
)
wrong_class_names = (
not class_change_from_names.issubset(set(params["customer_class_names"]))
) or (not class_change_to_names.issubset(set(params["customer_class_names"])))
if wrong_class_names:
raise ValueError(
"Ensure consistant customer classes used in class_change_time_distributions."
Expand Down
7 changes: 4 additions & 3 deletions ciw/individual.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ class Individual(object):
For more details on the attributes and methods, please refer to the class documentation.
"""

def __init__(self, id_number, customer_class='Customer', priority_class=0, simulation=False):
def __init__(
self, id_number, customer_class="Customer", priority_class=0, simulation=False
):
"""
Initialise an individual.
"""
Expand All @@ -101,6 +103,5 @@ def __init__(self, id_number, customer_class='Customer', priority_class=0, simul
self.simulation = simulation

def __repr__(self):
"""Represents an Individual instance as a string.
"""
"""Represents an Individual instance as a string."""
return f"Individual {self.id_number}"
16 changes: 13 additions & 3 deletions ciw/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,22 @@ def __init__(self, service_centres, customer_classes):
self.number_of_priority_classes = len(
set([clss.priority_class for clss in customer_classes.values()])
)
self.priority_class_mapping = {clss: customer_classes[clss].priority_class for clss in customer_classes.keys()}
self.priority_class_mapping = {
clss: customer_classes[clss].priority_class
for clss in customer_classes.keys()
}
for nd_id, node in enumerate(self.service_centres):
if all(clss.reneging_time_distributions[nd_id] == None for clss in self.customer_classes.values()):
if all(
clss.reneging_time_distributions[nd_id] == None
for clss in self.customer_classes.values()
):
node.reneging = False
else:
node.reneging = True
if any(dist is not None for clss in customer_classes.values() for dist in clss.class_change_time_distributions.values()):
if any(
dist is not None
for clss in customer_classes.values()
for dist in clss.class_change_time_distributions.values()
):
for node in self.service_centres:
node.class_change_time = True
Loading

0 comments on commit 1e3ed50

Please sign in to comment.