Multiple methods for rectify, merge of mapping. TODO: rectify loop
This commit is contained in:
parent
8ed9d800c3
commit
85e61f91fb
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in a new issue