私はhaskellを初めて使用しましたが、パフォーマンスの問題が発生したため、haskellプラットフォームではなく、自分のコードである必要があります。
私はレーベンシュタイン距離(独自のコード)のPython実装を持っており、これをhaskellに渡しました(またはそうしようとしました)。結果は次のとおりです。
bool2int :: Bool -> Int
bool2int True = 1
bool2int False = 0
levenshtein :: Eq a => [a] -> [a] -> Int -> Int -> Int
levenshtein u v 0 0 = 0
levenshtein u v i 0 = i
levenshtein u v 0 j = j
levenshtein u v i j = minimum [1 + levenshtein u v i (j - 1),
1 + levenshtein u v (i - 1) j,
bool2int (u !! (i - 1) /= v !! (j - 1) ) + levenshtein u v (i - 1) (j - 1) ]
distance :: Eq a => [a] -> [a] -> Int
distance u v = levenshtein u v (length u) (length v)
現在、長さが10以上の文字列の実行時間の違いは、pythonとhaskellの間でさまざまな10の累乗です。また、大まかな時間測定(これまでhaskellでclock()コマンドを見つけられなかったので壁掛け時計)を使用すると、私のhaskell実装のコストはO(mn)ではないようですが、他の途方もなく急速に増加するコストです。
注意: haskellの実装がPythonスクリプトと速度的に競合することは望ましくありません。宇宙全体が存在する時間の倍数ではなく、「賢明な」時間で実行したいだけです。
質問:
- 私の実装がとても遅いので、私は何を間違っていますか?
- それを修正する方法は?
- 「遅延評価」と言えば
levenshtein "cat" "kit" 2 2
、3回呼ばれると1回しか計算されないということです。これは正しいですか? - 私のbool2intには何かが組み込まれているはずですよね?
- Haskellをマスターするための大まかな道を私に突きつければ、他のどんな入力も高く評価されます。
編集:ここに比較のためのPythonコードがあります:
#! /usr/bin/python3.2
# -*- coding, utf-8 -*-
class Levenshtein:
def __init__ (self, u, v):
self.__u = ' ' + u
self.__v = ' ' + v
self.__D = [ [None for x in self.__u] for x in self.__v]
for x, _ in enumerate (self.__u): self.__D [0] [x] = x
for x, _ in enumerate (self.__v): self.__D [x] [0] = x
@property
def distance (self):
return self.__getD (len (self.__v) - 1, len (self.__u) - 1)
def __getD (self, i, j):
if self.__D [i] [j] != None: return self.__D [i] [j]
self.__D [i] [j] = min ( [self.__getD (i - 1, j - 1) + (0 if self.__v [i] == self.__u [j] else 1),
self.__getD (i, j - 1) + 1,
self.__getD (i - 1, j) + 1] )
return self.__D [i] [j]
print (Levenshtein ('first string', 'second string').distance)