Scala 多列表归纳法证明
我正在关注有关Coursera的Scala讲座中的函数编程,在视频5.7的结尾,Martin Odersky要求通过归纳证明以下等式的正确性:Scala 多列表归纳法证明,scala,functional-programming,induction,proof-of-correctness,equational-reasoning,Scala,Functional Programming,Induction,Proof Of Correctness,Equational Reasoning,我正在关注有关Coursera的Scala讲座中的函数编程,在视频5.7的结尾,Martin Odersky要求通过归纳证明以下等式的正确性: (xs ++ ys) map f = (xs map f) ++ (ys map f) 当涉及多个列表时,如何处理归纳法证明 我已经检查了xs为零和ys为零的基本情况。 我已经用归纳法证明了,当x被x::x替换时,方程成立,但是我们是否也需要用y::y替换y来检查方程 在这种情况下(不会破坏练习太多…无论如何都没有评分),您如何处理:(xs++(y::
(xs ++ ys) map f = (xs map f) ++ (ys map f)
当涉及多个列表时,如何处理归纳法证明
我已经检查了xs为零和ys为零的基本情况。
我已经用归纳法证明了,当x被x::x替换时,方程成立,但是我们是否也需要用y::y替换y来检查方程
在这种情况下(不会破坏练习太多…无论如何都没有评分),您如何处理:(xs++(y::ys))map f
这是我在一个类似的例子中使用的方法,以证明
(xs ++ ys).reverse = ys.reverse ++ xs.reverse
证明(省略基本情况和easy x::xs情况):
这是对的吗?正如@Phil的评论所说,首先是很好地理解方法
++
和:
在列表上的作用更好的方法是
如何证明列表程序的性质?
答案是结构归纳法!
通过结构归纳证明列表属性P(xs)的证明规则:
p(无)(基本情况)
对于所有x,xs:P(xs)=>P(x::xs)(诱导步骤)
对于所有xs:p(xs)(结果)
诱导步骤中的p(xs)称为诱导假说
因为唯一重要的是xs,ys是长度为l的fix-property列表,在为xs证明之后,您可以为ys证明,或者看到它是可交换的
让我们应用归纳法和函数的定义
p(xs):(xs++ys)map f=(xs-map f)++(ys-map 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
q、 急诊室
例如,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
您可以找到更多示例该属性涉及多个列表,但
++
仅在其左参数上递归。这是一个暗示,你们可以通过归纳法证明这个左论点。一般来说,当证明一个关于某个递归函数的命题时,首先要尝试的是归纳出函数递归的同一个参数
我将为您做一个示例:
索赔:(xs++ys)地图f
=(xs地图f)++(ys地图f)
证明:通过xs
上的归纳法
- 基本情况:
=xs
Nil
- lhs=
=(Nil++ys)映射f
(根据ys映射f
的定义)++
- rhs=
=(无图f)++(ys图f)
=Nil++ys图f
(通过ys图f
,然后通过映射
的定义)++
- 因此lhs=rhs
- lhs=
- 感应情况:
=xs
z::zs
- 假设:
=(zs++ys)映射f
(zs映射f)++(ys映射f)
- 目标:
=((z::zs)++ys)映射f
((z::zs)映射f)++ys映射f
- lhs=
=(z:(zs++ys))映射f
(1) (根据f(z:((zs++ys)映射f)
地图
的定义)
- rhs=
=((z::zs)映射f)++(ys映射f)
(根据(f(z):(zs映射f))++(ys映射f)
地图
的定义)
- 反过来,rhs=
(2) (根据f(z):((zs地图f)++(ys地图f))
的定义)++
- 从假设、(1)和(2),我们已经证明了目标
- 假设:
因此,我们已经证明了该声明是正确的,无需对
xs
、ys
和f
进行规范。请看++
和map
的定义。有两个列表,但它们分解哪一个当然,但是这个定义并不能证明……我们可以说“它已经被证明是正确的,通过归纳两个表达式列表中的一个,因此整个表达式是正确的”……我倾向于认为我们不能。谢谢你的回答。我的问题可能不是很清楚,你的答案与我证明的部分相符。我的问题是如何从“一个列表上的归纳”变成“整个表达式被证明是正确的”。@Gael你只需要在一个列表上归纳,然后不透明地引用另一个列表。
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