mirror of https://github.com/Qiskit/qiskit.git
instruction.repeat (#2901)
* from unittest.mock import patch * . * moving from a different branch to master * clean up import * style
This commit is contained in:
parent
fa72ba6640
commit
b970a21796
|
@ -42,6 +42,10 @@ class Gate(Instruction):
|
|||
"""
|
||||
raise QiskitError("to_matrix not defined for this {}".format(type(self)))
|
||||
|
||||
def _return_repeat(self, exponent):
|
||||
return Gate(name="%s*%s" % (self.name, exponent), num_qubits=self.num_qubits,
|
||||
params=self.params)
|
||||
|
||||
def assemble(self):
|
||||
"""Assemble a QasmQobjInstruction"""
|
||||
instruction = super().assemble()
|
||||
|
|
|
@ -39,6 +39,7 @@ import numpy
|
|||
|
||||
from qiskit.qasm.node import node
|
||||
from qiskit.exceptions import QiskitError
|
||||
from qiskit.circuit.quantumregister import QuantumRegister
|
||||
from qiskit.circuit.classicalregister import ClassicalRegister
|
||||
from qiskit.circuit.parameter import Parameter
|
||||
from qiskit.qobj.models.qasm import QasmQobjInstruction
|
||||
|
@ -311,3 +312,31 @@ class Instruction:
|
|||
flat_qargs = [qarg for sublist in qargs for qarg in sublist]
|
||||
flat_cargs = [carg for sublist in cargs for carg in sublist]
|
||||
yield flat_qargs, flat_cargs
|
||||
|
||||
def _return_repeat(self, exponent):
|
||||
return Instruction(name="%s*%s" % (self.name, exponent), num_qubits=self.num_qubits,
|
||||
num_clbits=self.num_clbits, params=self.params)
|
||||
|
||||
def repeat(self, n):
|
||||
"""Creates an instruction with `gate` repeated `n` amount of times.
|
||||
|
||||
Args:
|
||||
n (int): Number of times to repeat the instruction
|
||||
|
||||
Returns:
|
||||
Instruction: Containing the definition.
|
||||
|
||||
Raises:
|
||||
QiskitError: If n < 1.
|
||||
"""
|
||||
if int(n) != n or n < 1:
|
||||
raise QiskitError("Repeat can only be called with strictly positive integer.")
|
||||
|
||||
n = int(n)
|
||||
|
||||
instruction = self._return_repeat(n)
|
||||
qargs = [] if self.num_qubits == 0 else QuantumRegister(self.num_qubits, 'q')
|
||||
cargs = [] if self.num_clbits == 0 else ClassicalRegister(self.num_clbits, 'c')
|
||||
|
||||
instruction.definition = [(self, qargs[:], cargs[:])] * n
|
||||
return instruction
|
||||
|
|
|
@ -0,0 +1,227 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This code is part of Qiskit.
|
||||
#
|
||||
# (C) Copyright IBM 2019.
|
||||
#
|
||||
# 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.
|
||||
|
||||
|
||||
"""Test Qiskit's repeat instruction operation."""
|
||||
|
||||
import unittest
|
||||
from numpy import pi
|
||||
|
||||
from qiskit.transpiler import PassManager
|
||||
from qiskit import QuantumRegister, QuantumCircuit, ClassicalRegister
|
||||
from qiskit.test import QiskitTestCase
|
||||
from qiskit.extensions import SGate, U3Gate, UnitaryGate, CnotGate
|
||||
from qiskit.circuit import Instruction, Measure, Gate
|
||||
from qiskit.transpiler.passes import Unroller
|
||||
from qiskit.exceptions import QiskitError
|
||||
|
||||
|
||||
class TestRepeatInt1Q(QiskitTestCase):
|
||||
"""Test gate_q1.repeat() with integer"""
|
||||
|
||||
def test_standard_1Q_two(self):
|
||||
"""Test standard gate.repeat(2) method.
|
||||
"""
|
||||
qr = QuantumRegister(1, 'qr')
|
||||
expected_circ = QuantumCircuit(qr)
|
||||
expected_circ.append(SGate(), [qr[0]])
|
||||
expected_circ.append(SGate(), [qr[0]])
|
||||
expected = expected_circ.to_instruction()
|
||||
|
||||
result = SGate().repeat(2)
|
||||
|
||||
self.assertEqual(result.name, 's*2')
|
||||
self.assertEqual(result.definition, expected.definition)
|
||||
self.assertIsInstance(result, Gate)
|
||||
|
||||
def test_standard_1Q_one(self):
|
||||
"""Test standard gate.repeat(1) method.
|
||||
"""
|
||||
qr = QuantumRegister(1, 'qr')
|
||||
expected_circ = QuantumCircuit(qr)
|
||||
expected_circ.append(SGate(), [qr[0]])
|
||||
expected = expected_circ.to_instruction()
|
||||
|
||||
result = SGate().repeat(1)
|
||||
|
||||
self.assertEqual(result.name, 's*1')
|
||||
self.assertEqual(result.definition, expected.definition)
|
||||
self.assertIsInstance(result, Gate)
|
||||
|
||||
|
||||
class TestRepeatInt2Q(QiskitTestCase):
|
||||
"""Test gate_q2.repeat() with integer"""
|
||||
|
||||
def test_standard_2Q_two(self):
|
||||
"""Test standard 2Q gate.repeat(2) method.
|
||||
"""
|
||||
qr = QuantumRegister(2, 'qr')
|
||||
expected_circ = QuantumCircuit(qr)
|
||||
expected_circ.append(CnotGate(), [qr[0], qr[1]])
|
||||
expected_circ.append(CnotGate(), [qr[0], qr[1]])
|
||||
expected = expected_circ.to_instruction()
|
||||
|
||||
result = CnotGate().repeat(2)
|
||||
|
||||
self.assertEqual(result.name, 'cx*2')
|
||||
self.assertEqual(result.definition, expected.definition)
|
||||
self.assertIsInstance(result, Gate)
|
||||
|
||||
def test_standard_2Q_one(self):
|
||||
"""Test standard 2Q gate.repeat(1) method.
|
||||
"""
|
||||
qr = QuantumRegister(2, 'qr')
|
||||
expected_circ = QuantumCircuit(qr)
|
||||
expected_circ.append(CnotGate(), [qr[0], qr[1]])
|
||||
expected = expected_circ.to_instruction()
|
||||
|
||||
result = CnotGate().repeat(1)
|
||||
|
||||
self.assertEqual(result.name, 'cx*1')
|
||||
self.assertEqual(result.definition, expected.definition)
|
||||
self.assertIsInstance(result, Gate)
|
||||
|
||||
|
||||
class TestRepeatIntMeasure(QiskitTestCase):
|
||||
"""Test Measure.repeat() with integer"""
|
||||
|
||||
def test_measure_two(self):
|
||||
"""Test Measure.repeat(2) method.
|
||||
"""
|
||||
qr = QuantumRegister(1, 'qr')
|
||||
cr = ClassicalRegister(1, 'cr')
|
||||
expected_circ = QuantumCircuit(qr, cr)
|
||||
expected_circ.append(Measure(), [qr[0]], [cr[0]])
|
||||
expected_circ.append(Measure(), [qr[0]], [cr[0]])
|
||||
expected = expected_circ.to_instruction()
|
||||
|
||||
result = Measure().repeat(2)
|
||||
|
||||
self.assertEqual(result.name, 'measure*2')
|
||||
self.assertEqual(result.definition, expected.definition)
|
||||
self.assertIsInstance(result, Instruction)
|
||||
self.assertNotIsInstance(result, Gate)
|
||||
|
||||
def test_measure_one(self):
|
||||
"""Test Measure.repeat(1) method.
|
||||
"""
|
||||
qr = QuantumRegister(1, 'qr')
|
||||
cr = ClassicalRegister(1, 'cr')
|
||||
expected_circ = QuantumCircuit(qr, cr)
|
||||
expected_circ.append(Measure(), [qr[0]], [cr[0]])
|
||||
expected = expected_circ.to_instruction()
|
||||
|
||||
result = Measure().repeat(1)
|
||||
|
||||
self.assertEqual(result.name, 'measure*1')
|
||||
self.assertEqual(result.definition, expected.definition)
|
||||
self.assertIsInstance(result, Instruction)
|
||||
self.assertNotIsInstance(result, Gate)
|
||||
|
||||
|
||||
class TestRepeatUnroller(QiskitTestCase):
|
||||
"""Test unrolling Gate.repeat"""
|
||||
|
||||
def test_unroller_two(self):
|
||||
"""Test unrolling gate.repeat(2).
|
||||
"""
|
||||
qr = QuantumRegister(1, 'qr')
|
||||
|
||||
circuit = QuantumCircuit(qr)
|
||||
circuit.append(SGate().repeat(2), [qr[0]])
|
||||
result = PassManager(Unroller('u3')).run(circuit)
|
||||
|
||||
expected = QuantumCircuit(qr)
|
||||
expected.append(U3Gate(0, 0, pi / 2), [qr[0]])
|
||||
expected.append(U3Gate(0, 0, pi / 2), [qr[0]])
|
||||
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_unroller_one(self):
|
||||
"""Test unrolling gate.repeat(1).
|
||||
"""
|
||||
qr = QuantumRegister(1, 'qr')
|
||||
|
||||
circuit = QuantumCircuit(qr)
|
||||
circuit.append(SGate().repeat(1), [qr[0]])
|
||||
result = PassManager(Unroller('u3')).run(circuit)
|
||||
|
||||
expected = QuantumCircuit(qr)
|
||||
expected.append(U3Gate(0, 0, pi / 2), [qr[0]])
|
||||
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
|
||||
class TestRepeatErrors(QiskitTestCase):
|
||||
"""Test when Gate.repeat() should raise."""
|
||||
|
||||
def test_unitary_no_int(self):
|
||||
"""Test UnitaryGate.repeat(2/3) method. Raises, since n is not int.
|
||||
"""
|
||||
with self.assertRaises(QiskitError) as context:
|
||||
_ = UnitaryGate([[0, 1j], [-1j, 0]]).repeat(2 / 3)
|
||||
self.assertIn('strictly positive integer', str(context.exception))
|
||||
|
||||
def test_starndard_no_int(self):
|
||||
"""Test standard Gate.repeat(2/3) method. Raises, since n is not int.
|
||||
"""
|
||||
with self.assertRaises(QiskitError) as context:
|
||||
_ = SGate().repeat(2 / 3)
|
||||
self.assertIn('strictly positive integer', str(context.exception))
|
||||
|
||||
def test_measure_zero(self):
|
||||
"""Test Measure.repeat(0) method. Raises, since n<1
|
||||
"""
|
||||
with self.assertRaises(QiskitError) as context:
|
||||
_ = Measure().repeat(0)
|
||||
self.assertIn('strictly positive integer', str(context.exception))
|
||||
|
||||
def test_standard_1Q_zero(self):
|
||||
"""Test standard 2Q gate.repeat(0) method. Raises, since n<1.
|
||||
"""
|
||||
with self.assertRaises(QiskitError) as context:
|
||||
_ = SGate().repeat(0)
|
||||
self.assertIn('strictly positive integer', str(context.exception))
|
||||
|
||||
def test_standard_1Q_minus_one(self):
|
||||
"""Test standard 2Q gate.repeat(-1) method. Raises, since n<1.
|
||||
"""
|
||||
with self.assertRaises(QiskitError) as context:
|
||||
_ = SGate().repeat(-1)
|
||||
self.assertIn('strictly positive integer', str(context.exception))
|
||||
|
||||
def test_standard_2Q_minus_one(self):
|
||||
"""Test standard 2Q gate.repeat(-1) method. Raises, since n<1.
|
||||
"""
|
||||
with self.assertRaises(QiskitError) as context:
|
||||
_ = CnotGate().repeat(-1)
|
||||
self.assertIn('strictly positive integer', str(context.exception))
|
||||
|
||||
def test_measure_minus_one(self):
|
||||
"""Test Measure.repeat(-1) method. Raises, since n<1
|
||||
"""
|
||||
with self.assertRaises(QiskitError) as context:
|
||||
_ = Measure().repeat(-1)
|
||||
self.assertIn('strictly positive integer', str(context.exception))
|
||||
|
||||
def test_standard_2Q_zero(self):
|
||||
"""Test standard 2Q gate.repeat(0) method. Raises, since n<1.
|
||||
"""
|
||||
with self.assertRaises(QiskitError) as context:
|
||||
_ = CnotGate().repeat(0)
|
||||
self.assertIn('strictly positive integer', str(context.exception))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
Loading…
Reference in New Issue