def test_allow_zero_servers(self): params_c1 = { 'Arrival_distributions': [['Exponential', 5]], 'Service_distributions': [['Deterministic', 0.2]], 'Number_of_servers': [1] } params_c0 = { 'Arrival_distributions': [['Exponential', 5]], 'Service_distributions': [['Deterministic', 0.2]], 'Number_of_servers': [0] } ciw.seed(1) N = ciw.create_network(**params_c1) Q = ciw.Simulation(N) Q.simulate_until_max_time(100) total_inds_1 = len(Q.nodes[-1].all_individuals) + len(Q.nodes[1].all_individuals) ciw.seed(1) N = ciw.create_network(**params_c0) Q = ciw.Simulation(N) Q.simulate_until_max_time(100) recs = Q.get_all_records() total_inds_0 = len(Q.nodes[1].all_individuals) self.assertEqual(recs, []) self.assertEqual(total_inds_0, total_inds_1)
def test_create_network_returns_none(self): params1 = ['A', 'list', 'of', 'things.'] params2 = "notayamlfile.csv" params3 = 10 self.assertEqual(ciw.create_network(params1), None) self.assertEqual(ciw.create_network(params2), None) self.assertEqual(ciw.create_network(params3), None)
def test_simultaneous_events_example(self): # This should yield 3 or 2 customers finishing service. # Due to randomly choosing the order of events, the seed has # a big affect on this. params = {'Arrival_distributions': [['Deterministic', 10.0], 'NoArrivals'], 'Service_distributions': [['Deterministic', 5.0], ['Deterministic', 5.0]], 'Transition_matrices': [[1.0, 0.0], [0.0, 0.0]], 'Number_of_servers': [2, 1]} ciw.seed(36) Q = ciw.Simulation(ciw.create_network(params)) Q.simulate_until_max_time(36) inds = Q.get_all_individuals() recs = Q.get_all_records() self.assertEqual(len(inds), 2) self.assertTrue(all([x[6] == 5.0 for x in recs[1:]])) ciw.seed(40) Q = ciw.Simulation(ciw.create_network(params)) Q.simulate_until_max_time(36) inds = Q.get_all_individuals() recs = Q.get_all_records() self.assertEqual(len(inds), 3) self.assertTrue(all([x[6] == 5.0 for x in recs[1:]])) completed_inds = [] for _ in range(1000): Q = ciw.Simulation(ciw.create_network(params)) Q.simulate_until_max_time(36) inds = Q.get_all_individuals() completed_inds.append(len(inds)) self.assertAlmostEqual(completed_inds.count(2) / float(1000), 1 / 4.0, places=1)
def test_error_extra_args(self): params = {'Arrival_distributions': [['Exponential', 3.0]], 'Service_distributions': [['Exponential', 7.0]], 'Number_of_servers': [4], 'Something_else': 56 } with self.assertRaises(TypeError): ciw.create_network(**params)
def test_find_generators(self): # No generators: params_nogenerators = { 'Arrival_distributions': {'Class 0': [['Exponential', 5], ['Exponential', 5]], 'Class 1': [['Exponential', 5], ['Exponential', 5]]}, 'Service_distributions': {'Class 0': [['Exponential', 5], ['Exponential', 5]], 'Class 1': [['Exponential', 5], ['Exponential', 5]]}, 'Transition_matrices': {'Class 0': [[0.0, 0.0], [0.0, 0.0]], 'Class 1': [[0.0, 0.0], [0.0, 0.0]]}, 'Number_of_servers': [1, 1] } params_somegenerators = { 'Arrival_distributions': {'Class 0': [['Exponential', 5], ['Sequential', [5, 6]]], 'Class 1': [['Exponential', 5], ['Exponential', 5]]}, 'Service_distributions': {'Class 0': [['Exponential', 5], ['Exponential', 5]], 'Class 1': [['Sequential', [5, 6]], ['Exponential', 5]]}, 'Transition_matrices': {'Class 0': [[0.0, 0.0], [0.0, 0.0]], 'Class 1': [[0.0, 0.0], [0.0, 0.0]]}, 'Number_of_servers': [1, 1] } params_allgenerators = { 'Arrival_distributions': {'Class 0': [['Sequential', [5, 6]], ['Sequential', [5, 6]]], 'Class 1': [['Sequential', [5, 6]], ['Sequential', [5, 6]]]}, 'Service_distributions': {'Class 0': [['Sequential', [5, 6]], ['Sequential', [5, 6]]], 'Class 1': [['Sequential', [5, 6]], ['Sequential', [5, 6]]]}, 'Transition_matrices': {'Class 0': [[0.0, 0.0], [0.0, 0.0]], 'Class 1': [[0.0, 0.0], [0.0, 0.0]]}, 'Number_of_servers': [1, 1] } N_no = ciw.create_network(**params_nogenerators) N_some = ciw.create_network(**params_somegenerators) N_all = ciw.create_network(**params_allgenerators) Q_no = ciw.Simulation(N_no) Q_some = ciw.Simulation(N_some) Q_all = ciw.Simulation(N_all) self.assertEqual(Q_no.generators['Arr'][0], {}) self.assertEqual(Q_no.generators['Arr'][1], {}) self.assertEqual(Q_no.generators['Ser'][0], {}) self.assertEqual(Q_no.generators['Ser'][1], {}) self.assertEqual(Q_some.generators['Arr'][0], {}) self.assertTrue(isinstance(Q_some.generators['Arr'][1][0], cycle)) self.assertTrue(isinstance(Q_some.generators['Ser'][0][1], cycle)) self.assertEqual(Q_some.generators['Ser'][1], {}) self.assertTrue(isinstance(Q_all.generators['Arr'][0][0], cycle)) self.assertTrue(isinstance(Q_all.generators['Arr'][0][1], cycle)) self.assertTrue(isinstance(Q_all.generators['Arr'][1][0], cycle)) self.assertTrue(isinstance(Q_all.generators['Arr'][1][1], cycle)) self.assertTrue(isinstance(Q_all.generators['Ser'][0][0], cycle)) self.assertTrue(isinstance(Q_all.generators['Ser'][0][1], cycle)) self.assertTrue(isinstance(Q_all.generators['Ser'][1][0], cycle)) self.assertTrue(isinstance(Q_all.generators['Ser'][1][1], cycle))
def test_repr_method(self): N1 = ciw.create_network( 'ciw/tests/testing_parameters/params.yml') Q1 = ciw.Simulation(N1) self.assertEqual(str(Q1), 'Simulation') N2 = ciw.create_network( 'ciw/tests/testing_parameters/params.yml') Q = ciw.Simulation(N2, name='My special simulation instance!') self.assertEqual(str(Q), 'My special simulation instance!')
def test_have_event_method(self): ciw.seed(1) Q = ciw.Simulation(ciw.create_network( 'ciw/tests/testing_parameters/params.yml')) N = ciw.ArrivalNode(Q) self.assertEqual(Q.transitive_nodes[0].all_individuals, []) self.assertEqual(Q.transitive_nodes[0].individuals, [[]]) self.assertEqual(Q.transitive_nodes[1].all_individuals, []) self.assertEqual(Q.transitive_nodes[1].individuals, [[]]) self.assertEqual(Q.transitive_nodes[2].all_individuals, []) self.assertEqual(Q.transitive_nodes[2].individuals, [[]]) self.assertEqual(Q.transitive_nodes[3].all_individuals, []) self.assertEqual(Q.transitive_nodes[3].individuals, [[]]) self.assertEqual(round(N.next_event_date, 5), 0.00105) self.assertEqual(N.next_node, 1) N.have_event() self.assertEqual([str(obj) for obj in Q.transitive_nodes[0].all_individuals], ['Individual 1']) self.assertEqual([str(obj) for pr_cls in Q.transitive_nodes[0].individuals for obj in pr_cls], ['Individual 1']) self.assertEqual(Q.transitive_nodes[1].all_individuals, []) self.assertEqual(Q.transitive_nodes[1].individuals, [[]]) self.assertEqual(Q.transitive_nodes[2].all_individuals, []) self.assertEqual(Q.transitive_nodes[2].individuals, [[]]) self.assertEqual(Q.transitive_nodes[3].all_individuals, []) self.assertEqual(Q.transitive_nodes[3].individuals, [[]]) self.assertEqual(round(N.next_event_date, 5), 0.00518) self.assertEqual(N.next_node, 3) ciw.seed(12) Q = ciw.Simulation(ciw.create_network( 'ciw/tests/testing_parameters/params.yml')) N = ciw.ArrivalNode(Q) self.assertEqual(Q.transitive_nodes[0].all_individuals, []) self.assertEqual(Q.transitive_nodes[0].individuals, [[]]) self.assertEqual(Q.transitive_nodes[1].all_individuals, []) self.assertEqual(Q.transitive_nodes[1].individuals, [[]]) self.assertEqual(Q.transitive_nodes[2].all_individuals, []) self.assertEqual(Q.transitive_nodes[2].individuals, [[]]) self.assertEqual(Q.transitive_nodes[3].all_individuals, []) self.assertEqual(Q.transitive_nodes[3].individuals, [[]]) self.assertEqual(round(N.next_event_date, 5), 0.01938) self.assertEqual(N.next_node, 3) N.have_event() self.assertEqual(Q.transitive_nodes[0].all_individuals, []) self.assertEqual(Q.transitive_nodes[0].individuals, [[]]) self.assertEqual(Q.transitive_nodes[1].all_individuals, []) self.assertEqual(Q.transitive_nodes[1].individuals, [[]]) self.assertEqual([str(obj) for obj in Q.transitive_nodes[2].all_individuals], ['Individual 1']) self.assertEqual([str(obj) for pr_cls in Q.transitive_nodes[2].individuals for obj in pr_cls], ['Individual 1']) self.assertEqual(Q.transitive_nodes[3].all_individuals, []) self.assertEqual(Q.transitive_nodes[3].individuals, [[]]) self.assertEqual(round(N.next_event_date, 5), 0.02021) self.assertEqual(N.next_node, 2)
def test_update_next_event_date_method(self): Q = ciw.Simulation(ciw.create_network( 'ciw/tests/testing_parameters/params.yml')) N = Q.transitive_nodes[0] self.assertEqual(N.next_event_date, float('Inf')) self.assertEqual(N.all_individuals, []) N.update_next_event_date(0.0) self.assertEqual(N.next_event_date, float('Inf')) ind1 = ciw.Individual(1) ind1.arrival_date = 0.3 ind1.service_time = 0.2 ind1.service_end_date = 0.5 N.next_event_date = 0.3 N.individuals = [[ind1]] N.update_next_event_date(N.next_event_date + 0.000001) self.assertEqual(N.next_event_date, 0.5) ind2 = ciw.Individual(2) ind2.arrival_date = 0.4 ind2.service_time = 0.2 ind2.service_end_date = 0.6 ind2.exit_date = False N.individuals = [[ind1, ind2]] N.update_next_event_date(N.next_event_date + 0.000001) self.assertEqual(N.next_event_date, 0.6) ind2.exit_date = 0.9 N.update_next_event_date(N.next_event_date + 0.000001) self.assertEqual(N.next_event_date, float('Inf')) Q = ciw.Simulation(ciw.create_network( 'ciw/tests/testing_parameters/params_schedule.yml')) N = Q.transitive_nodes[0] self.assertEqual(N.next_event_date, 30) self.assertEqual(N.individuals, [[]]) N.update_next_event_date(0.0) self.assertEqual(N.next_event_date, 30) ind1 = ciw.Individual(1) ind1.arrival_date = 0.3 ind1.service_time = 0.2 ind1.service_end_date = 0.5 N.next_event_date = 0.3 N.individuals = [[ind1]] N.update_next_event_date(N.next_event_date + 0.000001) self.assertEqual(N.next_event_date, 0.5) N.update_next_event_date(N.next_event_date + 0.000001) self.assertEqual(N.next_event_date, 30)
def test_change_customer_class_method(self): ciw.seed(14) Q = ciw.Simulation(ciw.create_network( 'ciw/tests/testing_parameters/params_change_class.yml')) N1 = Q.transitive_nodes[0] ind = ciw.Individual(254, 0) self.assertEqual(ind.customer_class, 0) self.assertEqual(ind.previous_class, 0) N1.change_customer_class(ind) self.assertEqual(ind.customer_class, 1) self.assertEqual(ind.previous_class, 0) N1.change_customer_class(ind) self.assertEqual(ind.customer_class, 1) self.assertEqual(ind.previous_class, 1) N1.change_customer_class(ind) self.assertEqual(ind.customer_class, 1) self.assertEqual(ind.previous_class, 1) N1.change_customer_class(ind) self.assertEqual(ind.customer_class, 0) self.assertEqual(ind.previous_class, 1) # Test for case of having priorities ciw.seed(14) parameters_dictionary = ciw.load_parameters( 'ciw/tests/testing_parameters/params_priorities.yml') class_change_matrix = {'Node 1': [[.5, .5], [.25, .75]], 'Node 2': [[1, 0], [0, 1]]} parameters_dictionary['Class_change_matrices'] = class_change_matrix Q = ciw.Simulation(ciw.create_network(parameters_dictionary)) N1 = Q.transitive_nodes[0] ind = ciw.Individual(254, 0) self.assertEqual(ind.customer_class, 0) self.assertEqual(ind.priority_class, 0) self.assertEqual(ind.previous_class, 0) N1.change_customer_class(ind) self.assertEqual(ind.customer_class, 1) self.assertEqual(ind.priority_class, 1) self.assertEqual(ind.previous_class, 0) N1.change_customer_class(ind) self.assertEqual(ind.customer_class, 1) self.assertEqual(ind.priority_class, 1) self.assertEqual(ind.previous_class, 1) N1.change_customer_class(ind) self.assertEqual(ind.customer_class, 1) self.assertEqual(ind.priority_class, 1) self.assertEqual(ind.previous_class, 1) N1.change_customer_class(ind) self.assertEqual(ind.customer_class, 0) self.assertEqual(ind.priority_class, 0) self.assertEqual(ind.previous_class, 1)
def test_baulking(self): def my_baulking_function(n): if n < 3: return 0.0 return 1.0 params_dict = { 'Arrival_distributions': [['Deterministic', 5.0]], 'Service_distributions': [['Deterministic', 21.0]], 'Number_of_servers': [1], 'Baulking_functions': [my_baulking_function] } Q = ciw.Simulation(ciw.create_network(**params_dict)) Q.simulate_until_max_time(51) recs = Q.get_all_records() self.assertEqual(Q.baulked_dict, {1:{0:[20.0, 25.0, 35.0, 40.0, 45.0]}}) self.assertEqual([r.id_number for r in recs], [1, 2]) self.assertEqual([r.arrival_date for r in recs], [5.0, 10.0]) self.assertEqual([r.waiting_time for r in recs], [0.0, 16.0]) self.assertEqual([r.service_start_date for r in recs], [5.0, 26.0]) self.assertEqual([r.service_end_date for r in recs], [26.0, 47.0]) params_dict = { 'Arrival_distributions': [['Deterministic', 5.0], ['Deterministic', 23.0]], 'Service_distributions': [['Deterministic', 21.0], ['Deterministic', 1.5]], 'Transition_matrices': [[0.0, 0.0], [1.0, 0.0]], 'Number_of_servers': [1, 1], 'Baulking_functions': [my_baulking_function, None] } Q = ciw.Simulation(ciw.create_network(**params_dict)) Q.simulate_until_max_time(51) recs = Q.get_all_records() self.assertEqual(Q.baulked_dict, {1:{0:[20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0]}, 2:{0:[]}}) self.assertEqual(sorted([r.id_number for r in recs]), [1, 2, 5, 11]) self.assertEqual(sorted([r.arrival_date for r in recs]), [5.0, 10.0, 23.0, 46.0]) self.assertEqual(sorted([r.waiting_time for r in recs]), [0.0, 0.0, 0.0, 16.0]) self.assertEqual(sorted([r.service_start_date for r in recs]), [5.0, 23.0, 26.0, 46.0]) self.assertEqual(sorted([r.service_end_date for r in recs]), [24.5, 26.0, 47.0, 47.5])
def test_find_next_active_node_method(self): Q = ciw.Simulation(ciw.create_network( 'ciw/tests/testing_parameters/params.yml')) i = 0 for node in Q.nodes[:-1]: node.next_event_date = i i += 1 self.assertEqual(str(Q.find_next_active_node()), 'Arrival Node') Q = ciw.Simulation(ciw.create_network( 'ciw/tests/testing_parameters/params.yml')) i = 10 for node in Q.nodes[:-1]: node.next_event_date = i i -= 1 self.assertEqual(str(Q.find_next_active_node()), 'Node 4')
def test_setting_classes(self): class DummyNode(ciw.Node): pass class DummyArrivalNode(ciw.ArrivalNode): pass params = {'Arrival_distributions': [['Exponential', 20]], 'Service_distributions': [['Deterministic', 0.01]], 'Transition_matrices': [[0.0]], 'Number_of_servers': ['server_schedule'], 'server_schedule': [[0.5, 0], [0.55, 1], [3.0, 0]]} Q = ciw.Simulation(ciw.create_network(params)) self.assertEqual(Q.NodeType, ciw.Node) self.assertEqual(Q.ArrivalNodeType, ciw.ArrivalNode) Q.set_classes(None, None) self.assertEqual(Q.NodeType, ciw.Node) self.assertEqual(Q.ArrivalNodeType, ciw.ArrivalNode) Q.set_classes(DummyNode, None) self.assertEqual(Q.NodeType, DummyNode) self.assertEqual(Q.ArrivalNodeType, ciw.ArrivalNode) Q.set_classes(None, DummyArrivalNode) self.assertEqual(Q.NodeType, ciw.Node) self.assertEqual(Q.ArrivalNodeType, DummyArrivalNode) Q.set_classes(DummyNode, DummyArrivalNode) self.assertEqual(Q.NodeType, DummyNode) self.assertEqual(Q.ArrivalNodeType, DummyArrivalNode)
def test_sampling_triangular_dist(self): params = { 'Arrival_distributions': [['Triangular', 1.1, 6.6, 1.5]], 'Service_distributions': [['Triangular', 1.1, 6.6, 1.5]], 'Number_of_servers': [1], 'Transition_matrices': [[0.1]] } Q = ciw.Simulation(ciw.create_network(params)) Nt = Q.transitive_nodes[0] ciw.seed(5) self.assertEqual(round( Nt.simulation.service_times[Nt.id_number][0](), 2), 3.35) self.assertEqual(round( Nt.simulation.service_times[Nt.id_number][0](), 2), 3.91) self.assertEqual(round( Nt.simulation.service_times[Nt.id_number][0](), 2), 4.20) self.assertEqual(round( Nt.simulation.service_times[Nt.id_number][0](), 2), 5.33) self.assertEqual(round( Nt.simulation.service_times[Nt.id_number][0](), 2), 3.90) self.assertEqual(round( Nt.simulation.inter_arrival_times[Nt.id_number][0](), 2), 5.12) self.assertEqual(round( Nt.simulation.inter_arrival_times[Nt.id_number][0](), 2), 1.35) self.assertEqual(round( Nt.simulation.inter_arrival_times[Nt.id_number][0](), 2), 2.73) self.assertEqual(round( Nt.simulation.inter_arrival_times[Nt.id_number][0](), 2), 5.34) self.assertEqual(round( Nt.simulation.inter_arrival_times[Nt.id_number][0](), 2), 3.46)
def test_sampling_custom_dist(self): my_custom_dist_values = [3.7, 3.8, 4.1] my_custom_dist_probs = [0.2, 0.5, 0.3] params = { 'Arrival_distributions': [['Custom', my_custom_dist_values, my_custom_dist_probs]], 'Service_distributions': [['Custom', my_custom_dist_values, my_custom_dist_probs]], 'Number_of_servers': [1] } Q = ciw.Simulation(ciw.create_network(**params)) Nc = Q.transitive_nodes[0] ciw.seed(5) self.assertEqual(round( Nc.simulation.service_times[Nc.id_number][0](), 2), 3.8) self.assertEqual(round( Nc.simulation.service_times[Nc.id_number][0](), 2), 4.1) self.assertEqual(round( Nc.simulation.service_times[Nc.id_number][0](), 2), 4.1) self.assertEqual(round( Nc.simulation.service_times[Nc.id_number][0](), 2), 4.1) self.assertEqual(round( Nc.simulation.service_times[Nc.id_number][0](), 2), 4.1) self.assertEqual(round( Nc.simulation.inter_arrival_times[Nc.id_number][0](), 2), 4.1) self.assertEqual(round( Nc.simulation.inter_arrival_times[Nc.id_number][0](), 2), 3.7) self.assertEqual(round( Nc.simulation.inter_arrival_times[Nc.id_number][0](), 2), 3.8) self.assertEqual(round( Nc.simulation.inter_arrival_times[Nc.id_number][0](), 2), 4.1) self.assertEqual(round( Nc.simulation.inter_arrival_times[Nc.id_number][0](), 2), 3.8)
def forward(self, seed): N = ciw.create_network( arrival_distributions=[ ciw.dists.Exponential(self.params[0]), ciw.dists.NoArrivals(), ciw.dists.NoArrivals(), ciw.dists.NoArrivals(), ciw.dists.NoArrivals() ], service_distributions=[ ciw.dists.Lognormal(self.params[1], self.params[2]), ciw.dists.Lognormal(self.params[3], self.params[4]), ciw.dists.Lognormal(self.params[5], self.params[6]), ciw.dists.Exponential(self.params[7]), ciw.dists.Deterministic(0.05) ], routing=[[0.0, 0.5, 0.0, 0.5, 0.0], [0.0, 0.0, 0.7, 0.0, 0.3], [0.0, 0.0, 0.0, 0.5, 0.5], [0.2, 0.8, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0]], number_of_servers=[5, 3, 2, 2, 4], ) #batchsize == 20 batch = [] for i in range(10): ciw.seed(seed + i) Q = ciw.Simulation(N) Q.simulate_until_max_time(80) recs = Q.get_all_records() batch.append(self.recs_parser(recs, 5)) return batch
def test_priority_system_compare_literature(self): params_dict = { 'Arrival_distributions': {'Class 0': [['Exponential', 0.2]], 'Class 1': [['Exponential', 0.6]]}, 'Service_distributions': {'Class 0': [['Exponential', 1.0]], 'Class 1': [['Exponential', 1.0]]}, 'Transition_matrices': {'Class 0': [[0.0]], 'Class 1': [[0.0]]}, 'Number_of_servers': [1], 'Priority_classes': {'Class 0': 0, 'Class 1': 1} } # Results expected from analytical queueing theory are: # expected_throughput_class0 = 2.0, and expected_throughput_class1 = 6.0 throughput_class0 = [] throughput_class1 = [] ciw.seed(3231) for iteration in range(80): Q = ciw.Simulation(ciw.create_network(**params_dict)) Q.simulate_until_max_time(400) recs = Q.get_all_records() throughput_c0 = [r.waiting_time + r.service_time for r in recs if r.customer_class==0 if r.arrival_date > 100] throughput_c1 = [r.waiting_time + r.service_time for r in recs if r.customer_class==1 if r.arrival_date > 100] throughput_class0.append(sum(throughput_c0)/len(throughput_c0)) throughput_class1.append(sum(throughput_c1)/len(throughput_c1)) self.assertEqual(round(sum(throughput_class0)/80.0, 5), 1.94852) self.assertEqual(round(sum(throughput_class1)/80.0, 5), 5.92823)
def test_sampling_sequential_dist(self): params = { 'arrival_distributions': [ciw.dists.Sequential([0.2, 0.4, 0.6, 0.8])], 'service_distributions': [ciw.dists.Sequential([0.9, 0.7, 0.5, 0.3, 0.1])], 'number_of_servers': [1], 'routing': [[0.1]] } Q = ciw.Simulation(ciw.create_network(**params)) Ns = Q.transitive_nodes[0] samples = [ round(Ns.simulation.service_times[Ns.id_number][0]._sample(), 2) for _ in range(7) ] expected = [0.9, 0.7, 0.5, 0.3, 0.1, 0.9, 0.7] self.assertEqual(samples, expected) # First arrival will be offset by 1, as first customer's inter-arrival # time has already been sampled by the arrival node samples = [ round(Ns.simulation.inter_arrival_times[Ns.id_number][0]._sample(), 2) for _ in range(6) ] expected = [0.4, 0.6, 0.8, 0.2, 0.4, 0.6] self.assertEqual(samples, expected)
def test_change_shift_method(self): Q = ciw.Simulation( ciw.create_network( 'ciw/tests/testing_parameters/params_schedule.yml')) N = Q.transitive_nodes[0] N.next_event_date = 30 self.assertEqual([str(obs) for obs in N.servers], ['Server 1 at Node 1']) self.assertEqual([obs.busy for obs in N.servers], [False]) self.assertEqual([obs.offduty for obs in N.servers], [False]) self.assertEqual(N.c, 1) N.change_shift() self.assertEqual([str(obs) for obs in N.servers], ['Server 2 at Node 1', 'Server 3 at Node 1']) self.assertEqual([obs.busy for obs in N.servers], [False, False]) self.assertEqual([obs.offduty for obs in N.servers], [False, False]) self.assertEqual(N.c, 2) N.servers[0].busy = True N.next_event_date = 90 N.change_shift() self.assertEqual([str(obs) for obs in N.servers], [ 'Server 2 at Node 1', 'Server 4 at Node 1', 'Server 5 at Node 1', 'Server 6 at Node 1' ]) self.assertEqual([obs.busy for obs in N.servers], [True, False, False, False]) self.assertEqual([obs.offduty for obs in N.servers], [True, False, False, False]) self.assertEqual(N.c, 3)
def test_begin_service_if_possible_release_method(self): ciw.seed(50) Q = ciw.Simulation(ciw.create_network( 'ciw/tests/testing_parameters/params_deadlock.yml'), deadlock_detector='StateDigraph') inds = [[ciw.Individual(i) for i in range(30)]] Q.transitive_nodes[0].individuals = inds ind = Q.transitive_nodes[0].individuals[0][0] ind.service_time = 3.14 ind.arrival_date = 100.0 self.assertEqual( set(Q.deadlock_detector.statedigraph.nodes()), set([ 'Server 5 at Node 2', 'Server 5 at Node 1', 'Server 3 at Node 2', 'Server 1 at Node 2', 'Server 1 at Node 1', 'Server 2 at Node 1', 'Server 2 at Node 2', 'Server 3 at Node 1', 'Server 4 at Node 1', 'Server 4 at Node 2' ])) self.assertEqual(ind.arrival_date, 100.0) self.assertEqual(ind.service_time, 3.14) self.assertEqual(ind.service_start_date, False) self.assertEqual(ind.service_end_date, False) Q.transitive_nodes[0].begin_service_if_possible_release(200.0) self.assertEqual(ind.arrival_date, 100.0) self.assertEqual(round(ind.service_time, 5), 3.14) self.assertEqual(ind.service_start_date, 200.0) self.assertEqual(round(ind.service_end_date, 5), 203.14)
def test_timedependent_exact(self): params = { 'arrival_distributions': [TimeDependentDist1(), TimeDependentDist2()], 'service_distributions': [TimeDependentDist1(), TimeDependentDist2()], 'number_of_servers': [1, 1], 'routing': [[0.1, 0.1], [0.1, 0.1]] } Q = ciw.Simulation(ciw.create_network(**params), exact=26) N1 = Q.transitive_nodes[0] N2 = Q.transitive_nodes[1] ind = ciw.Individual(0) ciw.seed(5) samples = [] for t in [3.0, 9.0, 9.0, 11.0, 11.0]: Q.current_time = t samples.append(round(N1.get_service_time(ind), 2)) expected = [3.0, 3.0, 3.0, 5.0, 5.0] self.assertEqual(samples, expected) samples = [] for t in [4.0, 4.0, 17.0, 22.0, 22.0]: Q.current_time = t samples.append(round(N2.get_service_time(ind), 2)) expected = [2.0, 2.0, 8.5, 8.0, 8.0] self.assertEqual(samples, expected)
def test_batching_sequential(self): # Test sequential batches N = ciw.create_network( Arrival_distributions=[['Sequential', [5.0, 5.0, 100.0]]], Service_distributions=[['Sequential', [2.0, 3.0]]], Number_of_servers=[1], Batching_distributions=[['Sequential', [1, 1, 4, 2, 1, 5]]] ) Q = ciw.Simulation(N) N = Q.transitive_nodes[0] self.assertEqual(len(N.all_individuals), 0) Q.nodes[0].have_event() self.assertEqual(len(N.all_individuals), 1) Q.nodes[0].have_event() self.assertEqual(len(N.all_individuals), 2) Q.nodes[0].have_event() self.assertEqual(len(N.all_individuals), 6) Q.nodes[0].have_event() self.assertEqual(len(N.all_individuals), 8) Q.nodes[0].have_event() self.assertEqual(len(N.all_individuals), 9) Q.nodes[0].have_event() self.assertEqual(len(N.all_individuals), 14) Q.nodes[0].have_event() self.assertEqual(len(N.all_individuals), 15) Q.nodes[0].have_event() self.assertEqual(len(N.all_individuals), 16) Q.nodes[0].have_event() self.assertEqual(len(N.all_individuals), 20)
def test_sampling_lognormal_dist(self): params = { 'Arrival_distributions': [['Lognormal', 0.8, 0.2]], 'Service_distributions': [['Lognormal', 0.8, 0.2]], 'Number_of_servers': [1], 'Transition_matrices': [[0.1]] } Q = ciw.Simulation(ciw.create_network(params)) Nl = Q.transitive_nodes[0] ciw.seed(5) self.assertEqual(round( Nl.simulation.service_times[Nl.id_number][0](), 2), 2.62) self.assertEqual(round( Nl.simulation.service_times[Nl.id_number][0](), 2), 1.64) self.assertEqual(round( Nl.simulation.service_times[Nl.id_number][0](), 2), 2.19) self.assertEqual(round( Nl.simulation.service_times[Nl.id_number][0](), 2), 2.31) self.assertEqual(round( Nl.simulation.service_times[Nl.id_number][0](), 2), 2.48) self.assertEqual(round( Nl.simulation.inter_arrival_times[Nl.id_number][0](), 2), 2.51) self.assertEqual(round( Nl.simulation.inter_arrival_times[Nl.id_number][0](), 2), 2.33) self.assertEqual(round( Nl.simulation.inter_arrival_times[Nl.id_number][0](), 2), 1.96) self.assertEqual(round( Nl.simulation.inter_arrival_times[Nl.id_number][0](), 2), 2.32) self.assertEqual(round( Nl.simulation.inter_arrival_times[Nl.id_number][0](), 2), 2.70)
def test_sampling_pmf_dist(self): my_custom_dist_values = [3.7, 3.8, 4.1] my_custom_dist_probs = [0.2, 0.5, 0.3] params = { 'arrival_distributions': [ciw.dists.Pmf(my_custom_dist_values, my_custom_dist_probs)], 'service_distributions': [ciw.dists.Pmf(my_custom_dist_values, my_custom_dist_probs)], 'number_of_servers': [1] } Q = ciw.Simulation(ciw.create_network(**params)) Nc = Q.transitive_nodes[0] ciw.seed(5) samples = [ round(Nc.simulation.service_times[Nc.id_number][0]._sample(), 2) for _ in range(5) ] expected = [3.8, 4.1, 4.1, 4.1, 4.1] self.assertEqual(samples, expected) samples = [ round(Nc.simulation.inter_arrival_times[Nc.id_number][0]._sample(), 2) for _ in range(5) ] expected = [4.1, 3.7, 3.8, 4.1, 3.8] self.assertEqual(samples, expected)
def test_sampling_empirical_dist(self): my_empirical_dist = [8.0, 8.0, 8.0, 8.8, 8.8, 12.3] params = { 'arrival_distributions': [ ciw.dists.Empirical( import_empirical( 'ciw/tests/testing_parameters/sample_empirical_dist.csv' )) ], 'service_distributions': [ciw.dists.Empirical(my_empirical_dist)], 'number_of_servers': [1] } Q = ciw.Simulation(ciw.create_network(**params)) Nem = Q.transitive_nodes[0] ciw.seed(5) samples = [ round(Nem.simulation.service_times[Nem.id_number][0]._sample(), 2) for _ in range(5) ] expected = [8.8, 8.8, 8.8, 12.3, 8.8] self.assertEqual(samples, expected) samples = [ round( Nem.simulation.inter_arrival_times[Nem.id_number][0]._sample(), 2) for _ in range(5) ] expected = [7.3, 7.0, 7.7, 7.3, 7.1] self.assertEqual(samples, expected)
def test_timedependent_exact(self): params = { 'Arrival_distributions': [ ['TimeDependent', time_dependent_function_1], ['TimeDependent', time_dependent_function_2]], 'Service_distributions': [ ['TimeDependent', time_dependent_function_1], ['TimeDependent', time_dependent_function_2]], 'Number_of_servers': [1, 1], 'Transition_matrices': [[0.1, 0.1], [0.1, 0.1]] } Q = ciw.Simulation(ciw.create_network(**params), exact=26) N1 = Q.transitive_nodes[0] N2 = Q.transitive_nodes[1] ciw.seed(5) self.assertEqual(N1.get_service_time(0, 3.0), 3.0) self.assertEqual(N1.get_service_time(0, 9.0), 3.0) self.assertEqual(N1.get_service_time(0, 9.0), 3.0) self.assertEqual(N1.get_service_time(0, 11.0), 5.0) self.assertEqual(N1.get_service_time(0, 11.0), 5.0) self.assertEqual(N2.get_service_time(0, 4.0), 2.0) self.assertEqual(N2.get_service_time(0, 4.0), 2.0) self.assertEqual(N2.get_service_time(0, 17.0), 8.5) self.assertEqual(N2.get_service_time(0, 22.0), 8.0) self.assertEqual(N2.get_service_time(0, 22.0), 8.0)
def test_find_next_active_node_method(self): Q = ciw.Simulation( ciw.create_network('ciw/tests/testing_parameters/params.yml')) i = 0 for node in Q.nodes[:-1]: node.next_event_date = i i += 1 self.assertEqual(str(Q.find_next_active_node()), 'Arrival Node') Q = ciw.Simulation( ciw.create_network('ciw/tests/testing_parameters/params.yml')) i = 10 for node in Q.nodes[:-1]: node.next_event_date = i i -= 1 self.assertEqual(str(Q.find_next_active_node()), 'Node 4')
def test_sampling_exponential_dist(self): params = { 'Arrival_distributions': [['Exponential', 4.4]], 'Service_distributions': [['Exponential', 4.4]], 'Number_of_servers': [1], 'Transition_matrices': [[0.1]] } Q = ciw.Simulation(ciw.create_network(params)) Ne = Q.transitive_nodes[0] ciw.seed(5) self.assertEqual(round( Ne.simulation.service_times[Ne.id_number][0](), 2), 0.22) self.assertEqual(round( Ne.simulation.service_times[Ne.id_number][0](), 2), 0.31) self.assertEqual(round( Ne.simulation.service_times[Ne.id_number][0](), 2), 0.36) self.assertEqual(round( Ne.simulation.service_times[Ne.id_number][0](), 2), 0.65) self.assertEqual(round( Ne.simulation.service_times[Ne.id_number][0](), 2), 0.31) self.assertEqual(round( Ne.simulation.inter_arrival_times[Ne.id_number][0](), 2), 0.58) self.assertEqual(round( Ne.simulation.inter_arrival_times[Ne.id_number][0](), 2), 0.01) self.assertEqual(round( Ne.simulation.inter_arrival_times[Ne.id_number][0](), 2), 0.14) self.assertEqual(round( Ne.simulation.inter_arrival_times[Ne.id_number][0](), 2), 0.65) self.assertEqual(round( Ne.simulation.inter_arrival_times[Ne.id_number][0](), 2), 0.24)
def test_batching_multi_classes(self): N = ciw.create_network(arrival_distributions={ 'Class 0': [ciw.dists.Deterministic(20)], 'Class 1': [ciw.dists.Deterministic(23)], 'Class 2': [ciw.dists.Deterministic(25)] }, service_distributions={ 'Class 0': [ciw.dists.Deterministic(1)], 'Class 1': [ciw.dists.Deterministic(1)], 'Class 2': [ciw.dists.Deterministic(1)] }, number_of_servers=[10], batching_distributions={ 'Class 0': [ciw.dists.Deterministic(3)], 'Class 1': [ciw.dists.Deterministic(2)], 'Class 2': [ciw.dists.Deterministic(1)] }) ciw.seed(12) Q = ciw.Simulation(N) Q.simulate_until_max_time(28) recs = Q.get_all_records() arrivals = [r.arrival_date for r in recs] nodes = [r.node for r in recs] classes = [r.customer_class for r in recs] self.assertEqual(arrivals, [20, 20, 20, 23, 23, 25]) self.assertEqual(nodes, [1, 1, 1, 1, 1, 1]) self.assertEqual(classes, [0, 0, 0, 1, 1, 2])
def test_sampling_empirical_dist(self): my_empirical_dist = [8.0, 8.0, 8.0, 8.8, 8.8, 12.3] params = { 'Arrival_distributions': [['Empirical', 'ciw/tests/testing_parameters/sample_empirical_dist.csv']], 'Service_distributions': [['Empirical', my_empirical_dist]], 'Number_of_servers': [1], 'Transition_matrices': [[0.1]] } Q = ciw.Simulation(ciw.create_network(params)) Nem = Q.transitive_nodes[0] ciw.seed(5) self.assertEqual(round( Nem.simulation.service_times[Nem.id_number][0](), 2), 8.8) self.assertEqual(round( Nem.simulation.service_times[Nem.id_number][0](), 2), 12.3) self.assertEqual(round( Nem.simulation.service_times[Nem.id_number][0](), 2), 8.0) self.assertEqual(round( Nem.simulation.service_times[Nem.id_number][0](), 2), 8.0) self.assertEqual(round( Nem.simulation.service_times[Nem.id_number][0](), 2), 8.0) self.assertEqual(round( Nem.simulation.inter_arrival_times[Nem.id_number][0](), 2), 7.7) self.assertEqual(round( Nem.simulation.inter_arrival_times[Nem.id_number][0](), 2), 7.7) self.assertEqual(round( Nem.simulation.inter_arrival_times[Nem.id_number][0](), 2), 7.1) self.assertEqual(round( Nem.simulation.inter_arrival_times[Nem.id_number][0](), 2), 7.1) self.assertEqual(round( Nem.simulation.inter_arrival_times[Nem.id_number][0](), 2), 7.7)
def test_batching_multi_node(self): N = ciw.create_network( arrival_distributions=[ciw.dists.Deterministic(20), ciw.dists.Deterministic(23), ciw.dists.Deterministic(25)], service_distributions=[ciw.dists.Deterministic(1), ciw.dists.Deterministic(1), ciw.dists.Deterministic(1)], number_of_servers=[10, 10, 10], batching_distributions=[ciw.dists.Deterministic(3), ciw.dists.Deterministic(2), ciw.dists.Deterministic(1)], routing=[[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]] ) ciw.seed(12) Q = ciw.Simulation(N) Q.simulate_until_max_time(28) recs = Q.get_all_records() arrivals = [r.arrival_date for r in recs] nodes = [r.node for r in recs] classes = [r.customer_class for r in recs] self.assertEqual(arrivals, [20, 20, 20, 23, 23, 25]) self.assertEqual(nodes, [1, 1, 1, 2, 2, 3]) self.assertEqual(classes, [0, 0, 0, 0, 0, 0])
def test_setting_classes(self): class DummyNode(ciw.Node): pass class DummyArrivalNode(ciw.ArrivalNode): pass params = { 'Arrival_distributions': [['Exponential', 20]], 'Service_distributions': [['Deterministic', 0.01]], 'Transition_matrices': [[0.0]], 'Number_of_servers': ['server_schedule'], 'server_schedule': [[0.5, 0], [0.55, 1], [3.0, 0]] } Q = ciw.Simulation(ciw.create_network(params)) self.assertEqual(Q.NodeType, ciw.Node) self.assertEqual(Q.ArrivalNodeType, ciw.ArrivalNode) Q.set_classes(None, None) self.assertEqual(Q.NodeType, ciw.Node) self.assertEqual(Q.ArrivalNodeType, ciw.ArrivalNode) Q.set_classes(DummyNode, None) self.assertEqual(Q.NodeType, DummyNode) self.assertEqual(Q.ArrivalNodeType, ciw.ArrivalNode) Q.set_classes(None, DummyArrivalNode) self.assertEqual(Q.NodeType, ciw.Node) self.assertEqual(Q.ArrivalNodeType, DummyArrivalNode) Q.set_classes(DummyNode, DummyArrivalNode) self.assertEqual(Q.NodeType, DummyNode) self.assertEqual(Q.ArrivalNodeType, DummyArrivalNode)
def test_update_next_event_date_method(self): Net = ciw.create_network( Arrival_distributions=[['Deterministic', 10.0]], Service_distributions=[['Sequential', [0.5, 0.2]]], Number_of_servers=[5] ) Q = ciw.Simulation(Net) N = Q.transitive_nodes[0] self.assertEqual(N.next_event_date, float('Inf')) self.assertEqual(N.all_individuals, []) N.update_next_event_date(0.0) self.assertEqual(N.next_event_date, float('Inf')) ind1 = ciw.Individual(1) ind1.arrival_date = 0.3 N.next_event_date = 0.3 N.accept(ind1, 0.3) N.update_next_event_date(N.next_event_date) self.assertEqual(N.next_event_date, 0.8) ind2 = ciw.Individual(2) ind2.arrival_date = 0.4 N.accept(ind2, 0.4) N.update_next_event_date(N.next_event_date + 0.000001) self.assertEqual(round(N.next_event_date, 4), 0.6) N.finish_service() N.update_next_event_date(N.next_event_date) self.assertEqual(N.next_event_date, 0.8) N.finish_service() N.update_next_event_date(N.next_event_date) self.assertEqual(N.next_event_date, float('Inf'))
def test_simulate_until_deadlock_method(self): ciw.seed(3) Q = ciw.Simulation(ciw.create_network( 'ciw/tests/testing_parameters/params_deadlock.yml'), deadlock_detector='StateDigraph') Q.simulate_until_deadlock() self.assertEqual(round(Q.times_to_deadlock[((0, 0), (0, 0))], 8), 23.92401469)
def test_matrix_change_state_block_method(self): Q = ciw.Simulation(ciw.create_network( 'ciw/tests/testing_parameters/params.yml')) B = ciw.MatrixTracker(Q) B.state = [[[[], [], [], []], [[], [], [], []], [[], [], [], []], [[], [], [], []]], [2, 3, 1, 0]] B.change_state_block(1, 3, 2) self.assertEqual(B.state, [[[[], [], [1], []], [[], [], [], []], [[], [], [], []], [[], [], [], []]], [2, 3, 1, 0]]) B.change_state_block(2, 1, 0) self.assertEqual(B.state, [[[[], [], [1], []], [[2], [], [], []], [[], [], [], []], [[], [], [], []]], [2, 3, 1, 0]]) B.change_state_block(1, 3, 0) self.assertEqual(B.state, [[[[], [], [1, 3], []], [[2], [], [], []], [[], [], [], []], [[], [], [], []]], [2, 3, 1, 0]])
def test_base_change_state_release_method(self): Q = ciw.Simulation(ciw.create_network( 'ciw/tests/testing_parameters/params.yml')) B = ciw.StateTracker(Q) self.assertEqual(B.state, None) B.change_state_release(1, 1, 1, True) self.assertEqual(B.state, None)
def test_naive_change_state_block_method(self): Q = ciw.Simulation(ciw.create_network( 'ciw/tests/testing_parameters/params.yml')) B = ciw.NaiveTracker(Q) B.state = [[1, 0], [0, 0], [0, 0], [0, 0]] B.change_state_block(1, 1, 2) self.assertEqual(B.state, [[0, 1], [0, 0], [0, 0], [0, 0]])
def test_priority_system_compare_literature(self): params_dict = { 'Arrival_distributions': {'Class 0': [['Exponential', 0.2]], 'Class 1': [['Exponential', 0.6]]}, 'Service_distributions': {'Class 0': [['Exponential', 1.0]], 'Class 1': [['Exponential', 1.0]]}, 'Transition_matrices': {'Class 0': [[0.0]], 'Class 1': [[0.0]]}, 'Number_of_servers': [1], 'Priority_classes': {'Class 0': 0, 'Class 1': 1} } # Results expected from analytical queueing theory are: # expected_throughput_class0 = 2.0, and expected_throughput_class1 = 6.0 # Althought these results seem far from the theoretical, longer runs and # more runs give the desired results. A compromise was reached here to # reduce test suite runtime. throughput_class0 = [] throughput_class1 = [] ciw.seed(3231) for iteration in range(80): Q = ciw.Simulation(ciw.create_network(params_dict)) Q.simulate_until_max_time(400) recs = Q.get_all_records() throughput_class0.append(mean([r.waiting_time + r.service_time for r in recs if r.customer_class==0 if r.arrival_date > 100])) throughput_class1.append(mean([r.waiting_time + r.service_time for r in recs if r.customer_class==1 if r.arrival_date > 100])) self.assertEqual(round(mean(throughput_class0), 5), 1.94852) self.assertEqual(round(mean(throughput_class1), 5), 5.92823)
def test_sampling_sequential_dist_hypothesis(self, dist1, dist2): my_sequential_dist_1 = dist1 my_sequential_dist_2 = dist2 params = { 'Arrival_distributions': [['Sequential', my_sequential_dist_1]], 'Service_distributions': [['Sequential', my_sequential_dist_2]], 'Number_of_servers': [1], 'Transition_matrices': [[0.1]] } Q = ciw.Simulation(ciw.create_network(**params)) Nw = Q.transitive_nodes[0] len1 = len(my_sequential_dist_1) len2 = len(my_sequential_dist_2) expected_inter_arrival_times = 3 * my_sequential_dist_1 + my_sequential_dist_1[: 1] expected_service_times = 3 * my_sequential_dist_2 inter_arrivals = [ Nw.simulation.inter_arrival_times[Nw.id_number][0]() for _ in range(3 * len1) ] services = [ Nw.simulation.service_times[Nw.id_number][0]() for _ in range(3 * len2) ] self.assertEqual(inter_arrivals, expected_inter_arrival_times[1:]) self.assertEqual(services, expected_service_times)
def test_release_method(self): ciw.seed(4) Q = ciw.Simulation( ciw.create_network('ciw/tests/testing_parameters/params.yml')) N = Q.transitive_nodes[0] inds = [ciw.Individual(i + 1) for i in range(3)] for current_time in [0.01, 0.02, 0.03]: N.accept(inds[int(current_time * 100 - 1)], current_time) self.assertEqual([str(obs) for obs in N.all_individuals], ['Individual 1', 'Individual 2', 'Individual 3']) self.assertEqual([[str(obs) for obs in pr_cls] for pr_cls in N.individuals], [['Individual 1', 'Individual 2', 'Individual 3']]) N.update_next_event_date(0.03) self.assertEqual(round(N.next_event_date, 5), 0.03604) N.all_individuals[1].exit_date = 0.04 N.update_next_event_date(N.next_event_date + 0.00001) self.assertEqual(round(N.next_event_date, 5), 0.03708) N.release(1, Q.transitive_nodes[1], N.next_event_date) self.assertEqual([str(obs) for obs in N.all_individuals], ['Individual 1', 'Individual 3']) self.assertEqual([[str(obs) for obs in pr_cls] for pr_cls in N.individuals], [['Individual 1', 'Individual 3']]) N.update_next_event_date(N.next_event_date + 0.00001) self.assertEqual(round(N.next_event_date, 5), 0.06447)
def test_sampling_deterministic_dist(self): params = { 'Arrival_distributions': [['Deterministic', 4.4]], 'Service_distributions': [['Deterministic', 4.4]], 'Number_of_servers': [1] } Q = ciw.Simulation(ciw.create_network(**params)) Nd = Q.transitive_nodes[0] ciw.seed(5) self.assertEqual( round(Nd.simulation.service_times[Nd.id_number][0](), 2), 4.40) self.assertEqual( round(Nd.simulation.service_times[Nd.id_number][0](), 2), 4.40) self.assertEqual( round(Nd.simulation.service_times[Nd.id_number][0](), 2), 4.40) self.assertEqual( round(Nd.simulation.service_times[Nd.id_number][0](), 2), 4.40) self.assertEqual( round(Nd.simulation.service_times[Nd.id_number][0](), 2), 4.40) self.assertEqual( round(Nd.simulation.inter_arrival_times[Nd.id_number][0](), 2), 4.40) self.assertEqual( round(Nd.simulation.inter_arrival_times[Nd.id_number][0](), 2), 4.40) self.assertEqual( round(Nd.simulation.inter_arrival_times[Nd.id_number][0](), 2), 4.40) self.assertEqual( round(Nd.simulation.inter_arrival_times[Nd.id_number][0](), 2), 4.40) self.assertEqual( round(Nd.simulation.inter_arrival_times[Nd.id_number][0](), 2), 4.40)
def test_repr_method(self): Q = ciw.Simulation( ciw.create_network('ciw/tests/testing_parameters/params.yml')) N1 = ciw.Node(1, Q) N2 = ciw.Node(2, Q) self.assertEqual(str(N1), 'Node 1') self.assertEqual(str(N2), 'Node 2')
def test_sampling_triangular_dist(self): params = { 'Arrival_distributions': [['Triangular', 1.1, 6.6, 1.5]], 'Service_distributions': [['Triangular', 1.1, 6.6, 1.5]], 'Number_of_servers': [1] } Q = ciw.Simulation(ciw.create_network(**params)) Nt = Q.transitive_nodes[0] ciw.seed(5) self.assertEqual( round(Nt.simulation.service_times[Nt.id_number][0](), 2), 3.35) self.assertEqual( round(Nt.simulation.service_times[Nt.id_number][0](), 2), 3.91) self.assertEqual( round(Nt.simulation.service_times[Nt.id_number][0](), 2), 4.20) self.assertEqual( round(Nt.simulation.service_times[Nt.id_number][0](), 2), 5.33) self.assertEqual( round(Nt.simulation.service_times[Nt.id_number][0](), 2), 3.90) self.assertEqual( round(Nt.simulation.inter_arrival_times[Nt.id_number][0](), 2), 5.12) self.assertEqual( round(Nt.simulation.inter_arrival_times[Nt.id_number][0](), 2), 1.35) self.assertEqual( round(Nt.simulation.inter_arrival_times[Nt.id_number][0](), 2), 2.73) self.assertEqual( round(Nt.simulation.inter_arrival_times[Nt.id_number][0](), 2), 5.34) self.assertEqual( round(Nt.simulation.inter_arrival_times[Nt.id_number][0](), 2), 3.46)
def test_setting_classes(self): class DummyNode(ciw.Node): pass class DummyArrivalNode(ciw.ArrivalNode): pass params = { 'arrival_distributions': [ciw.dists.Exponential(20)], 'service_distributions': [ciw.dists.Deterministic(0.01)], 'routing': [[0.0]], 'number_of_servers': [[[0, 0.5], [1, 0.55], [0, 3.0]]] } Q = ciw.Simulation(ciw.create_network(**params)) self.assertEqual(Q.NodeType, ciw.Node) self.assertEqual(Q.ArrivalNodeType, ciw.ArrivalNode) Q.set_classes(None, None) self.assertEqual(Q.NodeType, ciw.Node) self.assertEqual(Q.ArrivalNodeType, ciw.ArrivalNode) Q.set_classes(DummyNode, None) self.assertEqual(Q.NodeType, DummyNode) self.assertEqual(Q.ArrivalNodeType, ciw.ArrivalNode) Q.set_classes(None, DummyArrivalNode) self.assertEqual(Q.NodeType, ciw.Node) self.assertEqual(Q.ArrivalNodeType, DummyArrivalNode) Q.set_classes(DummyNode, DummyArrivalNode) self.assertEqual(Q.NodeType, DummyNode) self.assertEqual(Q.ArrivalNodeType, DummyArrivalNode)
def test_sampling_exponential_dist(self): params = { 'Arrival_distributions': [['Exponential', 4.4]], 'Service_distributions': [['Exponential', 4.4]], 'Number_of_servers': [1] } Q = ciw.Simulation(ciw.create_network(**params)) Ne = Q.transitive_nodes[0] ciw.seed(5) self.assertEqual( round(Ne.simulation.service_times[Ne.id_number][0](), 2), 0.22) self.assertEqual( round(Ne.simulation.service_times[Ne.id_number][0](), 2), 0.31) self.assertEqual( round(Ne.simulation.service_times[Ne.id_number][0](), 2), 0.36) self.assertEqual( round(Ne.simulation.service_times[Ne.id_number][0](), 2), 0.65) self.assertEqual( round(Ne.simulation.service_times[Ne.id_number][0](), 2), 0.31) self.assertEqual( round(Ne.simulation.inter_arrival_times[Ne.id_number][0](), 2), 0.58) self.assertEqual( round(Ne.simulation.inter_arrival_times[Ne.id_number][0](), 2), 0.01) self.assertEqual( round(Ne.simulation.inter_arrival_times[Ne.id_number][0](), 2), 0.14) self.assertEqual( round(Ne.simulation.inter_arrival_times[Ne.id_number][0](), 2), 0.65) self.assertEqual( round(Ne.simulation.inter_arrival_times[Ne.id_number][0](), 2), 0.24)
def Realnet_data(self): N = ciw.create_network( arrival_distributions=[ ciw.dists.Exponential(2.0), ciw.dists.NoArrivals(), ciw.dists.NoArrivals(), ciw.dists.NoArrivals(), ciw.dists.NoArrivals() ], service_distributions=[ ciw.dists.Lognormal(torch.tensor(-0.3), torch.tensor(0.1)), ciw.dists.Lognormal(torch.tensor(0.0), torch.tensor(0.5)), ciw.dists.Lognormal(torch.tensor(0.5), torch.tensor(0.1)), ciw.dists.Exponential(1.0), ciw.dists.Deterministic(0.05) ], routing=[[0.0, 0.5, 0.0, 0.5, 0.0], [0.0, 0.0, 0.7, 0.0, 0.3], [0.0, 0.0, 0.0, 0.5, 0.5], [0.2, 0.8, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0]], number_of_servers=[5, 3, 2, 2, 4], ) num = 200 training_data = [] for i in range(num): ciw.seed(i) Q = ciw.Simulation(N) Q.simulate_until_max_time(80) recs = Q.get_all_records() training_data.append(self.recs_parser(recs, 5)) return training_data
def test_sampling_gamma_dist(self): params = { 'Arrival_distributions': [['Gamma', 0.6, 1.2]], 'Service_distributions': [['Gamma', 0.6, 1.2]], 'Number_of_servers': [1] } Q = ciw.Simulation(ciw.create_network(**params)) Ng = Q.transitive_nodes[0] ciw.seed(5) self.assertEqual( round(Ng.simulation.service_times[Ng.id_number][0](), 2), 0.00) self.assertEqual( round(Ng.simulation.service_times[Ng.id_number][0](), 2), 2.59) self.assertEqual( round(Ng.simulation.service_times[Ng.id_number][0](), 2), 1.92) self.assertEqual( round(Ng.simulation.service_times[Ng.id_number][0](), 2), 0.47) self.assertEqual( round(Ng.simulation.service_times[Ng.id_number][0](), 2), 0.61) self.assertEqual( round(Ng.simulation.inter_arrival_times[Ng.id_number][0](), 2), 0.00) self.assertEqual( round(Ng.simulation.inter_arrival_times[Ng.id_number][0](), 2), 1.07) self.assertEqual( round(Ng.simulation.inter_arrival_times[Ng.id_number][0](), 2), 1.15) self.assertEqual( round(Ng.simulation.inter_arrival_times[Ng.id_number][0](), 2), 0.75) self.assertEqual( round(Ng.simulation.inter_arrival_times[Ng.id_number][0](), 2), 0.00)
def test_sampling_normal_dist(self): params = { 'Arrival_distributions': [['Normal', 0.5, 0.1]], 'Service_distributions': [['Normal', 0.5, 0.1]], 'Number_of_servers': [1], 'Transition_matrices': [[0.1]] } Q = ciw.Simulation(ciw.create_network(**params)) Nw = Q.transitive_nodes[0] ciw.seed(5) self.assertEqual(round( Nw.simulation.service_times[Nw.id_number][0](), 2), 0.58) self.assertEqual(round( Nw.simulation.service_times[Nw.id_number][0](), 2), 0.35) self.assertEqual(round( Nw.simulation.service_times[Nw.id_number][0](), 2), 0.49) self.assertEqual(round( Nw.simulation.service_times[Nw.id_number][0](), 2), 0.52) self.assertEqual(round( Nw.simulation.service_times[Nw.id_number][0](), 2), 0.55) self.assertEqual(round( Nw.simulation.inter_arrival_times[Nw.id_number][0](), 2), 0.56) self.assertEqual(round( Nw.simulation.inter_arrival_times[Nw.id_number][0](), 2), 0.52) self.assertEqual(round( Nw.simulation.inter_arrival_times[Nw.id_number][0](), 2), 0.44) self.assertEqual(round( Nw.simulation.inter_arrival_times[Nw.id_number][0](), 2), 0.52) self.assertEqual(round( Nw.simulation.inter_arrival_times[Nw.id_number][0](), 2), 0.60)
def test_sampling_uniform_dist(self): params = { 'Arrival_distributions': [['Uniform', 2.2, 3.3]], 'Service_distributions': [['Uniform', 2.2, 3.3]], 'Number_of_servers': [1] } Q = ciw.Simulation(ciw.create_network(**params)) Nu = Q.transitive_nodes[0] ciw.seed(5) self.assertEqual( round(Nu.simulation.service_times[Nu.id_number][0](), 2), 2.89) self.assertEqual( round(Nu.simulation.service_times[Nu.id_number][0](), 2), 3.02) self.assertEqual( round(Nu.simulation.service_times[Nu.id_number][0](), 2), 3.07) self.assertEqual( round(Nu.simulation.service_times[Nu.id_number][0](), 2), 3.24) self.assertEqual( round(Nu.simulation.service_times[Nu.id_number][0](), 2), 3.01) self.assertEqual( round(Nu.simulation.inter_arrival_times[Nu.id_number][0](), 2), 3.21) self.assertEqual( round(Nu.simulation.inter_arrival_times[Nu.id_number][0](), 2), 2.23) self.assertEqual( round(Nu.simulation.inter_arrival_times[Nu.id_number][0](), 2), 2.71) self.assertEqual( round(Nu.simulation.inter_arrival_times[Nu.id_number][0](), 2), 3.24) self.assertEqual( round(Nu.simulation.inter_arrival_times[Nu.id_number][0](), 2), 2.91)
def test_userdefined_function_dist_hypothesis(self, const, dist, rm): my_empirical_dist = [8.0, 8.0, 8.0, 8.8, 8.8, 12.3] params = { 'Arrival_distributions': [ ['UserDefined', lambda : choice(my_empirical_dist)], ['UserDefined', lambda : const]], 'Service_distributions': [ ['UserDefined', lambda : random()], ['UserDefined', lambda : custom_function()]], 'Number_of_servers': [1, 1], 'Transition_matrices': [[0.1, 0.1], [0.1, 0.1]] } Q = ciw.Simulation(ciw.create_network(**params)) N1 = Q.transitive_nodes[0] N2 = Q.transitive_nodes[1] ciw.seed(5) for itr in range(10): # Because repition happens in the simulation self.assertTrue( N1.simulation.inter_arrival_times[N1.id_number][0]() in set(my_empirical_dist)) self.assertTrue( N2.simulation.inter_arrival_times[N2.id_number][0]() == const) self.assertTrue( 0.0 <= N1.simulation.service_times[N1.id_number][0]() <= 1.0) self.assertTrue( 0.0 <= N2.simulation.service_times[N2.id_number][0]() <= 2.0)
def test_sampling_lognormal_dist(self): params = { 'Arrival_distributions': [['Lognormal', 0.8, 0.2]], 'Service_distributions': [['Lognormal', 0.8, 0.2]], 'Number_of_servers': [1] } Q = ciw.Simulation(ciw.create_network(**params)) Nl = Q.transitive_nodes[0] ciw.seed(5) self.assertEqual( round(Nl.simulation.service_times[Nl.id_number][0](), 2), 2.62) self.assertEqual( round(Nl.simulation.service_times[Nl.id_number][0](), 2), 1.64) self.assertEqual( round(Nl.simulation.service_times[Nl.id_number][0](), 2), 2.19) self.assertEqual( round(Nl.simulation.service_times[Nl.id_number][0](), 2), 2.31) self.assertEqual( round(Nl.simulation.service_times[Nl.id_number][0](), 2), 2.48) self.assertEqual( round(Nl.simulation.inter_arrival_times[Nl.id_number][0](), 2), 2.51) self.assertEqual( round(Nl.simulation.inter_arrival_times[Nl.id_number][0](), 2), 2.33) self.assertEqual( round(Nl.simulation.inter_arrival_times[Nl.id_number][0](), 2), 1.96) self.assertEqual( round(Nl.simulation.inter_arrival_times[Nl.id_number][0](), 2), 2.32) self.assertEqual( round(Nl.simulation.inter_arrival_times[Nl.id_number][0](), 2), 2.70)
def test_sampling_deterministic_dist(self): params = { 'Arrival_distributions': [['Deterministic', 4.4]], 'Service_distributions': [['Deterministic', 4.4]], 'Number_of_servers': [1], 'Transition_matrices': [[0.1]] } Q = ciw.Simulation(ciw.create_network(params)) Nd = Q.transitive_nodes[0] ciw.seed(5) self.assertEqual(round( Nd.simulation.service_times[Nd.id_number][0](), 2), 4.40) self.assertEqual(round( Nd.simulation.service_times[Nd.id_number][0](), 2), 4.40) self.assertEqual(round( Nd.simulation.service_times[Nd.id_number][0](), 2), 4.40) self.assertEqual(round( Nd.simulation.service_times[Nd.id_number][0](), 2), 4.40) self.assertEqual(round( Nd.simulation.service_times[Nd.id_number][0](), 2), 4.40) self.assertEqual(round( Nd.simulation.inter_arrival_times[Nd.id_number][0](), 2), 4.40) self.assertEqual(round( Nd.simulation.inter_arrival_times[Nd.id_number][0](), 2), 4.40) self.assertEqual(round( Nd.simulation.inter_arrival_times[Nd.id_number][0](), 2), 4.40) self.assertEqual(round( Nd.simulation.inter_arrival_times[Nd.id_number][0](), 2), 4.40) self.assertEqual(round( Nd.simulation.inter_arrival_times[Nd.id_number][0](), 2), 4.40)
def test_sampling_weibull_dist(self): params = { 'Arrival_distributions': [['Weibull', 0.9, 0.8]], 'Service_distributions': [['Weibull', 0.9, 0.8]], 'Number_of_servers': [1] } Q = ciw.Simulation(ciw.create_network(**params)) Nw = Q.transitive_nodes[0] ciw.seed(5) self.assertEqual( round(Nw.simulation.service_times[Nw.id_number][0](), 2), 0.87) self.assertEqual( round(Nw.simulation.service_times[Nw.id_number][0](), 2), 1.31) self.assertEqual( round(Nw.simulation.service_times[Nw.id_number][0](), 2), 1.60) self.assertEqual( round(Nw.simulation.service_times[Nw.id_number][0](), 2), 3.34) self.assertEqual( round(Nw.simulation.service_times[Nw.id_number][0](), 2), 1.31) self.assertEqual( round(Nw.simulation.inter_arrival_times[Nw.id_number][0](), 2), 2.91) self.assertEqual( round(Nw.simulation.inter_arrival_times[Nw.id_number][0](), 2), 0.01) self.assertEqual( round(Nw.simulation.inter_arrival_times[Nw.id_number][0](), 2), 0.50) self.assertEqual( round(Nw.simulation.inter_arrival_times[Nw.id_number][0](), 2), 3.36) self.assertEqual( round(Nw.simulation.inter_arrival_times[Nw.id_number][0](), 2), 0.95)
def test_sampling_uniform_dist(self): params = { 'Arrival_distributions': [['Uniform', 2.2, 3.3]], 'Service_distributions': [['Uniform', 2.2, 3.3]], 'Number_of_servers': [1], 'Transition_matrices': [[0.1]] } Q = ciw.Simulation(ciw.create_network(params)) Nu = Q.transitive_nodes[0] ciw.seed(5) self.assertEqual(round( Nu.simulation.service_times[Nu.id_number][0](), 2), 2.89) self.assertEqual(round( Nu.simulation.service_times[Nu.id_number][0](), 2), 3.02) self.assertEqual(round( Nu.simulation.service_times[Nu.id_number][0](), 2), 3.07) self.assertEqual(round( Nu.simulation.service_times[Nu.id_number][0](), 2), 3.24) self.assertEqual(round( Nu.simulation.service_times[Nu.id_number][0](), 2), 3.01) self.assertEqual(round( Nu.simulation.inter_arrival_times[Nu.id_number][0](), 2), 3.21) self.assertEqual(round( Nu.simulation.inter_arrival_times[Nu.id_number][0](), 2), 2.23) self.assertEqual(round( Nu.simulation.inter_arrival_times[Nu.id_number][0](), 2), 2.71) self.assertEqual(round( Nu.simulation.inter_arrival_times[Nu.id_number][0](), 2), 3.24) self.assertEqual(round( Nu.simulation.inter_arrival_times[Nu.id_number][0](), 2), 2.91)
def test_sampling_normal_dist(self): params = { 'Arrival_distributions': [['Normal', 0.5, 0.1]], 'Service_distributions': [['Normal', 0.5, 0.1]], 'Number_of_servers': [1], 'Transition_matrices': [[0.1]] } Q = ciw.Simulation(ciw.create_network(**params)) Nw = Q.transitive_nodes[0] ciw.seed(5) self.assertEqual( round(Nw.simulation.service_times[Nw.id_number][0](), 2), 0.58) self.assertEqual( round(Nw.simulation.service_times[Nw.id_number][0](), 2), 0.35) self.assertEqual( round(Nw.simulation.service_times[Nw.id_number][0](), 2), 0.49) self.assertEqual( round(Nw.simulation.service_times[Nw.id_number][0](), 2), 0.52) self.assertEqual( round(Nw.simulation.service_times[Nw.id_number][0](), 2), 0.55) self.assertEqual( round(Nw.simulation.inter_arrival_times[Nw.id_number][0](), 2), 0.56) self.assertEqual( round(Nw.simulation.inter_arrival_times[Nw.id_number][0](), 2), 0.52) self.assertEqual( round(Nw.simulation.inter_arrival_times[Nw.id_number][0](), 2), 0.44) self.assertEqual( round(Nw.simulation.inter_arrival_times[Nw.id_number][0](), 2), 0.52) self.assertEqual( round(Nw.simulation.inter_arrival_times[Nw.id_number][0](), 2), 0.60)
def test_sampling_gamma_dist(self): params = { 'Arrival_distributions': [['Gamma', 0.6, 1.2]], 'Service_distributions': [['Gamma', 0.6, 1.2]], 'Number_of_servers': [1], 'Transition_matrices': [[0.1]] } Q = ciw.Simulation(ciw.create_network(params)) Ng = Q.transitive_nodes[0] ciw.seed(5) self.assertEqual(round( Ng.simulation.service_times[Ng.id_number][0](), 2), 0.00) self.assertEqual(round( Ng.simulation.service_times[Ng.id_number][0](), 2), 2.59) self.assertEqual(round( Ng.simulation.service_times[Ng.id_number][0](), 2), 1.92) self.assertEqual(round( Ng.simulation.service_times[Ng.id_number][0](), 2), 0.47) self.assertEqual(round( Ng.simulation.service_times[Ng.id_number][0](), 2), 0.61) self.assertEqual(round( Ng.simulation.inter_arrival_times[Ng.id_number][0](), 2), 0.00) self.assertEqual(round( Ng.simulation.inter_arrival_times[Ng.id_number][0](), 2), 1.07) self.assertEqual(round( Ng.simulation.inter_arrival_times[Ng.id_number][0](), 2), 1.15) self.assertEqual(round( Ng.simulation.inter_arrival_times[Ng.id_number][0](), 2), 0.75) self.assertEqual(round( Ng.simulation.inter_arrival_times[Ng.id_number][0](), 2), 0.00)
def test_userdefined_function_dist_hypothesis(self, const, dist, rm): my_empirical_dist = [8.0, 8.0, 8.0, 8.8, 8.8, 12.3] params = { 'Arrival_distributions': [['UserDefined', lambda: choice(my_empirical_dist)], ['UserDefined', lambda: const]], 'Service_distributions': [['UserDefined', lambda: random()], ['UserDefined', lambda: custom_function()]], 'Number_of_servers': [1, 1], 'Transition_matrices': [[0.1, 0.1], [0.1, 0.1]] } Q = ciw.Simulation(ciw.create_network(**params)) N1 = Q.transitive_nodes[0] N2 = Q.transitive_nodes[1] ciw.seed(5) for itr in range(10): # Because repition happens in the simulation self.assertTrue(N1.simulation.inter_arrival_times[N1.id_number][0] () in set(my_empirical_dist)) self.assertTrue( N2.simulation.inter_arrival_times[N2.id_number][0]() == const) self.assertTrue( 0.0 <= N1.simulation.service_times[N1.id_number][0]() <= 1.0) self.assertTrue( 0.0 <= N2.simulation.service_times[N2.id_number][0]() <= 2.0)
def test_sampling_weibull_dist(self): params = { 'Arrival_distributions': [['Weibull', 0.9, 0.8]], 'Service_distributions': [['Weibull', 0.9, 0.8]], 'Number_of_servers': [1], 'Transition_matrices': [[0.1]] } Q = ciw.Simulation(ciw.create_network(params)) Nw = Q.transitive_nodes[0] ciw.seed(5) self.assertEqual(round( Nw.simulation.service_times[Nw.id_number][0](), 2), 0.87) self.assertEqual(round( Nw.simulation.service_times[Nw.id_number][0](), 2), 1.31) self.assertEqual(round( Nw.simulation.service_times[Nw.id_number][0](), 2), 1.60) self.assertEqual(round( Nw.simulation.service_times[Nw.id_number][0](), 2), 3.34) self.assertEqual(round( Nw.simulation.service_times[Nw.id_number][0](), 2), 1.31) self.assertEqual(round( Nw.simulation.inter_arrival_times[Nw.id_number][0](), 2), 2.91) self.assertEqual(round( Nw.simulation.inter_arrival_times[Nw.id_number][0](), 2), 0.01) self.assertEqual(round( Nw.simulation.inter_arrival_times[Nw.id_number][0](), 2), 0.50) self.assertEqual(round( Nw.simulation.inter_arrival_times[Nw.id_number][0](), 2), 3.36) self.assertEqual(round( Nw.simulation.inter_arrival_times[Nw.id_number][0](), 2), 0.95)
def test_timedependent_exact(self): params = { 'Arrival_distributions': [['TimeDependent', time_dependent_function_1], ['TimeDependent', time_dependent_function_2]], 'Service_distributions': [['TimeDependent', time_dependent_function_1], ['TimeDependent', time_dependent_function_2]], 'Number_of_servers': [1, 1], 'Transition_matrices': [[0.1, 0.1], [0.1, 0.1]] } Q = ciw.Simulation(ciw.create_network(**params), exact=26) N1 = Q.transitive_nodes[0] N2 = Q.transitive_nodes[1] ciw.seed(5) self.assertEqual(N1.get_service_time(0, 3.0), 3.0) self.assertEqual(N1.get_service_time(0, 9.0), 3.0) self.assertEqual(N1.get_service_time(0, 9.0), 3.0) self.assertEqual(N1.get_service_time(0, 11.0), 5.0) self.assertEqual(N1.get_service_time(0, 11.0), 5.0) self.assertEqual(N2.get_service_time(0, 4.0), 2.0) self.assertEqual(N2.get_service_time(0, 4.0), 2.0) self.assertEqual(N2.get_service_time(0, 17.0), 8.5) self.assertEqual(N2.get_service_time(0, 22.0), 8.0) self.assertEqual(N2.get_service_time(0, 22.0), 8.0)
def test_sampling_custom_dist(self): my_custom_dist = [[0.2, 3.7], [0.5, 3.8], [0.3, 4.1]] params = { 'Arrival_distributions': [['Custom', my_custom_dist]], 'Service_distributions': [['Custom', my_custom_dist]], 'Number_of_servers': [1], 'Transition_matrices': [[0.1]] } Q = ciw.Simulation(ciw.create_network(params)) Nc = Q.transitive_nodes[0] ciw.seed(5) self.assertEqual(round( Nc.simulation.service_times[Nc.id_number][0](), 2), 3.8) self.assertEqual(round( Nc.simulation.service_times[Nc.id_number][0](), 2), 4.1) self.assertEqual(round( Nc.simulation.service_times[Nc.id_number][0](), 2), 3.8) self.assertEqual(round( Nc.simulation.service_times[Nc.id_number][0](), 2), 4.1) self.assertEqual(round( Nc.simulation.service_times[Nc.id_number][0](), 2), 3.8) self.assertEqual(round( Nc.simulation.inter_arrival_times[Nc.id_number][0](), 2), 3.8) self.assertEqual(round( Nc.simulation.inter_arrival_times[Nc.id_number][0](), 2), 4.1) self.assertEqual(round( Nc.simulation.inter_arrival_times[Nc.id_number][0](), 2), 3.8) self.assertEqual(round( Nc.simulation.inter_arrival_times[Nc.id_number][0](), 2), 3.8) self.assertEqual(round( Nc.simulation.inter_arrival_times[Nc.id_number][0](), 2), 3.7)
def test_state_dependent_distribution(self): N = ciw.create_network( arrival_distributions=[ciw.dists.Exponential(4)], service_distributions=[StateDependent()], number_of_servers=[1]) ciw.seed(0) Q = ciw.Simulation(N) Q.simulate_until_max_time(500) recs = Q.get_all_records() # Only samples 0.2, 0.15, 0.1, 0.05, or 0.0 services = [ round(r.service_time, 7) for r in recs if r.arrival_date > 100 ] self.assertLessEqual(set(services), {0.2, 0.15, 0.1, 0.05, 0.0}) # Check average service time correct transformation of average queue size queue_sizes = [ r.queue_size_at_arrival for r in recs if r.arrival_date > 100 ] + [r.queue_size_at_departure for r in recs if r.arrival_date > 100] average_queue_size = sum(queue_sizes) / len(queue_sizes) self.assertEqual(round(average_queue_size, 7), 0.9051833) self.assertEqual(round((-0.05 * average_queue_size) + 0.2, 7), 0.1547408) self.assertEqual(round(sum(services) / len(services), 7), 0.1549305)