Source code for dc_qiskit_qml.distance_based.hadamard.state.cnot._CCXToffoli

# -*- coding: utf-8 -*-

# Copyright 2018 Carsten Blank
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
r"""
CCXToffoli
============

.. currentmodule:: dc_qiskit_qml.distance_based.hadamard.state.cnot._CCXToffoli

This module implements a :py:class:`CCXFactory` to create a multi-controlled X-gate (or NOT gate) to a circuit
using the Toffoli gate cascade on ancillary qubits described by Nielsen & Chuang (https://doi.org/10.1017/CBO9780511976667).
Its advantage is that it doesn't need expnential gates w.r.t. to the controlled qubit count, however, its downside is
that it needs auxiliary qubits. It depends strongly on the use case whether to use this or the algorithm by
Möttönen et al. as implemented by :py:class:`CCXMöttönen`.

.. autosummary::
    :nosignatures:

    CCXToffoli

CCXToffoli
#############

.. autoclass:: CCXToffoli
    :members:

"""

import logging
from typing import List, Union, Tuple

from qiskit import QuantumCircuit, QuantumRegister
from qiskit.circuit.register import Register
from qiskit.extensions.standard.barrier import barrier
from qiskit.extensions.standard.ccx import ccx
from qiskit.extensions.standard.cx import cx
from qiskit.extensions.standard.x import x

from . import CCXFactory

log = logging.getLogger(__name__)


[docs]class CCXToffoli(CCXFactory): """ cc-X gate implemented via the Toffoli cascade with auxiliary qubits. """
[docs] def ccx(self, qc, conditial_case, control_qubits, tgt): # type:(CCXToffoli, QuantumCircuit, int, List[Tuple[Register, int]], Union[Tuple[Register, int], QuantumRegister]) -> QuantumCircuit """ Using the Toffoli gate cascade on auxiliary qubits, one can create multi-controlled NOT gate. The routine needs to add an auxiliary register called `` ccx_ancilla`` which also will be re-used if multiple calls of this routine are done within the same circuit. As the cascade is always 'undone', the ancilla register is left to the ground state. :param qc: the circuit to apply this operation to :param conditial_case: an integer whose binary representation signifies the branch to controll on :param control_qubits: the qubits that hold the desired conditional case :param tgt: the target to be applied the controlled X gate on :return: the circuit after application of the gate """ # Prepare conditional case bit_string = "{:b}".format(conditial_case).zfill(len(control_qubits)) for i, b in enumerate(reversed(bit_string)): if b == '0': x(qc, control_qubits[i]) barrier(qc) if len(control_qubits) == 1: # This is just the normal CNOT cx(qc, control_qubits[0], tgt) elif len(control_qubits) == 2: # This is the simple Toffoli ccx(qc, control_qubits[0], control_qubits[1], tgt) else: # Create ancilla qubit or take the one that is already there if 'ccx_ancilla' not in [q.name for q in qc.qregs]: ccx_ancilla = QuantumRegister(len(control_qubits) - 1, 'ccx_ancilla') # type: QuantumRegister qc.add_register(ccx_ancilla) else: ccx_ancilla = [q for q in qc.qregs if q.name == 'ccx_ancilla'][0] # type: QuantumRegister # Algorithm ccx(qc, control_qubits[0], control_qubits[1], ccx_ancilla[0]) for i in range(1, ccx_ancilla.size): ccx(qc, control_qubits[i], ccx_ancilla[i - 1], ccx_ancilla[i]) ccx(qc, control_qubits[-1], ccx_ancilla[ccx_ancilla.size - 1], tgt) for i in reversed(range(1, ccx_ancilla.size)): ccx(qc, control_qubits[i], ccx_ancilla[i - 1], ccx_ancilla[i]) ccx(qc, control_qubits[0], control_qubits[1], ccx_ancilla[0]) barrier(qc) # Undo the conditional case for i, b in enumerate(reversed(bit_string)): if b == '0': x(qc, control_qubits[i]) return qc