递归调度算法无法正确运行Python

时间:2018-10-30 22:50:29

标签: python arrays algorithm recursion scheduling

我创建了一个递归调度算法,该算法采用一个Event对象数组,这些对象包含一个开始时间和一个结束时间。这些时间是随机生成的,开始时间始终小于结束时间。时间是0-24之间的数字(一天24小时,24 == 0)

这是随机事件数组生成器的代码:

def randomEventArray(s):
    e = []
    rand1 = 0
    rand2 = 0
    for i in range(s):
        rand1 = random.randint(0,21)
        rand2 = random.randint(rand1+1,23)
        e.append(Event(rand1,rand2))
    return e

这是事件对象的代码:

class Event:
    def __init__(self, start, end):
        self.startTime = start
        self.endTime = end
    def __repr__(self):
        return str(self)
    def __str__(self):
        return (str([self.startTime,self.endTime]))

现在是引起问题的部分。我创建了一段代码,该代码递归地处理了生成的事件数组,并列出了可以在24小时内举行的最多事件。任何事件都不应重叠。

这是创建的递归贪婪算法:

def scheduleGD2(E):
    events = []
    scheduleRecGD2(E,0,0, events)

    return events[:]

def scheduleRecGD2(E, eventPos, startTime,events):

    while eventPos < len(E) and E[eventPos].startTime < startTime:

        eventPos += 1
    if eventPos == len(E):
        return []
    minEndPos = eventPos
    for i in range(eventPos+1, len(E)):
        if E[i].endTime < E[minEndPos].endTime:
            minEndPos = i
    events.append(E[minEndPos])
    return scheduleRecGD2(E, minEndPos+1, E[minEndPos].endTime, events)

E = randomEventArray(20)
print(scheduleGD2(E))

此算法的预期输出是具有最多事件的数组,这些事件可以在单个24小时内同时发生而不会发生重叠。例如

[[0, 1], [1, 3], [4, 8], [9, 17], [17, 24]]

但是,我收到以下输出:

[[0, 1], [12, 16], [12, 16], [5, 17], [21, 22]]

这清楚地表明Arr [2]与Arr [1](A​​rr [2] .StartTime(12)

出什么问题了,为什么会这样?

1 个答案:

答案 0 :(得分:1)

我检测了您的代码以进行调试,包括用简单的对元组替换“事件”包。

def scheduleRecGD2(E, eventPos, startTime, events):
    print("ENTER Rec", "eventPos", eventPos, "\tstartTime", startTime, "\n\tevents", events)

    while eventPos < len(E) and E[eventPos][0] < startTime:
        eventPos += 1

    if eventPos == len(E):
        return []

    minEndPos = eventPos
    print("\tFIRST: minEndPos", minEndPos, E[minEndPos])

    for i in range(eventPos+1, len(E)):
        if E[i][1] < E[minEndPos][1]:
            minEndPos = i 

    events.append(E[minEndPos])
    print("\tTRACE: minEndPos", minEndPos, E[minEndPos])

    return scheduleRecGD2(E, minEndPos+1, E[minEndPos][1], events)

# Main program
E = randomEventArray(8)
print(E)
print(scheduleGD2(E)) 

输出:

[(15, 20), (4, 7), (17, 20), (18, 23), (2, 7), (8, 23), (15, 23), (18, 20)]
ENTER Rec eventPos 0    startTime 0 
    events []
    FIRST: minEndPos 0 (15, 20)
    TRACE: minEndPos 1 (4, 7)
ENTER Rec eventPos 2    startTime 7 
    events [(4, 7)]
    FIRST: minEndPos 2 (17, 20)
    TRACE: minEndPos 4 (2, 7)
ENTER Rec eventPos 5    startTime 7 
    events [(4, 7), (2, 7)]
    FIRST: minEndPos 5 (8, 23)
    TRACE: minEndPos 7 (18, 20)
ENTER Rec eventPos 8    startTime 20 
    events [(4, 7), (2, 7), (18, 20)]
[(4, 7), (2, 7), (18, 20)]

分析

您的算法多次跳闸。最重要的是,当您第二次进入该例程时,您会找到具有可接受的开始时间的第一条记录,并将其结束时间作为“击败数字”。从那时起,您将完全忽略呼叫中给定的开始时间以及其余事件的开始时间,而仅 寻找比相对任意间隔的结束时间还要好的时间。

您将以这种方式继续浏览列表,随意更改给定的开始时间,直到到达列表的结尾。


修复

遵循在线提供的许多解决方案:首先,按照结束时间的顺序对列表进行排序,然后按照开始时间进行排序。现在,遍历您的列表很简单,找到第一个可用的开始时间,该时间(a)在列表中的时间比最近添加的元组晚; (b)不小于当前结束时间。

鉴于解决方案的可用性,我将其留给学生作为练习。从对随机化例程的简单更改开始:

return sorted(e)