Source code for dc_qiskit_algorithms.DraperAdder

# 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.
from typing import Optional, Tuple, List, Union

from qiskit import QuantumCircuit, QuantumRegister
from qiskit.circuit import Gate, Instruction, Qubit
from qiskit.extensions import XGate, CU1Gate

from dc_qiskit_algorithms.Qft import QuantumFourierTransformGate
from . import Qft as qft


[docs]class DraperAdderGate(Gate): def __init__(self, input_a, input_b, length=None): """ The Draper adder (arXiv:quant-ph/0008033), provide a and b and make sure to define a size of a register that can hold a or b :param input_a: integer a :param input_b: integer b :param length: size of qubit registers :return: tuple of the circuit and the length of the register """ a_01s = "{0:b}".format(input_a) b_01s = "{0:b}".format(input_b) length = DraperAdderGate.compute_length(input_a, input_b, length) a_01s = a_01s.zfill(length) b_01s = b_01s.zfill(length) super().__init__("add_draper", num_qubits=2*length, params=[input_a, input_b]) self.a_01s = a_01s self.b_01s = b_01s def _define(self): rule = [] # type: List[Tuple[Gate, list, list]] q = QuantumRegister(len(self.a_01s) + len(self.b_01s), "q") qc = QuantumCircuit(q, name=self.name) a = q[0:len(self.a_01s)] b = q[len(self.a_01s):] for i, c in enumerate(self.a_01s): if c == '1': rule.append((XGate(), [a[i]], [])) for i, c in enumerate(self.b_01s): if c == '1': rule.append((XGate(), [b[i]], [])) rule.append((QuantumFourierTransformGate(len(a)), a, [])) for b_index in reversed(range(len(b))): theta_index = 1 for a_index in reversed(range(b_index + 1)): rule.append((CU1Gate(qft.get_theta(theta_index)), [b[b_index], a[a_index]], [])) theta_index += 1 rule.append((QuantumFourierTransformGate(len(a)).inverse(), a, [])) qc._data = rule.copy() self.definition = qc
[docs] def inverse(self): return super().inverse()
[docs] @staticmethod def compute_length(input_a, input_b, length=None): a_01s = "{0:b}".format(input_a) b_01s = "{0:b}".format(input_b) length = max(len(a_01s), len(b_01s), length if length is not None else 0) return length
[docs]def add_draper(self, input_a, input_b, qubits, length=None): # type: (QuantumCircuit, int, int, Union[QuantumRegister, List[Qubit]], Optional[int]) -> Instruction if isinstance(qubits, QuantumRegister): qubits = list(qubits) return self.append(DraperAdderGate(input_a, input_b, length), qubits, [])
QuantumCircuit.add_draper = add_draper