Reputation: 175
I have the following algorithm:
I have a graph and a related I have a topological sorting (In graph theory, "a topological sort or topological ordering of a directed graph is a linear ordering of its vertices such that for every directed edge uv from vertex u to vertex v, u comes before v in the ordering. ").
Given a start_position
and an end_position
(different from the start_one), I want to verify if shifting the element of the list that is at start_position
to the end_position
preserves the topological order, i.e, if after the shifting I still have a topological order.
There are two cases : left_shift (if start_position
> end_position
) and right_shift (otherwise).
Here is my attempt:
def is_insert_ok(from_position:int, to_position:int, task_list:List[str], instance:pb.Problem):
# Problem has an attribute of all the tasks.
# it's a dictionnary whose keys are str and values are task objects
if from_position < to_position :
# right_shift
for task_temp in task_list[from_position+1:to_position+1]:
if task_list[from_position] in instance.all_tasks[task_temp].predecessors.keys():
return False
return True
if to_position < from_position :
# left shift
for task_temp in task_list[to_position:from_position]:
if task_temp in instance.all_tasks[task_list[from_position]].predecessors.keys():
return False
return True
What's wrong with that code? Well. Here is the thing, if I have some list and I want to compute
every possible shift for each element of the list, like in the function below:
def compute_neighbors(instance:pb.Problem, schedule:sl.Solution):
first_non_dummy_position = len(instance.orders) #there is some elements to ignore at the begining of the list because they can't be shifted
current_schedule = schedule
neighbors_list = []
task_list = current_schedule.activity_list.copy()
for first_task in task_list[first_non_dummy_position:]:
from_position = task_list.index(first_task)
for second_task in task_list[first_non_dummy_position:]:
task_list = current_schedule.activity_list.copy()
to_position = task_list.index(second_task)
if to_position != from_position:
if is_insert_ok(from_position,to_position, task_list, instance):
insert(from_position, to_position, task_list, instance) #see below the function insert
if task_list not in neighbors_list:
neighbors_list.append(task_list)
def insert(from_position:int, to_position:int, task_list:List[str], instance:pb.Problem):
element_to_insert = task_list.pop(from_position)
task_list.insert(to_position, element_to_insert)
When I have a list of length 2000, it took an eternity. Any ideas on how to make it faster?
I will welcome any attempt. Feel free to ask me if you don't understand something in my code.
Upvotes: 0
Views: 97
Reputation: 6103
if task_list not in neighbors_list
this is going to be expensive. The only case when you get duplicities is move right and move left by 1 position. Just skip one of these two cases.you should rearrange the program not to do the same things again and again and do only what you need.
Upvotes: 1