diff --git a/testcases/proof/proba/Coins.scala b/testcases/proof/proba/Coins.scala index 0a84cb072700fe9a4070ec0ed4003b4596bb03d7..c85893820fb157ba73a6961ba428af916e42eeea 100644 --- a/testcases/proof/proba/Coins.scala +++ b/testcases/proof/proba/Coins.scala @@ -3,55 +3,76 @@ import leon.lang._ object Coins { - case class CoinDist(pHead: Rational) { - def pTail: Rational = Rational(1) - pHead + case class CoinDist(pHead: Real) { + def pTail: Real = { + require(pHead >= Real(0) && pHead <= Real(1)) + Real(1) - pHead + } ensuring(res => res >= Real(0) && res <= Real(1)) } def isDist(dist: CoinDist): Boolean = - dist.pHead.isRational && dist.pHead >= Rational(0) && dist.pHead <= Rational(1) + dist.pHead >= Real(0) && dist.pHead <= Real(1) - case class CoinsJoinDist(hh: Rational, ht: Rational, th: Rational, tt: Rational) + case class CoinsJoinDist(hh: Real, ht: Real, th: Real, tt: Real) def isDist(dist: CoinsJoinDist): Boolean = - dist.hh.isRational && dist.hh >= Rational(0) && dist.hh <= Rational(1) && - dist.ht.isRational && dist.ht >= Rational(0) && dist.ht <= Rational(1) && - dist.th.isRational && dist.th >= Rational(0) && dist.th <= Rational(1) && - dist.tt.isRational && dist.tt >= Rational(0) && dist.tt <= Rational(1) && - (dist.hh + dist.ht + dist.th + dist.tt) ~ Rational(1) + dist.hh >= Real(0) && dist.hh <= Real(1) && + dist.ht >= Real(0) && dist.ht <= Real(1) && + dist.th >= Real(0) && dist.th <= Real(1) && + dist.tt >= Real(0) && dist.tt <= Real(1) && + (dist.hh + dist.ht + dist.th + dist.tt) == Real(1) def isUniform(dist: CoinDist): Boolean = { require(isDist(dist)) - dist.pHead ~ Rational(1, 2) + dist.pHead == Real(1, 2) } - def join(c1: CoinDist, c2: CoinDist): CoinsJoinDist = + def join(c1: CoinDist, c2: CoinDist): CoinsJoinDist = { + //require(isDist(c1) && isDist(c2)) + require( + c1.pHead >= Real(0) && c1.pHead <= Real(1) && + c2.pHead >= Real(0) && c2.pHead <= Real(1) + ) + CoinsJoinDist( c1.pHead*c2.pHead, - c1.pHead*c2.pTail, - c1.pTail*c2.pHead, - c1.pTail*c2.pTail) + c1.pHead*(Real(1)-c2.pHead), + (Real(1)-c1.pHead)*c2.pHead, + (Real(1)-c1.pHead)*(Real(1)-c2.pHead) + ) + } ensuring(res => + res.hh >= Real(0) && res.hh <= Real(1) && + res.ht >= Real(0) && res.ht <= Real(1) && + res.th >= Real(0) && res.th <= Real(1) && + res.tt >= Real(0) && res.tt <= Real(1) && + (res.hh + res.ht + res.th + res.tt) == Real(1) + ) def firstCoin(dist: CoinsJoinDist): CoinDist = { + require(isDist(dist)) CoinDist(dist.hh + dist.ht) - } ensuring(res => res.pTail ~ (dist.th + dist.tt)) + } ensuring(res => isDist(res) && res.pTail == (dist.th + dist.tt)) def secondCoin(dist: CoinsJoinDist): CoinDist = { + require(isDist(dist)) CoinDist(dist.hh + dist.th) - } ensuring(res => res.pTail ~ (dist.ht + dist.tt)) + } ensuring(res => isDist(res) && res.pTail == (dist.ht + dist.tt)) - def isIndependent(dist: CoinsJoinDist): Boolean = + def isIndependent(dist: CoinsJoinDist): Boolean = { + require(isDist(dist)) join(firstCoin(dist), secondCoin(dist)) == dist + } def isEquivalent(dist1: CoinsJoinDist, dist2: CoinsJoinDist): Boolean = { require(isDist(dist1) && isDist(dist2)) - (dist1.hh ~ dist2.hh) && - (dist1.ht ~ dist2.ht) && - (dist1.th ~ dist2.th) && - (dist1.tt ~ dist2.tt) + (dist1.hh == dist2.hh) && + (dist1.ht == dist2.ht) && + (dist1.th == dist2.th) && + (dist1.tt == dist2.tt) } @@ -98,12 +119,12 @@ object Coins { def sum(coin1: CoinDist, coin2: CoinDist): CoinDist = { require(isDist(coin1) && isDist(coin2)) CoinDist(coin1.pHead*coin2.pHead + coin1.pTail*coin2.pTail) - } ensuring(res => res.pTail ~ (coin1.pHead*coin2.pTail + coin1.pTail*coin2.pHead)) + } ensuring(res => res.pTail == (coin1.pHead*coin2.pTail + coin1.pTail*coin2.pHead)) def sum(dist: CoinsJoinDist): CoinDist = { require(isDist(dist)) CoinDist(dist.hh + dist.tt) - } ensuring(res => res.pTail ~ (dist.ht + dist.th)) + } ensuring(res => res.pTail == (dist.ht + dist.th)) diff --git a/testcases/proof/proba/coins.smt2 b/testcases/proof/proba/coins.smt2 new file mode 100644 index 0000000000000000000000000000000000000000..d6a7aeb515ac6b0002a18116fc286e70b12dbccb --- /dev/null +++ b/testcases/proof/proba/coins.smt2 @@ -0,0 +1,31 @@ +(declare-fun start!1 () Bool) + +(assert start!1) + +(declare-datatypes () ( (CoinDist!2 (CoinDist!3 (pHead!1 Real))) )) + +(declare-fun c1!0 () CoinDist!2) + +(declare-fun c2!0 () CoinDist!2) + +(declare-datatypes () ( (CoinsJoinDist!1 (CoinsJoinDist!2 (hh!1 Real) (ht!1 Real) (th!1 Real) (tt!1 Real))) )) + +(declare-fun lt!2 () CoinsJoinDist!1) + +(declare-fun isDist!1 (CoinsJoinDist!1) Bool) + +(assert (and (>= (pHead!1 c1!0) 0) (<= (pHead!1 c1!0) 1) (>= (pHead!1 c2!0) 0) (<= (pHead!1 c2!0) 1))) + +(assert (= lt!2 (CoinsJoinDist!2 (* (pHead!1 c1!0) (pHead!1 c2!0)) (* (pHead!1 c1!0) (- 1 (pHead!1 c2!0))) (* (- 1 (pHead!1 c1!0)) (pHead!1 c2!0)) (* (- 1 (pHead!1 c1!0)) (- 1 (pHead!1 c2!0)))))) + + +(assert (not + (and (>= (hh!1 lt!2) 0) (<= (hh!1 lt!2) 1) + (>= (ht!1 lt!2) 0) (<= (ht!1 lt!2) 1) + (>= (th!1 lt!2) 0) (<= (th!1 lt!2) 1) + (>= (tt!1 lt!2) 0) (<= (tt!1 lt!2) 1) + (= (+ (hh!1 lt!2) (ht!1 lt!2) (th!1 lt!2) (tt!1 lt!2)) 1)))) + + +(check-sat) + diff --git a/testcases/proof/proba/rationals/Coins.scala b/testcases/proof/proba/rationals/Coins.scala new file mode 100644 index 0000000000000000000000000000000000000000..f7f5b6f9a73ec07dddfad378d70139bb7fdb4fe3 --- /dev/null +++ b/testcases/proof/proba/rationals/Coins.scala @@ -0,0 +1,188 @@ +import leon.annotation._ +import leon.lang._ + +object Coins { + + case class CoinDist(pHead: Rational) { + def pTail: Rational = Rational(1) - pHead + } + + def isDist(dist: CoinDist): Boolean = + dist.pHead.isRational && dist.pHead >= Rational(0) && dist.pHead <= Rational(1) + + + case class CoinsJoinDist(hh: Rational, ht: Rational, th: Rational, tt: Rational) + + def isDist(dist: CoinsJoinDist): Boolean = + dist.hh.isRational && dist.hh >= Rational(0) && dist.hh <= Rational(1) && + dist.ht.isRational && dist.ht >= Rational(0) && dist.ht <= Rational(1) && + dist.th.isRational && dist.th >= Rational(0) && dist.th <= Rational(1) && + dist.tt.isRational && dist.tt >= Rational(0) && dist.tt <= Rational(1) && + (dist.hh + dist.ht + dist.th + dist.tt) ~ Rational(1) + + + def isUniform(dist: CoinDist): Boolean = { + require(isDist(dist)) + dist.pHead ~ Rational(1, 2) + } + + + def join(c1: CoinDist, c2: CoinDist): CoinsJoinDist = + CoinsJoinDist( + c1.pHead*c2.pHead, + c1.pHead*c2.pTail, + c1.pTail*c2.pHead, + c1.pTail*c2.pTail) + + def firstCoin(dist: CoinsJoinDist): CoinDist = { + require(isDist(dist)) + CoinDist(dist.hh + dist.ht) + } ensuring(res => res.pTail ~ (dist.th + dist.tt)) + + def secondCoin(dist: CoinsJoinDist): CoinDist = { + require(isDist(dist)) + CoinDist(dist.hh + dist.th) + } ensuring(res => res.pTail ~ (dist.ht + dist.tt)) + + def isIndependent(dist: CoinsJoinDist): Boolean = { + require(isDist(dist)) + join(firstCoin(dist), secondCoin(dist)) == dist + } + + def isEquivalent(dist1: CoinsJoinDist, dist2: CoinsJoinDist): Boolean = { + require(isDist(dist1) && isDist(dist2)) + + (dist1.hh ~ dist2.hh) && + (dist1.ht ~ dist2.ht) && + (dist1.th ~ dist2.th) && + (dist1.tt ~ dist2.tt) + } + + + //case class CoinCondDist(ifHead: CoinDist, ifTail: CoinDist) + + //def condByFirstCoin(dist: CoinsJoinDist): CoinCondDist = { + // CoinCondDist( + // CoinDist( + // dist.hh*(dist.th + dist.tt), //probability of head if head + // dist.ht*(dist.th + dist.tt) //probability of tail if head + // ), + // CoinDist( + // dist.th*(dist.hh + dist.ht), //probability of head if tail + // dist.tt*(dist.hh + dist.ht) //probability of tail if tail + // ) + // ) + //} + + //def combine(cond: CoinCondDist, dist: CoinDist): CoinsJoinDist = { + // require(isDist(dist) && dist.pHead > 0 && dist.pTail > 0) + + // val hh = cond.ifHead.pHead * dist.pHead + // val ht = cond.ifHead.pTail * dist.pHead + // val th = cond.ifTail.pHead * dist.pTail + // val tt = cond.ifTail.pTail * dist.pTail + // CoinsJoinDist(hh, ht, th, tt) + //} + // + //def condIsSound(dist: CoinsJoinDist): Boolean = { + // require(isDist(dist) && dist.hh > 0 && dist.ht > 0 && dist.th > 0 && dist.tt > 0) + + // val computedDist = combine(condByFirstCoin(dist), firstCoin(dist)) + // isEquivalent(dist, computedDist) + //} holds + + + //should be INVALID + def anyDistributionsNotEquivalent(dist1: CoinsJoinDist, dist2: CoinsJoinDist): Boolean = { + require(isDist(dist1) && isDist(dist2)) + isEquivalent(dist1, dist2) + } holds + + //sum modulo: face is 0, tail is 1 + def sum(coin1: CoinDist, coin2: CoinDist): CoinDist = { + require(isDist(coin1) && isDist(coin2)) + CoinDist(coin1.pHead*coin2.pHead + coin1.pTail*coin2.pTail) + } ensuring(res => res.pTail ~ (coin1.pHead*coin2.pTail + coin1.pTail*coin2.pHead)) + + def sum(dist: CoinsJoinDist): CoinDist = { + require(isDist(dist)) + CoinDist(dist.hh + dist.tt) + } ensuring(res => res.pTail ~ (dist.ht + dist.th)) + + + + + /*************************************************** + * properties of sum operation * + ***************************************************/ + + //def sumIsUniform1(coin1: CoinDist, coin2: CoinDist): Boolean = { + // require(isDist(coin1) && isDist(coin2) && isUniform(coin1) && isUniform(coin2)) + // val dist = sum(coin1, coin2) + // isUniform(dist) + //} holds + + //def sumIsUniform2(coin1: CoinDist, coin2: CoinDist): Boolean = { + // require(isDist(coin1) && isDist(coin2) && isUniform(coin1)) + // val dist = sum(coin1, coin2) + // isUniform(dist) + //} holds + + //def sumUniform3(coin1: CoinDist, coin2: CoinDist, coin3: CoinDist): Boolean = { + // require(isDist(coin1) && isDist(coin2) && isDist(coin3) && isUniform(coin1)) + // val dist = sum(sum(coin1, coin2), coin3) + // isUniform(dist) + //} holds + + //def sumUniformWithIndependence(dist: CoinsJoinDist): Boolean = { + // require(isDist(dist) && isIndependent(dist) && (isUniform(firstCoin(dist)) || isUniform(secondCoin(dist)))) + // val res = sum(dist) + // isUniform(res) + //} holds + + ////should find counterexample, indepenence is required + //def sumUniformWithoutIndependence(dist: CoinsJoinDist): Boolean = { + // require(isDist(dist) && (isUniform(firstCoin(dist)) || isUniform(secondCoin(dist)))) + // val res = sum(dist) + // isUniform(res) + //} holds + + + ////sum of two non-uniform dices is potentially uniform (no result) + //def sumNonUniform1(coin1: CoinDist, coin2: CoinDist): Boolean = { + // require(isDist(coin1) && isDist(coin2) && !isUniform(coin1) && !isUniform(coin2)) + // val dist = sum(coin1, coin2) + // !isUniform(dist) + //} holds + + //def sumNonUniform2(coin1: CoinDist, coin2: CoinDist, coin3: CoinDist): Boolean = { + // require(isDist(coin1) && isDist(coin2) && isDist(coin3) && !isUniform(coin1) && !isUniform(coin2) && !isUniform(coin3)) + // val dist = sum(sum(coin1, coin2), coin3) + // !isUniform(dist) + //} //holds + + //def sumNonUniformWithIndependence(dist: CoinsJoinDist): Boolean = { + // require(isDist(dist) && isIndependent(dist) && !isUniform(firstCoin(dist)) && !isUniform(secondCoin(dist))) + // val res = sum(dist) + // !isUniform(res) + //} holds + + ////independence is required + //def sumNonUniformWithoutIndependence(dist: CoinsJoinDist): Boolean = { + // require(isDist(dist) && !isUniform(firstCoin(dist)) && !isUniform(secondCoin(dist))) + // val res = sum(dist) + // !isUniform(res) + //} holds + + + //def sumIsCommutative(coin1: CoinDist, coin2: CoinDist, coin3: CoinDist): Boolean = { + // require(isDist(coin1) && isDist(coin2)) + // sum(coin1, coin2) == sum(coin2, coin1) + //} holds + + //def sumIsAssociative(coin1: CoinDist, coin2: CoinDist, coin3: CoinDist): Boolean = { + // require(isDist(coin1) && isDist(coin2) && isDist(coin3)) + // sum(sum(coin1, coin2), coin3) == sum(coin1, sum(coin2, coin3)) + //} //holds + +}