From d96d56b1087fdb5a5a3bb15ad1955242b50c75d6 Mon Sep 17 00:00:00 2001 From: Yusheng Zhao Date: Tue, 20 Dec 2022 15:26:52 +0800 Subject: [PATCH] Mermin magic square (#24) * implement MM game with example * tidy up implementation and use real number * add Project.toml * reformat initializing double bell state on 4 qbits * apply measurement cleaner * explain the shortcut used for a3 and b3 * add check for hermitianness and commutivity * remove notebook and remove helper function play() * add simple documentation * update compatibility information * let user enter col and row info * remove unnecessary import * reimplement bell state creation * reimplement measurement * reimplement hermitian and commutivity checking * reimplement user input * refactor main task to work with new functions * check typos and refine document * clean up code * change variable name and convert doc to comment * update readme and shell script * change matrix name everywhere --- README.md | 1 + examples/MerminMagic/Project.toml | 7 +++ examples/MerminMagic/main.jl | 97 +++++++++++++++++++++++++++++++ examples/run_examples.sh | 2 +- 4 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 examples/MerminMagic/Project.toml create mode 100644 examples/MerminMagic/main.jl mode change 100644 => 100755 examples/run_examples.sh diff --git a/README.md b/README.md index 9c7b7e7..01f4925 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ In examples folder, you will find - [Grover search](examples/Grover) - [Learning a general two qubit unitary gate](examples/GateLearning) - [Bernstein-Vazirani algorithm](examples/BernsteinVazirani) +- [Mermin Magic Square](examples/MerminMagic) Examples of using Yao in other projects - [QuODE](https://github.com/QuantumBFS/QuDiffEq.jl) diff --git a/examples/MerminMagic/Project.toml b/examples/MerminMagic/Project.toml new file mode 100644 index 0000000..43d538b --- /dev/null +++ b/examples/MerminMagic/Project.toml @@ -0,0 +1,7 @@ +[deps] +Yao = "5872b779-8223-5990-8dd0-5abbb0748c8c" +YaoPlots = "32cfe2d9-419e-45f2-8191-2267705d8dbc" + +[compat] +Yao = "0.8" +julia = "1.8" diff --git a/examples/MerminMagic/main.jl b/examples/MerminMagic/main.jl new file mode 100644 index 0000000..74f6281 --- /dev/null +++ b/examples/MerminMagic/main.jl @@ -0,0 +1,97 @@ +# Mermin-Peres Magic Square Game Algorithm +# https://www.gregegan.net/SCIENCE/MPMS/MPMS.html +using Yao + +# measurement operator table +# see Table S1 in https://arxiv.org/abs/2206.12042 +const magic_square = [kron(I2, Z) kron(Z, I2) kron(Z, Z) + kron(X, I2) kron(I2, X) kron(X, X) + kron(-X, Z) kron(-Z, X) kron(Y, Y)] + +""" + bell_state(which::Int) -> AbstractRegister + +Initialize bell state on a quantum register. + +# Arguments +- `which::Int`: which of the four bell states to initialize + 1 corresponds to ``(|00> + |11>)/√2`` + 2 corresponds to ``(|00> - |11>)/√2`` + 3 corresponds to ``(|01> + |10>)/√2`` + 4 corresponds to ``(|01> - |10>)/√2`` + +# Returns +- `AbstractRegister`: the register on which we have initialized the bell state +""" +function bell_state(which::Int) + + @assert 1 <= which <= 4 "Input $(which) is not in range 1..4" + reg = zero_state(2) + apply!(reg, chain(put(2, 1 => H), cnot(2, 1, 2))) + (which == 2 || which == 4) && apply!(reg, put(2, 1 => Z)) + (which == 3 || which == 4) && apply!(reg, put(2, 1 => X)) + return reg +end + +# Alice perform Measurement using Operator specified by row idx +alice_measure!(reg::AbstractRegister, row::Int) = [real(measure!(op, reg, (1, 3))) for op in magic_square[row, :]] +# Bob perform Measurement using Operator specified by row idx +bob_measure!(reg::AbstractRegister, col::Int) = [real(measure!(op, reg, (2, 4))) for op in magic_square[:, col]] + +""" + input_idx(which::String) -> Int + +# Arguments +- `which::String`: whether user is asked to provide the index for the row or column + +# Returns +- `Int`: index determined by the user +""" +function input_idx(which::String) + idx = 0 + while idx > 3 || idx < 1 + println("Please provide a $which number in the range [1,3]") + try + idx = parse(Int64, readline()) + catch e + showerror(stdout, e) + println(" Please enter a NUMBER!") + end + end + return idx +end + +function main() + println("Dealer: Let's Play Mermin's Magic Square Game!") + + # ask the user to input row and column index + i = input_idx("row") + j = input_idx("column") + + println("Alice will provide three numbers to be written on row: $(i)") + println("Bob will provide three numbers to be written on column: $(j)") + + # Initialize two pairs of bell state ``(|00> + |11>) ⊗ (|00> + |11>)/2``. + # First qubit of each bell state pair belongs to Alice and the others belong to Bob. + reg1 = join(bell_state(1), bell_state(1)) + + # do measurement and get answer string + a1, a2, a3 = alice_measure!(reg1, i) + b1, b2, b3 = bob_measure!(reg1, j) + + println("Alice should give answer: $a1 , $a2 , $a3") + println("Bob should give answer: $b1 , $b2 , $b3") + #We should see j_th element in [a1,a2,a3] is equal to i_th element in [b1,b2,b3] + @assert [a1, a2, a3][j] == [b1, b2, b3][i] ("Opps, something is wrong, the j_th item in + Alice's answer does not match the i_th item in Bob's answer") + + # To reveal some magic behind the scenes, you may check that + # measurements on each row and each columns commute with + # each other and all are hermitian + @assert (all(k -> iscommute(magic_square[k, :]...), 1:3) && + all(k -> iscommute(magic_square[:, k]...), 1:3) && + all(ishermitian, magic_square)) +end + + +main() diff --git a/examples/run_examples.sh b/examples/run_examples.sh old mode 100644 new mode 100755 index cf56f74..0961d47 --- a/examples/run_examples.sh +++ b/examples/run_examples.sh @@ -1,6 +1,6 @@ #! /bin/bash # run this file to make sure all examples work -FILES="Grover QAOA HHL QCBM QuGAN Shor VQE GateLearning GroundStateSolvers BernsteinVazirani" +FILES="Grover QAOA HHL QCBM QuGAN Shor VQE GateLearning GroundStateSolvers BernsteinVazirani MerminMagic" for folder in $FILES do echo "executing example: $folder"