【问题标题】:Recursive Scheduling algorithm does not work correctly Python递归调度算法无法正常工作 Python
【发布时间】:2019-04-04 01:35:06
【问题描述】:

我创建了一个递归调度算法,它采用一组包含开始时间和结束时间的事件对象。这些时间是随机生成的,并且开始时间总是小于结束时间。时间是 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] (Arr[2].StartTime (12)

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

【问题讨论】:

  • 您遗漏了一些关键的依赖项。我可以很容易地直觉random 包,但我不知道你使用的是什么event 系统。
  • 对不起@prune,这是一个定制的对象。我现在将添加此代码
  • 如果它是定制的,它几乎肯定不是Minimal, complete, verifiable example的一部分。
  • 欢迎来到 StackOverflow。请按照您创建此帐户时的建议阅读并遵循帮助文档中的发布指南。 Minimal, complete, verifiable example 适用于此。在您发布 MCVE 代码并准确描述问题之前,我们无法有效地帮助您。我们应该能够将您发布的代码粘贴到文本文件中并重现您描述的问题。除其他事项外,请将您的随机初始化例程替换为失败的特定测试用例。还包括您的调试跟踪。
  • @Prune 我已经为这个对象添加了代码,现在应该意味着它遵循该示例,因为列出了所有依赖项

标签: python arrays algorithm recursion scheduling


【解决方案1】:

我检测了您的代码以进行调试,包括将 Events 包替换为简单的对元组。

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)]

分析

您的算法不止一次地绊倒自己。最重要的是,当您第二次进入例程时,您会找到第一个具有可接受的开始时间的记录,并将其结束时间作为“要击败的数字”。从那时起,您将完全忽略调用中给出的开始时间以及剩余事件的开始时间,寻找比相对任意间隔的结束时间要快的东西。

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


修复

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

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

return sorted(e)

【讨论】:

    猜你喜欢
    • 2016-06-16
    • 2022-01-19
    • 2015-11-11
    • 1970-01-01
    • 2023-03-22
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多