diff --git a/README.md b/README.md index f90cf9a..0761ae9 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,36 @@ # CMU_Coin-flipping_Experience -A Coin Flipping machine. +A Coin Flipping machine inspired by the IBM Q Experience. -Usage: java -jar xxx.jar \ \ \ +15-459 Assignment + +## Usage + +java -jar xxx.jar \ \ \ + + +## Available operators: -Available operators: Tester: Run a simulation and print results -Prob0Init: Print the probabilities of each possible outcome - -Input commands: -$$ - \begin{align*} - \text{Flip} & & i & & \text{(randomly set coin~$i$ to $0$ or $1$ with probability $1/2$ each)} \\ - \text{Not} & & i & & \text{(turn over the $i$th coin; i.e., deterministically reverse its $0$/$1$ status)} \\ - \text{CNot} & & i\ j & & \text{(if coin~$i$ is $1$ (Tails) then do a Not on coin~$j$, else do nothing)}\\ - \text{CSwap} & & i\ j\ k & & \text{(if coin~$i$ is $1$ (Tails) then swap the values of coins $j$ and $k$)} - \end{align*} - \begin{align*} - \text{CCNot} & & i\ j \ k& & \text{(if coins~$i$ and $j$ are \emph{both} $1$ then do `Not~$k$', else do nothing)}\\ - \text{GenFlip} & & i\ p & & \text{(set coin~$i$ to $0$ with probability $1-p$, to $1$ with probability $p$)} \\ - \text{Gen1Bit} & & i\ p\ q & & \text{(if coin~$i$ is $0$ then make it~$1$ with probability $p$,\qquad}\\ - & & & & \text{else if coin~$i$ is $1$ then make it~$0$ with probability $q$)} - \end{align*} -$$ + +Prob0Init: Print the probabilities of each possible outcome (0 initialized) + +ProbAllInit: Print the probabilities of each coin being 1 for all initializations + + +## Input commands: + +``` +$$ \begin{align*} + \text{Flip} & & i & & \text{(randomly set coin~$i$ to $0$ or $1$ with probability $1/2$ each)} \\ + \text{Not} & & i & & \text{(turn over the $i$th coin; i.e., deterministically reverse its $0$/$1$ status)} \\ + \text{CNot} & & i\ j & & \text{(if coin~$i$ is $1$ (Tails) then do a Not on coin~$j$, else do nothing)}\\ + \text{CSwap} & & i\ j\ k & & \text{(if coin~$i$ is $1$ (Tails) then swap the values of coins $j$ and $k$)} +\end{align*} +\begin{align*} + \text{CCNot} & & i\ j \ k& & \text{(if coins~$i$ and $j$ are \emph{both} $1$ then do `Not~$k$', else do nothing)}\\ + \text{GenFlip} & & i\ p & & \text{(set coin~$i$ to $0$ with probability $1-p$, to $1$ with probability $p$)} \\ + \text{Gen1Bit} & & i\ p\ q & & \text{(if coin~$i$ is $0$ then make it~$1$ with probability $p$,\qquad}\\ + & & & & \text{else if coin~$i$ is $1$ then make it~$0$ with probability $q$)} +\end{align*} $$ +``` \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 9092efc..2f54022 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,9 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { kotlin("jvm") version "1.4.10" + id("com.github.johnrengelman.shadow") version "6.0.0" } group = "com.dedztbh" version = "1.0-SNAPSHOT" @@ -16,8 +18,25 @@ repositories { dependencies { implementation("org.deeplearning4j:deeplearning4j-core:${dl4jVersion}") implementation("org.nd4j:nd4j-native-platform:${dl4jVersion}") - testImplementation(kotlin("test-junit")) + implementation("org.slf4j:slf4j-nop:1.7.13") +// testImplementation(kotlin("test-junit")) } tasks.withType() { kotlinOptions.jvmTarget = "1.8" } + +tasks { + named("shadowJar") { + archiveBaseName.set("cmu_coin_flipping_experience") + mergeServiceFiles() + manifest { + attributes(mapOf("Main-Class" to "MainKt")) + } + } +} + +tasks { + build { + dependsOn(shadowJar) + } +} \ No newline at end of file diff --git a/input.txt b/input.txt index ad7a09e..b8052e4 100644 --- a/input.txt +++ b/input.txt @@ -1,8 +1,5 @@ -GenFlip 0 0.1 GenFlip 1 0.3 -GenFlip 2 0.5 GenFlip 3 0.7 -GenFlip 4 0.9 CNot 1 2 CSwap 3 4 0 CCNot 1 2 3 diff --git a/src/main/kotlin/operator/Prob0Init.kt b/src/main/kotlin/operator/Prob0Init.kt index 81898aa..efd3603 100644 --- a/src/main/kotlin/operator/Prob0Init.kt +++ b/src/main/kotlin/operator/Prob0Init.kt @@ -1,7 +1,7 @@ package operator +import allStates import org.nd4j.linalg.api.ndarray.INDArray -import kotlin.math.pow /** * Created by DEDZTBH on 2020/09/15. @@ -47,8 +47,7 @@ class Prob0Init(N: Int) : ProbFinder(N) { override fun printResult() { val probs = eval(getZeroVec()) - repeat(2.0.pow(N).toInt()) { - val endState = IntArray(N) { i -> (it shr i) and 1 }.apply { reverse() } + allStates(N).forEach { endState -> var prob = 1.0 endState.forEach { i -> prob *= if (i > 0) probs.getDouble(i) else (1.0 - probs.getDouble(i)) diff --git a/src/main/kotlin/operator/ProbAllInit.kt b/src/main/kotlin/operator/ProbAllInit.kt new file mode 100644 index 0000000..71990ac --- /dev/null +++ b/src/main/kotlin/operator/ProbAllInit.kt @@ -0,0 +1,81 @@ +package operator + +import allStates +import org.nd4j.linalg.api.buffer.DataType +import org.nd4j.linalg.api.ndarray.INDArray +import org.nd4j.linalg.factory.Nd4j + +/** + * Created by DEDZTBH on 2020/09/15. + * Project CMU_Coin-flipping_Experience + */ +class ProbAllInit(N: Int) : ProbFinder(N) { + fun eval(probs: INDArray): INDArray { + operations.forEach { + it.apply { + when (this) { + is Matrix -> { + probs.muliRowVector(opVec) + probs.addiRowVector(opBias) + } + is CNot -> { + val i = i.toLong() + val j = j.toLong() + val x = probs.getColumn(i) + val y = probs.getColumn(j) + //(1.0 - x) * y + x * (1.0 - y) + val newCol = x.mul(y).mul(-2.0).add(x).add(y) + probs.putColumn(this.j, newCol) + } + is CSwap -> { + val i = i.toLong() + val j = j.toLong() + val k = k.toLong() + val x = probs.getColumn(i) + val y = probs.getColumn(j) + val z = probs.getColumn(k) + val xy = x.mul(y) + val xz = x.mul(z) + //(1.0 - x) * y + x * z + probs.putColumn(this.j, y.sub(xy).add(xz)) + //(1.0 - x) * z + x * y + probs.putColumn(this.k, z.sub(xz).add(xy)) + } + is CCNot -> { + val i = i.toLong() + val j = j.toLong() + val k = k.toLong() + val x = probs.getColumn(i) + val y = probs.getColumn(j) + val z = probs.getColumn(k) + //(1.0 - x) * (1.0 - y) + val probBoth0 = x.mul(y).sub(x).sub(y).add(1.0) + //probBoth0 * z + (1.0 - probBoth0) * (1.0 - z) + probs.putColumn(this.k, probBoth0.mul(z).mul(2.0).sub(probBoth0).sub(z).add(1.0)) + } + is Gen1Bit -> { + val i = i.toLong() + val x = probs.getColumn(i) + val xx = x.mul(x) + val p_comp = 1.0 - p + probs.putColumn( + this.i, + //x * (1.0 - q) * x + (1.0 - x) * (p + (1.0 - p) * x) + //= xx(1-q) + p + (1-p)x - xp - xx(1-p) + xx.mul(1.0 - q).add(p).add(x.mul(p_comp)).sub(x.mul(p)).sub(xx.mul(p_comp)) + ) + } + } + } + } + return probs + } + + override fun printResult() { + val probs = eval( + // a 2^n by n matrix + Nd4j.create(allStates(N)).castTo(DataType.DOUBLE) + ) + println(probs) + } +} \ No newline at end of file diff --git a/src/main/kotlin/util.kt b/src/main/kotlin/util.kt index 1a721c1..a8cdb21 100644 --- a/src/main/kotlin/util.kt +++ b/src/main/kotlin/util.kt @@ -1,5 +1,6 @@ import java.io.BufferedReader import java.util.* +import kotlin.math.pow /** * Created by DEDZTBH on 2020/09/15. @@ -17,4 +18,9 @@ fun read(): String { fun readInt() = read().toInt() fun readDouble() = read().toDouble() +fun allStates(n: Int) = + Array(2.0.pow(n).toInt()) { + IntArray(n) { i -> (it shr i) and 1 }.apply { reverse() } + } + lateinit var reader: BufferedReader \ No newline at end of file