def test_calc_start_finish_time(self): """ Given a 'randomly' generated Solution, ensure that we calculate the correct start and finish times for the random allocation. Test 1: Duplicates `test_generate_exec_orders` to confirm RNG returns the same values for the same function parameters. Test 2: Initial conditions, where there are no allocations already in the solution Returns ------- Pass/Fail """ # Test 1 top_sort = generate_exec_orders(self.wf, popsize=4, rng=self.rng, skip_limit=1) curr = next(top_sort) self.assertListEqual([x.tid for x in curr], [0, 5, 4, 3, 2, 6, 1, 8, 7, 9]) machine = 0 solution = GASolution ast, aft = calc_start_finish_times(curr[0], 0, self.wf, solution)
def test_generate_allocations(self): # Generate allocations creates pairs. Solution is implied in allocation? top_sort = generate_exec_orders(self.wf, popsize=4, seed=self.SEED, skip_limit=1) curr = next(top_sort) machines = list(self.wf.env.machines.keys()) # Solution should contain allocations between tasks and machines soln = generate_allocations(machines, curr, self.wf, self.SEED) # Test seed is 10; RANDBOUNDS is 1000 # first should be 0,0,1,2,0 # For each Task in soln, we will have an allocation # e.g. tid=0, m='cat0_m0'. # If we go through each machine, and each task, the order should be ################## cat0_m1 |cat1_m1 | cat2_m2 # task_alloc_order = [0, 1, 4, 5, 2, 6, 8, 3, 7, 9] # task_alloc_order = [0, 5, 4, 1, 2, 8, 3, 7, 9] alloc_sets = [ {0, 5, 2, 6}, {4, 1, 7}, {3, 8, 9}, ] i = 0 for machine in machines: x = len(alloc_sets[i] & set(soln.list_machine_allocations(machine))) self.assertEqual(x, 0) # The difference between the sets should be 0 self.assertEqual(soln.makespan, 107) self.assertAlmostEqual(soln.solution_cost, 110.6, delta=0.01) return 0
def test_generate_allocations(self): """ After generating an execution order, we need to allocate tasks to machines whilst maintaining precedence constraints. Test 1: Duplicates `test_generate_exec_orders` Test2: Generate a list of allocations, and creates a set from this list of IDs. This compare to a list of sets; the difference between each set (which represents task-machin pairings) should be 0. Returns ------- """ top_sort = generate_exec_orders(self.wf, popsize=4, rng=self.rng, skip_limit=1) curr = next(top_sort) self.assertListEqual([x.tid for x in curr], [0, 5, 4, 3, 2, 6, 1, 8, 7, 9]) machines = list(self.wf.env.machines) # Solution should contain allocations between tasks and machines soln = generate_allocations(machines, curr, self.wf, self.rng) # first should be 0,0,1,2,0 # For each Task in soln, we will have an allocation # e.g. tid=0, m='cat0_m0'. # If we go through each machine, and each task, the order should be ################## cat0_m1 |cat1_m1 | cat2_m2 # task_alloc_order = [0, 1, 4, 5, 2, 6, 8, 3, 7, 9] # task_alloc_order = [0, 5, 4, 1, 2, 8, 3, 7, 9] alloc_sets = [ {0, 5, 4, 8, 7}, {6, 9}, {3, 2, 1}, ] i = 0 for machine in machines: x = len(alloc_sets[i] & set(soln.list_machine_allocations(machine))) self.assertEqual(x, 0) self.assertEqual(soln.makespan, 107)
def test_generate_exec_orders(self): """ Expected results from creating a topological sort of `self.wf` for a given population size. The `skip_limit` in this example is 1, which means that if we were to generate a population of execution orders, we would go through all topological sorts without skipping any. Population size: 4 Skip limit - 1 rng = default_rng(40) (This is specified in setUp). With `skip_limit=1`, the first top_sort created will be: [0, 5, 4, 3, 2, 6, 1, 8, 7, 9] Test 1: Check to make sure the expected topological sort generated is the one we get from `generate_exec_orders` Test 2: Check that the next topological sort is different - that is, we are not generating the same TopSort over and over again. Returns ------- Pass/Fail """ # Test 1 top_sort = generate_exec_orders(self.wf, popsize=4, rng=self.rng, skip_limit=1) order = [0, 5, 4, 3, 2, 6, 1, 8, 7, 9] curr = next(top_sort) sum = 0 for i in range(len(order)): if curr[i].tid != order[i]: sum += 1 self.assertEqual(sum, 0) # Test 2 curr = next(top_sort) for i in range(len(order)): if curr[i].tid != order[i]: sum += 1 self.assertGreater(sum, 0)
def test_pop_gen(self): top_sort = generate_exec_orders(self.wf, popsize=4, seed=self.SEED, skip_limit=1) curr_sort = next(top_sort) machines = list(self.wf.env.machines.keys()) # Solution should contain allocations between tasks and machines soln = generate_allocations(machines, self.wf.tasks, self.SEED) retval = calc_start_finish_times(soln, curr_sort) alloc = soln['cat0_m0'][1] # This should be task 5 self.assertEqual(alloc.tid, 5) self.assertEqual(alloc.ast, 17) self.assertEqual(alloc.aft, 41) alloc = soln['cat1_m1'][0] # this should be task 6 self.assertEqual(alloc.tid, 2) self.assertEqual(alloc.ast, 29) self.assertEqual(alloc.aft, 45)
def test_generate_exec_orders(self): # Calling generate_exec_orders with a population of 1 should return a simple top sort top_sort = generate_exec_orders(self.wf, popsize=4, seed=self.SEED, skip_limit=1) # The result of running the above with self.SEED = 10, no skips is: # The first should always be 'order' order = [0, 5, 4, 3, 2, 6, 1, 8, 7, 9] curr = next(top_sort) # Check that a comparison between top_sort and the correct order is correct sum = 0 for i in range(len(order)): if curr[i].tid != order[i]: sum += 1 self.assertEqual(sum, 0) curr = next(top_sort) for i in range(len(order)): if curr[i].tid != order[i]: sum += 1 self.assertGreater(sum, 0)