Source code for qiskit.aqua.circuits.polynomial_rotation

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

# This code is part of Qiskit.
#
# (C) Copyright IBM 2018, 2020.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""Polynomially controlled Pauli-rotations."""

import warnings
from itertools import product
from sympy.ntheory.multinomial import multinomial_coefficients

from qiskit.circuit.library import PolynomialPauliRotations
from qiskit.aqua.utils import CircuitFactory

# pylint: disable=invalid-name


[docs]class PolynomialRotation(CircuitFactory): r"""*DEPRECATED.* Polynomial rotation. .. deprecated:: 0.7.0 Use Terra's qiskit.circuit.library.PolynomialPauliRotations instead. | For a polynomial p(x), a basis state \|i> and a target qubit \|0> this operator acts as: | \|i>\|0> --> \|i>( cos(p(i))\|0> + sin(p(i))\|1> ) | Let n be the number of qubits representing the state, d the degree of p(x) and q_i the qubits, | where q_0 is the least significant qubit. Then for | x = sum_{i=0}^{n-1} 2^{i}*q_i, | we can write | p(x) = sum_{j=0}^{j=d} px[j]*(q_0 + 2*q_1 + ... + 2^{n-1}*q_n-1)^{j}. The expression above is used to obtain the list of controls and rotation angles for the circuit. """ def __init__(self, px, num_state_qubits, basis='Y'): """ Prepare an approximation to a state with amplitudes specified by a polynomial. Args: px (list): coefficients of the polynomial, px[i] is the coefficient of x^i num_state_qubits (int): number of qubits representing the state basis (str): type of Pauli rotation ('X', 'Y', 'Z') Raises: ValueError: invalid input """ warnings.warn('The qiskit.aqua.circuits.PolynomialRotation object is deprecated and ' 'will be removed no earlier than 3 months after the 0.7.0 release of Qiskit ' 'Aqua. You should use qiskit.circuit.library.PolynomialPauliRotations ' 'instead.', DeprecationWarning, stacklevel=2) super().__init__(num_state_qubits + 1) # Store parameters self.num_state_qubits = num_state_qubits self.px = px self.degree = len(px) - 1 self.basis = basis if self.basis not in ['X', 'Y', 'Z']: raise ValueError('Basis must be X, Y or Z')
[docs] def required_ancillas(self): return max(1, self.degree - 1)
[docs] def required_ancillas_controlled(self): return max(1, self.degree)
def _get_controls(self): """ The list of controls is the list of all monomials of the polynomial, where the qubits are the variables. """ t = [0] * (self.num_state_qubits - 1) + [1] cdict = {tuple(t): 0} clist = list(product([0, 1], repeat=self.num_state_qubits)) index = 0 while index < len(clist): tsum = 0 i = clist[index] for j in i: tsum = tsum + j if tsum > self.degree: clist.remove(i) else: index = index + 1 clist.remove(tuple([0] * self.num_state_qubits)) # For now set all angles to 0 for i in clist: cdict[i] = 0 return cdict def _get_thetas(self, cdict): """ Compute the coefficient of each monomial. This will be the argument for the controlled y-rotation. """ for j in range(1, len(self.px)): # List of multinomial coefficients mlist = multinomial_coefficients(self.num_state_qubits, j) # Add angles for m in mlist: temp_t = [] powers = 1 # Get controls for k in range(0, len(m)): # pylint: disable=consider-using-enumerate if m[k] > 0: temp_t.append(1) powers *= 2 ** (k * m[k]) else: temp_t.append(0) temp_t = tuple(temp_t) # Add angle cdict[temp_t] += self.px[j] * mlist[m] * powers return cdict # pylint: disable=arguments-differ
[docs] def build(self, qc, q, q_target, q_ancillas=None, reverse=0): r"""Build the circuit. Args: qc (QuantumCircuit): quantum circuit q (list): list of qubits (has to be same length as self.num_state_qubits) q_target (Qubit): qubit to be rotated. The algorithm is successful when this qubit is in the \|1> state q_ancillas (list): list of ancilla qubits (or None if none needed) reverse (int): if 1, apply with reversed list of qubits (i.e. q_n as q_0, q_n-1 as q_1, etc). """ instr = PolynomialPauliRotations(num_state_qubits=self.num_state_qubits, coeffs=self.px, basis=self.basis, reverse=reverse).to_instruction() # pylint:disable=unnecessary-comprehension qr = [qi for qi in q] + [q_target] if q_ancillas: qr += [qi for qi in q_ancillas[:self.required_ancillas()]] qc.append(instr, qr)