证明Dafny中的协方差不等式,使用矛盾



我试图在Dafny中证明以下属性:covariance(x,y) <= variance(x) * variance(y),其中xyreal

首先,我想知道我是否正确地解释了协方差和方差。因此,我提出以下问题:证明covariance(x,y) <= variance(x) * variance(y)和证明covariance(x,y) <= covariance(x,x) * covariance(y,y)是否相同?我提出这个问题是因为方差通常是2的幂(即sigma^2(x)(,这让我很困惑

然而,我从https://en.wikipedia.org/wiki/Covariance这种等价性成立。具体地说,如下所述:方差是协方差的一个特例,其中两个变量是相同的

我还从这个环节中得到了协方差的一个定义。具体为:cov(x,y)=(1/n)*summation(i from 1 to n){(x_i-mean(x))*(y_i-mean(y))}

因此,假设我必须证明covariance(x,y) <= covariance(x,x) * covariance(y,y),并且协方差是如上所述定义的,我在Dafny中测试以下引理:

lemma covariance_equality (x: seq<real>, y:seq<real>)
requires |x| > 1 && |y| > 1; //my conditions
requires |x| == |y|; //my conditions
requires forall elemX :: elemX in x ==> 0.0 < elemX; //my conditions
requires forall elemY :: elemY in y ==> 0.0 < elemY; //my conditions
ensures covariance_fun (x,y) <= covariance_fun(x,x) * covariance_fun (y,y);
{}

这是无法自动证明的。关键是我不知道如何手动证明它。我做了这种(没有用的(收缩证明方法,但我想这不是办法:

lemma covariance_equality (x: seq<real>, y:seq<real>)
requires |x| > 1 && |y| > 1; //my conditions
requires |x| == |y|; //my conditions
requires forall elemX :: elemX in x ==> 0.0 < elemX; //my conditions
requires forall elemY :: elemY in y ==> 0.0 < elemY; //my conditions
ensures covariance_fun (x,y) <= covariance_fun(x,x) * covariance_fun (y,y);
{
if !(covariance_fun(x,y) < covariance_fun(x,c) * covariance_fun (y,y)) {
//...
assert !(forall elemX' :: elemX' in x ==> 0.0<elemX') && (forall elemY' :: elemY' in y ==> 0.0<elemY'); //If we assume this, the proof is verified
assert false;
} 
}

我的主要问题是:如何证明这个引理?

这样你就有了所有的信息,我提供了协方差计算的函数。首先,协方差函数如下:

function method covariance_fun(x:seq<real>, y:seq<real>):real
requires |x| > 1 && |y| > 1;
requires |x| == |y|;
decreases |x|,|y|;
{
summation(x,mean_fun(x),y,mean_fun(y)) / ((|x|-1) as real)
}

正如你所看到的,它执行求和,然后除以长度。此外,请注意,求和函数接收x的平均值和y的平均值。Summation如下:

function method summation(x:seq<real>,x_mean:real,y:seq<real>,y_mean:real):real
requires |x| == |y|;
decreases |x|,|y|;
{
if x == [] then 0.0 
else ((x[0] - x_mean)*(y[0] - y_mean)) 
+ summation(x[1..],x_mean,y[1..],y_mean)
}

正如您所看到的,它递归地执行每个位置的(x-mean(x))*(y-mean(y))

对于辅助函数,mean_fun计算平均值,如下所示:

function method mean_fun(s:seq<real>):real
requires |s| >= 1;
decreases |s|;
{
sum_seq(s) / (|s| as real)
}

注意,它使用sum_seq函数,该函数在给定序列的情况下计算其所有位置的总和。它是递归定义的:

function method sum_seq(s:seq<real>):real
decreases s;
{
if s == [] then 0.0 else s[0] + sum_seq(s[1..])
}

现在,有了所有这些引理,有人能告诉我(1(我是否已经做错了什么和/或(2(如何证明引理吗?

PS:我一直在寻找,这个引理似乎是柯西-施瓦兹不等式,但仍然不知道如何求解。

详细说明答案

我将(1(用乘积定义一个协变函数cov,然后(2(在一个应该成立的新引理中使用这个定义。

此外,请注意,我添加了"x"one_answers"y"不为空的限制,但您可以修改此

//calculates the mean of a sequence
function method mean_fun(s:seq<real>):real
requires |s| >= 1;
decreases |s|;
{
sum_seq(s) / (|s| as real)
}
//from x it constructs a=[x[0]-x_mean, x[1]-x_mean...]
function construct_list (x:seq<real>, m:real) : (a:seq<real>)
requires |x| >= 1
ensures |x|==|a|
{
if |x| == 1 then [x[0]-m]
else [x[0]-m] + construct_list(x[1..],m)
}
//covariance is calculated in terms of product
function cov(x: seq<real>, y: seq<real>) : real
requires |x| == |y|
requires |x| >= 1
ensures cov(x,y) == product(construct_list(x, mean_fun(x)),construct_list(y, mean_fun(y))) / (|x| as real) //if we do '(|x| as real)-1', then we can have a division by zero
//i.e., ensures cov(x,y) == product(a,b) / (|x| as real)
{
//if |a| == 1 then 0.0 //we do base case in '|a|==1' instead of '|a|==1', because we have precondition '|a| >= 1'
//else 
var x_mean := mean_fun(x);
var y_mean := mean_fun(y);
var a := construct_list(x, x_mean);
var b := construct_list(y, y_mean);
product(a,b) / (|a| as real)
}
//Now, test that Cauchy holds for Cov
lemma cauchyInequality_usingCov (x: seq<real>, y: seq<real>)
requires |x| == |y|
requires |x| >= 1
requires forall i :: 0 <= i < |x| ==> x[i] >= 0.0 && y[i] >= 0.0
ensures square(cov(x,y)) <= cov(x,x)*cov(y,y)
{
CauchyInequality(x,y);
}
\IT DOES NOT HOLD!

证明帮助引理(不可证明?(

试图证明HelperLemma,我发现Dafny能够证明a*a*x + b*b*y >= 2.0*a*b*z的LHS是正的。

然后,我开始证明不同的情况(我知道这不是最好的程序(:

(1( 如果abz中的一个为阴性(其余为阳性(,或者当三个为阴性时;则RHS为负当RHS为负时,LHS大于或等于(因为LHS为正(。

(2( 如果abz0,则RHS是0,因此LHS大于或等于。

(3( 如果是a>=1b>=1z>=1,我试图用sqrt_ineq()来证明这一点。但是!我们可以找到反例。对于a=1b=1z=1,RHS为2;现在,选择x作为0y作为0(即LHS=0(。由于0<2,这是一个反例。

我说得对吗?如果不是,我该如何证明这个引理?


lemma HelperLemma(a: real, x: real, b: real, y: real, z: real)
requires x >= 0.0 && y >= 0.0 //&& z >= 0.0
requires square(z) <= x * y
ensures a*a*x + b*b*y >= 2.0*a*b*z
{
assert square(z) == z*z;
assert a*a*x + b*b*y >= 0.0; //a*a*x + b*b*y is always positive
if ((a<0.0 && b>=0.0 && z>=0.0) || (a>=0.0 && b<0.0 && z>=0.0) || (a>=0.0 && b>=0.0 && z<0.0) || (a<0.0 && b<0.0 && z<0.0)) {
assert 2.0*a*b*z <=0.0; //2.0*a*b*z <= 0.0 is negative or 0 when product is negative
assert a*a*x + b*b*y >= 2.0*a*b*z; // When 2.0*a*b*z <= 0.0 is negative or 0, a*a*x + b*b*y is necessarily greater
}
if (a==0.0 || b==0.0 || z==0.0){
assert a*a*x + b*b*y >= 2.0*a*b*z;
}
else if (a>=1.0 && b>=1.0 && z>= 1.0){
assert a*a >= a;
assert b*b >= b;
assert a*a+b*b >= a*b;
assert square(z) <= x * y;
//sqrt_ineq(square(z),x*y);
//assert square(z) == z*z;
//sqrt_square(z);
//assert sqrt(z) <= sqrt(x*y);
//assert (x==0.0 || y == 0.0) ==> (x*y==0.0) ==> (square(z) <= 0.0) ==> z<=0.0;
assert a*a*x + b*b*y >= 2.0*a*b*z;
//INDEED: COUNTER EXAMPLE: a=1, b=1, z=1. Thus: RHS is 2; now, choose x to be 0 and y to be 0 (i.e., LHS=0). Since 0<2, this is a counter example.
}
}

在澄清/修复帖子条件后编辑。

以下是在Dafny中使用计算和归纳法进行的尝试。关于验证的评论很少

由于手头的任务是验证,所以我假设了sqrt函数及其一些性质。HelperLemma是可证明的,前提是我们假定sqrt函数的一些性质。验证中有两个假设很容易证明。

function square(r: real) : real
ensures square(r) >=  0.0
{
r * r
}
function sqrt(r: real) : real
function {:fuel 2} product(a: seq<real>, b: seq<real>) : real
requires |a| == |b|
{
if |a| == 0 then 0.0
else a[0] * b[0] + product(a[1..], b[1..])
}
lemma sqrt_ineq(a: real, b: real)
requires a >= 0.0 && b >= 0.0
requires a <= b
ensures sqrt(a) <= sqrt(b)
lemma sqrt_square(a: real)
ensures sqrt(square(a)) == a
lemma CauchyBaseInequality(a1: real, a2: real, b1: real, b2: real)
ensures square(a1*b1 + a2*b2) <= (a1*a1 + a2*a2) * (b1*b1 + b2*b2)
{
calc <= {
square(a1*b1 + a2*b2) - (a1*a1 + a2*a2) * (b1*b1 + b2*b2);
a1*b1*a1*b1 + a2*b2*a2*b2 + 2.0*a1*b1*a2*b2 - a1*a1*b1*b1 - a1*a1*b2*b2 - a2*a2*b1*b1 - a2*a2*b2*b2;
2.0*a1*b1*a2*b2 - a1*a1*b2*b2 - a2*a2*b1*b1;
- square(a1*b2 - a2*b1);
0.0;
}
}
lemma HelperLemma(a: real, x: real, b: real, y: real, z: real)
requires x >= 0.0 && y >= 0.0
requires square(z) <= x * y
ensures a*a*x + b*b*y >= 2.0*a*b*z
lemma CauchyInequality(a: seq<real>, b: seq<real>)
requires |a| == |b|
ensures square(product(a, b)) <= product(a, a) * product(b, b)
{
if |a| <= 2 {
if |a| == 2 {
CauchyBaseInequality(a[0], a[1], b[0], b[1]);
}
}
else {
var x, xs := a[0], a[1..];
var y, ys := b[0], b[1..];
calc >= {
product(a, a) * product(b, b) - square((product(a, b)));
(x*x + product(xs, xs))*(y*y + product(ys, ys)) - square(x*y + product(xs, ys));
x*x*y*y + y*y*product(xs, xs) + x*x*product(ys, ys) + product(xs, xs)*product(ys, ys)
- x*x*y*y - square(product(xs, ys)) - 2.0*x*y*product(xs, ys);
y*y*product(xs, xs) + x*x*product(ys, ys) + product(xs, xs) * product(ys, ys)
- square(product(xs, ys)) - 2.0*x*y*product(xs, ys);
{ CauchyInequality(xs, ys); }
y*y*product(xs, xs) + x*x*product(ys, ys) - 2.0*x*y*product(xs, ys);
{
CauchyInequality(xs, ys);
assume product(xs, xs) >= 0.0;
assume product(ys, ys) >= 0.0;
HelperLemma(y, product(xs, xs), x, product(ys, ys), product(xs, ys));
}
0.0;
}
}
}
lemma cauchyInequality_usingCov (x: seq<real>, y: seq<real>)
requires |x| == |y|
requires |x| >= 1
requires forall i :: 0 <= i < |x| ==> x[i] >= 0.0 && y[i] >= 0.0
ensures square(cov(x,y)) <= cov(x,x)*cov(y,y)
{
var x_mean := mean_fun(x);
var y_mean := mean_fun(y);

var a := construct_list(x, x_mean);
var b := construct_list(y, y_mean);
assert cov(x, y) == product(a, b) / (|x| as real);
assert cov(x, x) == product(a, a) / (|x| as real);
assert cov(y, y) == product(b, b) / (|x| as real);
CauchyInequality(a, b);

}

Helper引理的验证

function square(r: real): real
ensures square(r) >= 0.0
{
r * r
}
function abs(a: real) : real
ensures abs(a) >= 0.0
{
if a < 0.0 then -a else a
}
function sqrt(r: real): real
requires r >= 0.0
ensures square(sqrt(r)) == r  && sqrt(r) >= 0.0

lemma sqrtIneq(a: real, b: real)
requires a >= 0.0 && b >= 0.0
requires a <= b
ensures sqrt(a) <= sqrt(b)
lemma sqrtLemma(a: real)
ensures sqrt(square(a)) == abs(a)
lemma sqrtMultiply(a: real, b: real)
requires a >= 0.0 && b >= 0.0
ensures sqrt(a*b) == sqrt(a) * sqrt(b);
lemma differenceLemma(a: real, b: real)
requires a >= abs(b) 
ensures a - b >= 0.0 && a + b >= 0.0
{
}
lemma HelperLemma(a: real, x: real, b: real, y: real, z: real)
requires x >= 0.0 && y >= 0.0
requires square(z) <= x * y
ensures a*a*x + b*b*y >= 2.0*a*b*z
{

var sx := sqrt(x);
var sy := sqrt(y);
assert sx * sx == x;
assert sy * sy == y;
if (a >= 0.0 && b >= 0.0) || (a < 0.0 && b < 0.0) {
calc >= {
a*a*x + b*b*y - 2.0*a*b*z;
a*a*sx*sx + b*b*sy*sy - 2.0*a*b*sx*sy + 2.0*a*b*sx*sy - 2.0*a*b*z;
square(a*sx - b*sy) + 2.0*a*b*sx*sy - 2.0*a*b*z;
2.0*a*b*sx*sy - 2.0*a*b*z;
2.0*a*b*(sx*sy - z);
{
sqrtIneq(square(z), x * y);
assert sqrt(x * y) >= sqrt(square(z));
sqrtMultiply(x, y);
assert sx * sy >= sqrt(square(z));
sqrtLemma(z);
assert sx * sy >= abs(z);
differenceLemma(sx*sy, z);
assert sx*sy >= z;
}
0.0;
}
}
else {
calc >= {
a*a*x + b*b*y - 2.0*a*b*z;
a*a*sx*sx + b*b*sy*sy + 2.0*a*b*sx*sy - 2.0*a*b*sx*sy - 2.0*a*b*z;
square(a*sx + b*sy) - 2.0*a*b*sx*sy - 2.0*a*b*z;
- 2.0*a*b*sx*sy - 2.0*a*b*z;
- 2.0*a*b*(sx*sy + z);
{
sqrtIneq(square(z), x * y);
assert sqrt(x * y) >= sqrt(square(z));
sqrtMultiply(x, y);
assert sx * sy >= sqrt(square(z));
sqrtLemma(z);
assert sx * sy >= abs(z);
differenceLemma(sx*sy, z);
assert sx*sy >= -z;
}
0.0;
}
}
}

最新更新