def teleportation(psi):
    qr = QuantumRegister(3)
    crz = ClassicalRegister(1)
    crx = ClassicalRegister(1)
    qc = QuantumCircuit(qr, crz, crx)
    init_gate = Initialize(psi)
    qc.append(init_gate, [alice])
    qc.barrier()

    create_bell_pair(qc, common, bob)
    qc.barrier()
    create_alice(qc, alice, common)
    qc.barrier()
    measure_and_send(qc, alice, common)
    qc.barrier()
    create_bob(qc, bob, crz, crx)
    print(qc.draw())

    result = execute(qc, Aer.get_backend('statevector_simulator')).result()
    print(result.get_statevector())

    reverse_init_gate = init_gate.gates_to_uncompute()
    qc.append(reverse_init_gate, [bob])
    print(qc.draw())

    cr_result = ClassicalRegister(1)
    qc.add_register(cr_result)
    qc.measure(bob, 2)
    print(qc.draw())

    result = execute(qc, Aer.get_backend('qasm_simulator')).result()
    print(result.get_counts())
Ejemplo n.º 2
0
    def from_vector(statevector: np.ndarray) -> 'CircuitStateFn':
        """ Construct the CircuitStateFn from a vector representing the statevector.

        Args:
            statevector: The statevector representing the desired state.

        Returns:
            The CircuitStateFn created from the vector.
        """
        normalization_coeff = np.linalg.norm(statevector)
        normalized_sv = statevector / normalization_coeff
        return CircuitStateFn(Initialize(normalized_sv), coeff=normalization_coeff)
Ejemplo n.º 3
0
    def from_vector(statevector: np.ndarray) -> 'CircuitStateFn':
        """ Construct the CircuitStateFn from a vector representing the statevector.

        Args:
            statevector: The statevector representing the desired state.

        Returns:
            The CircuitStateFn created from the vector.

        Raises:
            ValueError: If a vector with complex values is passed, which the Initializer cannot
            handle.
        """
        normalization_coeff = np.linalg.norm(statevector)
        normalized_sv = statevector / normalization_coeff
        if not np.all(np.abs(statevector) == statevector):
            # TODO maybe switch to Isometry?
            raise ValueError('Qiskit circuit Initializer cannot handle non-positive statevectors.')
        return CircuitStateFn(Initialize(normalized_sv), coeff=normalization_coeff)
Ejemplo n.º 4
0
    def __init__(
        self,
        num_qubits: Union[int, List[int]],
        mu: Optional[Union[float, List[float]]] = None,
        sigma: Optional[Union[float, List[float]]] = None,
        bounds: Optional[Union[Tuple[float, float],
                               List[Tuple[float, float]]]] = None,
        upto_diag: bool = False,
        name: str = "P(X)",
    ) -> None:
        r"""
        Args:
            num_qubits: The number of qubits used to discretize the random variable. For a 1d
                random variable, ``num_qubits`` is an integer, for multiple dimensions a list
                of integers indicating the number of qubits to use in each dimension.
            mu: The parameter :math:`\mu`, which is the expected value of the distribution.
                Can be either a float for a 1d random variable or a list of floats for a higher
                dimensional random variable. Defaults to 0.
            sigma: The parameter :math:`\sigma^2` or :math:`\Sigma`, which is the variance or
                covariance matrix. Default to the identity matrix of appropriate size.
            bounds: The truncation bounds of the distribution as tuples. For multiple dimensions,
                ``bounds`` is a list of tuples ``[(low0, high0), (low1, high1), ...]``.
                If ``None``, the bounds are set to ``(-1, 1)`` for each dimension.
            upto_diag: If True, load the square root of the probabilities up to multiplication
                with a diagonal for a more efficient circuit.
            name: The name of the circuit.
        """
        _check_dimensions_match(num_qubits, mu, sigma, bounds)
        _check_bounds_valid(bounds)

        # set default arguments
        dim = 1 if isinstance(num_qubits, int) else len(num_qubits)
        if mu is None:
            mu = 0 if dim == 1 else [0] * dim

        if sigma is None:
            sigma = 1 if dim == 1 else np.eye(dim)

        if bounds is None:
            bounds = (-1, 1) if dim == 1 else [(-1, 1)] * dim

        if isinstance(num_qubits, int):  # univariate case
            super().__init__(num_qubits, name=name)

            x = np.linspace(bounds[0], bounds[1],
                            num=2**num_qubits)  # type: Any
        else:  # multivariate case
            super().__init__(sum(num_qubits), name=name)

            # compute the evaluation points using numpy.meshgrid
            # indexing 'ij' yields the "column-based" indexing
            meshgrid = np.meshgrid(
                *[
                    np.linspace(bound[0], bound[1],
                                num=2**num_qubits[i])  # type: ignore
                    for i, bound in enumerate(bounds)
                ],
                indexing="ij",
            )
            # flatten into a list of points
            x = list(zip(*[grid.flatten() for grid in meshgrid]))

        from scipy.stats import multivariate_normal

        # compute the normalized, truncated probabilities
        probabilities = multivariate_normal.pdf(x, mu, sigma)
        normalized_probabilities = probabilities / np.sum(probabilities)

        # store the values, probabilities and bounds to make them user accessible
        self._values = x
        self._probabilities = normalized_probabilities
        self._bounds = bounds

        # use default the isometry (or initialize w/o resets) algorithm to construct the circuit
        # pylint: disable=no-member
        if upto_diag:
            self.isometry(np.sqrt(normalized_probabilities), self.qubits, None)
        else:
            from qiskit.extensions import Initialize  # pylint: disable=cyclic-import

            initialize = Initialize(np.sqrt(normalized_probabilities))
            circuit = initialize.gates_to_uncompute().inverse()
            self.compose(circuit, inplace=True)
Ejemplo n.º 5
0
def quantum_teleporation_experiment():

    experiment = Experiment("quantum_teleportation")

    qc = QuantumCircuit(1)  # Create a quantum circuit with one qubit
    psi = [1 / sqrt(2),
           1 / sqrt(2)]  # Define initial_state in a superposition state
    initial_state = Initialize(psi)
    qc.append(initial_state,
              [0])  # Apply initialisation operation to the 0th qubit
    result = execute(qc, Aer.get_backend('statevector_simulator')).result(
    )  # Do the simulation, returning the result
    exp_state = result.get_statevector(qc)

    qr = QuantumRegister(3)
    cr = ClassicalRegister(1)
    circuit = QuantumCircuit(qr, cr)

    circuit.append(initial_state, [0])
    circuit.barrier()

    circuit.h(qr[1])
    circuit.cx(qr[1], qr[2])
    circuit.barrier()

    circuit.cx(qr[0], qr[1])
    circuit.h(qr[0])
    circuit.barrier()

    circuit.cz(qr[0], qr[2])
    circuit.cx(qr[1], qr[2])

    circuit.measure(qr[2], cr)

    t = time.time()

    backend = Aer.get_backend('qasm_simulator')
    job_circuit = execute(circuit, backend=backend, shots=4096)
    device_counts = job_circuit.result().get_counts(circuit)

    experiment.write_measurement(device_counts)

    qc = QuantumRegister(3)
    circuit = QuantumCircuit(qc)

    circuit.append(initial_state, [0])
    circuit.barrier()

    circuit.h(qc[1])
    circuit.cx(qc[1], qc[2])
    circuit.barrier()

    circuit.cx(qc[0], qc[1])
    circuit.h(qc[0])
    circuit.barrier()

    circuit.cz(qc[0], qc[2])
    circuit.cx(qc[1], qc[2])

    t = time.time()

    qst_circuit = state_tomography_circuits(circuit, qc[2])
    job_circuit = execute(qst_circuit, backend=backend, shots=4096)

    tomo_circuit = StateTomographyFitter(job_circuit.result(), qst_circuit)
    tomo_circuit.data

    rho_circuit = tomo_circuit.fit()

    F_state = state_fidelity(exp_state, rho_circuit)

    pur = purity(rho_circuit)

    experiment.write_metric("purity", float(pur))
    experiment.write_metric("fit_fidelity_state", float(F_state))
    experiment.write_metric("execution time", int(time.time() - t))

    experiment.write_parameter("backend", "qasm_simulator")
    experiment.write_parameter("number of shots", 4096)
    experiment.write_parameter("job id", str(job_circuit.job_id()))

    experiment.save_exoeriment()

    print("WOOHOO!")  # that exact feeling when your code is working
teleportation_circuit.draw(output='mpl')

# In[16]:

#STEP 5 COMEBACK HERE!
#import a helpful package for math stuff including sqrt
from math import *

#define a state for a single qubit
psi = [1 / sqrt(2), 1 / sqrt(2)]

from qiskit.extensions import Initialize

#qcircuit.initialize #This initialize circuits NOT states

init_gate = Initialize(psi)

teleportation_circuit.append(
    init_gate, [0])  #use init gate on ALice's qubit to put it into that state.

# In[17]:
'''
Step 1 

Alice has the first qubit in some state psi 
Bob has the third qubit
Bob entangles his qubit with a the second qubit ancillary qubit to make the teleportation. 
'''

###Set up entanglement between Bob's and ancillary qubit
teleportation_circuit.h(1)
Ejemplo n.º 7
0
    def __init__(self,
                 num_qubits: Union[int, List[int]],
                 mu: Optional[Union[float, List[float]]] = None,
                 sigma: Optional[Union[float, List[float]]] = None,
                 bounds: Optional[Union[Tuple[float, float],
                                        List[Tuple[float, float]]]] = None,
                 upto_diag: bool = False,
                 name: str = 'P(X)') -> None:
        r"""
        Args:
            num_qubits: The number of qubits used to discretize the random variable. For a 1d
                random variable, ``num_qubits`` is an integer, for multiple dimensions a list
                of integers indicating the number of qubits to use in each dimension.
            mu: The parameter :math:`\mu` of the distribution.
                Can be either a float for a 1d random variable or a list of floats for a higher
                dimensional random variable.
            sigma: The parameter :math:`\sigma^2` or :math:`\Sigma`, which is the variance or
                covariance matrix.
            bounds: The truncation bounds of the distribution as tuples. For multiple dimensions,
                ``bounds`` is a list of tuples ``[(low0, high0), (low1, high1), ...]``.
                If ``None``, the bounds are set to ``(0, 1)`` for each dimension.
            upto_diag: If True, load the square root of the probabilities up to multiplication
                with a diagonal for a more efficient circuit.
            name: The name of the circuit.
        """
        _check_dimensions_match(num_qubits, mu, sigma, bounds)
        _check_bounds_valid(bounds)

        # set default arguments
        dim = 1 if isinstance(num_qubits, int) else len(num_qubits)
        if mu is None:
            mu = 0 if dim == 1 else [0] * dim

        if sigma is None:
            sigma = 1 if dim == 1 else np.eye(dim)

        if bounds is None:
            bounds = (0, 1) if dim == 1 else [(0, 1)] * dim

        if not isinstance(num_qubits, list):  # univariate case
            super().__init__(num_qubits, name=name)

            x = np.linspace(bounds[0], bounds[1],
                            num=2**num_qubits)  # evaluation points
        else:  # multivariate case
            super().__init__(sum(num_qubits), name=name)

            # compute the evaluation points using numpy's meshgrid
            # indexing 'ij' yields the "column-based" indexing
            meshgrid = np.meshgrid(*[
                np.linspace(bound[0], bound[1], num=2**num_qubits[i])
                for i, bound in enumerate(bounds)
            ],
                                   indexing='ij')
            # flatten into a list of points
            x = list(zip(*[grid.flatten() for grid in meshgrid]))

        # compute the normalized, truncated probabilities
        probabilities = []
        from scipy.stats import multivariate_normal

        for x_i in x:
            # pylint: disable=line-too-long
            # map probabilities from normal to log-normal reference:
            # https://stats.stackexchange.com/questions/214997/multivariate-log-normal-probabiltiy-density-function-pdf
            if np.min(x_i) > 0:
                det = 1 / np.prod(x_i)
                probability = multivariate_normal.pdf(np.log(x_i), mu,
                                                      sigma) * det
            else:
                probability = 0
            probabilities += [probability]
        normalized_probabilities = probabilities / np.sum(probabilities)

        # store as properties
        self._values = x
        self._probabilities = normalized_probabilities
        self._bounds = bounds

        # use default the isometry (or initialize w/o resets) algorithm to construct the circuit
        # pylint: disable=no-member
        if upto_diag:
            self.isometry(np.sqrt(normalized_probabilities), self.qubits, None)
        else:
            from qiskit.extensions import Initialize  # pylint: disable=cyclic-import
            initialize = Initialize(np.sqrt(normalized_probabilities))
            circuit = initialize.gates_to_uncompute().inverse()
            self.compose(circuit, inplace=True)
Ejemplo n.º 8
0
def Q4C(NumberOfStrokes):

    # Define vectors for Each stroke

    Thaa = [10, 75, 10, 50, 25, 50, 25, 50, 75, 50, 0, 0, 0, 0, 0, 0]
    Ki = [75, 10, 75, 75, 95, 50, 5, 5, 10, 50, 0, 0, 0, 0, 0, 0]
    Thom = [10, 75, 25, 75, 25, 50, 50, 50, 75, 50, 0, 0, 0, 0, 0, 0]
    Nam = [50, 75, 75, 25, 5, 95, 95, 25, 25, 50, 0, 0, 0, 0, 0, 0]
    Ta = [50, 95, 95, 5, 5, 5, 75, 25, 5, 50, 0, 0, 0, 0, 0, 0]
    Dhin = [50, 50, 50, 95, 5, 50, 95, 25, 5, 50, 0, 0, 0, 0, 0, 0]
    Mi = [25, 5, 50, 95, 75, 95, 5, 5, 5, 50, 0, 0, 0, 0, 0, 0]
    Cha = [50, 5, 50, 25, 25, 25, 5, 5, 5, 50, 0, 0, 0, 0, 0, 0]
    Chapu = [75, 10, 75, 25, 5, 5, 5, 5, 5, 50, 0, 0, 0, 0, 0, 0]
    Kaarvai = [50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 0, 0, 0, 0, 0, 0]

    # Then calculate the norm from the frequency distribution
    Norm_Thaa = linalg.norm(Thaa)
    Norm_Ki = linalg.norm(Ki)
    Norm_Thom = linalg.norm(Thom)
    Norm_Nam = linalg.norm(Nam)
    Norm_Ta = linalg.norm(Ta)
    Norm_Dhin = linalg.norm(Dhin)
    Norm_Mi = linalg.norm(Mi)
    Norm_Cha = linalg.norm(Cha)
    Norm_Chapu = linalg.norm(Chapu)
    Norm_Kaarvai = linalg.norm(Kaarvai)

    # Then normalize the vector to be used with the QuGate
    Thaa_Norm = Thaa / Norm_Thaa
    Ki_Norm = Ki / Norm_Ki
    Thom_Norm = Thom / Norm_Thom
    Nam_Norm = Nam / Norm_Nam
    Ta_Norm = Ta / Norm_Ta
    Dhin_Norm = Dhin / Norm_Dhin
    Mi_Norm = Mi / Norm_Mi
    Cha_Norm = Cha / Norm_Cha
    Chapu_Norm = Chapu / Norm_Chapu
    Kaarvai_Norm = Kaarvai / Norm_Kaarvai

    InitialState = [
        Thaa_Norm, Ki_Norm, Thom_Norm, Nam_Norm, Ta_Norm, Dhin_Norm, Mi_Norm,
        Cha_Norm, Chapu_Norm, Kaarvai_Norm
    ]
    ProbState = [Thaa, Ki, Thom, Nam, Ta, Dhin, Mi, Cha, Chapu, Kaarvai]
    # Print all the normalized input vectors
    #for item in InitialState:
    #    print(item)

    # Select an arbitray input state using random function
    # Though this means that all the states have equal probability as input,
    # it is still a valid assumption for the use-case
    firstSelect = True
    while (firstSelect):
        input_state = random.randint(0, len(InitialState))
        if (input_state != 6 or input_state != 9):
            firstSelect = False

    # Defining Backend for Quantum Simulator
    backend = Aer.get_backend('statevector_simulator')

    # Initialise our qubit and measure it
    NumberofQbits = 4
    NumberofQuOutputBits = 4

    # Define the Quantum Circuit
    qc = QuantumCircuit(NumberofQbits, NumberofQuOutputBits)
    FinalList = []
    for i in range(0, NumberOfStrokes):
        redo_stroke = True
        # print("State " + str (i) + " is " + FindStrokeWithIndex(input_state))
        FinalList.append(FindStrokeWithIndex(input_state))
        while (redo_stroke):
            randomSelect = True
            # Now that the ciruit is setup - Algorithm to generate Music
            initializer = Initialize(InitialState[input_state])
            initializer.label = str("input stroke")
            qc.append(initializer, [0, 1, 2, 3])
            qc.h(0)
            qc.h(1)
            qc.h(2)
            qc.h(3)
            qc.measure_all()
            # qc.draw()
            # State Vector Simulator for Output
            result = execute(qc, backend).result()
            counts = result.get_counts()
            next_state = (list(counts.keys())[list(
                counts.values()).index(1)]).split()[0]
            if (int(next_state, 2) < 10
                    and ProbState[input_state][int(next_state, 2)] >= 25):
                redo_stroke = False
                input_state = int(next_state, 2)
            if (i == NumberOfStrokes - 2):
                if (input_state == 1 or input_state == 3 or input_state == 5
                        or input_state == 6):
                    redo_stroke = False
                else:
                    redo_stroke = True

    return (FinalList)
    qc.measure(qr[b], crz)


#Bobs transformation
def bob_transformation(qc, qubit):
    qc.barrier()
    qc.x(qubit).c_if(crx, 1)
    qc.z(qubit).c_if(crz, 1)


#note: bob's transformation may change depending upon the entanglement channel

#creating a state that we want to teleport : alice will be the sender
state = random_statevector(2, seed=3)
state.probabilities()
init_gate = Initialize(state.data)
qc.append(init_gate, [0])

create_ent_channel(qc, 1, 2)
bell_measurement(qc, 0, 1)
bob_transformation(qc, 2)
#qc.draw('mpl')

#thus the bob qubit will be transformed to state which alice want to sent.
#state of the alice's qubit get collapsed during the process
'''#checking the bobs state
backend=BasicAer.get_backend('statevector_simulator')
in_state=state
plot_bloch_multivector(in_state)'''

disentangler = init_gate.gates_to_uncompute()  #re
Ejemplo n.º 10
0
def initialize_teleport_state(qc, tel_qbit, state):
    init_gate = Initialize(state)
    init_gate.label = "init"
    qc.append(init_gate, [tel_qbit])
    return qc
Ejemplo n.º 11
0
from matplotlib import *
import teleport_algo

# Initialise backend.
backend = Aer.get_backend('statevector_simulator')

# Initialise Circuit.
inp = QuantumRegister(1, name='input register')
out = QuantumRegister(1, name='output register')
circuit = QuantumCircuit(inp, out)

# Set input register to a random state.
psi = random_state(1)
array_to_latex(psi, pretext="|\\psi\\rangle =")
plot_bloch_multivector(psi)
init_gate = Initialize(psi)
circuit.append(init_gate, [inp])
circuit.barrier()

# Perform teleportation.
teleport_algo.quantum_teleport(circuit, inp, out)

# Execute simulation and display result.
job = execute(circuit, backend)
result = job.result()
outputstate = result.get_statevector(circuit, decimals=4)
array_to_latex(psi, pretext="|output\\rangle =")
plot_bloch_multivector(outputstate)

print(circuit.draw())
Ejemplo n.º 12
0
    def __init__(self,
                 num_qubits: Union[int, List[int]],
                 cdfs: Union[Callable[[float], float], List[Callable[[float],
                                                                     float]]],
                 sigma: Optional[Union[float, List[float]]] = None,
                 bounds: Optional[Union[Tuple[float, float],
                                        List[Tuple[float, float]]]] = None,
                 pdfs: Optional[Union[Callable[[float], float],
                                      List[Callable[[float], float]]]] = None,
                 dx: Optional[float] = 1e-6,
                 upto_diag: bool = False,
                 name: str = 'P(X)') -> None:
        r"""
        Args:
            num_qubits: The number of qubits used to discretize the random variable. For a 1d
                random variable, ``num_qubits`` is an integer, for multiple dimensions a list
                of integers indicating the number of qubits to use in each dimension.
            cdfs: The cumulative marginal probability density functions for each dimension.
            sigma: The parameter :math:`\sigma^2` or :math:`\Sigma`, which is the correlation matrix. 
                Defaults to the identity matrix of appropriate size.
            bounds: The truncation bounds of the distribution as tuples. For multiple dimensions,
                ``bounds`` is a list of tuples ``[(low0, high0), (low1, high1), ...]``.
                If ``None``, the bounds are set to ``(-1, 1)`` for each dimension.
            pdfs: The marginal probability density functions for each dimension. 
                If ''None'', marginal pdf is calculated from the pdf by finite differences, but
                consider using automatic differentiation of cdf. 
            dx: The spacing, if finite differences is used to calculate the pdf.
            upto_diag: If True, load the square root of the probabilities up to multiplication
                with a diagonal for a more efficient circuit.
            name: The name of the circuit.
        """
        _check_dimensions_match(num_qubits, cdfs, pdfs, sigma, bounds)
        _check_bounds_valid(bounds)

        # set default arguments
        dim = 1 if isinstance(num_qubits, int) else len(num_qubits)

        mu = 0 if dim == 1 else [0] * dim

        if sigma is None:
            sigma = 1 if dim == 1 else np.eye(dim)

        if bounds is None:
            bounds = (-1, 1) if dim == 1 else [(-1, 1)] * dim

        if not isinstance(cdfs, list):
            cdfs = [cdfs]

        if pdfs is None:
            pdfs = [lambda x: derivative(cdf, x, dx=dx) for cdf in cdfs]

        if not isinstance(num_qubits, list):  # univariate case
            super().__init__(num_qubits, name=name)

            x = np.linspace(bounds[0], bounds[1], num=2**num_qubits)
        else:  # multivariate case
            super().__init__(sum(num_qubits), name=name)

            # compute the evaluation points using numpy's meshgrid
            # indexing 'ij' yields the "column-based" indexing
            meshgrid = np.meshgrid(*[
                np.linspace(bound[0], bound[1], num=2**num_qubits[i])
                for i, bound in enumerate(bounds)
            ],
                                   indexing='ij')
            # flatten into a list of points
            x = list(zip(*[grid.flatten() for grid in meshgrid]))

        from scipy.stats import multivariate_normal

        # compute the normalized, truncated probabilities
        probabilities = multivariate_normal.pdf(x, mu, sigma)

        xa = np.asarray(x, dtype=float)
        zeta = np.concatenate([
            norm.ppf(cdfs[i](xa[:, i])).reshape(xa.shape[0], 1)
            for i in range(dim)
        ], 1)
        probabilities = multivariate_normal.pdf(zeta, mu, sigma) * np.exp(
            0.5 * np.sum(np.square(zeta), axis=-1)) * np.sqrt((2 * np.pi)**dim)
        for i in range(xa.shape[1]):
            probabilities = probabilities * pdfs[i](xa[:, i])

        normalized_probabilities = probabilities / np.sum(probabilities)

        # store the values, probabilities and bounds to make them user accessible
        self._values = x
        self._probabilities = normalized_probabilities
        self._bounds = bounds

        # use default the isometry (or initialize w/o resets) algorithm to construct the circuit
        # pylint: disable=no-member
        if upto_diag:
            self.isometry(np.sqrt(normalized_probabilities), self.qubits, None)
        else:
            from qiskit.extensions import Initialize  # pylint: disable=cyclic-import
            initialize = Initialize(np.sqrt(normalized_probabilities))
            circuit = initialize.gates_to_uncompute().inverse()
            self.compose(circuit, inplace=True)