2017-04-18 5 views
-2

Hochrangigen Tor

Ich habe eine Aufgabe mit einer Dauer von 5 machen, die sich auch zwischen dem Zeitpunkt 0 und 10 beginnen, ich habe Pausen in Intervallen [2, 4), und [6, 7) im Horizont [0, 10].Wie Python Looping Logik schneller

Wenn eine Aufgabe zu einem bestimmten Zeitpunkt beginnt, sollte sie die Pausenzeit prüfen und die Dauer so verlängern, dass sie ihre tatsächliche Dauer erreicht. Wenn eine Aufgabe zum Beispiel zu Zeitpunkt 1 beginnt, sollte sie idealerweise zum Zeitpunkt 6 abgeschlossen sein. Aufgrund von Unterbrechungen bei 2,3 und 6 sollte sie jedoch bis 9 verlängert werden, um die Aufgabe abzuschließen. Das bedeutet, Dauer = 5 + 3 = 8.

Nachfolgend ist die Dauer der Aufgabe zu jedem Zeitpunkt unter Berücksichtigung der Brüche [8, 8, -1, -1, 6, 6, -1, 5, 5 , 5] Ich benutze -1, um dies als Startpunkt zum Pausenzeitpunkt zu verbieten. Das obige Beispiel ist für Ihr Verständnis der Logik, die ich versuche zu etablieren und zu codieren.

Spezifisches Problem

Ich könnte dieses Problem lösen, indem Sie eine Funktion definieren, wie folgt. Für die obigen kleinen Daten funktioniert es gut. Aber wenn mein Horizont länger ist, sagen wir 86400 (zwei Monate in Minuten), und meine Anzahl an Pausen ist höher (sagen wir 2 Pausen an jedem Tag von 4 Stunden), dann nimmt mein Looping mehr Zeit in Anspruch.

Invalid_Timings2 = [ 
    (0, 8640, 10080), 
    (0, 18720, 20160), 
    (0, 28800, 30240), 
    ... 
    (44, 59040, 60480), 
    (44, 69120, 70560), 
    (44, 79200, 80640) 
    ] 

def Duration_Pre_Compute_Task_Split(Invalid_Timings2): 
    Duration1 = [] 
    original_task_duration = 1380 # My task duration is 1380 minutes 
    for h in xrange(0, 86400):  # task can start anywhere between 0 to 86400 minutes 
     dur = original_task_duration 
     k=0 
     for t in Invalid_Timings2: # break timings given at the end [(0,480,600), (0,960, 1200) etc..] 
      # current time point h should be outside break range 
      # also new duration calculated should not fall into next break range similar to the case explained with small data. 
      # If it falls, this break time should be added to the calculated duration 
      if t[1] - dur <= h <= t[1]+ dur and h not in range(t[1], t[2]) and h < t[2]: 
       k = 1 
       dur += t[2] - t[1] 
     if k != 0: #if k=1 means h is not in break range, task cannot start during break range 
      Duration1.append((h,dur)) # for each time point, final calculated duration is appended. 
    return Duration1 

Mein Problem ist über die Leistung. Wenn mein Horizont länger ist und die Anzahl der Unterbrechungen am Horizont zunimmt, nimmt diese Rechenzeit exponentiell zu.

Wie kann ich diese Funktion verbessern, um die Berechnungszeiten zu reduzieren?

+0

Diese Frage ist zu allgemein, eher wie ein Hausaufgabenproblem, das Sie tun müssen. Sie können es verbessern, indem Sie hinzufügen, was Sie versucht haben. Außerdem sollten Sie sich auf den spezifischen Teil des Problems konzentrieren, an dem Sie feststecken. – Gijs

+0

Hallo, es ist kein Hausaufgabenproblem. Es ist ein sehr kleiner Teil einer Planungsanwendung. Und ich habe getan, was ich konnte, um es zu verbessern. Früher hat es eine Stunde gedauert und ich habe es auf 15 Minuten reduziert, indem ich die unnötigen Schritte reduziert habe. Ich möchte nur Expertenmeinung wissen, wenn es verbessert werden kann. Lassen Sie mich wissen, was ich hinzufügen kann, so dass Sie das Problem selbst sehen können – ASK

+0

Versuchen Sie es genauer zu machen. Zum Beispiel hat die Funktion, die Sie zeigen, die Dauer 1380, aber Ihr Text sagt nur 5. Die Funktion läuft auf 86400, aber das wird nirgends erklärt. Versuchen Sie auch, der Funktion einige Kommentare hinzuzufügen, damit wir besser verstehen, was Sie versuchen. – Dan

Antwort

0

Eine Mikro-Optimierung wäre das Auspacken t zu Variablen, um die wiederholten Look-Ups zu vermeiden. zB:

for t in Invalid_Timings2: 
     t0, t1, t2 = t 
     if t1 - dur <= h <= t1 + dur and h not in range(t1, t1 + t2) and t0==10 and h < t1 + t2: 
      k = 1 
      dur += t2 

Dies ersetzt 9-Lookups mit einem einzigen

Auspacken
+0

ok. Danke, Brian. Ich habe es aktualisiert. – ASK

0

Ihr Performance-Problem von sehr großen verschachtelten Schleifen kommt (h, dann t) mit halb komplexer Logik auf dem Kern (eine if Aussage mit dem Elemente Nachschlagen, Berechnungen, Bereichserstellung usw.).

Hier ist eine Art und Weise der Schleifen loszuwerden und die if Aussage:

def Duration_Pre_Compute_Task_Split(Invalid_Timings2): 
    original_task_duration = 5 

    # start with list assuming no delays 
    Duration1 = [original_task_duration] * 10 

    # work backward, updating all durations based on each invalid timing 
    for t in reversed(Invalid_Timings2): 
     # unpack once (thanks Brian) 
     t0, stt, end = t 
     delay = end - stt 

     # any duration between stt/end -> invalid 
     Duration1[stt:end] = [-1] * delay 

     # any duration before stt -> delayed 
     # (everything from 0 to stt is the same, so just use the first element) 
     Duration1[:stt] = [Duration1[0] + delay] * stt 

    return Duration1 

Das funktionierte ok mit dem High-Level-Beispiel (0-10). Sie müssen es offensichtlich für Ihre echte Anwendung testen/optimieren. Lassen Sie mich wissen, wenn Sie Fragen dazu haben, wie es funktioniert. Viel Glück!

+0

Ihre Aussage, dass "jede Dauer vor STT -> verzögert" nicht korrekt ist. Nur wenn die Dauer in den ungültigen Zeitbereich fällt, wird es verzögert. Nehmen Sie es als eine Maschine an, Wir können auf der Maschine nur in den gültigen Zeiten verarbeiten. Die Maschine wird in den Pausenzeiten heruntergefahren. Daher wird der Job zusätzliche Zeit benötigen, für die die Maschine nicht verfügbar ist. Wenn die Maschine für eine bestimmte Dauer verfügbar ist, wird es keine Verzögerung geben. Sie können dies überprüfen, indem Sie die ursprüngliche_Aufgabe_Zeit auf 2 in Ihrem Code ändern. Da die erste Pause von 2 beginnt, wird die Aufgabe nicht verzögert, wenn wir bei 0 beginnen. – ASK