Esempio n. 1
0
    def __init__(self, name: str,
                 qiskrypt_quantum_circuit: QiskryptQuantumCircuit,
                 bell_state_sub_type: str):
        """
        Constructor of the Qiskrypt's Bell State.

        :param name: the name of the Qiskrypt's Bell State.
        :param qiskrypt_quantum_circuit: the name of the Qiskrypt's Bell State.
        :param bell_state_sub_type: the sub-type of the Qiskrypt's Bell State.
        """

        if bell_state_sub_type in POSSIBLE_CONFIGURATIONS_BELL_STATES:
            """
            If the Qiskrypt's Quantum Entanglement is a valid Bell State.
            """

            if qiskrypt_quantum_circuit.get_total_num_qubits() >= 2:
                """
                If the number of qubits of
                the given Qiskrypt's Quantum Circuit is greater or equal than 2.
                """

                super().__init__(
                    name, POSSIBLE_QUANTUM_ENTANGLEMENT_CARDINALITIES[0],
                    POSSIBLE_QUANTUM_ENTANGLEMENT_TYPES[0],
                    qiskrypt_quantum_circuit, bell_state_sub_type)
                """
                Call of the constructor of the super-class Qiskrypt's Quantum Entanglement.
                """

                self.qiskit_quantum_register_control_index = None
                """
                Set the index of the control IBM Qiskit's Quantum Register, as None.
                """

                self.qiskit_quantum_register_target_index = None
                """
                Set the index of the target IBM Qiskit's Quantum Register, as None.
                """

                self.control_qubit_index = None
                """
                Set the index of a qubit inside the control IBM Qiskit's Quantum Register, as None.
                """

                self.target_qubit_index = None
                """
                Set the index of a qubit inside the target IBM Qiskit's Quantum Register, as None.
                """

            else:
                """
                If the number of qubits and bits of
                the given Qiskrypt's Quantum Circuit is strictly lower than 2.
                """

                # TODO - Throw Exception

        else:
            """
Esempio n. 2
0
    def __init__(self, name: str, qiskrypt_quantum_circuit: QiskryptQuantumCircuit, resource_type: str):
        """
        Constructor of the Qiskrypt's Resource State.

        :param name: the name of the Qiskrypt's Resource State.
        :param qiskrypt_quantum_circuit: the name of the Qiskrypt's Resource State.
        :param resource_type: the resource type (i.e., Graph or Cluster) for
                              the Qiskrypt's Resource State.
        """

        if qiskrypt_quantum_circuit.get_total_num_qubits() >= 3:
            """
            If the number of qubits of
            the given Qiskrypt's Quantum Circuit is greater or equal than 3.
            """

            if resource_type in POSSIBLE_CONFIGURATIONS_RESOURCE_STATES:
                """
                If the given resource type of the Qiskrypt's Resource State is valid.
                """

                super().__init__(name, POSSIBLE_QUANTUM_ENTANGLEMENT_CARDINALITIES[1],
                                 POSSIBLE_QUANTUM_ENTANGLEMENT_TYPES[5],
                                 qiskrypt_quantum_circuit)
                """
                Call of the constructor of the super-class Qiskrypt's Quantum Entanglement.
                """

                self.resource_type = resource_type
                """
                Set the resource type of the Qiskrypt's Resource State.
                """

        else:
            """
Esempio n. 3
0
    def __init__(self, name: str,
                 qiskrypt_quantum_circuit: QiskryptQuantumCircuit):
        """
        Constructor of the Qiskrypt's Cluster State.

        :param name: the name of the Qiskrypt's Cluster State.
        :param qiskrypt_quantum_circuit: the name of the Qiskrypt's Cluster State.
        """

        if qiskrypt_quantum_circuit.get_total_num_qubits() >= 1:
            """
            If the number of qubits of
            the given Qiskrypt's Quantum Circuit is greater or equal than 1.
            """

            super().__init__(name, qiskrypt_quantum_circuit,
                             POSSIBLE_CONFIGURATIONS_RESOURCE_STATES[1])
            """
            Call of the constructor of the super-class Qiskrypt's Resource State.
            """

            self.qiskit_quantum_registers_indexes = None
            """
            Set the indexes of the IBM Qiskit's Quantum Registers, associated to the Cluster State itself,
            as the given indexes for it, as None.
            """

            self.qubits_vertices_indexes = None
            """
            Set the indexes of the qubits inside the IBM Qiskit's Quantum Register,
            representing the vertices of the Cluster State, as the given indexes for it, as None.
            """

        else:
            """
Esempio n. 4
0
    def __init__(self, name: str,
                 qiskrypt_quantum_circuit: QiskryptQuantumCircuit):
        """
        Constructor of the Qiskrypt's W State.

        :param name: the name of the Qiskrypt's W State.
        :param qiskrypt_quantum_circuit: the name of the Qiskrypt's W State.
        """

        if qiskrypt_quantum_circuit.get_total_num_qubits() >= 3:
            """
            If the number of qubits of
            the given Qiskrypt's Quantum Circuit is greater or equal than 3.
            """

            super().__init__(name,
                             POSSIBLE_QUANTUM_ENTANGLEMENT_CARDINALITIES[1],
                             POSSIBLE_QUANTUM_ENTANGLEMENT_TYPES[2],
                             qiskrypt_quantum_circuit)
            """
            Call of the constructor of the super-class Qiskrypt's Quantum Entanglement.
            """

            self.qiskit_quantum_registers_indexes = None
            """
            Set the index of the IBM Qiskit's Quantum Registers, as None.
            """

            self.qubits_indexes = None
            """
            Set the indexes of the qubits inside the IBM Qiskit's Quantum Registers, as None.
            """

        else:
            """
    def test_no_1_qiskrypt_quantum_pauli_x_transform_1_qubit(self):
        """
        Test Case #1:

        - Setup the Qiskrypt's Quantum Pauli-X Transform, given a Qiskrypt's Quantum Circuit,
          and apply the Transform to the respective indexes of IBM Qiskit's Quantum Registers and qubits,
          for 1 qubit involved.

        Description of the Steps for the Unitary Test:
        1) The required arguments for the Qiskrypt's Quantum Pauli-X Transform are passed to it,
           i.e., a custom name for it, the associated Qiskrypt's Quantum Circuit,
           and two lists of indexes of IBM Qiskit's Quantum Registers and qubits;
        2) The Pauli-X Transform it is applied to the respective indexes of
           IBM Qiskit's Quantum Registers and qubits defined previously
           (i.e., 1 IBM Qiskit's Quantum Register and 1 qubit);

        Return OK (or FAIL) if, all the Tests performed are OK (or FAIL, otherwise).
        """

        quantum_register_num_qubits = 1
        """
        Set the number of qubits for the Qiskrypt's Quantum Register.
        """

        qiskrypt_quantum_register_quantum_pauli_x_transform_1_qubit = \
            QiskryptQuantumRegister("qu_reg_pauli_x_transform_1", quantum_register_num_qubits)
        """
        Create a Qiskrypt's Quantum Register with 1 qubit.
        """

        qiskrypt_quantum_circuit_quantum_pauli_x_transform_1_qubit = \
            QiskryptQuantumCircuit("qu_circ_pauli_x_transform_1",
                                   qiskrypt_quantum_registers=[qiskrypt_quantum_register_quantum_pauli_x_transform_1_qubit],
                                   qiskrypt_fully_quantum_registers=None,
                                   qiskrypt_semi_quantum_registers=None,
                                   qiskrypt_ancilla_quantum_registers=None,
                                   qiskrypt_ancilla_fully_quantum_registers=None,
                                   qiskrypt_ancilla_semi_quantum_registers=None,
                                   qiskrypt_classical_registers=None,
                                   global_phase=0, qiskit_quantum_circuit=None)
        """
        Create a Qiskrypt's Quantum Circuit with
        the previously created Qiskrypt's Quantum Register.
        """

        qiskrypt_quantum_pauli_x_transform = \
            QiskryptQuantumPauliXTransform("pauli_x_transform_1",
                                           qiskrypt_quantum_circuit_quantum_pauli_x_transform_1_qubit,
                                           ([0] * quantum_register_num_qubits),
                                           [*range(quantum_register_num_qubits)])
        """
        Create the Qiskrypt's Quantum Pauli-X Transform, for 1 Qiskrypt's Quantum Register and 1 qubit.
        """

        qiskrypt_quantum_pauli_x_transform.apply_transform()
        """
        Apply the Quantum Pauli-X Transform to the Qiskrypt's Quantum Registers and qubits involved.
        """

        qiskit_state_vector_backend = Aer.get_backend("statevector_simulator")
        """
        Getting the Aer Simulator Backend for the State Vector Representation
        (i.e., the quantum_regime state represented as its state vector).
        """

        final_quantum_state_vector_state = \
            execute(qiskrypt_quantum_circuit_quantum_pauli_x_transform_1_qubit.qiskit_quantum_circuit,
                    qiskit_state_vector_backend).result().get_statevector()
        """
        Execute the IBM Qiskit's Quantum Circuit of the Qiskrypt's Quantum Circuit
        and store the resulted quantum_regime state represented in a final state vector.
        """

        num_possible_outcomes = (2**quantum_register_num_qubits)
        """
        Compute the number of possible outcomes (i.e., 2^(quantum_register_num_qubits)).
        """

        quantum_pauli_x_transform_1_qubit_array_expected_amplitudes = \
            full((num_possible_outcomes,), (0. + 0.j))
        """
        Create and fill an array with the zeros for the expected values of
        the Qiskrypt's Quantum Pauli-X Transform.
        """

        quantum_pauli_x_transform_1_qubit_array_expected_amplitudes[(
            num_possible_outcomes - 1)] = (1. + 0.j)
        """
        Fill the last position of the expected values of
        the Qiskrypt's Quantum Pauli-X Transform, with 1.
        """

        assert_allclose(
            final_quantum_state_vector_state,
            quantum_pauli_x_transform_1_qubit_array_expected_amplitudes,
            rtol=1e-7,
            atol=1e-7)
        """
        Perform the Assertion of all close values in the values of the quantum_regime state,
        represented by its state vector describing the given qubit,
        after be applied the Qiskrypt's Quantum Pauli-X Transform.
        """
        """
        Dummy Assert Equal for the Unittest.
        """
        self.assertEqual(True, True)
Esempio n. 6
0
    def configure(self, dice_type: str) -> None:
        """
        Configure the Qiskrypt's Quantum Dice Throwing,
        given the type of Dice for its configuration.

        :param dice_type: the type of the Dice for
                          the Qiskrypt's Quantum Dice Throwing.
        """

        if not self.is_configured():
            """
            If the Qiskrypt's Quantum Dice Throwing is not configured yet.
            """

            if dice_type in DICE_TYPES:
                """
                If the given type of the Dice for
                the Qiskrypt's Quantum Dice Throwing is valid.
                """

                self.dice_type = dice_type
                """
                Set the Dice type of the configuration to be used on
                the Qiskrypt's Quantum Dice Throwing,
                according to the given Dice type.
                """

                self.num_dice_sides = NUM_SIDES_FOR_DICE_TYPES[dice_type]
                """
                Set the number of sides of the Dice configured for
                the Qiskrypt's Quantum Dice Throwing, from the size given.
                """

                num_qubits = num_bits = ceil(log2(self.num_dice_sides))
                """
                Set the number of qubits and bits, according to
                the respective number of sides of the Dice configured.
                """

                qiskrypt_quantum_register_quantum_dice_throwing = \
                    QiskryptQuantumRegister("qu_reg_dice_throw", num_qubits)
                """
                Create a Qiskrypt's Quantum Register for the current Qiskrypt's Quantum Dice Throwing,
                with a number of qubits corresponding to the respective number of sides of the Dice configured.
                """

                qiskrypt_classical_register_quantum_dice_throwing = \
                    QiskryptClassicalRegister("cl_reg_dice_throw", num_bits)
                """
                Create a Qiskrypt's Classical Register for the current Qiskrypt's Quantum Dice Throwing,
                with a number of bits corresponding to the respective number of sides of the Dice configured.
                """

                qiskrypt_quantum_circuit = \
                    QiskryptQuantumCircuit("qu_circ_dice_throw",
                                           qiskrypt_quantum_registers=[qiskrypt_quantum_register_quantum_dice_throwing],
                                           qiskrypt_fully_quantum_registers=None,
                                           qiskrypt_semi_quantum_registers=None,
                                           qiskrypt_ancilla_quantum_registers=None,
                                           qiskrypt_ancilla_fully_quantum_registers=None,
                                           qiskrypt_ancilla_semi_quantum_registers=None,
                                           qiskrypt_classical_registers=[qiskrypt_classical_register_quantum_dice_throwing],
                                           global_phase=0, qiskit_quantum_circuit=None)
                """
                Create a Qiskrypt's Quantum Circuit with the both previously created
                Qiskrypt's Quantum Register and Qiskrypt's Classical Register.
                """

                self.qiskrypt_quantum_hadamard_transform = \
                    QiskryptQuantumHadamardTransform("quantum_hadamard_transform_qrg",
                                                     qiskrypt_quantum_circuit,
                                                     ([0] * num_qubits),
                                                     [*range(num_qubits)])
                """
                Setup the currently created Qiskrypt's Quantum Hadamard Transform for
                the Qiskrypt's Quantum Dice Throwing.
                """

                self.qiskrypt_quantum_hadamard_transform.apply_transform()
                """
                Apply the Quantum Hadamard Transform to the Qiskrypt's Quantum Registers and qubits involved
                in the current Qiskrypt's Quantum Hadamard Transform for the Qiskrypt's Quantum Dice Throwing.
                """

                self.qiskrypt_quantum_hadamard_transform \
                    .qiskrypt_quantum_circuit.measure_all_qubits_in_qiskit_quantum_register(0, 0)
                """
                Measure all the qubits in the IBM Qiskit's Quantum Register to
                the IBM Qiskit's Classical Register, in the Qiskrypt's Quantum Circuit of
                the current Qiskrypt's Quantum Hadamard Transform for the Qiskrypt's Quantum Dice Throwing.
                """

            else:
                """
                If the given type of the Dice for
                the Qiskrypt's Quantum Dice Throwing is not valid.
                """
                """
                Return/Raise a Dice Type Not Valid Error for
                the Qiskrypt's Quantum Dice Throwing.
                """
                self.raise_dice_type_not_valid_error()

            self.configured = True
            """
            Set the boolean flag to keep the information about if
            the Qiskrypt's Quantum Dice Throwing is configured or not, as True.
            """

        else:
            """
            If the Qiskrypt's Quantum Dice Throwing is already configured.
            """
            """
            Return/Raise a Dice Already Configured Error for
            the Qiskrypt's Quantum Dice Throwing.
            """
            self.raise_dice_already_configured_error()
    def generate_base_quantum_circuit(self) -> QiskryptQuantumCircuit:
        """
        Generate the base Qiskrypt's Quantum Circuit for each round of
        the Qiskrypt's Communication Session, from the Qiskrypt's Registers
        retrieved of the sender and receiver Qiskrypt's Party Clients,
        and respective associated Qiskrypt's Link connecting them.

        :return quantum_circuit:
        """

        if self.is_started():
            """
            If the Qiskrypt's Communication Session is already started.
            """

            quantum_registers_list = list()
            """
            Create an empty list of the Qiskrypt's Quantum Registers
            to be used for the generation of the base Qiskrypt's Quantum Circuit for
            each round of the Qiskrypt's Communication Session.
            """

            classical_registers_list = list()
            """
            Create an empty list of the Qiskrypt's Classical Registers
            to be used for the generation of the base Qiskrypt's Quantum Circuit for
            each round of the Qiskrypt's Communication Session.
            """

            sender_party_clients = self.get_sender_party_clients()
            """
            Retrieve the list of the sender Qiskrypt's Party Clients.
            """

            num_sender_party_clients = self.get_num_sender_party_clients()
            """
            Retrieve the number of the sender Qiskrypt's Party Clients.
            """

            for current_sender_party_client_index in range(num_sender_party_clients):
                """
                For each sender Qiskrypt's Party Client's index in
                the given list of possible sender Qiskrypt's Party Clients.
                """

                current_sender_party_client = \
                    sender_party_clients[current_sender_party_client_index]
                """
                Retrieve the current sender Qiskrypt's Party Client in
                the given list of possible sender Qiskrypt's Party Clients.
                """

                if isinstance(current_sender_party_client, QiskryptPartyClient):
                    """
                    If the current sender Qiskrypt's Party Client is
                    really a Qiskrypt's Party Client.
                    """

                    current_sender_party_client_quantum_registers = \
                        current_sender_party_client.get_quantum_registers()
                    """
                    Retrieve the Qiskrypt's Quantum Registers of
                    the current sender Qiskrypt's Party Client.
                    """

                    for current_sender_party_client_quantum_register in \
                            current_sender_party_client_quantum_registers:
                        """
                        For each Qiskrypt's Quantum Register of
                        the current sender Qiskrypt's Party Client.
                        """

                        quantum_registers_list.append(current_sender_party_client_quantum_register)
                        """
                        Append the current Qiskrypt's Quantum Register of
                        the current sender Qiskrypt's Party Client to
                        the list of the Qiskrypt's Quantum Registers
                        to be used for the generation of the base Qiskrypt's Quantum Circuit for
                        each round of the Qiskrypt's Communication Session.
                        """

                    current_sender_party_client_classical_registers = \
                        current_sender_party_client.get_classical_registers()
                    """
                    Retrieve the Qiskrypt's Classical Registers of
                    the current sender Qiskrypt's Party Client.
                    """

                    for current_sender_party_client_classical_register in \
                            current_sender_party_client_classical_registers:
                        """
                        For each Qiskrypt's Classical Register of
                        the current sender Qiskrypt's Party Client.
                        """

                        classical_registers_list.append(current_sender_party_client_classical_register)
                        """
                        Append the current Qiskrypt's Classical Register of
                        the current sender Qiskrypt's Party Client to
                        the list of the Qiskrypt's Classical Registers
                        to be used for the generation of the base Qiskrypt's Quantum Circuit for
                        each round of the Qiskrypt's Communication Session.
                        """

                else:
                    """
                    If the current sender Qiskrypt's Party Client is
                    not a Qiskrypt's Party Client.
                    """

                    # TODO Throw - Exception

            link = self.get_link()
            """
            Retrieve the Qiskrypt's Link of the Qiskrypt's Communication Session.
            """

            link_quantum_registers = link.get_quantum_registers()
            """
            Retrieve the Qiskrypt's Quantum Registers of the Qiskrypt's Link.
            """

            for current_link_quantum_register in link_quantum_registers:
                """
                For each Qiskrypt's Quantum Register of the Qiskrypt's Link.
                """

                if isinstance(current_link_quantum_register, QiskryptQuantumRegister):
                    """
                    If the current Qiskrypt's Quantum Register of the Qiskrypt's Link
                    is really a Qiskrypt's Quantum Register.
                    """

                    quantum_registers_list.append(current_link_quantum_register)
                    """
                    Append the current Qiskrypt's Quantum Register of the Qiskrypt's Link to
                    the list of the Qiskrypt's Quantum Registers to be used for
                    the generation of the base Qiskrypt's Quantum Circuit for
                    each round of the Qiskrypt's Communication Session.
                    """

            link_classical_registers = link.get_classical_registers()
            """
            Retrieve the Qiskrypt's Classical Registers of the Qiskrypt's Link.
            """

            for current_link_classical_register in link_classical_registers:
                """
                For each Qiskrypt's Classical Register of the Qiskrypt's Link.
                """

                if isinstance(current_link_classical_register, QiskryptClassicalRegister):
                    """
                    If the current Qiskrypt's Classical Register of the Qiskrypt's Link
                    is really a Qiskrypt's Classical Register.
                    """

                    classical_registers_list.append(current_link_classical_register)
                    """
                    Append the current Qiskrypt's Quantum Register of the Qiskrypt's Link to
                    the list of the Qiskrypt's Classical Registers to be used for
                    the generation of the base Qiskrypt's Quantum Circuit for
                    each round of the Qiskrypt's Communication Session.
                    """

            receiver_party_clients = self.get_receiver_party_clients()
            """
            Retrieve the list of the receiver Qiskrypt's Party Clients.
            """

            num_receiver_party_clients = self.get_num_receiver_party_clients()
            """
            Retrieve the number of the receiver Qiskrypt's Party Clients.
            """

            for current_receiver_party_client_index in range(num_receiver_party_clients):
                """
                For each receiver Qiskrypt's Party Client's index in
                the given list of possible receiver Qiskrypt's Party Clients.
                """

                current_receiver_party_client = \
                    receiver_party_clients[current_receiver_party_client_index]
                """
                Retrieve the current receiver Qiskrypt's Party Client in
                the given list of possible sender Qiskrypt's Party Clients.
                """

                if isinstance(current_receiver_party_client, QiskryptPartyClient):
                    """
                    If the current receiver Qiskrypt's Party Client is
                    really a Qiskrypt's Party Client.
                    """

                    current_receiver_party_client_quantum_registers = \
                        current_receiver_party_client.get_quantum_registers()
                    """
                    Retrieve the Qiskrypt's Quantum Registers of
                    the current receiver Qiskrypt's Party Client.
                    """

                    for current_receiver_party_client_quantum_register in \
                            current_receiver_party_client_quantum_registers:
                        """
                        For each Qiskrypt's Quantum Register of
                        the current receiver Qiskrypt's Party Client.
                        """

                        quantum_registers_list.append(current_receiver_party_client_quantum_register)
                        """
                        Append the current Qiskrypt's Quantum Register of
                        the current receiver Qiskrypt's Party Client to
                        the list of the Qiskrypt's Quantum Registers
                        to be used for the generation of the base Qiskrypt's Quantum Circuit for
                        each round of the Qiskrypt's Communication Session.
                        """

                    current_receiver_party_client_classical_registers = \
                        current_receiver_party_client.get_classical_registers()
                    """
                    Retrieve the Qiskrypt's Classical Registers of
                    the current receiver Qiskrypt's Party Client.
                    """

                    for current_receiver_party_client_classical_register in \
                            current_receiver_party_client_classical_registers:
                        """
                        For each Qiskrypt's Classical Register of
                        the current receiver Qiskrypt's Party Client.
                        """

                        classical_registers_list.append(current_receiver_party_client_classical_register)
                        """
                        Append the current Qiskrypt's Classical Register of
                        the current receiver Qiskrypt's Party Client to
                        the list of the Qiskrypt's Classical Registers
                        to be used for the generation of the base Qiskrypt's Quantum Circuit for
                        each round of the Qiskrypt's Communication Session.
                        """

                else:
                    """
                    If the current sender Qiskrypt's Party Client is
                    not a Qiskrypt's Party Client.
                    """

                    # TODO Throw - Exception

            base_quantum_circuit = \
                QiskryptQuantumCircuit(name="qu_circ_{}".format(self.get_name()),
                                       qiskrypt_quantum_registers=quantum_registers_list,
                                       qiskrypt_fully_quantum_registers=None,
                                       qiskrypt_semi_quantum_registers=None,
                                       qiskrypt_ancilla_quantum_registers=None,
                                       qiskrypt_ancilla_fully_quantum_registers=None,
                                       qiskrypt_ancilla_semi_quantum_registers=None,
                                       qiskrypt_classical_registers=classical_registers_list)
            """
            Create the base Qiskrypt's Quantum Circuit for each round of
            the Qiskrypt's Communication Session, from the Qiskrypt's Registers
            retrieved of the sender and receiver Qiskrypt's Party Clients,
            and respective associated Qiskrypt's Link connecting them.
            """

            """
            Return the base Qiskrypt's Quantum Circuit for each round of
            the Qiskrypt's Communication Session, from the Qiskrypt's Registers
            retrieved of the sender and receiver Qiskrypt's Party Clients,
            and respective associated Qiskrypt's Link connecting them.
            """
            return base_quantum_circuit

        else:
            """
    def __init__(self, name: str,
                 qiskrypt_quantum_circuit: QiskryptQuantumCircuit,
                 qiskit_quantum_registers_indexes: list, qubits_indexes: list):
        """
        Constructor of the Qiskrypt's Quantum Hadamard Transform.

        :param name: the name for the Qiskrypt's Quantum Hadamard Transform.
        :param qiskrypt_quantum_circuit: the Qiskrypt's Quantum Circuit of the Qiskrypt's Quantum Hadamard Transform.
        :param qiskit_quantum_registers_indexes: the indexes of the IBM Qiskit's Quantum Registers,
                                                 involved in the Qiskrypt's Quantum Hadamard Transform.
        :param qubits_indexes: the indexes of the qubits in the IBM Qiskit's Quantum Registers,
                               to which will be applied the Hadamard Gates/Operations,
                               involved in the Qiskrypt's Quantum Hadamard Transform.
        """

        if qiskrypt_quantum_circuit is not None:
            """
            If some Qiskrypt's Quantum Circuit is given.
            """

            if isinstance(qiskrypt_quantum_circuit, QiskryptQuantumCircuit):
                """
                If the Qiskrypt's Quantum Circuit given as argument,
                is really a Qiskrypt's Quantum Circuit.
                """

                num_qiskit_quantum_registers = len(
                    qiskit_quantum_registers_indexes)
                """
                Retrieve the number of the IBM Qiskit's Quantum Registers
                to which will be applied the Quantum Hadamard Transform.
                """

                num_qubits = len(qiskit_quantum_registers_indexes)
                """
                Retrieve the number of the qubits
                to which will be applied the Quantum Hadamard Transform.
                """

                if num_qiskit_quantum_registers == num_qubits:
                    """
                    If the number of the IBM Qiskit's Quantum Registers
                    and the number of the qubits is the same.
                    """

                    if num_qubits <= QISKIT_QASM_SIMULATOR_MAX_NUM_QUBITS:
                        """
                        If the number of qubits given for the Qiskrypt's Quantum Hadamard Transform
                        is lower or equal to the maximum number of Qubits for
                        the QASM (Quantum Assembly) Simulator of the IBM's Qiskit.
                        """

                        for qiskit_quantum_register_index, qubit_index \
                                in zip(qiskit_quantum_registers_indexes, qubits_indexes):
                            """
                            For each pair of indexes of IBM Qiskit's Quantum Registers and qubits. 
                            """

                            qiskrypt_quantum_circuit.check_if_is_possible_to_apply_quantum_operation(
                                qiskit_quantum_register_index,
                                qubit_index,
                                is_operation_only_supported_for_fully_quantum_registers
                                =True)
                            """
                            Check if it is possible to apply a specific Operation,
                            regarding the current IBM Qiskit's Quantum Register index and the current qubit index.
                            """

                        self.name = name
                        """
                        Set the name for the Qiskrypt's Quantum Hadamard Transform.
                        """

                        self.qiskrypt_quantum_circuit = qiskrypt_quantum_circuit
                        """
                        Set the Qiskrypt's Quantum Circuit of
                        the Qiskrypt's Quantum Hadamard Transform.
                        """

                        self.qiskit_quantum_registers_indexes = \
                            qiskit_quantum_registers_indexes
                        """
                        Set the indexes of the IBM Qiskit's Quantum Registers,
                        involved in the Qiskrypt's Quantum Hadamard Transform.
                        """

                        self.qubits_indexes = qubits_indexes
                        """
                        Set the indexes of the qubits in the IBM Qiskit's Quantum Registers,
                        to which will be applied the Hadamard Gates/Operations,
                        involved in the Qiskrypt's Quantum Hadamard Transform.
                        """

                    else:
                        """
                        If the number of qubits given for the Qiskrypt's Quantum Hadamard Transform
                        is greater than the maximum number of Qubits for
                        the QASM (Quantum Assembly) Simulator of the IBM's Qiskit.
                        """

                        self.raise_number_of_qubits_greater_than_maximum_for_qasm_error(
                        )
                        """
                        Return/Raise a Number of Qubits Greater Than Maximum for QASM (Quantum Assembly) Error for
                        the Qiskrypt's Quantum Hadamard Transform.
                        """

                else:
                    """
                    If the number of the IBM Qiskit's Quantum Registers
                    and the number of the qubits is not the same.
                    """

                    self.raise_number_of_qubits_and_number_of_quantum_registers_not_equal_error(
                    )
                    """
                    Return/Raise a Number Of Qubits And Number Of Quantum Registers Not Equal Error for
                    the Qiskrypt's Quantum Hadamard Transform.
                    """

            else:
                """
                If the Qiskrypt's Quantum Circuit given as argument,
                is really a Qiskrypt's Quantum Circuit.
                """

                self.raise_not_an_instance_of_quantum_circuit_error()
                """
                Return/Raise a Not An Instance Of Quantum Circuit Error for
                the Qiskrypt's Quantum Hadamard Transform.
                """

        else:
            """
            If none Qiskrypt's Quantum Circuit is given.
            """

            self.raise_invalid_or_none_quantum_circuit_given_error()
            """
Esempio n. 9
0
    def initialise_qiskrypt_quantum_circuit(self) -> None:
        """
        Initialise the Qiskrypt's Quantum Circuit for the Qiskrypt's Quantum Coin Tossing.
        """

        if not self.is_qiskrypt_quantum_circuit_initialised(
        ) and not self.is_already_tossed():
            """
            If neither the Qiskrypt's Quantum Circuit for
            the Qiskrypt's Quantum Coin Tossing was initialised yet,
            nor the Coin was tossed yet.
            """

            quantum_register_name = "qu_reg_coin_toss"
            """
            Set the name of the Qiskrypt's Quantum Register.
            """

            qiskrypt_quantum_register_coin_tossing = \
                QiskryptQuantumRegister(name=quantum_register_name,
                                        num_qubits=NUM_QUBITS_FOR_COIN)
            """
            Create a Qiskrypt's Quantum Register, given its name and number of qubits.
            """

            classical_register_name = "cl_reg_coin_toss"
            """
            Set the name of the Qiskrypt's Classical Register.
            """

            qiskrypt_classical_register_coin_tossing = \
                QiskryptClassicalRegister(name=classical_register_name,
                                          num_bits=NUM_BITS_FOR_COIN)
            """
            Create a Qiskrypt's Classical Register, given its name and number of bits.
            """

            self.qiskrypt_quantum_circuit = \
                QiskryptQuantumCircuit("qu_circ_coin_toss",
                                       qiskrypt_quantum_registers=[qiskrypt_quantum_register_coin_tossing],
                                       qiskrypt_fully_quantum_registers=None,
                                       qiskrypt_semi_quantum_registers=None,
                                       qiskrypt_ancilla_quantum_registers=None,
                                       qiskrypt_ancilla_fully_quantum_registers=None,
                                       qiskrypt_ancilla_semi_quantum_registers=None,
                                       qiskrypt_classical_registers=[qiskrypt_classical_register_coin_tossing],
                                       global_phase=0, qiskit_quantum_circuit=None)
            """
            Set the Qiskrypt's Quantum Circuit for the Qiskrypt's Quantum Coin Tossing with
            the previously created Qiskrypt's Quantum and Classical Registers.
            """

            self.qiskrypt_quantum_circuit_initialised = True
            """
            Set the boolean flag to keep information about if
            the Qiskrypt's Quantum Circuit for the Qiskrypt's Quantum Coin Tossing
            was already initialised or not, as True.
            """

        else:
            """
            If the Qiskrypt's Quantum Circuit for
            the Qiskrypt's Quantum Coin Tossing was already initialised and/or
            the Coin was also already tossed.
            """

            if self.is_qiskrypt_quantum_circuit_initialised():
                """
                If the Qiskrypt's Quantum Circuit for
                the Qiskrypt's Quantum Coin Tossing was already initialised.
                """
                """
                Return/Raise a Quantum Circuit Already Initialised Error for
                the Qiskrypt's Quantum Coin Tossing.
                """
                self.raise_quantum_circuit_already_initialised_error()

            if self.is_already_tossed():
                """
                If the Coin was already tossed.
                """
                """
                Return/Raise a Coin Already Tossed Error for the Qiskrypt's Quantum Coin Tossing.
                """
                self.raise_coin_already_tossed_error()
Esempio n. 10
0
class QiskryptQuantumCoinTossing:
    """
    Object class for the Qiskrypt's Quantum Coin Tossing.
    """
    def __init__(self, name: str):
        """
        Constructor of the Qiskrypt's Quantum Coin Tossing.

        :param name: the name of the Qiskrypt's Quantum Coin Tossing.
        """

        self.name = name
        """
        Set the name of the Qiskrypt's Quantum Coin Tossing.
        """

        self.qiskrypt_quantum_circuit = None
        """
        Set the Qiskrypt's Quantum Circuit, as None.
        """

        self.qiskrypt_quantum_circuit_initialised = False
        """
        Set the boolean flag to keep information about if
        the Qiskrypt's Quantum Circuit for the Qiskrypt's Quantum Coin Tossing
        was already initialised or not, as False.
        """

        self.already_tossed = False
        """
        Set the boolean flag to keep information about if
        the Coin was already tossed or not, as False.
        """

        self.coin_tossing_outcome_bit = None
        """
        Set the bit outcome for the Coin Tossing,
        from the measurement of the Qiskrypt's Quantum Circuit for
        the Qiskrypt's Quantum Coin Tossing, as None.
        """

    def get_name(self) -> str:
        """
        Return the name of the Qiskrypt's Quantum Coin Tossing.

        :return self.name: the name of the Qiskrypt's Quantum Coin Tossing.
        """
        """
        Return the name of the Qiskrypt's Quantum Coin Tossing.
        """
        return self.name

    def get_qiskrypt_quantum_circuit(self) -> QiskryptQuantumCircuit:
        """
        Return the Qiskrypt's Quantum Circuit for the Qiskrypt's Quantum Coin Tossing.

        :return self.qiskrypt_quantum_circuit: the Qiskrypt's Quantum Circuit for
                                               the Qiskrypt's Quantum Coin Tossing.
        """
        """
        Return the Qiskrypt's Quantum Circuit for the Qiskrypt's Quantum Coin Tossing.
        """
        return self.qiskrypt_quantum_circuit

    def is_qiskrypt_quantum_circuit_initialised(self) -> bool:
        """
        Return the boolean flag to keep information about if
        the Qiskrypt's Quantum Circuit for the Qiskrypt's Quantum Coin Tossing
        was already initialised or not.

        :return self.qiskrypt_quantum_circuit_initialised: the boolean flag to keep information about if
                                                           the Qiskrypt's Quantum Circuit for
                                                           the Qiskrypt's Quantum Coin Tossing
                                                           was already initialised or not.
        """
        """
        Return the boolean flag to keep information about if
        the Qiskrypt's Quantum Circuit for the Qiskrypt's Quantum Coin Tossing
        was already initialised or not.
        """
        return self.qiskrypt_quantum_circuit_initialised

    def is_already_tossed(self) -> bool:
        """
        Return the boolean flag to keep information about if
        the Coin was already tossed or not.

        :return self.already_tossed: the boolean flag to keep information about if
                                     the Coin was already tossed or not.
        """
        """
        Return the boolean flag to keep information about if
        the Coin was already tossed or not.
        """
        return self.already_tossed

    def get_coin_tossing_outcome_bit(self) -> str:
        """
        Return the classical outcome (i.e., the observation) from the Coin Tossing,
        through the execution of the respective Qiskrypt's Quantum Circuit,
        in a binary digit format (i.e., a bit).

        :return self.coin_tossing_outcome_bit: the classical outcome (i.e., the observation) from the Coin Tossing,
                                               through the execution of the respective Qiskrypt's Quantum Circuit,
                                               in a binary digit format (i.e., a bit).
        """

        if self.is_already_tossed():
            """
            If the Coin was already tossed.          
            """
            """
            Return the classical outcome (i.e., the observation) from the Coin Tossing,
            through the execution of the respective Qiskrypt's Quantum Circuit,
            in a binary digit format (i.e., a bit).
            """
            return self.coin_tossing_outcome_bit

        else:
            """
            If the Coin was not tossed yet.          
            """
            """
            Return/Raise a Coin Not Tossed Yet Error for the Qiskrypt's Quantum Coin Tossing.
            """
            self.raise_coin_not_tossed_yet_error()

    def get_coin_tossing_outcome_bit_as_int_base_2(self) -> int:
        """
        Return the classical outcome (i.e., the observation) from the Coin Tossing,
        through the execution of the respective Qiskrypt's Quantum Circuit,
        in an integer base-2 format (i.e., an integer representation of a bit).

        :return int(self.coin_tossing_outcome_bit, base=2): the classical outcome (i.e., the observation) from
                                                            the Coin Tossing, through the execution of
                                                            the respective Qiskrypt's Quantum Circuit,
                                                            in an integer base-2 format
                                                            (i.e., an integer representation of a bit).
        """

        if self.is_already_tossed():
            """
            If the Coin was already tossed.          
            """
            """
            Return the classical outcome (i.e., the observation) from the Coin Tossing,
            through the execution of the respective Qiskrypt's Quantum Circuit,
            in an integer base-2 format (i.e., an integer representation of a bit).
            """
            return int(self.coin_tossing_outcome_bit, base=2)

        else:
            """
            If the Coin was not tossed yet.          
            """
            """
            Return/Raise a Coin Not Tossed Yet Error for the Qiskrypt's Quantum Coin Tossing.
            """
            self.raise_coin_not_tossed_yet_error()

    def get_coin_tossing_outcome_bit_as_head_or_tails(self) -> str:
        """
        Return the classical outcome (i.e., the observation) from the Coin Tossing,
        through the execution of the respective Qiskrypt's Quantum Circuit,
        in an anatomic part format (i.e., 'Heads' for |0⟩ and 'Tails' for |1⟩).

        :return ANATOMIC_PARTS_OF_A_COIN[self.coin_tossing_outcome_bit]: the classical outcome
                                                                         (i.e., the observation) from
                                                                         the Coin Tossing, through the execution of
                                                                         the respective Qiskrypt's Quantum Circuit,
                                                                         in an anatomic part format
                                                                         (i.e., 'Heads' for |0⟩ and 'Tails' for |1⟩).
        """

        if self.is_already_tossed():
            """
            If the Coin was already tossed.          
            """
            """
            Return the classical outcome (i.e., the observation) from the Coin Tossing,
            through the execution of the respective Qiskrypt's Quantum Circuit,
            in a physical anatomic part format (i.e., 'Heads' for |0⟩ and 'Tails' for |1⟩).
            """
            return PHYSICAL_ANATOMIC_PARTS_OF_A_COIN[
                self.coin_tossing_outcome_bit]

        else:
            """
            If the Coin was not tossed yet.          
            """
            """
            Return/Raise a Coin Not Tossed Yet Error for the Qiskrypt's Quantum Coin Tossing.
            """
            self.raise_coin_not_tossed_yet_error()

    def initialise_qiskrypt_quantum_circuit(self) -> None:
        """
        Initialise the Qiskrypt's Quantum Circuit for the Qiskrypt's Quantum Coin Tossing.
        """

        if not self.is_qiskrypt_quantum_circuit_initialised(
        ) and not self.is_already_tossed():
            """
            If neither the Qiskrypt's Quantum Circuit for
            the Qiskrypt's Quantum Coin Tossing was initialised yet,
            nor the Coin was tossed yet.
            """

            quantum_register_name = "qu_reg_coin_toss"
            """
            Set the name of the Qiskrypt's Quantum Register.
            """

            qiskrypt_quantum_register_coin_tossing = \
                QiskryptQuantumRegister(name=quantum_register_name,
                                        num_qubits=NUM_QUBITS_FOR_COIN)
            """
            Create a Qiskrypt's Quantum Register, given its name and number of qubits.
            """

            classical_register_name = "cl_reg_coin_toss"
            """
            Set the name of the Qiskrypt's Classical Register.
            """

            qiskrypt_classical_register_coin_tossing = \
                QiskryptClassicalRegister(name=classical_register_name,
                                          num_bits=NUM_BITS_FOR_COIN)
            """
            Create a Qiskrypt's Classical Register, given its name and number of bits.
            """

            self.qiskrypt_quantum_circuit = \
                QiskryptQuantumCircuit("qu_circ_coin_toss",
                                       qiskrypt_quantum_registers=[qiskrypt_quantum_register_coin_tossing],
                                       qiskrypt_fully_quantum_registers=None,
                                       qiskrypt_semi_quantum_registers=None,
                                       qiskrypt_ancilla_quantum_registers=None,
                                       qiskrypt_ancilla_fully_quantum_registers=None,
                                       qiskrypt_ancilla_semi_quantum_registers=None,
                                       qiskrypt_classical_registers=[qiskrypt_classical_register_coin_tossing],
                                       global_phase=0, qiskit_quantum_circuit=None)
            """
            Set the Qiskrypt's Quantum Circuit for the Qiskrypt's Quantum Coin Tossing with
            the previously created Qiskrypt's Quantum and Classical Registers.
            """

            self.qiskrypt_quantum_circuit_initialised = True
            """
            Set the boolean flag to keep information about if
            the Qiskrypt's Quantum Circuit for the Qiskrypt's Quantum Coin Tossing
            was already initialised or not, as True.
            """

        else:
            """
            If the Qiskrypt's Quantum Circuit for
            the Qiskrypt's Quantum Coin Tossing was already initialised and/or
            the Coin was also already tossed.
            """

            if self.is_qiskrypt_quantum_circuit_initialised():
                """
                If the Qiskrypt's Quantum Circuit for
                the Qiskrypt's Quantum Coin Tossing was already initialised.
                """
                """
                Return/Raise a Quantum Circuit Already Initialised Error for
                the Qiskrypt's Quantum Coin Tossing.
                """
                self.raise_quantum_circuit_already_initialised_error()

            if self.is_already_tossed():
                """
                If the Coin was already tossed.
                """
                """
                Return/Raise a Coin Already Tossed Error for the Qiskrypt's Quantum Coin Tossing.
                """
                self.raise_coin_already_tossed_error()

    def toss_coin(self):
        """
        Toss the Coin related to the Qiskrypt's Quantum Coin Tossing,
        through the application of the respective Quantum Gate/Operation
        (Hadamard Gate/Operation), execution of the respective Qiskrypt's Quantum Circuit
        and the measurement of the qubit representing the Coin in a 50/50 Quantum Superposition,
        storing, the classical result/outcome from the observation of it, in a bit.
        """

        if not self.is_already_tossed(
        ) and self.is_qiskrypt_quantum_circuit_initialised():
            """
            If the Coin is not already tossed and
            the Qiskrypt's Quantum Circuit for the Qiskrypt's Quantum Coin Tossing is already initialised.
            """

            self.qiskrypt_quantum_circuit.apply_hadamard(0, 0)
            """
            Start the Coin Tossing, through the application of the Hadamard Gate/Operation to
            the 1st qubit, to create a Quantum Superposition of 50/50 for the possible outcomes
            (i.e., Head or Tails). 
            """

            self.qiskrypt_quantum_circuit.measure_single_qubit_in_qiskit_quantum_register(
                0, 0, 0, 0)
            """
            Finish the Coin Tossing, through the measurement of the 1st qubit representing the Coin,
            in a Quantum Superposition of 50/50 for the possible outcomes (i.e., Head or Tails) into
            the respective bit, representing the result from the observation of the experiment of
            the IBM Qiskit's Quantum Circuit of the Qiskrypt's Quantum Circuit.
            """

            qiskit_qasm_backend = Aer.get_backend("qasm_simulator")
            """
            Getting the Aer Simulator Backend for the QASM (Quantum Assembly) Simulation
            (i.e., the classical simulation of an IBM Qiskit's Quantum Circuit).
            """

            final_results_frequency_counting = \
                execute(self.qiskrypt_quantum_circuit.get_qiskit_quantum_circuit(),
                        qiskit_qasm_backend, shots=1).result().get_counts()
            """
            Execute the IBM Qiskit's Quantum Circuit of the Qiskrypt's Quantum Circuit
            and store the resulted measurement of its final quantum state.
            """

            self.coin_tossing_outcome_bit = \
                bin(int(final_results_frequency_counting.most_frequent(), base=2))
            """
            Set the bit outcome for the Coin Tossing,
            from the measurement of the Qiskrypt's Quantum Circuit for
            the Qiskrypt's Quantum Coin Tossing, as the resulted outcome
            from the measurement of the IBM Qiskit's Quantum Circuit,
            in an binary format (i.e., the Python's representation for a bit).
            """

            self.already_tossed = True
            """
            Set the boolean flag to keep information about if
            the Coin was already tossed or not, as True.
            """

        else:
            """
            If the Coin is already tossed and/or
            the Qiskrypt's Quantum Circuit for the Qiskrypt's Quantum Coin Tossing is not initialised yet.
            """

            if not self.is_qiskrypt_quantum_circuit_initialised():
                """
                If the Qiskrypt's Quantum Circuit for
                the Qiskrypt's Quantum Coin Tossing is not initialised yet.
                """
                """
                Return/Raise the Quantum Circuit Not Initialised Yet Error for
                the Qiskrypt's Quantum Coin Tossing.
                """
                self.raise_quantum_circuit_not_initialised_yet_error()

            if self.is_already_tossed():
                """
                If the Coin was already tossed.
                """
                """
                Return/Raise a Coin Already Tossed Error for the Qiskrypt's Quantum Coin Tossing.
                """
                self.raise_coin_already_tossed_error()

    @staticmethod
    def raise_quantum_circuit_not_initialised_yet_error() -> None:
        """
        Return/Raise a Quantum Circuit Not Initialised Yet Error for the Qiskrypt's Quantum Coin Tossing.

        :raise quantum_circuit_not_initialised_yet_error: a Quantum Circuit Not Initialised Yet Error for
                                                          the Qiskrypt's Quantum Coin Tossing.
        """

        quantum_circuit_not_initialised_yet_error = \
            QiskryptQuantumCircuitNotInitialisedYetError(primitive="Qiskrypt's Quantum Coin Tossing")
        """
        Retrieve the Quantum Circuit Not Initialised Yet Error for the Qiskrypt's Quantum Coin Tossing.
        """
        """
        Raise the Quantum Circuit Not Initialised Yet Error for the Qiskrypt's Quantum Coin Tossing.
        """
        raise quantum_circuit_not_initialised_yet_error

    @staticmethod
    def raise_quantum_circuit_already_initialised_error() -> None:
        """
        Return/Raise a Quantum Circuit Already Initialised Error for the Qiskrypt's Quantum Coin Tossing.

        :raise quantum_circuit_already_initialised_error: a Quantum Circuit Already Initialised Error for
                                                          the Qiskrypt's Quantum Coin Tossing.
        """

        quantum_circuit_already_initialised_error = \
            QiskryptQuantumCircuitAlreadyInitialisedError(primitive="Qiskrypt's Quantum Coin Tossing")
        """
        Retrieve the Quantum Circuit Already Initialised Error for the Qiskrypt's Quantum Coin Tossing.
        """
        """
        Raise the Quantum Circuit Already Initialised Error for the Qiskrypt's Quantum Coin Tossing.
        """
        raise quantum_circuit_already_initialised_error

    @staticmethod
    def raise_coin_not_tossed_yet_error() -> None:
        """
        Return/Raise a Coin Not Tossed Yet Error for the Qiskrypt's Quantum Coin Tossing.

        :raise coin_not_tossed_yet_error: a Coin Not Tossed Yet Error for
                                          the Qiskrypt's Quantum Coin Tossing.
        """

        coin_not_tossed_yet_error = QiskryptQuantumCoinTossingCoinNotTossedYetError(
        )
        """
        Retrieve the Coin Not Tossed Yet Error for the Qiskrypt's Quantum Coin Tossing.
        """
        """
        Raise the Coin Not Tossed Yet Error for the Qiskrypt's Quantum Coin Tossing.
        """
        raise coin_not_tossed_yet_error

    @staticmethod
    def raise_coin_already_tossed_error() -> None:
        """
        Return/Raise a Coin Already Tossed Error for the Qiskrypt's Quantum Coin Tossing.

        :raise coin_not_tossed_yet_error: a Coin Already Tossed Error for
                                          the Qiskrypt's Quantum Coin Tossing.
        """

        coin_already_tossed_error = QiskryptQuantumCoinTossingCoinAlreadyTossedError(
        )
        """
        Retrieve the Coin Already Tossed Error for the Qiskrypt's Quantum Coin Tossing.
        """
        """
        Raise the Coin Already Tossed Error for the Qiskrypt's Quantum Coin Tossing.
        """
        raise coin_already_tossed_error