【问题标题】:Memoization list Ocaml记忆列表 Ocaml
【发布时间】:2016-12-07 18:00:12
【问题描述】:

我有一个递归函数,我想要在 Mémoïsant 中重写

我的递归函数:

let rec sum_cube l =
    match l with
    | [] -> 0
    | x :: s -> (x * x * x) + sum_cube s

我试过了:

let memo = Hashtbl.create 17 
let rec sum_cub_memo l =
    try 
      Hashtbl.find memo l 
    with Not_found -> 
      let fn = function
        | [] -> 0
        | x::s -> (x * x * x ) sum_cub_memo s
      in
        Hashtbl.add memo l fn 

fn ;;

我有一个错误:

此表达式的类型为 int list -> int 但表达式应为 int list 类型!!

【问题讨论】:

  • 哪个表达式?
  • 啊。仔细看看fn。它是什么?你是怎么用的?
  • @melpomene Hashtbl.add memo l fn

标签: list ocaml memoization


【解决方案1】:

你应该记住的不是函数,而是函数的结果,例如,使用你对sum_cube的定义:

let sum_cube_memo xs = 
  try Hashtbl.find memo xs with Not_found ->
    let res = sum_cube xs in
    Hashtbl.add memo xs res;
    res

这会起作用,但是有一个警告。您正在使用整数列表作为键。这意味着,首先将键转换为其哈希(基本上是 O(n),并且将花费与计算 3 的幂的时间基本相同的时间),其次,如果存在哈希冲突,则bucket 将与参数列表进行比较。结果,您的记忆函数与非记忆函数具有相同的复杂性,它的性能更差,并且还消耗无限量的内存。值得吗?

【讨论】:

  • 此表达式的类型为 int,但表达式应为 int list 类型!!
  • 这是因为(是的,我是预言机),你有两个定义,一个是你的(不正确的),另一个是我的(正确的)。它们都使用相同的全局变量memo。一种定义是试图将int list -> int 类型的函数存储在memo 中,另一种(正确的)试图存储计算结果(类型为int)。因此,如果您在顶层工作,请通过删除错误的定义或重新创建 memo 值来清理您的代码。
【解决方案2】:

sum_cube 无需记忆。

let sum_cube l =
  let cube x =x*x*x in
  List.fold_left ( fun acc x -> acc+cube x) 0 l

sum_cube 具有记忆和追踪功能。

let sum_cube l =
  let memo = Hashtbl.create 17 in
  let cube_memo x =
    try
      let xcube= Hashtbl.find memo x in
      Printf.printf "find %d -> %d\n" x xcube;
      xcube
    with Not_found -> 
      let xcube=x*x*x in
      Printf.printf "add  %d -> %d\n" x xcube;
      Hashtbl.add memo x xcube;
      xcube
  in
  List.fold_left ( fun acc x -> acc+cube_memo x) 0 l

测试:

#  sum_cube [4;4;2;3;4;2];;
add  4 -> 64
find 4 -> 64
add  2 -> 8
add  3 -> 27
find 4 -> 64
find 2 -> 8
- : int = 235

【讨论】:

    猜你喜欢
    • 2013-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-20
    • 2017-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多