簡體   English   中英

通過多個清單進行歸納證明

[英]Proof by induction with multiple lists

我正在聽有關Coursera的Scala中的Functional Programming in Scala講座,在視頻5.7的結尾,Martin Odersky要求通過歸納證明以下等式的正確性:

(xs ++ ys) map f = (xs map f) ++ (ys map f)

當涉及多個列表時,如何通過歸納法處理證明?

我檢查了xs為Nil和ys為Nil的基本情況。 我通過歸納證明,當xs替換為x :: xs時方程成立,但是我們還需要檢查ys替換為y :: ys的方程嗎?

在那種情況下(不會過度破壞練習...無論如何也不會評分)您如何處理: (xs ++ (y::ys)) map f

這是我在類似示例中使用的方法,以證明

(xs ++ ys).reverse = ys.reverse ++ xs.reverse

證明(省略基本情況和簡單的x :: xs情況):

(xs ++ (y::ys)).reverse
= (xs ++ (List(y) ++ ys)).reverse         //y::ys = List(y) ++ ys
= ((xs ++ List(y)) ++ ys).reverse         //concat associativity
= ys.reverse ++ (xs ++ List(y)).reverse   //by induction hypothesis (proven with x::xs)
= ys.reverse ++ List(y).reverse ++ xs.reverse //by induction hypothesis
= ys.reverse ++ (y::Nil).reverse ++ xs.reverse //List(y) = y :: Nil
= ys.reverse ++ Nil.reverse ++ List(y) ++ xs.reverse //reverse definition
= (ys.reverse ++ List(y)) ++ xs.reverse //reverse on Nil (base case)
= (y :: ys).reverse ++ xs.reverse         //reverse definition

這是正確的嗎 ?

該屬性涉及多個列表,但是++僅在其左參數上遞歸。 這暗示您可以通過對左引數的歸納來證明。 通常,當證明某個遞歸函數的命題時, 您嘗試做的第一件事是引入函數遞歸於的相同參數

我將為您做一個例子:

索賠(xs ++ ys) map f = (xs map f) ++ (ys map f)

證明 :通過對xs的歸納。

  • 基本情況: xs = Nil

    • lhs = (Nil ++ ys) map f = ys map f

      (通過++的定義)

    • rhs = (Nil map f) ++ (ys map f) = Nil ++ ys map f = ys map f

      (按map的定義,然后按++的定義)

    • 因此lhs = rhs
  • 歸納案例: xs = z :: zs

    • 假設(zs ++ ys) map f = (zs map f) ++ (ys map f)
    • 目標((z :: zs) ++ ys) map f = ((z :: zs) map f) ++ (ys map f)
    • lhs = (z :: (zs ++ ys)) map f = f(z) :: ((zs ++ ys) map f) (1)

      (根據map的定義)

    • rhs = ((z :: zs) map f) ++ (ys map f) = (f(z) :: (zs map f)) ++ (ys map f)

      (根據map的定義)

    • 反過來, rhs = f(z) :: ((zs map f) ++ (ys map f)) (2)

      (通過++的定義)

    • 根據假設 (1)(2) ,我們證明了目標

因此,我們證明了該主張對xsysf毫無保留。

正如@Phil的評論所說,首先要很好地了解++::在列表上的方法,更好的方法是文檔

我們如何證明列表程序的屬性? 答案是通過結構歸納法! 通過結構歸納證明列表屬性P(xs)的證明規則:

所有x,xs的P(無)(基本情況):P(xs)=> P(x :: xs)(歸納步驟)

對於所有xs:P(xs)(結果)

歸納步驟中的P(xs)稱為歸納假設

因為唯一重要的是xs,ys固定長度為l的正確列表,在證明xs之后,您可以證明ys,或者看到它是可交換的

因此,讓我們應用歸納法和函數定義

P(xs):(xs ++ ys)映射f =(xs映射f)++(ys映射f)

基本情況下,我們用nil代替xs

(nil ++ ys) map f [definition of ++ ] 
ys map f  on the other hand 
(xs map f) ++ (ys map p) [apply map over NIL] 
(NIL) ++ (ys map p) [definition pf ++] 
ys map p

誘導步驟

((x::xs) ++ ys) map f [definition ++]
(x:: (xs ++ ys)) map f [definition map]
f(x) :: ((xs ++ ys) map f) [induction hypothesis]
f(x) :: ((xs map f) ++ (ys map f)) [definition ++]
(f(x) :: (xs map f)) ++ (ys map f) [definition map]
(x::xs) map f ++ ys map f

QED

例如在scala工作表中的另一種情況

import scala.util.Random

// P : length ( append(as,bs) )) = length ( as ) + length (bs)

def length[T](as: List[T]): Int = as match {
    case Nil => 0
    case _::xs => 1 + length(xs)
}

def append[T](as: List[T], bs: List[T]): List[T] = as match {
  case Nil => bs
  case x :: xs => x :: append(xs, bs)
}

// base case  we substitute Nil for as in P

val a:List[Int] = Nil
val n = 10
val b:List[Int] = Seq.fill(n)(Random.nextInt).toList

length((append(a,b)))

length(a)

length(b)

導入scala.util.Random

length: length[T](val as: List[T]) => Int




append: append[T](val as: List[T],val bs: List[T]) => List[T]






a: List[Int] = List()
n: Int = 10
b: List[Int] = List(1168053950, 922397949, -1884264936, 869558369, -165728826, -1052466354, -1696038881, 246666877, 1673332480, -975585734)

res0: Int = 10

res1: Int = 0

res2: Int = 10

在這里您可以找到更多的例子

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM