简体   繁体   English

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

[英]Recursive Scheduling algorithm does not work correctly Python

I've created a recursive scheduling algorithm that takes an array of Event objects which hold a start-time and end-time. 我创建了一个递归调度算法,该算法采用了一组包含开始时间和结束时间的Event对象。 These times are randomly generated and start-time is always less than end time. 这些时间是随机生成的,开始时间始终小于结束时间。 The time is a number between 0-24 (24 hours in a day, 24 == 0) 时间是0-24之间的数字(一天24小时,24 == 0)

Here is the code to the random event array generator: 这是随机事件数组生成器的代码:

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

Here is the code for the Event object: 这是Event对象的代码:

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

Now here comes the part which is causing issue. 现在是引起问题的部分。 I've created a piece of code that recursively goes through a generated array of events, and lists the most events that can be held in a single 24 hours. 我创建了一段代码,该代码递归地处理了生成的事件数组,并列出了可以在24小时内举行的最多事件。 No event should overlap. 任何事件都不应重叠。

Here is the recursive greedy algorithm created: 这是创建的递归贪婪算法:

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

The expected output of this algorithm is an array with the most events that can simultaneously occur in a single 24 hours without overlapping. 该算法的预期输出是具有最多事件的数组,这些事件可以在单个24小时内同时发生而不会重叠。 eg 例如

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

However, I'm receiving the following output: 但是,我收到以下输出:

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

Which clearly shows Arr[2] overlapping with Arr[1] (Arr[2].StartTime (12) < Arr[1].EndTime [16]) which should not be happening. 这清楚地显示了Arr [2]与Arr [1](A​​rr [2] .StartTime(12)<Arr [1] .EndTime [16])重叠,这是不应该发生的。

What is wrong and why this is happening? 有什么问题,为什么会这样?

I instrumented your code for debugging, including replacing the Events package with simple pair tuples. 我对您的代码进行了调试,包括用简单的对元组替换“事件”包。

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

Output: 输出:

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

ANALYSIS 分析

Your algorithm trips over itself more than once. 您的算法多次跳闸。 Most of all, when you enter the routine a second time, you find the first record with an acceptable start time, and take its ending time as the "figure to beat". 最重要的是,当您第二次进入该例程时,您会找到具有可接受的开始时间的第一条记录,并将其结束时间作为“击败数字”。 From then on, you entirely ignore the start time given in the call, and the start times of the remaining events, looking only for something that beats the end time of a relative arbitrary interval. 从那时起,您将完全忽略呼叫中给定的开始时间以及其余事件的开始时间, 查找超出相对任意间隔的结束时间的内容。

You continue through the list this way, changing the given start time somewhat haphazardly, until you reach the end of the list. 您可以通过这种方式继续浏览列表,随意更改给定的开始时间,直到到达列表的末尾。


REPAIR 修理

Follow the many solutions available on line: First, sort your list in order of ending time, then start time. 请遵循在线提供的许多解决方案:首先,按照结束时间的顺序对列表进行排序,然后按照开始时间进行排序。 Now it's a simple matter to walk through your list, finding the first available start time that is (a) later in the list than the most recently added tuple; 现在,遍历列表很简单,找到第一个可用的开始时间比列表中最近添加的元组晚(a)。 (b) no less than the current end time. (b)不少于当前结束时间。

Given the availability of solutions, I'll leave this to as an exercise for the student. 鉴于解决方案的可用性,我将其留给学生作为练习。 Start with the simple change in the randomization routine: 从对随机化例程的简单更改开始:

return sorted(e)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM