Skip to content
This repository was archived by the owner on May 17, 2022. It is now read-only.

fix: Fix test with new opencontrol version #24

Merged
merged 6 commits into from
Nov 26, 2021
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
4 changes: 2 additions & 2 deletions .github/workflows/on-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
source <(curl -sL http://ci.q-ctrl.com)
./ci vault login -r ${{ secrets.VAULT_ROLE_ID }} -s ${{ secrets.VAULT_SECRET_ID }}
./ci vault login -r ${{ secrets.VAULT_ROLE_ID }} -s ${{ secrets.VAULT_SECRET_ID }}
./ci docker run qctrl/ci-images:python-3.7-ci /scripts/housekeeping.sh

linting:
Expand All @@ -44,7 +44,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python: [3.7, 3.8, 3.9]
python: [3.7, 3.8]
steps:
- uses: actions/checkout@v1
- name: Install Python dependencies
Expand Down
4 changes: 2 additions & 2 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 9 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ license = "Apache-2.0"
authors = ["Q-CTRL <[email protected]>"]
readme = "README.md"
keywords = [
"quantum",
"computing",
"open source",
"quantum",
"computing",
"open source",
"engineering",
"qiskit"
]
Expand All @@ -33,7 +33,7 @@ packages = [
]

[tool.poetry.dependencies] # https://poetry.eustace.io/docs/versions
python = ">=3.7,<3.10"
python = ">=3.7,<3.9"
numpy = "^1.16"
scipy = "^1.3"
toml = "^0.10.0"
Expand All @@ -50,6 +50,11 @@ pylint_runner = "*"
sphinx = "^2.2.0"
nbval = "^0.9.5"
qctrl-visualizer = "^2.12.1"
isort = "^5.7.0"

[tool.isort]
profile = "black"
force_grid_wrap = "2"

[tool.dephell.main]
from = {format = "poetry", path = "pyproject.toml"}
Expand All @@ -70,4 +75,3 @@ build-backend = "poetry.masonry.api"
# (__)\ )\/\
# ||----w |
# || ||

154 changes: 94 additions & 60 deletions qctrlqiskit/quantum_circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,32 @@
# limitations under the License.

"""
======================
qiskit.quantum_circuit
======================
"""

import numpy as np

from qctrlopencontrols import DynamicDecouplingSequence
from qctrlopencontrols.exceptions import ArgumentsValueError
from qiskit import (
QuantumRegister, ClassicalRegister, QuantumCircuit)
ClassicalRegister,
QuantumCircuit,
QuantumRegister,
)
from qiskit.qasm import pi

from qctrlopencontrols import DynamicDecouplingSequence

from qctrlopencontrols.globals import (FIX_DURATION_UNITARY, INSTANT_UNITARY)
from qctrlopencontrols.exceptions.exceptions import ArgumentsValueError
FIX_DURATION_UNITARY = "fixed duration unitary"
INSTANT_UNITARY = "instant unitary"


def convert_dds_to_qiskit_quantum_circuit(
dynamic_decoupling_sequence,
target_qubits=None,
gate_time=0.1,
add_measurement=True,
algorithm=INSTANT_UNITARY,
quantum_registers=None,
circuit_name=None):
dynamic_decoupling_sequence,
target_qubits=None,
gate_time=0.1,
add_measurement=True,
algorithm=INSTANT_UNITARY,
quantum_registers=None,
circuit_name=None,
):
"""Converts a Dynamic Decoupling Sequence into QuantumCircuit
as defined in Qiskit

Expand Down Expand Up @@ -99,39 +100,50 @@ def convert_dds_to_qiskit_quantum_circuit(
"""

if dynamic_decoupling_sequence is None:
raise ArgumentsValueError('No dynamic decoupling sequence provided.',
{'dynamic_decoupling_sequence': dynamic_decoupling_sequence})
raise ArgumentsValueError(
"No dynamic decoupling sequence provided.",
{"dynamic_decoupling_sequence": dynamic_decoupling_sequence},
)

if not isinstance(dynamic_decoupling_sequence, DynamicDecouplingSequence):
raise ArgumentsValueError('Dynamical decoupling sequence is not recognized.'
'Expected DynamicDecouplingSequence instance',
{'type(dynamic_decoupling_sequence)':
type(dynamic_decoupling_sequence)})
raise ArgumentsValueError(
"Dynamical decoupling sequence is not recognized."
"Expected DynamicDecouplingSequence instance",
{"type(dynamic_decoupling_sequence)": type(dynamic_decoupling_sequence)},
)

target_qubits = target_qubits or [0]

if gate_time <= 0:
raise ArgumentsValueError(
'Time delay of identity gate must be greater than zero.',
{'gate_time': gate_time})
"Time delay of identity gate must be greater than zero.",
{"gate_time": gate_time},
)

if np.any(target_qubits) < 0:
raise ArgumentsValueError(
'Every target qubits index must be non-negative.',
{'target_qubits': target_qubits})
"Every target qubits index must be non-negative.",
{"target_qubits": target_qubits},
)

if algorithm not in [FIX_DURATION_UNITARY, INSTANT_UNITARY]:
raise ArgumentsValueError('Algorithm must be one of {} or {}'.format(
INSTANT_UNITARY, FIX_DURATION_UNITARY), {'algorithm': algorithm})
raise ArgumentsValueError(
f"Algorithm must be one of {INSTANT_UNITARY} or {FIX_DURATION_UNITARY}",
{"algorithm": algorithm},
)

if quantum_registers is not None:
if (max(target_qubits)+1) > len(quantum_registers):
raise ArgumentsValueError('Target qubit is not present in quantum_registers',
{'target_qubits': target_qubits,
'size(quantum_registers)': len(quantum_registers)},
extras={'max(target_qubits)': max(target_qubits)})
if (max(target_qubits) + 1) > len(quantum_registers):
raise ArgumentsValueError(
"Target qubit is not present in quantum_registers",
{
"target_qubits": target_qubits,
"size(quantum_registers)": len(quantum_registers),
},
extras={"max(target_qubits)": max(target_qubits)},
)
else:
quantum_registers = QuantumRegister(max(target_qubits)+1)
quantum_registers = QuantumRegister(max(target_qubits) + 1)

classical_registers = None
if add_measurement:
Expand All @@ -143,7 +155,7 @@ def convert_dds_to_qiskit_quantum_circuit(
if circuit_name is not None:
quantum_circuit.name = circuit_name

unitary_time = 0.
unitary_time = 0.0
if algorithm == FIX_DURATION_UNITARY:
unitary_time = gate_time

Expand All @@ -155,8 +167,11 @@ def convert_dds_to_qiskit_quantum_circuit(

time_covered = 0
for offset, rabi_rotation, azimuthal_angle, detuning_rotation in zip(
list(offsets), list(rabi_rotations),
list(azimuthal_angles), list(detuning_rotations)):
list(offsets),
list(rabi_rotations),
list(azimuthal_angles),
list(detuning_rotations),
):

offset_distance = offset - time_covered

Expand All @@ -168,13 +183,20 @@ def convert_dds_to_qiskit_quantum_circuit(
"Offsets cannot be placed properly. Spacing between the rotations"
"is smaller than the time required to perform the rotation. Provide"
"a longer dynamic decoupling sequence or shorted gate time.",
{'dynamic_decoupling_sequence': dynamic_decoupling_sequence,
'gate_time': gate_time})
{
"dynamic_decoupling_sequence": dynamic_decoupling_sequence,
"gate_time": gate_time,
},
)

while (time_covered+gate_time) <= offset:
while (time_covered + gate_time) <= offset:
for qubit in target_qubits:
quantum_circuit.iden(quantum_registers[qubit]) # pylint: disable=no-member
quantum_circuit.barrier(quantum_registers[qubit]) # pylint: disable=no-member
quantum_circuit.iden( # pylint: disable=no-member
quantum_registers[qubit]
)
quantum_circuit.barrier( # pylint: disable=no-member
quantum_registers[qubit]
)
time_covered += gate_time

x_rotation = rabi_rotation * np.cos(azimuthal_angle)
Expand All @@ -186,41 +208,53 @@ def convert_dds_to_qiskit_quantum_circuit(
nonzero_pulse_counts = 3 - np.sum(zero_pulses)
if nonzero_pulse_counts > 1:
raise ArgumentsValueError(
'Open Controls support a sequence with one '
'valid rotation at any offset. Found a sequence '
'with multiple rotation operations at an offset.',
{'dynamic_decoupling_sequence': dynamic_decoupling_sequence},
extras={'offset': offset,
'rabi_rotation': rabi_rotation,
'azimuthal_angle': azimuthal_angle,
'detuning_rotation': detuning_rotation}
"Open Controls support a sequence with one "
"valid rotation at any offset. Found a sequence "
"with multiple rotation operations at an offset.",
{"dynamic_decoupling_sequence": dynamic_decoupling_sequence},
extras={
"offset": offset,
"rabi_rotation": rabi_rotation,
"azimuthal_angle": azimuthal_angle,
"detuning_rotation": detuning_rotation,
},
)

for qubit in target_qubits:
if nonzero_pulse_counts == 0:
quantum_circuit.u3(
0., 0., 0., # pylint: disable=no-member
quantum_registers[qubit])
0.0, 0.0, 0.0, quantum_registers[qubit] # pylint: disable=no-member
)
else:
if not np.isclose(rotations[0], 0.0):
quantum_circuit.u3(
rotations[0], -pi / 2, pi / 2, # pylint: disable=no-member
quantum_registers[qubit])
rotations[0],
-pi / 2,
pi / 2, # pylint: disable=no-member
quantum_registers[qubit],
)
elif not np.isclose(rotations[1], 0.0):
quantum_circuit.u3(
rotations[1], 0., 0., # pylint: disable=no-member
quantum_registers[qubit])
elif not np.isclose(rotations[2], 0.):
rotations[1],
0.0,
0.0, # pylint: disable=no-member
quantum_registers[qubit],
)
elif not np.isclose(rotations[2], 0.0):
quantum_circuit.u1(
rotations[2], # pylint: disable=no-member
quantum_registers[qubit])
quantum_circuit.barrier(quantum_registers[qubit]) # pylint: disable=no-member
quantum_registers[qubit],
)
quantum_circuit.barrier(
quantum_registers[qubit]
) # pylint: disable=no-member

time_covered = offset + unitary_time

if add_measurement:
for q_index, qubit in enumerate(target_qubits):
quantum_circuit.measure(quantum_registers[qubit], #pylint: disable=no-member
classical_registers[q_index])
quantum_circuit.measure( # pylint: disable=no-member
quantum_registers[qubit], classical_registers[q_index]
)

return quantum_circuit
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
name='qctrl-qiskit',
version='0.0.3',
description='Q-CTRL Qiskit Adapter',
python_requires='<3.10,>=3.7',
python_requires='<3.9,>=3.7',
project_urls={"repository": "https://github.com/qctrl/python-qiskit"},
author='Q-CTRL',
author_email='[email protected]',
Expand All @@ -37,5 +37,5 @@
package_dir={"": "."},
package_data={},
install_requires=['numpy==1.*,>=1.16.0', 'qctrl-open-controls==8.*,>=8.5.1', 'qiskit-ibmq-provider==0.*,>=0.3.3', 'qiskit-terra==0.*,>=0.12.0', 'scipy==1.*,>=1.3.0', 'toml==0.*,>=0.10.0'],
extras_require={"dev": ["nbval==0.*,>=0.9.5", "pylama", "pylint", "pylint-runner", "pytest", "qctrl-visualizer==2.*,>=2.12.1", "sphinx==2.*,>=2.2.0"]},
extras_require={"dev": ["isort==5.*,>=5.7.0", "nbval==0.*,>=0.9.5", "pylama", "pylint", "pylint-runner", "pytest", "qctrl-visualizer==2.*,>=2.12.1", "sphinx==2.*,>=2.2.0"]},
)
Loading