#!/usr/bin/env python

"""Demonstration of quantum dense coding."""

from sympy import pprint
from sympy.physics.quantum import qapply
from sympy.physics.quantum.gate import H, X, Z, CNOT
from sympy.physics.quantum.grover import superposition_basis


def main():
    psi = superposition_basis(2)
    psi

    # Dense coding demo:

    # Assume Alice has the left QBit in psi
    print("An even superposition of 2 qubits.  Assume Alice has the left QBit.")
    pprint(psi)

    # The corresponding gates applied to Alice's QBit are:
    # Identity Gate (1), Not Gate (X), Z Gate (Z), Z Gate and Not Gate (ZX)
    # Then there's the controlled not gate (with Alice's as control):CNOT(1, 0)
    # And the Hadamard gate applied to Alice's Qbit: H(1)

    # To Send Bob the message |0>|0>
    print("To Send Bob the message |00>.")
    circuit = H(1)*CNOT(1, 0)
    result = qapply(circuit*psi)
    result
    pprint(result)

    # To send Bob the message |0>|1>
    print("To Send Bob the message |01>.")
    circuit = H(1)*CNOT(1, 0)*X(1)
    result = qapply(circuit*psi)
    result
    pprint(result)

    # To send Bob the message |1>|0>
    print("To Send Bob the message |10>.")
    circuit = H(1)*CNOT(1, 0)*Z(1)
    result = qapply(circuit*psi)
    result
    pprint(result)

    # To send Bob the message |1>|1>
    print("To Send Bob the message |11>.")
    circuit = H(1)*CNOT(1, 0)*Z(1)*X(1)
    result = qapply(circuit*psi)
    result
    pprint(result)

if __name__ == "__main__":
    main()
