Ce cas particulier de problème d'ordonnancement est-il résoluble en temps linéaire?

12

Alice, une étudiante, a beaucoup de devoirs au cours des prochaines semaines. Chaque devoir lui prend exactement une journée. Chaque élément a également une date limite et un impact négatif sur ses notes (supposez un nombre réel, des points bonus pour ne supposer que la comparabilité), si elle manque la date limite.

Écrivez une fonction qui donne une liste (échéance, impact sur la note) un calendrier pour les devoirs à faire le jour qui minimise la somme du mauvais impact sur ses notes.

Tous les devoirs doivent être faits éventuellement, mais si elle manque une date limite pour un article, peu importe l'heure à laquelle elle le remet.

Dans une formulation alternative:

ACME corp veut fournir de l'eau aux clients. Ils vivent tous le long d'une rue en montée. ACME a plusieurs puits distribués le long de la rue. Chaque puits contient suffisamment d'eau pour un client. Les clients offrent différents montants d'argent à fournir. L'eau ne coule qu'en descente. Maximisez les revenus en choisissant les clients à approvisionner.

Nous pouvons trier les délais à l'aide du tri par compartiment (ou simplement supposer que nous avons déjà trié par date limite).

Nous pouvons résoudre le problème facilement avec un algorithme gourmand, si nous trions d'abord par impact décroissant de grade. Cette solution ne sera pas meilleure que O (n log n).

Inspiré par la médiane des médianes et les algorithmes d' arbre couvrant linéaire minimal randomisé , je soupçonne que nous pouvons également résoudre mon problème de planification / flux simple en temps linéaire (randomisé?).

Je cherche:

  • un algorithme de temps linéaire (potentiellement randomisé)
  • ou bien un argument selon lequel le temps linéaire n'est pas possible

Comme tremplin:

  • J'ai déjà prouvé que le simple fait de savoir quels éléments peuvent être effectués avant leur échéance est suffisant pour reconstruire le programme complet en temps linéaire. (Cette idée sous-tend la deuxième formulation où je ne pose que des questions sur le certificat.)
  • Un programme linéaire simple (intégral!) Peut modéliser ce problème.
  • En utilisant la dualité de ce programme, on peut vérifier une solution proposée candidate en temps linéaire pour l'optimalité, si on donne également la solution au programme double. (Les deux solutions peuvent être représentées dans un nombre linéaire de bits.)

Idéalement, je veux résoudre ce problème dans un modèle qui utilise uniquement la comparaison entre les impacts de grade, et ne suppose pas de chiffres là-bas.

J'ai deux approches à ce problème: l'une basée sur des tracés utilisant la date limite et l'impact, l'autre similaire à QuickSelect basée sur le choix d'éléments pivotants aléatoires et le partitionnement des éléments par impact. Les deux ont les pires cas qui forcent O (n log n) ou des performances moins bonnes, mais je n'ai pas été en mesure de construire un cas spécial simple qui dégrade les performances des deux.

Matthias
la source

Réponses:

1

Quelques choses que j'ai découvert jusqu'à présent.

Nous pouvons nous réduire à résoudre le problème connexe suivant:

newtype Slot = Slot Int
newtype Schedule a = Schedule [(Slot, [a])]

findSchedule :: Ord a => Schedule a -> Schedule (a, Bool)

C'est-à-dire donner les données d'entrée déjà triées par date limite, mais autoriser un nombre arbitraire non négatif de tâches à effectuer chaque jour. Donnez la sortie en marquant simplement les éléments pour savoir s'ils peuvent être planifiés à temps ou non.

La fonction suivante peut vérifier si un calendrier donné dans ce format est réalisable, c'est-à-dire si tous les articles encore dans le calendrier peuvent être planifiés avant leur échéance:

leftOverItems :: Schedule a -> [Int]
leftOverItems (Schedule sch) = scanr op 0 sch where
  op (Slot s, items) itemsCarried = max 0 (length items - s + itemsCarried)

feasible schedule = head (leftOverItems schedule) == 0

Si nous avons une solution candidate proposée, et tous les éléments laissés de côté, nous pouvons vérifier en temps linéaire si le candidat est optimal, ou s'il y a des éléments dans l'ensemble laissé de côté qui amélioreraient la solution. Nous appelons ces éléments légers , par analogie avec la terminologie de l'algorithme Minimum Spanning Tree

carry1 :: Ord a => Schedule a -> [Bound a]
carry1 (Schedule sch) = map (maybe Top Val . listToMaybe) . scanr op [] $ sch where
  op (Slot s, items) acc = remNonMinN s (foldr insertMin acc items)

-- We only care about the number of items, and the minimum item.
-- insertMin inserts an item into a list, keeping the smallest item at the front.
insertMin :: Ord a => a -> [a] -> [a]
insertMin a [] = [a]
insertMin a (b:bs) = min a b : max a b : bs

-- remNonMin removes an item from the list,
-- only picking the minimum at the front, if it's the only element.
remNonMin :: [a] -> [a]
remNonMin [] = []
remNonMin [x] = []
remNonMin (x:y:xs) = x : xs

remNonMinN :: Int -> [a] -> [a]
remNonMinN n l = iterate remNonMin l !! n

data Bound a = Bot | Val a | Top
  deriving (Eq, Ord, Show, Functor)

-- The curve of minimum reward needed for each deadline to make the cut:
curve :: Ord a => Schedule a -> [Bound a]
curve = zipWith min <$> runMin <*> carry1

-- Same curve extended to infinity (in case the Schedules have a different length)
curve' :: Ord a => Schedule a -> [Bound a]
curve' = ((++) <*> repeat . last) . curve

-- running minimum of items on left:
runMin :: Ord a => Schedule a -> [Bound a]
runMin = scanl1 min . map minWithBound . items . fmap Val

minWithBound :: Ord a => [Bound a] -> Bound a
minWithBound = minimum . (Top:)

-- The pay-off for our efforts, this function uses
-- the candidate solution to classify the left-out items
-- into whether they are definitely _not_ in
-- the optimal schedule (heavy items), or might be in it (light items).
heavyLight :: Ord a => Schedule a -> Schedule a -> ([[a]],[[a]])
heavyLight candidate leftOut =
    unzip . zipWith light1 (curve' candidate) . items $ leftOut
  where
    light1 pivot = partition (\item -> pivot < Val item)

heavyLight non seulement vérifie l'optimalité d'un programme proposé, mais il vous donne également une liste d'éléments qui peuvent améliorer un programme non optimal.

Matthias
la source
-4

Non. Ce n'est pas un cas particulier d'un problème d'écoulement résoluble en temps linéaire. Parce que la complexité est donnée par et en se triant nous obtenons la complexité en et afin d'exécuter tous les autres n processus, la complexité ne resterait certainement pas linéaire.O ( n log n )O(n2)O(nlogn)

Sheetal U
la source
1
Je ne trouve pas cela un argument très convaincant que ce problème n'est pas résoluble en temps linéaire.
Tom van der Zanden
Moi non plus. Le but est d'éviter de trier par impact des diplômés, car vous n'avez pas besoin des informations sur la permutation complète .. (Même idée que dans QuickSelect.)
Matthias
@ Sheetal-U, Également pour clarifier, je ne veux rien exécuter --- je veux juste construire le planning.
Matthias