Ich schreibe einen Algorithmus zum Finden von Longs Pfad über mehrere Wendepunkte mit einer Liste von Koordinaten (die einen Pfad beschreiben). Der dynamische Programmieralgorithmus funktioniert gut in O (kn^2), wobei k die Anzahl der Wendepunkte und n Anzahl der Punkte ist. Um die Geschichte kurz zu machen: Der langsamste Teil ist die Abstandsberechnung zwischen 2 Koordinaten; der Algorithmus erfordert, dass er für das gleiche Punktepaar "k" -mal neu berechnet wird. Memoisierung ist keine Option (zu viele Punkte). Es ist möglich, den Algorithmus zu invertieren - aber irgendwie ist der invertierte Algorithmus in Haskell sehr langsam und isst zu viel Speicher.Effizient mehrere Maxima in der Liste der Listen in Haskell zu finden
Es scheint mir, dass das Problem folgt; Sie sind ein Array von Arrays mit fester Größe (plus einige dynamisch berechneten Wert gegeben - zum Beispiel würde dies das Ergebnis von zippen den Wert mit der Liste:
arr = [ (2, [10,5,12]), (1, [2,8, 20]), (4, [3, 2, 10]) ]
Ich versuche, ein Maximum über die Elemente der finden Liste und der feste Wert:
[12, 9, 21]
Was ich tue - so etwas wie:
foldl' getbest (replicate 3 0) arr
getbest acc (fixval, item) = map comparator $ zip acc item
comparator orig new
| new + fixval > orig = new + fixval
| otherwise = orig
das Problem ist, dass ein neu ‚acc‘ mit jedem Aufruf von ‚getbest‘ gebaut wird - das ist n^2 was viel ist. Die Zuordnung ist teuer und das ist wahrscheinlich das Problem. Hast du eine Idee, wie man so etwas effizient macht?
Um es klar zu machen: Das ist der eigentliche Code der Funktion:
dynamic2FreeFlight :: Int -> [ Coord ] -> [ Coord ]
dynamic2FreeFlight numpoints points = reverse $ (dsCoord bestPoint) : (snd $ (dsScore bestPoint) !! (numpoints - 2))
where
bestPoint :: DSPoint
bestPoint = maximumBy (\x y -> (getFinalPointScore x) `compare` (getFinalPointScore y)) compresult
getFinalPointScore :: DSPoint -> Double
getFinalPointScore sc = fst $ (dsScore sc) !! (numpoints - 2)
compresult :: [ DSPoint ]
compresult = foldl' onestep [] points
onestep :: [ DSPoint ] -> Coord -> [ DSPoint ]
onestep lst point = (DSPoint point (genmax lst)) : lst
where
genmax :: [ DSPoint ] -> [ (Double, [ Coord ]) ]
genmax lst = map (maximumBy comparator) $ transpose prepared
comparator a b = (fst a) `compare` (fst b)
distances :: [ Double ]
distances = map (distance point . dsCoord) lst
prepared :: [ [ (Double, [ Coord ]) ] ]
prepared
| length lst == 0 = [ replicate (numpoints - 1) (0, []) ]
| otherwise = map prepare $ zip distances lst
prepare :: (Double, DSPoint) -> [ (Double, [ Coord ]) ]
prepare (dist, item) = (dist, [dsCoord item]) : map addme (take (numpoints - 2) (dsScore item))
where
addme (score, coords) = (score + dist, dsCoord item : coords)
'[a, b, c]' ist * nicht * ein Array, es ist eine (einzeln verlinkte) Liste. – sepp2k
Woher kommt '[12, 9, 21]? – Gabe
12 ist das Maximum des 'ersten Artikels + feste Nummer' (dh 10 + 2), 9 ist der 'zweite Artikel + feste Nummer (8 + 1)' usw. – ondra