Multiple methods for rectify, merge of mapping. TODO: rectify loop
This commit is contained in:
parent
8ed9d800c3
commit
85e61f91fb
|
@ -4,7 +4,8 @@ import random
|
|||
|
||||
|
||||
def pull_fwd(solution):
|
||||
""" Pull a task from a pseudo-random position to the position of
|
||||
"""
|
||||
Pull a task from a pseudo-random position to the position of
|
||||
a random task forward. If the task directly in front is part
|
||||
of the same job, pull that instead. The first task can never
|
||||
be pulled forward. Will not rectify solutions.
|
||||
|
@ -15,57 +16,108 @@ def pull_fwd(solution):
|
|||
while(solution[old_idx][1][0] == solution[old_idx-1][1][0]):
|
||||
old_idx -= 1
|
||||
new_idx = random.randint(0, old_idx-1)
|
||||
for task in solution[new:old_idx]:
|
||||
for task in solution[new_idx:old_idx]:
|
||||
if(task[1][0] == solution[old_idx][1][0]):
|
||||
break
|
||||
else:
|
||||
new_solution = solution[:]
|
||||
task = solution[old_idx]
|
||||
new_solution.remove(task)
|
||||
new_solution.insert(new_idx, task)
|
||||
return (new_solution, new_idx)
|
||||
solution.remove(task)
|
||||
solution.insert(new_idx, task)
|
||||
return (solution, new_idx)
|
||||
|
||||
|
||||
def accept(solution):
|
||||
""" Accept the current generated solution and evaluate it.
|
||||
"""
|
||||
Accept the current generated solution and evaluate it.
|
||||
Maybe skip this during the first step to generate a more
|
||||
random solution.
|
||||
"""
|
||||
return 3
|
||||
|
||||
|
||||
#TODO: Loop over successors
|
||||
def rectify(solution, idx):
|
||||
""" Transform solution by adapting the begin times and delaying
|
||||
"""
|
||||
Transform solution by adapting the begin times and delaying
|
||||
tasks on the same machine if affected.
|
||||
"""
|
||||
global problem
|
||||
solution[idx][0] = solution[idx+1][0]
|
||||
|
||||
#move previous task on the same machine back if clash
|
||||
""" task = solution[idx][1]
|
||||
prev_task = solution[idx-1][1]
|
||||
while(problem[task[0]][task[1]][1] == problem[prev_task[0]][prev_task[1]][1]):
|
||||
solution[idx-1][0] += problem[task[0]][task[1]][0]
|
||||
solution[idx], solution[idx-1] = solution[idx-1], solution[idx]
|
||||
idx -= 1
|
||||
task = solution[idx][1]
|
||||
prev_task = solution[idx-1][1]
|
||||
del prev_task
|
||||
update_begin(solution, idx)
|
||||
correct_indices(solution, idx)
|
||||
for task in solution[idx:]:
|
||||
correct_machine(solution, solution.index(task))
|
||||
correct_precedence(solution, solution.index(task))
|
||||
|
||||
def update_begin(solution, idx):
|
||||
"""
|
||||
Update the start time of the given task.
|
||||
"""
|
||||
#make parallel
|
||||
solution[idx][0] = solution[idx-1][0]
|
||||
|
||||
global problem
|
||||
task = solution[idx]
|
||||
|
||||
machine = ( x for x in solution[idx-1::-1] if problem[x[1]][1] == problem[task[1]][1] )
|
||||
prev_mach = next(machine, None)
|
||||
job = ( x for x in solution[idx-1::-1] if task[1][0] == x[1][0] )
|
||||
prev_job = next( job, None)
|
||||
end_mach = 0
|
||||
end_job = 0
|
||||
if prev_mach:
|
||||
end_mach = problem[prev_mach[1]][0] + prev_mach[0]
|
||||
if prev_job:
|
||||
end_job = problem[prev_job[1]][0] + prev_job[0]
|
||||
solution[idx][0] = max(end_mach, end_job, task[0])
|
||||
|
||||
|
||||
def correct_indices(solution, idx):
|
||||
"""
|
||||
Adapt solution to reestablish ascending order of execution times.
|
||||
"""
|
||||
task = solution[idx]
|
||||
tasks = [ x for x in solution[idx:] if x[0] < task[0]]
|
||||
if tasks:
|
||||
solution.remove(task)
|
||||
solution.insert(idx + len(tasks), task)
|
||||
|
||||
def correct_machine(solution, idx):
|
||||
"""
|
||||
Push jobs on machines back if conflicts exist.
|
||||
"""
|
||||
task = solution[idx]
|
||||
end = problem[task[1]][0] + task[0]
|
||||
possible_conf = ( x for x in solution[idx+1:] if problem[x[1]][1] == problem[task[1]][1])
|
||||
conflict = next(( x for x in possible_conf if x[0] < end ), None)
|
||||
if(conflict):
|
||||
idx = solution.index(conflict)
|
||||
solution[idx][0] = end
|
||||
|
||||
|
||||
def correct_precedence(solution, idx):
|
||||
"""
|
||||
Check precedence relation and correct if needed.
|
||||
"""
|
||||
task = solution[idx]
|
||||
end = problem[task[1][0] + task[0]
|
||||
possible_conf = ( x for x in solution[idx+1:] if x[1][0] == task[1][0] )
|
||||
conflict = next(( x for x in possible_conf if x[0] < end ), None)
|
||||
if(conflict):
|
||||
idx = solution.index(conflict)
|
||||
solution[idx][0] = end
|
||||
|
||||
def generate(solution, steps):
|
||||
"""Generate a new solution from an existing solution with a
|
||||
"""
|
||||
Generate a new solution from an existing solution with a
|
||||
specified number of max steps.
|
||||
"""
|
||||
solution = solution[:]
|
||||
options = [pull_fwd, accept]
|
||||
option = random.choice(options)
|
||||
return option(solution)
|
||||
|
||||
|
||||
def mock():
|
||||
""" Reads a mock problem and creates the corresponding enumerated
|
||||
"""
|
||||
Reads a mock problem and creates the corresponding enumerated
|
||||
solution. Should clean up the namespace afterwards.
|
||||
"""
|
||||
global problem
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
from Parser import JobShopProblem as Problem
|
||||
|
||||
def enumerate(problem):
|
||||
schedule = ( (job, task) for job in range(0, problem.jobs) for task in range(0, len(problem[job])) )
|
||||
schedule = ( (job, task) for job in range(0, problem.jobs) for task in range(0, problem.get_tasks_by_job(job)) )
|
||||
begin = 0
|
||||
solution = []
|
||||
for task in schedule:
|
||||
|
|
Loading…
Reference in a new issue