[基础软件理论与实践] 第三节作业实现(採石)

採石 採石 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区

作业信息

  • 课程信息:https://bbs.csdn.net/topics/608593392
  • 第二节作业提交帖:https://bbs.csdn.net/topics/608988916
  1. Complete the de Bruijn index based interpreter in natural semantics
  2. Apply the de Bruijn index for extended lambda calculus (+ Let)

作业实现

任务1

在此稱術語:(de Bruijn index)爲德布朗數,(de Bruijn level)爲德布朗水平線。

我們先假定一種約定:

  1. λn表示函式式項的參數有n個,即λ3.N式指代λ.λ.λ.N或λλλ.N。具體案例如:λ3.(0)(1)(2),爲λ.λ.λ.(0)(1)(2)或λλλ.(0)(1)(2)。
  2. 假定處理的lambda式項均爲閉項,即其沒有自由變量。即λn.N,N當前層級的所有德布朗數均不大于n。

故解釋lambda式項時,首次進入後,將首先訪問函式項分支或調用項分支。

我們先假設初始lambda式項的形式爲λn.N。

我們在程式中,取n,並賦值給count變量;取N,並賦值給body變量。並對body進行演算,得果爲result。此時注意,程式裏後續使用了wrap_func函式把原函式項參數λn重新補充回result。即λn.(result)。


Fun(_) => {
  let (count, body) = extract(lambda)
  let result = calculus(body)
  wrap_func(count, result)
}

wrap_func函式的關鍵邏輯在于,演算結果result是否是函式項。若是函式項,則原函式德布朗參數會跟演算結果result的德布朗參數發生索引衝突。

假設演算結果result爲λm.M,則lambda等價于λn.(λm.M)。

具體案例如λ2.(λ2.(0)(1)(2)(3))。其n=2,m=2,λm.M爲λ2.(0)(1)(2)(3),wrap_func(2, λ2.(0)(1)(2)(3))運行結果應當爲λ4.(2)(3)(0)(1)。

我們應注意到,輸入λ2.(λ2.M),真正形態是λ(0).λ(1).(λ(0').λ(1').M),運行結果形態爲λ(0).λ(1).λ(2).λ(3).M。

故程式邏輯,應將(0')爲(2),將(1')爲(3)。代碼如下:

let rec wrap_func = (count, lambda) => {
  if count < 0 {
    assert false
  } else if count == 0 {
    lambda
  } else {
    switch lambda {
    | Fun(_) => {
        let (bcount, body) = extract(lambda)
        let t1 = direct_wrap_func(count + bcount, shift_one(body, 0))
        let t2 = direct_reduce(t1, Var(0), 2)
        let new_count = count - 1
        wrap_func(new_count, direct_unwrap_func(new_count, t2))
        /*
          性能優化版
          let (bcount, body) = extract(lambda)
          let t1 = direct_wrap_func(bcount, shift_one(body, 0))
          let t2 = Fun(reduce(t1, Var(0), count, count))
          let new_count = count - 1
          wrap_func(new_count, t2)
         */
      }

    | _ => direct_wrap_func(count, lambda)
    }
  }
}

若假設初始lambda式項的形式爲(X)(Y)。

又若X爲函式項λn.N,則應執行歸約(λn.N)[Y'/0],其中Y'=shift(n, Y, 0)。

並對歸約結果,以當前層級爲基準,將所有德布朗數減一,把原函式項參數盡數補充回。

  let call_reduce = (lambda, va) => {
    let (count, body) = extract(lambda)
    let t = direct_reduce(body, shift(count, va, 0), 0)
    wrap_func(count - 1, unshift_one(t, 0))
  }

測試結果集:

常規測試
用例    (λ.0)(λ.0) ==> λ.0
輸入    (λ.0)(λ.0)
輸出    λ.0

用例    (λ.(0)(λ.0))(λ.0) ==> λ.0
輸入    (λ.(0)(λ.0))(λ.0)
輸出    λ.0

用例    (λ.0)(λλ.(0)(1)) ==> λλ.(0)(1)
輸入    (λ.0)(λλ.(0)(1))
輸出    λλ.(0)(1)

用例    (λλ.(1)(0))(λλ.(1)(0)) ==> λ.(0)(λλ.(1)(0))
輸入    (λλ.(1)(0))(λλ.(1)(0))
輸出    λ.(0)(λλ.(1)(0))

用例    (λλλ.(1)(2))(λλλ.(0)(1)(2)) ==> λλ.(0)(1)
輸入    (λλλ.(1)(2))(λλλ.(0)(1)(2))
輸出    λλ.(0)(1)

用例    (λλλ.(1)(2))(λλλ.(0)((1)(2))) ==> λλ.(0)(1)
輸入    (λλλ.(1)(2))(λλλ.(0)((1)(2)))
輸出    λλ.(0)(1)

用例    (λλλ.0)(λλλ.(0)((1)(2))) ==> λλλλλ.(2)((3)(4))
輸入    (λλλ.0)(λλλ.(0)((1)(2)))
輸出    λλλλλ.(2)((3)(4))

用例    λ.(λλ.(0)(1))(0) ==> λλ.(0)(1)
輸入    λ.(λλ.(0)(1))(0)
輸出    λλ.(0)(1)

用例    λλ.(λλλλ.(0)(1)(2)(3))(1)(0) ==> λλλλ.(1)(0)(2)(3)
輸入    λλ.(λλλλ.(0)(1)(2)(3))(1)(0)
輸出    λλλλ.(1)(0)(2)(3)

邱奇測試
用例    if_zero_then_else 0 ==> T
輸入    (λ.(0)(λλλ.2)(λλ.0))(λλ.1)
輸出    λλ.0

用例    if_zero_then_else 2 ==> F
輸入    (λ.(0)(λλλ.2)(λλ.0))(λλ.(0)((0)(1)))
輸出    λλ.1

用例    succ 3 ==> 4
輸入    (λλλ.(1)((0)(1)(2)))(λλ.(0)((0)((0)(1))))
輸出    λλ.(0)((0)((0)((0)(1))))

用例    pred 4 ==> 3
輸入    (λ.(λ.(0)(λλ.0))((0)(λ.(λλλ.(2)(0)(1))((λ.(0)(λλ.1))(0))((λλλ.(1)((0)(1)(2)))((λ.(0)(λλ.1))(0))))((λλλ.(2)(0)(1))(λλ.1)(λλ.1))))(λλ.(0)((0)((0)((0)(1)))))
輸出    λλ.(0)((0)((0)(1)))

用例    2 + 3 ==> 5
輸入    (λλλλ.(0)(2)((1)(2)(3)))(λλ.(0)((0)(1)))(λλ.(0)((0)((0)(1))))
輸出    λλ.(0)((0)((0)((0)((0)(1)))))

用例    5 - 2 ==> 3
輸入    (λλ.(1)(λ.(λ.(0)(λλ.0))((0)(λ.(λλλ.(2)(0)(1))((λ.(0)(λλ.1))(0))((λλλ.(1)((0)(1)(2)))((λ.(0)(λλ.1))(0))))((λλλ.(2)(0)(1))(λλ.1)(λλ.1))))(0))(λλ.(0)((0)((0)((0)((0)(1))))))(λλ.(0)((0)(1)))
輸出    λλ.(0)((0)((0)(1)))

用例    multi1 4 × 3 ==> 12
輸入    (λλ.(λ.(0)(λλλ.2)(λλ.0))(0)(λλ.1)((0)(λ.(λλλλ.(0)(2)((1)(2)(3)))(0)(2))(λλ.1)))(λλ.(0)((0)((0)((0)(1)))))(λλ.(0)((0)((0)(1))))
輸出    λλ.(0)((0)((0)((0)((0)((0)((0)((0)((0)((0)((0)((0)(1))))))))))))

用例    multi2 4 × 3 ==> 12
輸入    (λλλλ.(0)(λ.(2)(3)(0))(3))(λλ.(0)((0)((0)((0)(1)))))(λλ.(0)((0)((0)(1))))
輸出    λλ.(0)((0)((0)((0)((0)((0)((0)((0)((0)((0)((0)((0)(1))))))))))))

用例    multi_wF 4 × 3 ==> 12
輸入    (λ.(0)(0))(λλλ.(λ.(0)(λλλ.2)(λλ.0))(1)(λλ.1)((λλλλ.(0)(2)((1)(2)(3)))(2)((λ.(0)(0))(0)((λ.(λ.(0)(λλ.0))((0)(λ.(λλλ.(2)(0)(1))((λ.(0)(λλ.1))(0))((λλλ.(1)((0)(1)(2)))((λ.(0)(λλ.1))(0))))((λλλ.(2)(0)(1))(λλ.1)(λλ.1))))(1))(2))))(λλ.(0)((0)((0)((0)(1)))))(λλ.(0)((0)((0)(1))))
輸出    λλ.(0)((0)((0)((0)((0)((0)((0)((0)((0)((0)((0)((0)(1))))))))))))

用例    multi_YF 4 × 3 ==> 12
輸入    (λ.(λ.(0)(0))(λ.(1)((λ.(0)(0))(0))))(λλλ.(λ.(0)(λλλ.2)(λλ.0))(1)(λλ.1)((λλλλ.(0)(2)((1)(2)(3)))(2)((0)((λ.(λ.(0)(λλ.0))((0)(λ.(λλλ.(2)(0)(1))((λ.(0)(λλ.1))(0))((λλλ.(1)((0)(1)(2)))((λ.(0)(λλ.1))(0))))((λλλ.(2)(0)(1))(λλ.1)(λλ.1))))(1))(2))))(λλ.(0)((0)((0)((0)(1)))))(λλ.(0)((0)((0)(1))))
輸出    λλ.(0)((0)((0)((0)((0)((0)((0)((0)((0)((0)((0)((0)(1))))))))))))

用例    factorial_wF 3 ==> 6
輸入    (λ.(0)(0))(λλ.(λ.(0)(λλλ.2)(λλ.0))(1)(λλ.(0)(1))((λ.(0)(0))(λλλ.(λ.(0)(λλλ.2)(λλ.0))(1)(λλ.1)((λλλλ.(0)(2)((1)(2)(3)))(2)((λ.(0)(0))(0)((λ.(λ.(0)(λλ.0))((0)(λ.(λλλ.(2)(0)(1))((λ.(0)(λλ.1))(0))((λλλ.(1)((0)(1)(2)))((λ.(0)(λλ.1))(0))))((λλλ.(2)(0)(1))(λλ.1)(λλ.1))))(1))(2))))(1)((λ.(0)(0))(0)((λ.(λ.(0)(λλ.0))((0)(λ.(λλλ.(2)(0)(1))((λ.(0)(λλ.1))(0))((λλλ.(1)((0)(1)(2)))((λ.(0)(λλ.1))(0))))((λλλ.(2)(0)(1))(λλ.1)(λλ.1))))(1)))))(λλ.(0)((0)((0)(1))))
輸出    λλ.(0)((0)((0)((0)((0)((0)(1))))))

用例    factorial_YF 3 ==> 6
輸入    (λ.(λ.(0)(0))(λ.(1)((λ.(0)(0))(0))))(λλ.(λ.(0)(λλλ.2)(λλ.0))(1)(λλ.(0)(1))((λ.(λ.(0)(0))(λ.(1)((λ.(0)(0))(0))))(λλλ.(λ.(0)(λλλ.2)(λλ.0))(1)(λλ.1)((λλλλ.(0)(2)((1)(2)(3)))(2)((0)((λ.(λ.(0)(λλ.0))((0)(λ.(λλλ.(2)(0)(1))((λ.(0)(λλ.1))(0))((λλλ.(1)((0)(1)(2)))((λ.(0)(λλ.1))(0))))((λλλ.(2)(0)(1))(λλ.1)(λλ.1))))(1))(2))))(1)((0)((λ.(λ.(0)(λλ.0))((0)(λ.(λλλ.(2)(0)(1))((λ.(0)(λλ.1))(0))((λλλ.(1)((0)(1)(2)))((λ.(0)(λλ.1))(0))))((λλλ.(2)(0)(1))(λλ.1)(λλ.1))))(1)))))(λλ.(0)((0)((0)(1))))
輸出    λλ.(0)((0)((0)((0)((0)((0)(1))))))

 程式碼具體實現

open Belt
open Common

let roundString = str => "(" ++ str ++ ")"
let assoc = (x, env) => env->List.getAssoc(x, (a, b) => a == b)

type rec lambda /* 式項 */ =
  | Var(int) // 底項
  | Fun(lambda) // 函式項
  | App(lambda, lambda) // 調用項

let print_lambda = lambda => {
  let print_dot = is_parent_function =>
    if is_parent_function {
      "."
    } else {
      ""
    }
  let print_paren = (test, x) =>
    if test {
      roundString(x)
    } else {
      x
    }

  let rec go = (lambda, is_parent_function) => {
    switch lambda {
    | Fun(body) => "λ" ++ go(body, true)
    | Var(x) => print_dot(is_parent_function) ++ x->Int.toString
    | App(m, n) =>
      print_dot(is_parent_function) ++
      print_paren(
        switch m {
        | App(_, _) => false
        | _ => true
        },
        go(m, false),
      ) ++
      roundString(go(n, false))
    }
  }
  go(lambda, false)
}

let shift = (offset, lambda, depth) => {
  let rec go = (offset, lambda, depth) => {
    switch lambda {
    | App(m, n) => App(go(offset, m, depth), go(offset, n, depth))
    | Fun(body) => Fun(go(offset, body, depth + 1))
    | Var(index) =>
      if index >= depth {
        Var(index + offset)
      } else {
        lambda
      }
    }
  }
  go(offset, lambda, depth)
}

let shift_one = (lambda, depth) => shift(1, lambda, depth)
let unshift_one = (lambda, depth) => shift(-1, lambda, depth)

let rec reduce = (lambda, va, index, p_start_index) => {
  switch lambda {
  | App(m, n) =>
    App(reduce(m, va, index, p_start_index), reduce(n, va, index, p_start_index))
  | Fun(body) => Fun(reduce(body, shift_one(va, p_start_index), index + 1, p_start_index))

  | Var(n) =>
    if n == index {
      va
    } else {
      lambda
    }
  }
}

let direct_reduce = (lambda, va, p_start_index) => reduce(lambda, va, 0, p_start_index)

let rec extract = lambda =>
  switch lambda {
  | Fun(body) => {
      let (n, b) = extract(body)
      (1 + n, b)
    }

  | _ => (0, lambda)
  }

let rec wrap_func = (count, lambda) => {
  let rec direct_wrap_func = (count, body) => {
    if count == 0 {
      body
    } else if count < 0 {
      switch body {
      | Fun(child) => direct_wrap_func(count + 1, child)
      | _ => assert false
      }
    } else {
      direct_wrap_func(count - 1, Fun(body))
    }
  }
  let direct_unwrap_func = (count, body) => direct_wrap_func(-count, body)

  if count < 0 {
    assert false
  } else if count == 0 {
    lambda
  } else {
    switch lambda {
    | Fun(_) => {
        let (bcount, body) = extract(lambda)
        let t1 = direct_wrap_func(count + bcount, shift_one(body, 0))
        let t2 = direct_reduce(t1, Var(0), 2)
        let new_count = count - 1
        wrap_func(new_count, direct_unwrap_func(new_count, t2))
        /*
          let (bcount, body) = extract(lambda)
          let t1 = direct_wrap_func(bcount, shift_one(body, 0))
          let t2 = Fun(reduce(t1, Var(0), count, count))
          let new_count = count - 1
          wrap_func(new_count, t2)
         */
      }

    | _ => direct_wrap_func(count, lambda)
    }
  }
}

let rec calculus = lambda => {
  let call_reduce = (lambda, va) => {
    let (count, body) = extract(lambda)
    let t = direct_reduce(body, shift(count, va, 0), 0)
    wrap_func(count - 1, unshift_one(t, 0))
  }

  // 此式項內是否存在函式項。
  let rec has_unreduced_function = lambda =>
    switch lambda {
    | App(m, _) =>
      switch m {
      | Fun(_) => true
      | _ => has_unreduced_function(m)
      }
    | _ => false
    }

  let rec go = (lambda, depth) => {
    switch lambda {
    | Var(_) => lambda
    | Fun(_) => {
        let (count, body) = extract(lambda)
        wrap_func(count, calculus(body))
      }

    | App(m, n) =>
      switch m {
      | Fun(_) => {
          let t = call_reduce(m, n)
          if depth == 0 {
            calculus(t)
          } else {
            t
          }
        }

      | _ =>
        if has_unreduced_function(m) {
          // 若左式項尚存在未歸約的函式項,則先演算左式項。
          let ma = go(m, depth + 1)
          go(App(ma, n), depth)
        } else {
          // 因左式項全部歸約完畢,故開始演算右式項。
          App(m, calculus(n))
        }
      }
    }
  }
  go(lambda, 0)
}

type case_pair = {
  case: string,
  lambda: lambda,
}

let normal_lambdas = list{
  {
    case: "(λ.0)(λ.0) ==> λ.0",
    lambda: App(Fun(Var(0)), Fun(Var(0))),
  },
  {
    case: "(λ.(0)(λ.0))(λ.0) ==> λ.0",
    lambda: App(Fun(App(Var(0), Fun(Var(0)))), Fun(Var(0))),
  },
  {
    case: "(λ.0)(λλ.(0)(1)) ==> λλ.(0)(1)",
    lambda: App(Fun(Var(0)), Fun(Fun(App(Var(0), Var(1))))),
  },
  {
    case: "(λλ.(1)(0))(λλ.(1)(0)) ==> λ.(0)(λλ.(1)(0))",
    lambda: App(Fun(Fun(App(Var(1), Var(0)))), Fun(Fun(App(Var(1), Var(0))))),
  },
  {
    case: "(λλλ.(1)(2))(λλλ.(0)(1)(2)) ==> λλ.(0)(1)",
    lambda: App(
      Fun(Fun(Fun(App(Var(1), Var(2))))),
      Fun(Fun(Fun(App(App(Var(0), Var(1)), Var(2))))),
    ),
  },
  {
    case: "(λλλ.(1)(2))(λλλ.(0)((1)(2))) ==> λλ.(0)(1)",
    lambda: App(
      Fun(Fun(Fun(App(Var(1), Var(2))))),
      Fun(Fun(Fun(App(Var(0), App(Var(1), Var(2)))))),
    ),
  },
  {
    case: "(λλλ.0)(λλλ.(0)((1)(2))) ==> λλλλλ.(2)((3)(4))",
    lambda: App(Fun(Fun(Fun(Var(0)))), Fun(Fun(Fun(App(Var(0), App(Var(1), Var(2))))))),
  },
  {
    case: "λ.(λλ.(0)(1))(0) ==> λλ.(0)(1)",
    lambda: Fun(App(Fun(Fun(App(Var(0), Var(1)))), Var(0))),
  },
  {
    case: "λλ.(λλλλ.(0)(1)(2)(3))(1)(0) ==> λλλλ.(1)(0)(2)(3)",
    lambda: Fun(
      Fun(
        App(App(Fun(Fun(Fun(Fun(App(App(App(Var(0), Var(1)), Var(2)), Var(3)))))), Var(1)), Var(0)),
      ),
    ),
  },
}

// λλ.0
let b_true = Fun(Fun(Var(0)))
// λλ.1
let b_false = Fun(Fun(Var(1)))

// λλλ.(1)((0)(1)(2))
let succ = Fun(Fun(Fun(App(Var(1), App(App(Var(0), Var(1)), Var(2))))))

// λλ.1
let zero = Fun(Fun(Var(1)))
// λλ.(0)(1)
let one = calculus(App(succ, zero))
// λλ.(0)((0)(1))
let two = calculus(App(succ, one))
// λλ.(0)((0)((0)(1)))
let three = calculus(App(succ, two))
// λλ.(0)((0)((0)((0)(1))))
let four = calculus(App(succ, three))
// λλ.(0)((0)((0)((0)((0)(1)))))
let five = calculus(App(succ, four))

// λ.(0)(λ.(F))(T)
let if_zero_then_else = Fun(App(App(Var(0), wrap_func(1, b_false)), b_true))
// λλλ.(2)(0)(1)
let pair = Fun(Fun(Fun(App(App(Var(2), Var(0)), Var(1)))))
// λ.(0)(b_true)
let first = Fun(App(Var(0), b_true))
// λ.(0)(b_false)
let second = Fun(App(Var(0), b_false))

// λλλλ.(0)(2)((1)(2)(3))
let add = Fun(Fun(Fun(Fun(App(App(Var(0), Var(2)), App(App(Var(1), Var(2)), Var(3)))))))
// λ.(pair)(second (0))((succ)(second (0)))
let pred_it = Fun(App(App(pair, App(second, Var(0))), App(succ, App(second, Var(0)))))
// (pair)(zero)(zero)
let pair_zero = App(App(pair, zero), zero)
// λ.(first)((0)(pred_it)(pair_zero))
let pred = Fun(App(first, App(App(Var(0), pred_it), pair_zero)))
// λλ.(1)(pred)(0)
let minus = Fun(Fun(App(App(Var(1), pred), Var(0))))
// λλ.(if_zero_then_else)(0)(zero)((0)(λ.(add)(0)(2))(zero))
let multi1 = Fun(
  Fun(
    App(
      App(App(if_zero_then_else, Var(0)), zero),
      App(App(Var(0), Fun(App(App(add, Var(0)), Var(2)))), zero),
    ),
  ),
)
// λλλλ.(0)(λ.(2)(3)(0))(3)
let multi2 = Fun(Fun(Fun(Fun(App(App(Var(0), Fun(App(App(Var(2), Var(3)), Var(0)))), Var(3))))))

// λ.(0)(0)
let combinator_w = Fun(App(Var(0), Var(0)))
// λ.(combinator_w)(λ.(1)((combinator_w)(0)))
let combinator_Y = Fun(App(combinator_w, Fun(App(Var(1), App(combinator_w, Var(0))))))

// (combinator_w)(λλλ.(if_zero_then_else)(1)(zero)((add)(2)((combinator_w)(0)((pred)(1))(2))))
let multi_wF = App(
  combinator_w,
  Fun(
    Fun(
      Fun(
        App(
          App(App(if_zero_then_else, Var(1)), zero),
          App(App(add, Var(2)), App(App(App(combinator_w, Var(0)), App(pred, Var(1))), Var(2))),
        ),
      ),
    ),
  ),
)
// λλλ.(if_zero_then_else)(1)(zero)((add)(2)((0)((pred)(1))(2)))
let multi_F = Fun(
  Fun(
    Fun(
      App(
        App(App(if_zero_then_else, Var(1)), zero),
        App(App(add, Var(2)), App(App(Var(0), App(pred, Var(1))), Var(2))),
      ),
    ),
  ),
)
let multi_YF = App(combinator_Y, multi_F)

// (combinator_w)(λλ.(if_zero_then_else)(1)(one)((multi_wF)(1)((combinator_w)(0)((pred)(1)))))
let factorial_wF = App(
  combinator_w,
  Fun(
    Fun(
      App(
        App(App(if_zero_then_else, Var(1)), one),
        App(App(multi_wF, Var(1)), App(App(combinator_w, Var(0)), App(pred, Var(1)))),
      ),
    ),
  ),
)
// λλ.(if_zero_then_else)(1)(one)((multi_YF)(1)((0)((pred)(1))))
let factorial_F = Fun(
  Fun(
    App(
      App(App(if_zero_then_else, Var(1)), one),
      App(App(multi_YF, Var(1)), App(Var(0), App(pred, Var(1)))),
    ),
  ),
)
let factorial_YF = App(combinator_Y, factorial_F)

let church_lambdas = list{
  {
    case: "if_zero_then_else 0 ==> T",
    lambda: App(if_zero_then_else, zero),
  },
  {
    case: "if_zero_then_else 2 ==> F",
    lambda: App(if_zero_then_else, two),
  },
  {
    case: "succ 3 ==> 4",
    lambda: App(succ, three),
  },
  {
    case: "pred 4 ==> 3",
    lambda: App(pred, four),
  },
  {
    case: "2 + 3 ==> 5",
    lambda: App(App(add, two), three),
  },
  {
    case: "5 - 2 ==> 3",
    lambda: App(App(minus, five), two),
  },
  {
    case: "multi1 4 × 3 ==> 12",
    lambda: App(App(multi1, four), three),
  },
  {
    case: "multi2 4 × 3 ==> 12",
    lambda: App(App(multi2, four), three),
  },
  {
    case: "multi_wF 4 × 3 ==> 12",
    lambda: App(App(multi_wF, four), three),
  },
  {
    case: "multi_YF 4 × 3 ==> 12",
    lambda: App(App(multi_YF, four), three),
  },
  {
    case: "factorial_wF 3 ==> 6",
    lambda: App(factorial_wF, three),
  },
  {
    case: "factorial_YF 3 ==> 6",
    lambda: App(factorial_YF, three),
  },
}

let testSuit = pairs => {
  pairs->List.forEach(pair => {
    let {case, lambda} = pair
    Js.log("用例\t" ++ case)
    Js.log("輸入\t" ++ print_lambda(lambda))
    let reduction = calculus(lambda)
    Js.log("輸出\t" ++ print_lambda(reduction))
    Js.log("")
  })
}
Js.log("常規測試")
testSuit(normal_lambdas)
Js.log("邱奇測試")
testSuit(church_lambdas)

 

...全文

相关推荐

基于线性车辆三自由度动力学+无迹卡尔曼滤波UKF估计模型(横摆角速度+质心侧偏角+车速)联合仿真

内容概要:通过构建基于线性车辆三自由度动力学模型与无迹卡尔曼滤波(UKF)的联合仿真系统,实现对车辆关键状态参数的高精度估计,重点包括横摆角速度、质心侧偏角和车速。该方法利用车辆动力学模型描述其横向、纵向及横摆运动行为,结合UKF这一适用于非线性系统的先进状态估计算法,有效处理传感器噪声和模型不确定性,从而在缺乏直接测量手段的情况下,实现对难以获取状态量的可靠估计。整个仿真框架通常在MATLAB/Simulink环境中搭建,能够模拟真实驾驶工况,验证算法的有效性和鲁棒性,为车辆稳定性控制、自动驾驶感知与决策等高级功能提供重要的状态信息支撑。; 适合人群:具备车辆动力学、现代控制理论和MATLAB/Simulink仿真基础,从事汽车工程、自动驾驶或状态估计相关研究的研发人员与研究生。; 使用场景及目标:① 深入理解并掌握非线性系统状态估计的核心方法,特别是UKF的原理与实现;② 学习如何将理论化的车辆动力学模型转化为可用于仿真的模块;③ 实践并验证车辆关键状态(如质心侧偏角)的间接估计技术,服务于车辆动态控制系统的设计与测试。; 阅读建议:此资源以开发仿真模型为核心,不仅关注代码和模型的实现,更强调对车辆动力学机理和滤波算法设计思路的理解。学习者应结合理论知识,动手搭建并调试仿真模型,通过改变工况和参数来观察估计效果,从而深刻领会系统辨识与状态估计在实际工程中的应用价值。

三伯

基于PID控制的ABS汽车防抱死制动系统、车轮滑移率+最优滑移率Carsim和Simulink联合仿真(带参考文献)

内容概要:本文档主要围绕基于PID控制的汽车防抱死制动系统(ABS)开展研究,重点聚焦于车轮滑移率与最优滑移率的精确控制。通过Carsim与Simulink联合仿真平台,构建整车动力学模型与ABS控制器,利用PID算法实时调节制动压力,使实际滑移率逼近理论最优值,从而最大化轮胎与路面间的纵向附着力并保障横向稳定性,有效提升紧急制动工况下的制动效能与操控安全性。研究涵盖了从车辆建模、滑移率特性分析、PID控制器设计到联合仿真验证的全过程,并提供了完整的仿真模型、MATLAB/Simulink代码及参考文献,为相关领域的科研与工程实践提供了详实的技术参考。; 适合人群:具备车辆工程、自动化或控制理论基础知识,从事汽车电控系统开发、自动驾驶或车辆动力学仿真的研究生、工程师及科研人员。; 使用场景及目标:① 实现ABS系统的核心控制逻辑,掌握滑移率控制的关键技术;② 学习Carsim与Simulink联合仿真的搭建方法,进行车辆动力学与控制算法的协同仿真;③ 基于PID控制策略优化制动性能,完成相关学术研究或工程项目。; 阅读建议:在学习过程中,应结合所提供的完整仿真模型和代码,深入理解车辆动力学与ABS控制的交互机制,重点分析不同路面附着系数下最优滑移率的设定及PID参数的整定过程,以达到最佳的仿真效果和理论认知。

三伯

R语言SCINature绘图模板SCI科研绘图-雷达图

R语言SCINature绘图模板SCI科研绘图--雷达图

codedadi

JESD82-543 DDR5MRCD03 Multiplexed Rank Registering Clock Driver.rar

JESD82-543 DDR5MRCD03 Multiplexed Rank Registering Clock Driver.rar

Red Car

【多机器人路径规划】基于动态边权膨胀与节点预留历史机制的多智能体无冲突轨迹生成方法(Matlab代码实现)

内容概要:本文提出了一种基于动态边权膨胀与节点预留历史机制的多智能体无冲突轨迹生成方法,旨在高效解决多机器人路径规划中的碰撞与死锁问题。该方法通过动态调整路径图中边的权重以反映局部拥堵状况,实现路径的实时优化;同时引入节点预留机制,记录各机器人对路径节点的占用历史,确保时空冲突的有效规避。算法融合了路径搜索、冲突检测、权重自适应更新与调度协调等核心模块,形成了完整的无冲突轨迹规划框架,并配套提供了Matlab代码实现,便于算法验证与性能分析。该方法在复杂动态环境中表现出良好的鲁棒性与可扩展性,适用于多机器人系统的协同运动控制。; 适合人群:具备一定编程基础和路径规划基础知识,从事自动化、机器人、智能交通、智能制造等相关领域的科研人员、工程技术人员及研究生。; 使用场景及目标:①应用于仓储物流、智能工厂、无人驾驶车队等多智能体协同作业场景中的路径规划与动态避障;②为解决多机器人系统中的路径冲突、通信协调与死锁预防等关键技术难题提供理论支持与算法工具;③通过Matlab仿真平台复现算法逻辑,进行不同规模与场景下的性能测试、对比分析与算法优化。; 阅读建议:建议读者结合提供的Matlab代码逐模块实现与调试,重点理解动态边权调整策略的设计原理与节点预留机制的实现细节,通过设置不同初始条件与障碍环境开展仿真实验,以全面掌握算法的运行机制与优化潜力。

优化算法侠_科研
评论
收藏 已收藏
分享
返回顶部
採石
raelidea 231 成员 35 内容