Multiple methods for rectify, merge of mapping. TODO: rectify loop

This commit is contained in:
Maximilian Schlosser 2017-07-09 18:57:52 +02:00
parent 8ed9d800c3
commit 85e61f91fb
2 changed files with 82 additions and 30 deletions

View file

@ -4,70 +4,122 @@ import random
def pull_fwd(solution): 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 a random task forward. If the task directly in front is part
of the same job, pull that instead. The first task can never of the same job, pull that instead. The first task can never
be pulled forward. Will not rectify solutions. be pulled forward. Will not rectify solutions.
Returns the modified solution and the tasks index. Returns the modified solution and the tasks index.
""" """
old_idx = random.randint(1, len(solution)-1) old_idx = random.randint(1, len(solution)-1)
while(solution[old_idx][1][0] == solution[old_idx-1][1][0]): while(solution[old_idx][1][0] == solution[old_idx-1][1][0]):
old_idx -= 1 old_idx -= 1
new_idx = random.randint(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]): if(task[1][0] == solution[old_idx][1][0]):
break break
else: else:
new_solution = solution[:]
task = solution[old_idx] task = solution[old_idx]
new_solution.remove(task) solution.remove(task)
new_solution.insert(new_idx, task) solution.insert(new_idx, task)
return (new_solution, new_idx) return (solution, new_idx)
def accept(solution): 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 Maybe skip this during the first step to generate a more
random solution. random solution.
""" """
return 3 return 3
#TODO: Loop over successors
def rectify(solution, idx): 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. tasks on the same machine if affected.
""" """
solution[idx][0] = solution[idx+1][0]
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.
"""
global problem global problem
task = solution[idx]
#move previous task on the same machine back if clash machine = ( x for x in solution[idx-1::-1] if problem[x[1]][1] == problem[task[1]][1] )
""" task = solution[idx][1] prev_mach = next(machine, None)
prev_task = solution[idx-1][1] job = ( x for x in solution[idx-1::-1] if task[1][0] == x[1][0] )
while(problem[task[0]][task[1]][1] == problem[prev_task[0]][prev_task[1]][1]): prev_job = next( job, None)
solution[idx-1][0] += problem[task[0]][task[1]][0] end_mach = 0
solution[idx], solution[idx-1] = solution[idx-1], solution[idx] end_job = 0
idx -= 1 if prev_mach:
task = solution[idx][1] end_mach = problem[prev_mach[1]][0] + prev_mach[0]
prev_task = solution[idx-1][1] if prev_job:
del prev_task end_job = problem[prev_job[1]][0] + prev_job[0]
""" solution[idx][0] = max(end_mach, end_job, task[0])
#make parallel
solution[idx][0] = solution[idx-1][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): 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. specified number of max steps.
""" """
solution = solution[:]
options = [pull_fwd, accept] options = [pull_fwd, accept]
option = random.choice(options) option = random.choice(options)
return option(solution) return option(solution)
def mock(): 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. solution. Should clean up the namespace afterwards.
""" """
global problem global problem
global solution global solution
from Parser.js2_style import parse_file as mockload from Parser.js2_style import parse_file as mockload

View file

@ -1,7 +1,7 @@
from Parser import JobShopProblem as Problem from Parser import JobShopProblem as Problem
def enumerate(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 begin = 0
solution = [] solution = []
for task in schedule: for task in schedule: