Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion qctrlopencontrols/qiskit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@
=============
"""

from .constants import (FIX_DURATION_UNITARY, INSTANT_UNITARY)
from .constants import (FIX_DURATION_UNITARY, INSTANT_UNITARY,
DEFAULT_PRE_POST_GATE_PARAMETERS)
from .quantum_circuit import convert_dds_to_quantum_circuit
6 changes: 6 additions & 0 deletions qctrlopencontrols/qiskit/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
================
"""

import numpy as np

FIX_DURATION_UNITARY = 'fixed duration unitary'
"""Algorithm to convert a DDS to Quantum circuit
where the unitaries are considered as gates with finite duration
Expand All @@ -27,3 +29,7 @@
"""Algorithm to convert a DDS to Quantum circuit where the
unitaties are considered as instantaneous operation.
"""

DEFAULT_PRE_POST_GATE_PARAMETERS = (np.pi / 2, -np.pi / 2, np.pi / 2)
"""Parameters of a default U3 gate for pre-post rotation for circuits.
"""
52 changes: 27 additions & 25 deletions qctrlopencontrols/qiskit/quantum_circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
from qctrlopencontrols.dynamic_decoupling_sequences import DynamicDecouplingSequence
from qctrlopencontrols.exceptions import ArgumentsValueError

from .constants import (FIX_DURATION_UNITARY, INSTANT_UNITARY)
from .constants import (FIX_DURATION_UNITARY, INSTANT_UNITARY,
DEFAULT_PRE_POST_GATE_PARAMETERS)


def _get_circuit_gate_list(dynamic_decoupling_sequence,
Expand Down Expand Up @@ -131,7 +132,7 @@ def convert_dds_to_quantum_circuit(
dynamic_decoupling_sequence,
target_qubits=None,
gate_time=0.1,
pre_post_gate_parameters=None,
pre_post_gate_parameters=DEFAULT_PRE_POST_GATE_PARAMETERS,
add_measurement=True,
algorithm=FIX_DURATION_UNITARY,
quantum_registers=None,
Expand All @@ -148,13 +149,14 @@ def convert_dds_to_quantum_circuit(
defaults to None
gate_time : float, optional
Time (in seconds) delay introduced by a gate; defaults to 0.1
pre_post_gate_parameters : list, optional
List of (length 3) floating point numbers; These numbers correspond to :math:`\\theta,
\\phi, \\lambda` parameters in `U3` gate defined in Qiskit as `U3Gate(theta, phi, lamda)`.
Qiskit documentation suggests this to be the most generalized definition of unitary
gates. Defaults to None; if None, the parameters are assumed to be
:math:`[pi/2, -pi/2, pi/2]` that corresponds to `pi/2` rotation around X-axis.
See `IBM-Q Documentation
pre_post_gate_parameters : tuple or None, optional
Tuple of (length 3) floating point numbers that correspond to :math:`\\theta,
\\phi, \\lambda` parameters respectively in `U3` gate defined in Qiskit
as `U3Gate(theta, phi, lambda)`. Qiskit documentation suggests this to be
the most generalized definition of unitary gates. Defaults to
(pi/2, -pi/2, pi/2) that corresponds to a :math:`pi/2`
rotation around X-axis; if None, the resulting circuit will have no `pre` or `post`
gates. See `IBM-Q Documentation
<https://quantumexperience.ng.bluemix.net/proxy/tutorial/full-user-guide/
002-The_Weird_and_Wonderful_World_of_the_Qubit/004-advanced_qubit_gates.html?` _.
add_measurement : bool, optional
Expand Down Expand Up @@ -217,10 +219,8 @@ def convert_dds_to_quantum_circuit(
if target_qubits is None:
target_qubits = [0]

if pre_post_gate_parameters is None:
pre_post_gate_parameters = [np.pi / 2, -pi / 2, pi / 2]

if len(pre_post_gate_parameters) != 3:
if (pre_post_gate_parameters is not None and
len(pre_post_gate_parameters) != 3):
raise ArgumentsValueError('Pre-Post gate parameters must be a list of 3 '
'floating point numbers.',
{'pre_post_gate_params': pre_post_gate_parameters})
Expand Down Expand Up @@ -267,12 +267,13 @@ def convert_dds_to_quantum_circuit(
gate_time=gate_time,
unitary_time=unitary_time)

for qubit in target_qubits:
quantum_circuit.u3(pre_post_gate_parameters[0], #pylint: disable=no-member
pre_post_gate_parameters[1],
pre_post_gate_parameters[2],
quantum_registers[qubit])
quantum_circuit.barrier(quantum_registers[qubit]) #pylint: disable=no-member
if pre_post_gate_parameters is not None:
for qubit in target_qubits:
quantum_circuit.u3(pre_post_gate_parameters[0], #pylint: disable=no-member
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For my education, why's the disable=no-member tag necessary? Is there something in quantum_circuit we need to fix?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@charmasaur - no it is a strange way how these are added to Qiskit library (the IBM One). This one might shed some light - https://quantumcomputing.stackexchange.com/questions/4962/how-to-fix-e1101instance-of-quantumcircuit-has-no-h-member-and-e1101in

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha, thanks. Python is scary :S

pre_post_gate_parameters[1],
pre_post_gate_parameters[2],
quantum_registers[qubit])
quantum_circuit.barrier(quantum_registers[qubit]) #pylint: disable=no-member

offset_count = 0
for gate in circuit_gate_list:
Expand Down Expand Up @@ -318,12 +319,13 @@ def convert_dds_to_quantum_circuit(

offset_count += 1

for qubit in target_qubits:
quantum_circuit.u3(pre_post_gate_parameters[0], #pylint: disable=no-member
pre_post_gate_parameters[1],
pre_post_gate_parameters[2],
quantum_registers[qubit])
quantum_circuit.barrier(quantum_registers) # pylint: disable=no-member
if pre_post_gate_parameters is not None:
for qubit in target_qubits:
quantum_circuit.u3(pre_post_gate_parameters[0], #pylint: disable=no-member
pre_post_gate_parameters[1],
pre_post_gate_parameters[2],
quantum_registers[qubit])
quantum_circuit.barrier(quantum_registers) # pylint: disable=no-member

if add_measurement:
for q_index, qubit in enumerate(target_qubits):
Expand Down
14 changes: 6 additions & 8 deletions tests/test_qiskit_sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,19 +75,14 @@ def _create_test_sequence(sequence_scheme):
return sequence


def _check_circuit_unitary(pre_post_gate_parameters):
def _check_circuit_unitary(pre_post_gate_parameters, multiplier):
"""Check the unitary of a dynamic decoupling operation
"""

backend = 'unitary_simulator'
number_of_shots = 1
backend_simulator = BasicAer.get_backend(backend)

if pre_post_gate_parameters is None:
multiplier = (1. / np.power(2, 0.5)) * np.array([[1, -1j], [-1j, 1]], dtype='complex')
else:
multiplier = np.array([[1, 0], [0, 1]])

for sequence_scheme in ['Carr-Purcell', 'Carr-Purcell-Meiboom-Gill',
'Uhrig single-axis', 'periodic single-axis', 'Walsh single-axis',
'quadratic', 'X concatenated',
Expand Down Expand Up @@ -115,9 +110,12 @@ def test_identity_operation():
"""Tests if the Dynamic Decoupling Sequence gives rise to Identity
operation in Qiskit
"""
_multiplier = np.array([[1, 0], [0, 1]])
_check_circuit_unitary([0., 0., 0.], _multiplier)
_check_circuit_unitary(None, _multiplier)

_check_circuit_unitary([0., 0., 0.])
_check_circuit_unitary(None)
_multiplier = (1. / np.power(2, 0.5)) * np.array([[1, -1j], [-1j, 1]], dtype='complex')
_check_circuit_unitary([np.pi / 2, -np.pi / 2, np.pi / 2], _multiplier)

if __name__ == '__main__':
pass