私はOCamlに数学的に記述されたアルゴリズムの実装を書いています。私は実装をきれいにして紙に近づけようとしており、パフォーマンスを改善するために暗記のような明確なテクニックしか使用していません。列挙によるOCamlの複雑なデータ型の自動的なメモ帳化?
残念ながら、memoizationは整数ではうまく機能しますが、大規模または複雑なデータ型の場合でもO(n)になります。メモの前にデータ型を列挙してO(1)のパフォーマンスを得ることは可能です。 たとえば、memo len
はまだO(n)になりますが、DroidMemoized.len
はO(1)になり、DroidMemoized
はDroid
の代わりとなります。
DroidMemoized
をDroid
から自動的に作成することはできますか?たとえば、モジュールEnumMemoは、let DroidMemoized = EnumMemo.Make(Droid)
と書くことができますか?
module Droid = struct
type t = string
let empty = ""
let beep x = x^" notdroids"
let boop x = x^" lookingfor"
let len x = String.length x
end
let memo f =
let m = Hashtbl.create 9 in
fun x ->
try Hashtbl.find m x
with Not_found ->
let y = f x in
Hashtbl.add m x y; y
module DroidMemoized = struct
(* Boilerplate *)
let to_id_h : (Droid.t, int) Hashtbl.t = Hashtbl.create 9
let from_id_h : (int, Droid.t) Hashtbl.t = Hashtbl.create 9 (*or use array*)
let size = ref 0
let from_id i = (Hashtbl.find from_id_h i)
let to_id (x :Droid.t) : int =
if Hashtbl.mem to_id_h x
then Hashtbl.find to_id_h x
else (size := (!size)+1;
Hashtbl.add to_id_h x (!size);
Hashtbl.add from_id_h (!size) x;
!size)
(* Function wrappers *)
let empty = to_id Droid.empty
let beep = memo (fun x -> to_id (Droid.beep (from_id x)))
let boop = memo (fun x -> to_id (Droid.boop (from_id x)))
let len = memo (fun x -> (Droid.len (from_id x)))
end
なぜ '〜O(n個のログ)' '(1)O'でHashtblではありませんか? –
さて、O(1)は良いハッシュ関数を持つ平均的なケースで、O(n)最悪のケースでは、赤い黒のツリーでO(log n)最悪のケースを得ることができます。これらの詳細は質問にあまり関係しないので、私はO(1)に変更します。 – gmatht