简体   繁体   English

通过多个清单进行归纳证明

[英]Proof by induction with multiple lists

I am following the Functional Programming in Scala lecture on Coursera and at the end of the video 5.7, Martin Odersky asks to prove by induction the correctness of the following equation : 我正在听有关Coursera的Scala中的Functional Programming in Scala讲座,在视频5.7的结尾,Martin Odersky要求通过归纳证明以下等式的正确性:

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

How to handle proof by induction when there are multiple lists involved ? 当涉及多个列表时,如何通过归纳法处理证明?

I have checked the base cases of xs being Nil and ys being Nil. 我检查了xs为Nil和ys为Nil的基本情况。 I have proven by induction that the equation holds when xs is replaced by x::xs, but do we also need to check the equation with ys replaced by y::ys ? 我通过归纳证明,当xs替换为x :: xs时方程成立,但是我们还需要检查ys替换为y :: ys的方程吗?

And in that case (without spoiling the exercise too much...which is not graded anyway) how do you handle : (xs ++ (y::ys)) map f ? 在那种情况下(不会过度破坏练习...无论如何也不会评分)您如何处理: (xs ++ (y::ys)) map f

This is the approach I have used on a similar example, to prove that 这是我在类似示例中使用的方法,以证明

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

Proof (omitting the base case, and easy x::xs case) : 证明(省略基本情况和简单的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

Is this right ? 这是正确的吗 ?

The property involves multiple lists, but ++ only recurses on its left argument. 该属性涉及多个列表,但是++仅在其左参数上递归。 That's a hint that you can prove by induction on that left argument. 这暗示您可以通过对左引数的归纳来证明。 In general, when proving a proposition about some recursive function, the first thing you try is inducting on the same argument that function recurses on . 通常,当证明某个递归函数的命题时, 您尝试做的第一件事是引入函数递归于的相同参数

I'll do this one for you as an example: 我将为您做一个例子:

Claim : (xs ++ ys) map f = (xs map f) ++ (ys map f) 索赔(xs ++ ys) map f = (xs map f) ++ (ys map f)

Proof : by induction on xs . 证明 :通过对xs的归纳。

  • Base case: xs = Nil 基本情况: xs = Nil

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

      (by ++ 's definition) (通过++的定义)

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

      (by map 's, then ++ 's definitions) (按map的定义,然后按++的定义)

    • Hence lhs = rhs 因此lhs = rhs
  • Inductive case: xs = z :: zs 归纳案例: xs = z :: zs

    • hypothesis : (zs ++ ys) map f = (zs map f) ++ (ys map f) 假设(zs ++ ys) map f = (zs map f) ++ (ys map f)
    • goal : ((z :: zs) ++ ys) map f = ((z :: 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) lhs = (z :: (zs ++ ys)) map f = f(z) :: ((zs ++ ys) map f) (1)

      (by map 's definition) (根据map的定义)

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

      (by map 's definition) (根据map的定义)

    • in turn, rhs = f(z) :: ((zs map f) ++ (ys map f)) (2) 反过来, rhs = f(z) :: ((zs map f) ++ (ys map f)) (2)

      (by ++ 's definition) (通过++的定义)

    • From hypothesis , (1) and (2) , we have proven goal . 根据假设 (1)(2) ,我们证明了目标

Therefore, we have proven the claim to be true reguardless of xs , ys , and f . 因此,我们证明了该主张对xsysf毫无保留。

As the comment of @Phil says, first is a good understaning of what the methods ++ and :: are doing on the lists the better way is the documentation 正如@Phil的评论所说,首先要很好地了解++::在列表上的方法,更好的方法是文档

How can we prove properties of list programs? 我们如何证明列表程序的属性? The answer is by Structural induction! 答案是通过结构归纳法! Proof rule for proving a list property P(xs) via structural induction: 通过结构归纳证明列表属性P(xs)的证明规则:

P(Nil) (base case) for all x,xs : P(xs) => P(x::xs) (induction step) 所有x,xs的P(无)(基本情况):P(xs)=> P(x :: xs)(归纳步骤)

for all xs : P(xs) (consequence) 对于所有xs:P(xs)(结果)

P(xs) in induction step is called induction hypothesis 归纳步骤中的P(xs)称为归纳假设

for as the only important thing is xs, ys is fix proper List with lenght l, after proving for xs you can proof for ys, or see that is commutative 因为唯一重要的是xs,ys固定长度为l的正确列表,在证明xs之后,您可以证明ys,或者看到它是可交换的

So let's apply induction and the definitions of the functions 因此,让我们应用归纳法和函数定义

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

Base case we substitue xs by nil 基本情况下,我们用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

Induction Step 诱导步骤

((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 QED

for example another case in a scala work sheet 例如在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)

import scala.util.Random 导入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

here you can find more examples 在这里您可以找到更多的例子

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM