From e6b99125472676e27398e7bf659c1eb146c36866 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Wed, 22 May 2019 11:15:53 +1000 Subject: [PATCH 01/42] working version of dds to cirq objects --- qctrlopencontrols/cirq/__init__.py | 23 ++ qctrlopencontrols/cirq/cirq_circuit.py | 483 +++++++++++++++++++++++++ qctrlopencontrols/cirq/constants.py | 37 ++ 3 files changed, 543 insertions(+) create mode 100644 qctrlopencontrols/cirq/__init__.py create mode 100644 qctrlopencontrols/cirq/cirq_circuit.py create mode 100644 qctrlopencontrols/cirq/constants.py diff --git a/qctrlopencontrols/cirq/__init__.py b/qctrlopencontrols/cirq/__init__.py new file mode 100644 index 00000000..76204b42 --- /dev/null +++ b/qctrlopencontrols/cirq/__init__.py @@ -0,0 +1,23 @@ +# Copyright 2019 Q-CTRL Pty Ltd & Q-CTRL Inc +# +# 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. + +""" +============= +cirq module +============= +""" + +from .constants import (SCHEDULED_CIRCUIT, STANDARD_CIRCUIT, + DEFAULT_ROTATION_MATRIX) +from .cirq_circuit import convert_dds_to_cirq_circuit \ No newline at end of file diff --git a/qctrlopencontrols/cirq/cirq_circuit.py b/qctrlopencontrols/cirq/cirq_circuit.py new file mode 100644 index 00000000..96f22d5c --- /dev/null +++ b/qctrlopencontrols/cirq/cirq_circuit.py @@ -0,0 +1,483 @@ +# Copyright 2019 Q-CTRL Pty Ltd & Q-CTRL Inc +# +# 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. + +""" +====================== +cirq.cirq_circuit +====================== +""" + +import numpy as np + +import cirq + +from qctrlopencontrols.dynamic_decoupling_sequences import DynamicDecouplingSequence +from qctrlopencontrols.exceptions import ArgumentsValueError + +from .constants import (SCHEDULED_CIRCUIT, STANDARD_CIRCUIT, DEFAULT_ROTATION_MATRIX) + + +def _get_circuit_gate_list(dynamic_decoupling_sequence, + gate_time, + unitary_time): + + """Converts the operations in a sequence into list of gates + of a quantum circuit + + Parameters + ---------- + dynamic_decoupling_sequence : DynamicDecouplingSequence + Dynamic decoupling sequence instance + gate_time : float + Indicates the delay time of the identity gates + unitary_time : float + Indicates the delay time introduced by unitary gates + + Returns + ------- + list + A list of circuit components with required parameters + + Raises + ------ + ArgumentsValueError + If the offsets cannot be placed properly + """ + + rabi_rotations = dynamic_decoupling_sequence.rabi_rotations + azimuthal_angles = dynamic_decoupling_sequence.azimuthal_angles + detuning_rotations = dynamic_decoupling_sequence.detuning_rotations + + if len(rabi_rotations.shape) == 1: + rabi_rotations = rabi_rotations[np.newaxis, :] + if len(azimuthal_angles.shape) == 1: + azimuthal_angles = azimuthal_angles[np.newaxis, :] + if len(detuning_rotations.shape) == 1: + detuning_rotations = detuning_rotations[np.newaxis, :] + + operations = np.vstack((rabi_rotations, azimuthal_angles, detuning_rotations)) + offsets = dynamic_decoupling_sequence.offsets + + time_covered = 0 + circuit_operations = [] + for operation_idx in range(operations.shape[1]): + + offset_distance = offsets[operation_idx] - time_covered + + if np.isclose(offset_distance, 0.0): + offset_distance = 0.0 + + if offset_distance < 0: + raise ArgumentsValueError("Offsets cannot be placed properly", + {'sequence_operations': operations}) + if offset_distance == 0: + circuit_operations.append('offset') + if np.isclose(np.sum(operations[:, operation_idx]), 0.0): + time_covered = offsets[operation_idx] + else: + time_covered = offsets[operation_idx] + unitary_time + else: + number_of_id_gates = 0 + while (time_covered + (number_of_id_gates+1) * gate_time) <= \ + offsets[operation_idx]: + circuit_operations.append('id') + number_of_id_gates += 1 + circuit_operations.append('offset') + time_covered = offsets[operation_idx] + unitary_time + + return circuit_operations + + +def _get_rotations(operation): + + """Returns the pulses based of the rotation operation + + Parameters + ---------- + operation : numpy.ndarray + 1-D array (length=3) consisting of rabi rotation, azimuthal_angle + and detuning_rotation at an offset of a sequence + + Returns + ------- + numpy.ndarray + A 1-D array of length 3 containing x_rotation, y_rotation and z-rotation + calculate from sequence operation + """ + + x_rotation = operation[0] * np.cos(operation[1]) + y_rotation = operation[0] * np.sin(operation[1]) + z_rotation = operation[2] + + pulses = np.array([x_rotation, y_rotation, z_rotation]) + + return pulses + + +def _get_scheduled_circuit(dynamic_decoupling_sequence, + target_qubits, + gate_time, + pre_post_gate, + add_measurement, + device): + + """Returns a scheduled circuit operation constructed from + dynamic decoupling sequence + + Parameters + ---------- + dynamic_decoupling_sequence : DynamicDecouplingSequence + The dynamic decoupling sequence + target_qubits : list + List of target qubits for the sequence operation; the qubits must be + cirq.Qid type + gate_time : float, optional + Time (in seconds) delay introduced by a gate; defaults to 0.1 + pre_post_gate : SingleQubitGate + A SingleQubitGate type (defined in cirq package) defined by a 2x2 + unitary matrix. + add_measurement : bool + If True, a measurement operation is added to each of the qubits. + device : cirq.Device + The device where these operations will be running. + + Returns + ------- + cirq.Schedule + The scheduled circuit operations + """ + + gate_time = gate_time * 1e9 + + rabi_rotations = dynamic_decoupling_sequence.rabi_rotations + azimuthal_angles = dynamic_decoupling_sequence.azimuthal_angles + detuning_rotations = dynamic_decoupling_sequence.detuning_rotations + + if len(rabi_rotations.shape) == 1: + rabi_rotations = rabi_rotations[np.newaxis, :] + if len(azimuthal_angles.shape) == 1: + azimuthal_angles = azimuthal_angles[np.newaxis, :] + if len(detuning_rotations.shape) == 1: + detuning_rotations = detuning_rotations[np.newaxis, :] + + operations = np.vstack((rabi_rotations, azimuthal_angles, detuning_rotations)) + offsets = dynamic_decoupling_sequence.offsets + offsets = offsets * 1e9 + + circuit_operations = [] + if pre_post_gate is not None: + for qubit in target_qubits: + op = cirq.ScheduledOperation(time=cirq.Timestamp(nanos=0), + duration=cirq.Duration(nanos=gate_time), + operation=pre_post_gate(qubit)) + circuit_operations.append(op) + offsets = offsets + gate_time + + offset_count = 0 + for op_idx in range(operations.shape[1]): + instance_operation = np.array([dynamic_decoupling_sequence.rabi_rotations[op_idx], + dynamic_decoupling_sequence.azimuthal_angles[op_idx], + dynamic_decoupling_sequence.detuning_rotations[op_idx] + ]) + + rotations = _get_rotations(instance_operation) + nonzero_pulse_counts = 0 + for rotation in rotations: + if not np.isclose(rotation, 0.0): + nonzero_pulse_counts += 1 + if nonzero_pulse_counts > 1: + raise ArgumentsValueError('Open Controls support a sequence with one ' + 'valid pulse at any offset. Found sequence ' + 'with multiple rotation operations at an offset.', + {'dynamic_decoupling_sequence': str( + dynamic_decoupling_sequence), + 'instance_operation': instance_operation}) + for qubit in target_qubits: + if nonzero_pulse_counts == 0: + op = cirq.ScheduledOperation(time=cirq.Timestamp(nanos=offsets[op_idx]), + duration=cirq.Duration(nanos=gate_time), + operation=cirq.I(qubit)) + else: + if not np.isclose(rotations[0], 0.0): + op = cirq.ScheduledOperation(time=cirq.Timestamp(nanos=offsets[op_idx]), + duration=cirq.Duration(nanos=gate_time), + operation=cirq.Rx(rotations[0])(qubit)) + elif not np.isclose(rotations[1], 0.0): + op = cirq.ScheduledOperation(time=cirq.Timestamp(nanos=offsets[op_idx]), + duration=cirq.Duration(nanos=gate_time), + operation=cirq.Rx(rotations[1])(qubit)) + elif not np.isclose(rotations[2], 0.): + op = cirq.ScheduledOperation(time=cirq.Timestamp(nanos=offsets[op_idx]), + duration=cirq.Duration(nanos=gate_time), + operation=cirq.Rx(rotations[2])(qubit)) + offset_count += 1 + circuit_operations.append(op) + + if pre_post_gate is not None: + for qubit in target_qubits: + op = cirq.ScheduledOperation(time=cirq.Timestamp(nanos=offsets[-1] + gate_time), + duration=cirq.Duration(nanos=gate_time), + operation=pre_post_gate(qubit)) + circuit_operations.append(op) + offsets = offsets + gate_time + + if add_measurement: + for idx, qubit in enumerate(target_qubits): + op = cirq.ScheduledOperation(time=cirq.Timestamp(nanos=offsets[-1] + gate_time), + duration=cirq.Duration(nanos=gate_time), + operation=cirq.MeasurementGate( + 1 ,key='qubit-{}'.format(idx))(qubit)) + circuit_operations.append(op) + + schedule = cirq.Schedule(device=device, scheduled_operations=circuit_operations) + return schedule + + +def _get_standard_circuit(dynamic_decoupling_sequence, + target_qubits, + gate_time, + pre_post_gate, + add_measurement): + + """Returns a standard circuit construncted from dynamic + decoupling sequence + + Parameters + ---------- + dynamic_decoupling_sequence : DynamicDecouplingSequence + The dynamic decoupling sequence + target_qubits : list + List of target qubits for the sequence operation; the qubits must be + cirq.Qid type + gate_time : float, optional + Time (in seconds) delay introduced by a gate; defaults to 0.1 + pre_post_gate : SingleQubitGate + A SingleQubitGate type (defined in cirq package) defined by a 2x2 + unitary matrix. + add_measurement : bool + If True, a measurement operation is added to each of the qubits. + + Returns + ------- + cirq.Circuit + The circuit prepared from dynamic decoupling sequence. In standard circuit + the desired decoupling pulses are placed at offsets and the duration between + the pulses are constructed from identity gates with delays equal to 'gate_time'. + """ + + unitary_time = gate_time + circuit_gate_list = _get_circuit_gate_list( + dynamic_decoupling_sequence=dynamic_decoupling_sequence, + gate_time=gate_time, + unitary_time=unitary_time) + + circuit = cirq.Circuit() + + if pre_post_gate is not None: + gate_list = [] + for qubit in target_qubits: + gate_list.append(pre_post_gate(qubit)) + circuit.append(gate_list) + + offset_count = 0 + for gate in circuit_gate_list: + + if gate == 'id': + gate_list = [] + for qubit in target_qubits: + gate_list.append(cirq.I(qubit)) + circuit.append(gate_list) + continue + + instance_operation = np.array( + [dynamic_decoupling_sequence.rabi_rotations[offset_count], + dynamic_decoupling_sequence.azimuthal_angles[offset_count], + dynamic_decoupling_sequence.detuning_rotations[offset_count] + ]) + + rotations = _get_rotations(instance_operation) + nonzero_pulse_counts = 0 + for rotation in rotations: + if not np.isclose(rotation, 0.0): + nonzero_pulse_counts += 1 + if nonzero_pulse_counts > 1: + raise ArgumentsValueError('Open Controls support a sequence with one ' + 'valid pulse at any offset. Found sequence ' + 'with multiple rotation operations at an offset.', + {'dynamic_decoupling_sequence': str( + dynamic_decoupling_sequence), + 'instance_operation': instance_operation}) + gate_list = [] + for qubit in target_qubits: + if nonzero_pulse_counts == 0: + gate_list.append(cirq.I(qubit)) + else: + if not np.isclose(rotations[0], 0.0): + gate_list.append(cirq.Rx(rotations[0])(qubit)) + elif not np.isclose(rotations[1], 0.0): + gate_list.append(cirq.Ry(rotations[1])(qubit)) + elif not np.isclose(rotations[2], 0.): + gate_list.append(cirq.Rz(rotations[2])(qubit)) + offset_count += 1 + circuit.append(gate_list) + + if pre_post_gate is not None: + gate_list = [] + for qubit in target_qubits: + gate_list.append(pre_post_gate(qubit)) + circuit.append(gate_list) + + if add_measurement: + gate_list = [] + for idx, qubit in enumerate(target_qubits): + gate_list.append(cirq.measure(qubit, key='qubit-{}'.format(idx))) + circuit.append(gate_list) + + return circuit + + +def convert_dds_to_cirq_circuit( + dynamic_decoupling_sequence, + target_qubits=None, + gate_time=0.1, + pre_post_gate_unitary_matrix=DEFAULT_ROTATION_MATRIX, + add_measurement=True, + circuit_type=STANDARD_CIRCUIT, + device=None): + + """Converts a Dynamic Decoupling Sequence into QuantumCircuit + as defined in Qiskit + Parameters + ---------- + dynamic_decoupling_sequence : DynamicDecouplingSequence + The dynamic decoupling sequence + target_qubits : list, optional + List of target qubits for the sequence operation; the qubits must be + cirq.Qid type; defaults to None in which case a 1-D lattice of one + qubit is used. + gate_time : float, optional + Time (in seconds) delay introduced by a gate; defaults to 0.1 + pre_post_gate_unitary_matrix : numpy.ndarray or None, optional + A 2x2 unitary matrix as pre-post gate operations. Defaults to + the unitary matrix corresponding to a rotation of :math:'pi/2' around + X-axis. If None, pre-post gate is omitted from the circuit. + add_measurement : bool, optional + If True, the circuit contains a measurement operation for each of the + target qubits. Each measurement will have a string as the key. The string + is formatted as 'qubit-X' where X is a numeral between 0 and len(target_qubits). + circuit_type : str, optional + One of 'scheduled circuit' or 'standard circuit'. In the case of + 'standard circuit', the circuit will be a sequence of desired operations + at offsets specified by the supplied dynamic decoupling sequence and the + duration between any two offsets will have 'identity' gates; the method + will return a 'cirq.Circuit'. In the case of 'scheduled circuit', the desired + operations will be scheduled at offsets specified by the dynamic decoupling + sequence; in this case a 'cirq.Schedule' object is returned. Both `cirq.Circuit` + and 'cirq.Schedule' can be used with 'cirq.Simulator'; see example usage in + [XXXXX]. See `Circuits ` _, + `Schedules ` _ and + `Simulation ` _. + device : cirq.Device, optional + A cirq.Device that specifies hardware constraints for validating circuits + and schedules. If None, a unconstrained device is used. See `Cirq Documentation + ` _. + + Returns + ------- + cirq.circuit or cirq.schedule + The circuit or schedule (depending on circuit_type option). + Either of them can be used with cirq.Simulator. + + Raises + ------ + ArgumentsValueError + If any of the input parameters are invalid + + Notes + ----- + + Dynamic Decoupling Sequences (DDS) consist of idealized pulse operation. Theoretically, + these operations (pi-pulses in X,Y or Z) occur instantaneously. However, in practice, + pulses require time. Therefore, this method of converting an idealized sequence + results to a circuit that is only an approximate implementation of the idealized sequence. + + In idealized definition of DDS, `offsets` represents the instances within sequence + `duration` where a pulse occurs instantaneously. A series of appropriate circuit components + is placed in order to represent these pulses. + + In 'standard circuit' type, the `gaps` or idle + time in between active pulses are filled up with `identity` gates. Each identity gate + introduces a delay of `gate_time`. In this implementation, the number of identity gates + is determined by :math:`np.int(np.floor(offset_distance / gate_time))`. As a consequence, the duration of + the real-circuit is :math:`gate_time \\times number_of_identity_gates + + pulse_gate_time \\times number_of_pulses`. + + In 'scheduled circuit', the active pulses are scheduled to be activated at a certain + instant calculated from the start of the sequence. This does not require identity gates + to be placed between offsets. + + Q-CTRL Open Controls support operation resulting in rotation around at most one axis at + any offset. + """ + + if dynamic_decoupling_sequence is None: + 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)}) + + if gate_time <= 0: + raise ArgumentsValueError( + 'Time delay of gates must be greater than zero.', + {'gate_time': gate_time}) + + if target_qubits is None: + target_qubits = [cirq.LineQubit(0)] + + if pre_post_gate_unitary_matrix is None: + pre_post_gate = None + else: + pre_post_gate = cirq.SingleQubitMatrixGate(pre_post_gate_unitary_matrix) + + if circuit_type not in [SCHEDULED_CIRCUIT, STANDARD_CIRCUIT]: + raise ArgumentsValueError('Circuit type must be one of {} or {}'.format( + SCHEDULED_CIRCUIT, STANDARD_CIRCUIT), {'algorithm': circuit_type}) + + if circuit_type == STANDARD_CIRCUIT: + return _get_standard_circuit(dynamic_decoupling_sequence=dynamic_decoupling_sequence, + target_qubits=target_qubits, + gate_time=gate_time, + pre_post_gate=pre_post_gate, + add_measurement=add_measurement) + + elif circuit_type == SCHEDULED_CIRCUIT: + if device is None: + device = cirq.UnconstrainedDevice + + if not isinstance(device, cirq.Device): + raise ArgumentsValueError('Device must be a cirq.Device type.', + {'device': device}) + + return _get_scheduled_circuit(dynamic_decoupling_sequence=dynamic_decoupling_sequence, + target_qubits=target_qubits, + gate_time=gate_time, + pre_post_gate=pre_post_gate, + add_measurement=add_measurement, + device=device) + + diff --git a/qctrlopencontrols/cirq/constants.py b/qctrlopencontrols/cirq/constants.py new file mode 100644 index 00000000..86d3a509 --- /dev/null +++ b/qctrlopencontrols/cirq/constants.py @@ -0,0 +1,37 @@ +# Copyright 2019 Q-CTRL Pty Ltd & Q-CTRL Inc +# +# 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. + +""" +===================== +cirq.constants module +===================== +""" + +import numpy as np + +SCHEDULED_CIRCUIT = 'scheduled circuit' +"""Constructs the circuit as schedule of rotation +operations at specified offsets. Scheduled circuit +only contains gates specific to desired rotation operations. +""" + +STANDARD_CIRCUIT = 'standard circuit' +"""Constructs the circuit as a series of operations that include +identity gates between desired rotation operations. +""" + +DEFAULT_ROTATION_MATRIX = (1. / np.power(2, 0.5)) * np.array( + [[1, -1j], [-1j, 1]], dtype='complex') +"""Unitary matrix of a Hadamard gate +""" From f90291593b60be369ef03b09996f733eb8e5d723 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Wed, 22 May 2019 11:17:15 +1000 Subject: [PATCH 02/42] cirq module added to qctrlopencontrols --- qctrlopencontrols/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/qctrlopencontrols/__init__.py b/qctrlopencontrols/__init__.py index b7268b97..c7147ce0 100644 --- a/qctrlopencontrols/__init__.py +++ b/qctrlopencontrols/__init__.py @@ -23,3 +23,4 @@ convert_dds_to_driven_controls) from .driven_controls import DrivenControl, new_predefined_driven_control from .qiskit import convert_dds_to_quantum_circuit +from .cirq import convert_dds_to_cirq_circuit From d70f62fa464ded5cd1bcfac37f2d98956d3bee5a Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Wed, 22 May 2019 11:36:41 +1000 Subject: [PATCH 03/42] linted --- qctrlopencontrols/cirq/__init__.py | 2 +- qctrlopencontrols/cirq/cirq_circuit.py | 130 ++++++++++++++----------- qctrlopencontrols/cirq/constants.py | 4 +- 3 files changed, 75 insertions(+), 61 deletions(-) diff --git a/qctrlopencontrols/cirq/__init__.py b/qctrlopencontrols/cirq/__init__.py index 76204b42..83b8b29d 100644 --- a/qctrlopencontrols/cirq/__init__.py +++ b/qctrlopencontrols/cirq/__init__.py @@ -20,4 +20,4 @@ from .constants import (SCHEDULED_CIRCUIT, STANDARD_CIRCUIT, DEFAULT_ROTATION_MATRIX) -from .cirq_circuit import convert_dds_to_cirq_circuit \ No newline at end of file +from .cirq_circuit import convert_dds_to_cirq_circuit diff --git a/qctrlopencontrols/cirq/cirq_circuit.py b/qctrlopencontrols/cirq/cirq_circuit.py index 96f22d5c..4698e89c 100644 --- a/qctrlopencontrols/cirq/cirq_circuit.py +++ b/qctrlopencontrols/cirq/cirq_circuit.py @@ -156,6 +156,11 @@ def _get_scheduled_circuit(dynamic_decoupling_sequence, ------- cirq.Schedule The scheduled circuit operations + + Raises + ------ + ArgumentsValueError + If there is rotations around more than one axis at any of the offsets """ gate_time = gate_time * 1e9 @@ -178,10 +183,11 @@ def _get_scheduled_circuit(dynamic_decoupling_sequence, circuit_operations = [] if pre_post_gate is not None: for qubit in target_qubits: - op = cirq.ScheduledOperation(time=cirq.Timestamp(nanos=0), - duration=cirq.Duration(nanos=gate_time), - operation=pre_post_gate(qubit)) - circuit_operations.append(op) + operation = cirq.ScheduledOperation( + time=cirq.Timestamp(nanos=0), + duration=cirq.Duration(nanos=gate_time), + operation=pre_post_gate(qubit)) + circuit_operations.append(operation) offsets = offsets + gate_time offset_count = 0 @@ -197,48 +203,55 @@ def _get_scheduled_circuit(dynamic_decoupling_sequence, if not np.isclose(rotation, 0.0): nonzero_pulse_counts += 1 if nonzero_pulse_counts > 1: - raise ArgumentsValueError('Open Controls support a sequence with one ' - 'valid pulse at any offset. Found sequence ' - 'with multiple rotation operations at an offset.', - {'dynamic_decoupling_sequence': str( - dynamic_decoupling_sequence), - 'instance_operation': instance_operation}) + raise ArgumentsValueError( + 'Open Controls support a sequence with one ' + 'valid pulse at any offset. Found sequence ' + 'with multiple rotation operations at an offset.', + {'dynamic_decoupling_sequence': str(dynamic_decoupling_sequence), + 'instance_operation': instance_operation}) + for qubit in target_qubits: if nonzero_pulse_counts == 0: - op = cirq.ScheduledOperation(time=cirq.Timestamp(nanos=offsets[op_idx]), - duration=cirq.Duration(nanos=gate_time), - operation=cirq.I(qubit)) + operation = cirq.ScheduledOperation( + time=cirq.Timestamp(nanos=offsets[op_idx]), + duration=cirq.Duration(nanos=gate_time), + operation=cirq.I(qubit)) else: if not np.isclose(rotations[0], 0.0): - op = cirq.ScheduledOperation(time=cirq.Timestamp(nanos=offsets[op_idx]), - duration=cirq.Duration(nanos=gate_time), - operation=cirq.Rx(rotations[0])(qubit)) + operation = cirq.ScheduledOperation( + time=cirq.Timestamp(nanos=offsets[op_idx]), + duration=cirq.Duration(nanos=gate_time), + operation=cirq.Rx(rotations[0])(qubit)) elif not np.isclose(rotations[1], 0.0): - op = cirq.ScheduledOperation(time=cirq.Timestamp(nanos=offsets[op_idx]), - duration=cirq.Duration(nanos=gate_time), - operation=cirq.Rx(rotations[1])(qubit)) + operation = cirq.ScheduledOperation( + time=cirq.Timestamp(nanos=offsets[op_idx]), + duration=cirq.Duration(nanos=gate_time), + operation=cirq.Rx(rotations[1])(qubit)) elif not np.isclose(rotations[2], 0.): - op = cirq.ScheduledOperation(time=cirq.Timestamp(nanos=offsets[op_idx]), - duration=cirq.Duration(nanos=gate_time), - operation=cirq.Rx(rotations[2])(qubit)) + operation = cirq.ScheduledOperation( + time=cirq.Timestamp(nanos=offsets[op_idx]), + duration=cirq.Duration(nanos=gate_time), + operation=cirq.Rx(rotations[2])(qubit)) offset_count += 1 - circuit_operations.append(op) + circuit_operations.append(operation) if pre_post_gate is not None: for qubit in target_qubits: - op = cirq.ScheduledOperation(time=cirq.Timestamp(nanos=offsets[-1] + gate_time), - duration=cirq.Duration(nanos=gate_time), - operation=pre_post_gate(qubit)) - circuit_operations.append(op) + operation = cirq.ScheduledOperation( + time=cirq.Timestamp(nanos=offsets[-1] + gate_time), + duration=cirq.Duration(nanos=gate_time), + operation=pre_post_gate(qubit)) + circuit_operations.append(operation) offsets = offsets + gate_time if add_measurement: for idx, qubit in enumerate(target_qubits): - op = cirq.ScheduledOperation(time=cirq.Timestamp(nanos=offsets[-1] + gate_time), - duration=cirq.Duration(nanos=gate_time), - operation=cirq.MeasurementGate( - 1 ,key='qubit-{}'.format(idx))(qubit)) - circuit_operations.append(op) + operation = cirq.ScheduledOperation( + time=cirq.Timestamp(nanos=offsets[-1] + gate_time), + duration=cirq.Duration(nanos=gate_time), + operation=cirq.MeasurementGate( + 1, key='qubit-{}'.format(idx))(qubit)) + circuit_operations.append(operation) schedule = cirq.Schedule(device=device, scheduled_operations=circuit_operations) return schedule @@ -274,6 +287,11 @@ def _get_standard_circuit(dynamic_decoupling_sequence, The circuit prepared from dynamic decoupling sequence. In standard circuit the desired decoupling pulses are placed at offsets and the duration between the pulses are constructed from identity gates with delays equal to 'gate_time'. + + Raises + ------ + ArgumentsValueError + If there is rotations around more than one axis at any of the offsets """ unitary_time = gate_time @@ -303,8 +321,7 @@ def _get_standard_circuit(dynamic_decoupling_sequence, instance_operation = np.array( [dynamic_decoupling_sequence.rabi_rotations[offset_count], dynamic_decoupling_sequence.azimuthal_angles[offset_count], - dynamic_decoupling_sequence.detuning_rotations[offset_count] - ]) + dynamic_decoupling_sequence.detuning_rotations[offset_count]]) rotations = _get_rotations(instance_operation) nonzero_pulse_counts = 0 @@ -312,12 +329,12 @@ def _get_standard_circuit(dynamic_decoupling_sequence, if not np.isclose(rotation, 0.0): nonzero_pulse_counts += 1 if nonzero_pulse_counts > 1: - raise ArgumentsValueError('Open Controls support a sequence with one ' - 'valid pulse at any offset. Found sequence ' - 'with multiple rotation operations at an offset.', - {'dynamic_decoupling_sequence': str( - dynamic_decoupling_sequence), - 'instance_operation': instance_operation}) + raise ArgumentsValueError( + 'Open Controls support a sequence with one ' + 'valid pulse at any offset. Found sequence ' + 'with multiple rotation operations at an offset.', + {'dynamic_decoupling_sequence': str(dynamic_decoupling_sequence), + 'instance_operation': instance_operation}) gate_list = [] for qubit in target_qubits: if nonzero_pulse_counts == 0: @@ -370,7 +387,7 @@ def convert_dds_to_cirq_circuit( Time (in seconds) delay introduced by a gate; defaults to 0.1 pre_post_gate_unitary_matrix : numpy.ndarray or None, optional A 2x2 unitary matrix as pre-post gate operations. Defaults to - the unitary matrix corresponding to a rotation of :math:'pi/2' around + the unitary matrix corresponding to a rotation of :math:'\\pi/2' around X-axis. If None, pre-post gate is omitted from the circuit. add_measurement : bool, optional If True, the circuit contains a measurement operation for each of the @@ -402,7 +419,7 @@ def convert_dds_to_cirq_circuit( Raises ------ ArgumentsValueError - If any of the input parameters are invalid + If any of the input parameters result in an invalid operation. Notes ----- @@ -419,8 +436,8 @@ def convert_dds_to_cirq_circuit( In 'standard circuit' type, the `gaps` or idle time in between active pulses are filled up with `identity` gates. Each identity gate introduces a delay of `gate_time`. In this implementation, the number of identity gates - is determined by :math:`np.int(np.floor(offset_distance / gate_time))`. As a consequence, the duration of - the real-circuit is :math:`gate_time \\times number_of_identity_gates + + is determined by :math:`np.int(np.floor(offset_distance / gate_time))`. As a consequence, + the duration of the real-circuit is :math:`gate_time \\times number_of_identity_gates + pulse_gate_time \\times number_of_pulses`. In 'scheduled circuit', the active pulses are scheduled to be activated at a certain @@ -465,19 +482,16 @@ def convert_dds_to_cirq_circuit( pre_post_gate=pre_post_gate, add_measurement=add_measurement) - elif circuit_type == SCHEDULED_CIRCUIT: - if device is None: - device = cirq.UnconstrainedDevice - - if not isinstance(device, cirq.Device): - raise ArgumentsValueError('Device must be a cirq.Device type.', - {'device': device}) - - return _get_scheduled_circuit(dynamic_decoupling_sequence=dynamic_decoupling_sequence, - target_qubits=target_qubits, - gate_time=gate_time, - pre_post_gate=pre_post_gate, - add_measurement=add_measurement, - device=device) + if device is None: + device = cirq.UnconstrainedDevice + if not isinstance(device, cirq.Device): + raise ArgumentsValueError('Device must be a cirq.Device type.', + {'device': device}) + return _get_scheduled_circuit(dynamic_decoupling_sequence=dynamic_decoupling_sequence, + target_qubits=target_qubits, + gate_time=gate_time, + pre_post_gate=pre_post_gate, + add_measurement=add_measurement, + device=device) diff --git a/qctrlopencontrols/cirq/constants.py b/qctrlopencontrols/cirq/constants.py index 86d3a509..fc23b829 100644 --- a/qctrlopencontrols/cirq/constants.py +++ b/qctrlopencontrols/cirq/constants.py @@ -32,6 +32,6 @@ """ DEFAULT_ROTATION_MATRIX = (1. / np.power(2, 0.5)) * np.array( - [[1, -1j], [-1j, 1]], dtype='complex') -"""Unitary matrix of a Hadamard gate + [[1, -1j], [-1j, 1]], dtype='complex') +"""Unitary matrix for a :math:`\\pi/2` rotation around X-axis. """ From f78932aa2ccb8eba61a289573ed4c7fc37a1c02b Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Wed, 22 May 2019 13:12:50 +1000 Subject: [PATCH 04/42] tests for cirq circuits added --- tests/test_cirq_circuits.py | 126 ++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 tests/test_cirq_circuits.py diff --git a/tests/test_cirq_circuits.py b/tests/test_cirq_circuits.py new file mode 100644 index 00000000..333c0da4 --- /dev/null +++ b/tests/test_cirq_circuits.py @@ -0,0 +1,126 @@ +# Copyright 2019 Q-CTRL Pty Ltd & Q-CTRL Inc +# +# 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. + +""" +=================================== +Tests converstion to Qiskit Circuit +=================================== +""" + +import numpy as np +import cirq + +from qctrlopencontrols import ( + new_predefined_dds, convert_dds_to_cirq_circuit) + + +def _create_test_sequence(sequence_scheme): + + """Create a DD sequence of choice''' + + Parameters + ---------- + sequence_scheme : str + One of 'Spin echo', 'Carr-Purcell', 'Carr-Purcell-Meiboom-Gill', + 'Uhrig single-axis', 'Periodic single-axis', 'Walsh single-axis', + 'Quadratic', 'X concatenated', + 'XY concatenated' + + Returns + ------- + DynamicDecouplingSequence + The Dynamical Decoupling Sequence instance built from supplied + schema information + """ + + dd_sequence_params = dict() + dd_sequence_params['scheme'] = sequence_scheme + dd_sequence_params['duration'] = 4 + + # 'spin_echo' does not need any additional parameter + + if dd_sequence_params['scheme'] in ['Carr-Purcell', 'Carr-Purcell-Meiboom-Gill', + 'Uhrig single-axis', 'periodic single-axis']: + + dd_sequence_params['number_of_offsets'] = 2 + + elif dd_sequence_params['scheme'] in ['Walsh single-axis']: + + dd_sequence_params['paley_order'] = 5 + + elif dd_sequence_params['scheme'] in ['quadratic']: + + dd_sequence_params['duration'] = 16 + dd_sequence_params['number_outer_offsets'] = 4 + dd_sequence_params['number_inner_offsets'] = 4 + + elif dd_sequence_params['scheme'] in ['X concatenated', + 'XY concatenated']: + + dd_sequence_params['duration'] = 16 + dd_sequence_params['concatenation_order'] = 2 + + sequence = new_predefined_dds(**dd_sequence_params) + return sequence + + +def _check_circuit_unitary(pre_post_gate_unitary_matrix, + circuit_type, expected_result): + """Check the unitary of a dynamic decoupling operation + """ + + simulator = cirq.Simulator() + for sequence_scheme in ['Carr-Purcell', 'Carr-Purcell-Meiboom-Gill', + 'Uhrig single-axis', 'periodic single-axis', + 'Walsh single-axis', 'quadratic', 'X concatenated', + 'XY concatenated']: + sequence = _create_test_sequence(sequence_scheme) + cirq_circuit = convert_dds_to_cirq_circuit( + dynamic_decoupling_sequence=sequence, + pre_post_gate_unitary_matrix=pre_post_gate_unitary_matrix, + add_measurement=True, circuit_type=circuit_type) + + results = simulator.run(cirq_circuit) + assert results.measurements['qubit-0'] == expected_result + + +def test_identity_operation(): + + """Tests if the Dynamic Decoupling Sequence gives rise to expected + state with different pre-post gates + """ + _check_circuit_unitary(None, 'scheduled circuit', 0) + pre_post_gate_unitary_matrix = (1. / np.power(2, 0.5)) * np.array( + [[1, -1j], [-1j, 1]], dtype='complex') + _check_circuit_unitary(pre_post_gate_unitary_matrix, + 'scheduled circuit', 1) + + pre_post_gate_unitary_matrix = np.array( + [[1, 0], [0, 1]], dtype='complex') + _check_circuit_unitary(pre_post_gate_unitary_matrix, + 'scheduled circuit', 0) + + _check_circuit_unitary(None, 'standard circuit', 0) + pre_post_gate_unitary_matrix = (1. / np.power(2, 0.5)) * np.array( + [[1, -1j], [-1j, 1]], dtype='complex') + _check_circuit_unitary(pre_post_gate_unitary_matrix, + 'standard circuit', 1) + + pre_post_gate_unitary_matrix = np.array( + [[1, 0], [0, 1]], dtype='complex') + _check_circuit_unitary(pre_post_gate_unitary_matrix, + 'standard circuit', 0) + +if __name__ == '__main__': + pass From 224fff90a896303afed2b6c8bfb3e70d73e27c24 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Wed, 22 May 2019 13:22:22 +1000 Subject: [PATCH 05/42] docstring fixed/modified --- qctrlopencontrols/cirq/cirq_circuit.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/qctrlopencontrols/cirq/cirq_circuit.py b/qctrlopencontrols/cirq/cirq_circuit.py index 4698e89c..85cada94 100644 --- a/qctrlopencontrols/cirq/cirq_circuit.py +++ b/qctrlopencontrols/cirq/cirq_circuit.py @@ -33,7 +33,7 @@ def _get_circuit_gate_list(dynamic_decoupling_sequence, unitary_time): """Converts the operations in a sequence into list of gates - of a quantum circuit + of a circuit Parameters ---------- @@ -155,7 +155,9 @@ def _get_scheduled_circuit(dynamic_decoupling_sequence, Returns ------- cirq.Schedule - The scheduled circuit operations + The scheduled circuit operations. The Schedule object contains a + series of desired gates at specific times measured from the start + of the duration. Raises ------ @@ -263,7 +265,7 @@ def _get_standard_circuit(dynamic_decoupling_sequence, pre_post_gate, add_measurement): - """Returns a standard circuit construncted from dynamic + """Returns a standard circuit constructed from dynamic decoupling sequence Parameters @@ -375,6 +377,7 @@ def convert_dds_to_cirq_circuit( """Converts a Dynamic Decoupling Sequence into QuantumCircuit as defined in Qiskit + Parameters ---------- dynamic_decoupling_sequence : DynamicDecouplingSequence @@ -412,7 +415,7 @@ def convert_dds_to_cirq_circuit( Returns ------- - cirq.circuit or cirq.schedule + cirq.Circuit or cirq.Schedule The circuit or schedule (depending on circuit_type option). Either of them can be used with cirq.Simulator. @@ -433,10 +436,11 @@ def convert_dds_to_cirq_circuit( `duration` where a pulse occurs instantaneously. A series of appropriate circuit components is placed in order to represent these pulses. - In 'standard circuit' type, the `gaps` or idle - time in between active pulses are filled up with `identity` gates. Each identity gate - introduces a delay of `gate_time`. In this implementation, the number of identity gates - is determined by :math:`np.int(np.floor(offset_distance / gate_time))`. As a consequence, + In 'standard circuit', the `gaps` or idle time in between active pulses are filled up + with `identity` gates. Each identity gate introduces a delay of `gate_time`. In this + implementation, the number of identity gates is determined by + :math:`np.int(np.floor(offset_distance / gate_time))`. As a consequence, + :math:`np.int(np.floor(offset_distance / gate_time))`. As a consequence, the duration of the real-circuit is :math:`gate_time \\times number_of_identity_gates + pulse_gate_time \\times number_of_pulses`. From 08bc84bdf3250edbc5480ea7fb8328cba0c954f5 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Wed, 22 May 2019 15:53:48 +1000 Subject: [PATCH 06/42] first draft of the notebook example added --- examples/running_a_dds_on_cirq.ipynb | 308 +++++++++++++++++++++++++++ 1 file changed, 308 insertions(+) create mode 100644 examples/running_a_dds_on_cirq.ipynb diff --git a/examples/running_a_dds_on_cirq.ipynb b/examples/running_a_dds_on_cirq.ipynb new file mode 100644 index 00000000..8e9301a2 --- /dev/null +++ b/examples/running_a_dds_on_cirq.ipynb @@ -0,0 +1,308 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Running a Dynamical Decoupling Sequence on Cirq\n", + "\n", + "Q-CTRL Open Controls provides easy-to-use methods to construct Dynamical Decoupling Sequences (DDS) according to well-known dynamical decoupling schemes. This is described in the [creating a DDS notebook](creating_a_dds.ipynb). Here we show how a DDS from Q-CTRL Open Controls can be exported to a `cirq.Circuit` to run in `cirq.Simulator`.\n", + "\n", + "Note : You can install `cirq` by simply running `pip install cirq`. Please consult [Cirq Documentation](https://cirq.readthedocs.io/en/stable/) for installation instruction and general introduction to `cirq` package." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Imports" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "#General\n", + "\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from matplotlib.gridspec import GridSpec\n", + "\n", + "#Q-CTRL Open Controls\n", + "from qctrlopencontrols import new_predefined_dds, convert_dds_to_cirq_circuit\n", + "\n", + "#Cirq\n", + "import cirq" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Running a DDS on a Cirq Simulator\n", + "\n", + "This section demonstrates how a DDS can be prepared and a corresponding `cirq.Circuit` made and executed on a `cirq` simulator (`cirq.Simulator`).\n", + "\n", + "Q-CTRL Open Controls defines a DDS as a set of instantaneous unitary operations performed at specific offset times, see the [technical documentation](https://docs.q-ctrl.com/control-library#dynamical-decoupling-sequences) for mathematical details.\n", + "\n", + "`cirq` implements quantum computation through a series of [gates](https://cirq.readthedocs.io/en/stable/gates.html). Standard way to create a circuit is through `cirq.Circuit` that accepts a list of valid gates. If a user wants to add pauses (in time) during a computation they can use identity gates. Alternatively, `cirq` provides `ScheduledOperation` that specifies an operation (application of a gate operating on one more qubits) at a certain instant measured in \"nano-seconds\" or \"pico-seconds\" from the start of the sequence. A list of `ScheduledOperation` is collated by `cirq.Schedule`. Both `cirq.Circuit` and `cirq.Schedule` can be used in `cirq.Simulator` to simulate the circuit. We provide a `circuit_type` option to select between `cirq.Circuit` and `cirq.Schedule` as desired output from the conversion method.\n", + "\n", + "Converting a DDS into a `cirq` circuit is an approximate process where the instantaneous unitaries are replaced with finite duration gates. Morver, in `cirq.Circuit`, the pauses in-between unitaries are replaced with the closest integer number of identity gates. The exact algorithm used to make this approximation is documented in the [source code](../qctrlopencontrols/cirq/cirq_circuit.py).\n", + "\n", + "In this example we will define a Quadratic DDS and convert it into a circuit that we can later run on a simulator. See [creating_a_DDS.ipynb](creating_a_DDS.ipynb) to see how other sequences can be created." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Preparing the Sequences" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Quadratic sequence:\n", + "Duration = 2e-05\n", + "Offsets = [0.0,0.06249999999999998,0.18749999999999994,0.24999999999999994,0.37499999999999994,0.6249999999999999,0.7499999999999999,0.8124999999999999,0.9375,1.0] x 2e-05\n", + "Rabi Rotations = [0.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,0.0] x pi\n", + "Azimuthal Angles = [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0] x pi\n", + "Detuning Rotations = [0.0,1.0,1.0,0.0,1.0,1.0,0.0,1.0,1.0,0.0] x pi\n" + ] + } + ], + "source": [ + "## Quadratic sequence, total duration: 20us\n", + "quadratic_sequence = new_predefined_dds(\n", + " scheme='quadratic',\n", + " duration=20e-6, \n", + " number_inner_offsets=2,\n", + " number_outer_offsets=2,\n", + " name='Quadratic sequence')\n", + "print(quadratic_sequence)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Constructing the Circuit Using Q-CTRL Open Controls\n", + "\n", + "To construct a circuit/schedule from a DDS, we need to provide the DDS (`dynamic_decoupling_sequence`). You can also provide a list of target qubits (each of `cirq.Qid` type) to indicate qubits on which the DDS will be applied. `gate_time` is the delay (in seconds) introduced by each of the gates. If measurement is required, use `add_measurement=True`.\n", + "\n", + "See the [source code](../qctrlopencontrols/cirq/cirq_circuit.py) for more information and other parameters that may be useful.\n", + "\n", + "In this example, we will use the default single qubit on 1-D lattice and $X_{\\pi/2}$ rotation as the pre-post gate. We specify the `gate_time` to be $0.4$ $\\mu$s. Finally we will add a measurement operation. In this example we will convert the DDS into a `cirq.Circuit`." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "## Prepare the conversion related parameters\n", + "'''\n", + "gate_time : float\n", + " Time delay (in seconds) introduced by identity gate\n", + "'''\n", + "gate_time = 0.4e-6\n", + "\n", + "'''\n", + "add_measurement : bool\n", + " Indicates if the circuit requires a measurement step.\n", + " Required for 'qasm_simulator' and real device backends\n", + "'''\n", + "add_measurement = True\n", + "\n", + "'''\n", + "circuit_type : str\n", + " One of 'scheduled circuit' (convert to cirq.Schedule) or \n", + " 'standard circuit' (convert to cirq.Circuit). See source code\n", + " documentation for more details.\n", + "'''\n", + "circuit_type = 'standard circuit'\n", + "\n", + "\n", + "## convert the quadratic sequence to cirq.Circuit\n", + "quadratic_cirq_circuit = convert_dds_to_cirq_circuit(\n", + " dynamic_decoupling_sequence=quadratic_sequence,\n", + " gate_time=gate_time,\n", + " add_measurement=add_measurement,\n", + " circuit_type=circuit_type\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plotting the DDS\n", + "\n", + "We can use Q-CTRL Open Controls to plot the DDS for comparison against its `cirq` circuit approximations." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "formatted_plot_data = quadratic_sequence.get_plot_formatted_arrays()\n", + "rabi_rotations, azimuthal_angles, detuning_rotations, times = (\n", + " formatted_plot_data['rabi_rotations'],\n", + " formatted_plot_data['azimuthal_angles'],\n", + " formatted_plot_data['detuning_rotations'],\n", + " formatted_plot_data['times']\n", + ")\n", + "\n", + "# prepare the axes\n", + "figure, (rabi_plot_axis, azimuth_plot_axis, detuning_plot_axis) = plt.subplots(\n", + " 3, 1, figsize=(20,5))\n", + "\n", + "rabi_plot_axis.plot(times, rabi_rotations)\n", + "rabi_plot_axis.ticklabel_format(style='sci', axis='x', scilimits=(0, 2))\n", + "rabi_plot_axis.set_xlabel('Time (sec)')\n", + "rabi_plot_axis.set_ylabel('Rabi Rotations (rad)')\n", + "\n", + "azimuth_plot_axis.plot(times, azimuthal_angles)\n", + "azimuth_plot_axis.ticklabel_format(style='sci', axis='x', scilimits=(0, 2))\n", + "azimuth_plot_axis.set_xlabel('Time (sec)')\n", + "azimuth_plot_axis.set_ylabel('Azimuthal Angle (rad)')\n", + "\n", + "detuning_plot_axis.plot(times, detuning_rotations)\n", + "detuning_plot_axis.ticklabel_format(style='sci', axis='x', scilimits=(0, 2))\n", + "detuning_plot_axis.set_xlabel('Time (sec)')\n", + "detuning_plot_axis.set_ylabel('Detuning Rotation (rad)')\n", + "\n", + "plt.suptitle('Quadratic Sequence')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Printing the Circuit\n", + "\n", + "We can print a `cirq.Circuit` generated by Q-CTRL Open Controls.\n", + "\n", + "Note that both DDS will be applied with $X_{\\pi/2}$ rotations at beginning and end, that is, at offsets of $[0, 20]$ $\\mu$s, to create the desired superposition state. The $X_{\\pi/2}$ rotations are not part of the DDS objects but are added to the circuits in the form of pre-post-gates that are implemented via `cirq.SingleQubitGate`. The `SingleQubitGate` is specified by a $2\\times 2$ unitary matrix. In this case, the following unitary matrix (corresponding to $X_{\\pi/2}$ rotation) is supplied as default by the conversion method.\n", + "\n", + "$$\n", + "\\frac{1}{\\sqrt{2}}\\times\\begin{bmatrix}1 & -1j\\\\-1j & 1\\end{bmatrix}\n", + "$$\n", + "\n", + "The $Rz(\\pi)$ gates are $Z_\\pi$ pulses (a $\\pi$ rotation around $Z$-axis) and $Rx(\\pi)$ gates correspond to $X_{\\pi}$ pulses (a $\\pi$ rotation around $X$-axis). The gates match the pulses in the DDS.\n", + "\n", + "The `Id` in the drawing corresponds to the `identity` gate. In the DDS, the first $Z_{\\pi}$-pulse is applied at a delay of $1.25$ $\\mu$s. This is approximated by introducing 3-`Id` gates with a delay of $0.4\\times 3=1.2$ $\\mu$s. Application of $Z_{\\pi}$ pulse will take another $0.4\\mu$s. Similarly, the second set of 5 `Id` gates introduces a delay of $2$ $\\mu$s close to the actual delay of $3.75-1.65=2.10$ microseconds.\n", + "\n", + "At the end of each circuit, we place a `measurement` ($M$) operator to read out the result." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " ┌ ┐ ┌ ┐\n", + "0: ───│0.707+0.j 0. -0.707j│───I───I───I───I───Rz(π)───I───I───I───I───I───Rz(π)───I───I───Rx(π)───I───I───I───I───I───Rz(π)───I───I───I───I───I───I───I───I───I───I───I───Rz(π)───I───I───I───I───I───Rx(π)───I───I───Rz(π)───I───I───I───I───I───Rz(π)───I───I───I───│0.707+0.j 0. -0.707j│───M('qubit-0')───\n", + " │0. -0.707j 0.707+0.j │ │0. -0.707j 0.707+0.j │\n", + " └ ┘ └ ┘\n" + ] + } + ], + "source": [ + "##Printing the Quadratic Circuit\n", + "print(quadratic_cirq_circuit)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Run the Circuit on Cirq Simulator using Cirq API\n", + "\n", + "Consult [Simulation](https://cirq.readthedocs.io/en/stable/simulation.html) for a description of available simulation APIs and their respective properties. Here, we will use the `run` method of `cirq.Simulator` to run the circuit. The circuit is run multiple times upto `repetitions` times. The result is printed after the simulation." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "qubit-0=1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\n", + "Counter({1: 100})\n" + ] + } + ], + "source": [ + "## Prepares the simulator parameters\n", + "'''\n", + "repetitions : int\n", + " The number of times the circuit will be executed\n", + "'''\n", + "repetitions = 100\n", + "\n", + "simulator = cirq.Simulator()\n", + "result = simulator.run(quadratic_cirq_circuit, repetitions=repetitions)\n", + "\n", + "#print the outcome of each repetition\n", + "print(result)\n", + "\n", + "#you can also collect the outcome as histogram (calculated as dict)\n", + "print(result.histogram(key=['qubit-0']))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.8" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 4afc86bfaf1c208ad6d4d2b160c5bef9ca7f001e Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Wed, 22 May 2019 16:21:50 +1000 Subject: [PATCH 07/42] modified test method; added cirq dependency in setup --- qctrlopencontrols/cirq/__init__.py | 2 +- qctrlopencontrols/cirq/cirq_circuit.py | 5 +++-- qctrlopencontrols/cirq/constants.py | 2 +- setup.py | 4 +++- tests/test_cirq_circuits.py | 26 +++++++++++++------------- 5 files changed, 21 insertions(+), 18 deletions(-) diff --git a/qctrlopencontrols/cirq/__init__.py b/qctrlopencontrols/cirq/__init__.py index 83b8b29d..381efad9 100644 --- a/qctrlopencontrols/cirq/__init__.py +++ b/qctrlopencontrols/cirq/__init__.py @@ -19,5 +19,5 @@ """ from .constants import (SCHEDULED_CIRCUIT, STANDARD_CIRCUIT, - DEFAULT_ROTATION_MATRIX) + DEFAULT_PRE_POST_ROTATION_MATRIX) from .cirq_circuit import convert_dds_to_cirq_circuit diff --git a/qctrlopencontrols/cirq/cirq_circuit.py b/qctrlopencontrols/cirq/cirq_circuit.py index 85cada94..49dcbec4 100644 --- a/qctrlopencontrols/cirq/cirq_circuit.py +++ b/qctrlopencontrols/cirq/cirq_circuit.py @@ -25,7 +25,8 @@ from qctrlopencontrols.dynamic_decoupling_sequences import DynamicDecouplingSequence from qctrlopencontrols.exceptions import ArgumentsValueError -from .constants import (SCHEDULED_CIRCUIT, STANDARD_CIRCUIT, DEFAULT_ROTATION_MATRIX) +from .constants import (SCHEDULED_CIRCUIT, STANDARD_CIRCUIT, + DEFAULT_PRE_POST_ROTATION_MATRIX) def _get_circuit_gate_list(dynamic_decoupling_sequence, @@ -370,7 +371,7 @@ def convert_dds_to_cirq_circuit( dynamic_decoupling_sequence, target_qubits=None, gate_time=0.1, - pre_post_gate_unitary_matrix=DEFAULT_ROTATION_MATRIX, + pre_post_gate_unitary_matrix=DEFAULT_PRE_POST_ROTATION_MATRIX, add_measurement=True, circuit_type=STANDARD_CIRCUIT, device=None): diff --git a/qctrlopencontrols/cirq/constants.py b/qctrlopencontrols/cirq/constants.py index fc23b829..437f61c6 100644 --- a/qctrlopencontrols/cirq/constants.py +++ b/qctrlopencontrols/cirq/constants.py @@ -31,7 +31,7 @@ identity gates between desired rotation operations. """ -DEFAULT_ROTATION_MATRIX = (1. / np.power(2, 0.5)) * np.array( +DEFAULT_PRE_POST_ROTATION_MATRIX = (1. / np.power(2, 0.5)) * np.array( [[1, -1j], [-1j, 1]], dtype='complex') """Unitary matrix for a :math:`\\pi/2` rotation around X-axis. """ diff --git a/setup.py b/setup.py index c299a99c..ee781d59 100644 --- a/setup.py +++ b/setup.py @@ -45,7 +45,9 @@ def main(): packages=find_packages(), setup_requires=['pytest-runner'], tests_require=['pytest'], - install_requires=['numpy', 'scipy', 'pytest', 'nbval', 'qiskit-terra', 'qiskit-ibmq-provider'], + install_requires=['numpy', 'scipy', 'pytest', 'nbval', + 'qiskit-terra', 'qiskit-ibmq-provider', + 'cirq'], author='Q-CTRL', author_email='support@q-ctrl.com', description='Q-CTRL Open Controls', diff --git a/tests/test_cirq_circuits.py b/tests/test_cirq_circuits.py index 333c0da4..e7cbc9ba 100644 --- a/tests/test_cirq_circuits.py +++ b/tests/test_cirq_circuits.py @@ -14,7 +14,7 @@ """ =================================== -Tests converstion to Qiskit Circuit +Tests converstion to Cirq Circuit =================================== """ @@ -75,8 +75,8 @@ def _create_test_sequence(sequence_scheme): return sequence -def _check_circuit_unitary(pre_post_gate_unitary_matrix, - circuit_type, expected_result): +def _check_circuit_output(pre_post_gate_unitary_matrix, + circuit_type, expected_result): """Check the unitary of a dynamic decoupling operation """ @@ -100,27 +100,27 @@ def test_identity_operation(): """Tests if the Dynamic Decoupling Sequence gives rise to expected state with different pre-post gates """ - _check_circuit_unitary(None, 'scheduled circuit', 0) + _check_circuit_output(None, 'scheduled circuit', 0) pre_post_gate_unitary_matrix = (1. / np.power(2, 0.5)) * np.array( [[1, -1j], [-1j, 1]], dtype='complex') - _check_circuit_unitary(pre_post_gate_unitary_matrix, - 'scheduled circuit', 1) + _check_circuit_output(pre_post_gate_unitary_matrix, + 'scheduled circuit', 1) pre_post_gate_unitary_matrix = np.array( [[1, 0], [0, 1]], dtype='complex') - _check_circuit_unitary(pre_post_gate_unitary_matrix, - 'scheduled circuit', 0) + _check_circuit_output(pre_post_gate_unitary_matrix, + 'scheduled circuit', 0) - _check_circuit_unitary(None, 'standard circuit', 0) + _check_circuit_output(None, 'standard circuit', 0) pre_post_gate_unitary_matrix = (1. / np.power(2, 0.5)) * np.array( [[1, -1j], [-1j, 1]], dtype='complex') - _check_circuit_unitary(pre_post_gate_unitary_matrix, - 'standard circuit', 1) + _check_circuit_output(pre_post_gate_unitary_matrix, + 'standard circuit', 1) pre_post_gate_unitary_matrix = np.array( [[1, 0], [0, 1]], dtype='complex') - _check_circuit_unitary(pre_post_gate_unitary_matrix, - 'standard circuit', 0) + _check_circuit_output(pre_post_gate_unitary_matrix, + 'standard circuit', 0) if __name__ == '__main__': pass From a1833c89e54827b095019e1ad3ba3cfa5e374d1b Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Wed, 22 May 2019 17:38:51 +1000 Subject: [PATCH 08/42] notebook updated; test docstring modified --- examples/running_a_dds_on_cirq.ipynb | 56 ++++++++++++++++------------ tests/test_cirq_circuits.py | 8 ++-- 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/examples/running_a_dds_on_cirq.ipynb b/examples/running_a_dds_on_cirq.ipynb index 8e9301a2..f238b023 100644 --- a/examples/running_a_dds_on_cirq.ipynb +++ b/examples/running_a_dds_on_cirq.ipynb @@ -25,7 +25,6 @@ "outputs": [], "source": [ "#General\n", - "\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "from matplotlib.gridspec import GridSpec\n", @@ -43,13 +42,13 @@ "source": [ "## Running a DDS on a Cirq Simulator\n", "\n", - "This section demonstrates how a DDS can be prepared and a corresponding `cirq.Circuit` made and executed on a `cirq` simulator (`cirq.Simulator`).\n", + "This section demonstrates how a DDS can be prepared, a corresponding quantum circuit made and executed on a `cirq` simulator.\n", "\n", "Q-CTRL Open Controls defines a DDS as a set of instantaneous unitary operations performed at specific offset times, see the [technical documentation](https://docs.q-ctrl.com/control-library#dynamical-decoupling-sequences) for mathematical details.\n", "\n", - "`cirq` implements quantum computation through a series of [gates](https://cirq.readthedocs.io/en/stable/gates.html). Standard way to create a circuit is through `cirq.Circuit` that accepts a list of valid gates. If a user wants to add pauses (in time) during a computation they can use identity gates. Alternatively, `cirq` provides `ScheduledOperation` that specifies an operation (application of a gate operating on one more qubits) at a certain instant measured in \"nano-seconds\" or \"pico-seconds\" from the start of the sequence. A list of `ScheduledOperation` is collated by `cirq.Schedule`. Both `cirq.Circuit` and `cirq.Schedule` can be used in `cirq.Simulator` to simulate the circuit. We provide a `circuit_type` option to select between `cirq.Circuit` and `cirq.Schedule` as desired output from the conversion method.\n", + "`cirq` implements quantum operations through a series of [gates](https://cirq.readthedocs.io/en/stable/gates.html). Standard way to create a circuit is through `cirq.Circuit` that accepts a list of valid gates. If a user wants to add pauses (in time) during a computation they can use identity gates. Alternatively, `cirq` provides `ScheduledOperation` that specifies an operation (application of a gate on one more qubits) at a certain instant measured in \"nano-seconds\" or \"pico-seconds\" from the start of the sequence. A list of `ScheduledOperation` is collated by `cirq.Schedule`. Both `cirq.Circuit` and `cirq.Schedule` can be used in `cirq.Simulator` to simulate the circuit. We provide a `circuit_type` option to select between `cirq.Circuit` and `cirq.Schedule` as desired output from the conversion method.\n", "\n", - "Converting a DDS into a `cirq` circuit is an approximate process where the instantaneous unitaries are replaced with finite duration gates. Morver, in `cirq.Circuit`, the pauses in-between unitaries are replaced with the closest integer number of identity gates. The exact algorithm used to make this approximation is documented in the [source code](../qctrlopencontrols/cirq/cirq_circuit.py).\n", + "Converting a DDS into a `cirq.Circuit` or `cirq.Schedule` is an approximate process where the instantaneous unitaries are replaced with finite duration gates. Moreover, in `cirq.Circuit`, the pauses in-between unitaries are replaced with the closest integer number of identity gates. The exact algorithm used to make this approximation is documented in the [source code](../qctrlopencontrols/cirq/cirq_circuit.py).\n", "\n", "In this example we will define a Quadratic DDS and convert it into a circuit that we can later run on a simulator. See [creating_a_DDS.ipynb](creating_a_DDS.ipynb) to see how other sequences can be created." ] @@ -87,7 +86,7 @@ " number_inner_offsets=2,\n", " number_outer_offsets=2,\n", " name='Quadratic sequence')\n", - "print(quadratic_sequence)\n" + "print(quadratic_sequence)" ] }, { @@ -100,7 +99,7 @@ "\n", "See the [source code](../qctrlopencontrols/cirq/cirq_circuit.py) for more information and other parameters that may be useful.\n", "\n", - "In this example, we will use the default single qubit on 1-D lattice and $X_{\\pi/2}$ rotation as the pre-post gate. We specify the `gate_time` to be $0.4$ $\\mu$s. Finally we will add a measurement operation. In this example we will convert the DDS into a `cirq.Circuit`." + "In this example, we will use a single qubit on 1-D lattice and $X_{\\pi/2}$ rotation as the pre-post gate. We specify the `gate_time` to be $0.4$ $\\mu$s. Finally we will add a measurement operation. In this example we will convert the DDS into a `cirq.Circuit`." ] }, { @@ -111,6 +110,14 @@ "source": [ "## Prepare the conversion related parameters\n", "'''\n", + "target_qubits : list\n", + " A list of cirq.Qid. In this case we are using a single\n", + " qubit (indexed 0) on 1-D lattice.\n", + "'''\n", + "target_qubits = [cirq.LineQubit(0)]\n", + "\n", + "\n", + "'''\n", "gate_time : float\n", " Time delay (in seconds) introduced by identity gate\n", "'''\n", @@ -135,6 +142,7 @@ "## convert the quadratic sequence to cirq.Circuit\n", "quadratic_cirq_circuit = convert_dds_to_cirq_circuit(\n", " dynamic_decoupling_sequence=quadratic_sequence,\n", + " target_qubits=target_qubits,\n", " gate_time=gate_time,\n", " add_measurement=add_measurement,\n", " circuit_type=circuit_type\n", @@ -147,7 +155,7 @@ "source": [ "### Plotting the DDS\n", "\n", - "We can use Q-CTRL Open Controls to plot the DDS for comparison against its `cirq` circuit approximations." + "We can use Q-CTRL Open Controls to plot the DDS for comparison against its `cirq.Circuit` approximations." ] }, { @@ -204,21 +212,18 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Printing the Circuit\n", - "\n", - "We can print a `cirq.Circuit` generated by Q-CTRL Open Controls.\n", + "### Drawing the Circuit\n", "\n", - "Note that both DDS will be applied with $X_{\\pi/2}$ rotations at beginning and end, that is, at offsets of $[0, 20]$ $\\mu$s, to create the desired superposition state. The $X_{\\pi/2}$ rotations are not part of the DDS objects but are added to the circuits in the form of pre-post-gates that are implemented via `cirq.SingleQubitGate`. The `SingleQubitGate` is specified by a $2\\times 2$ unitary matrix. In this case, the following unitary matrix (corresponding to $X_{\\pi/2}$ rotation) is supplied as default by the conversion method.\n", + "We can draw a text diagram of the `cirq.Circuit` generated by Q-CTRL Open Controls.\n", "\n", - "$$\n", - "\\frac{1}{\\sqrt{2}}\\times\\begin{bmatrix}1 & -1j\\\\-1j & 1\\end{bmatrix}\n", - "$$\n", + "Note that a $X_{\\pi/2}$ rotation will be added at beginning and end, that is, at offsets of $[0, 20]$ $\\mu$s, to create the desired superposition state. The $X_{\\pi/2}$ rotations are not part of the DDS objects but are added to the circuits in the form of pre-post-gates that are implemented via `cirq.SingleQubitGate`. The `SingleQubitGate` is specified by a $2\\times 2$ unitary matrix. In this case, the unitary matrix $\n", + "\\frac{1}{\\sqrt{2}}\\times\\begin{bmatrix}1 & -1j\\\\-1j & 1\\end{bmatrix}$ (corresponding to $X_{\\pi/2}$ rotation) is supplied as default by the conversion method.\n", "\n", "The $Rz(\\pi)$ gates are $Z_\\pi$ pulses (a $\\pi$ rotation around $Z$-axis) and $Rx(\\pi)$ gates correspond to $X_{\\pi}$ pulses (a $\\pi$ rotation around $X$-axis). The gates match the pulses in the DDS.\n", "\n", - "The `Id` in the drawing corresponds to the `identity` gate. In the DDS, the first $Z_{\\pi}$-pulse is applied at a delay of $1.25$ $\\mu$s. This is approximated by introducing 3-`Id` gates with a delay of $0.4\\times 3=1.2$ $\\mu$s. Application of $Z_{\\pi}$ pulse will take another $0.4\\mu$s. Similarly, the second set of 5 `Id` gates introduces a delay of $2$ $\\mu$s close to the actual delay of $3.75-1.65=2.10$ microseconds.\n", + "The `I` in the drawing corresponds to the `identity` gate. In the DDS, the first $Z_{\\pi}$-pulse is applied at a delay of $1.25$ $\\mu$s. This is approximated by introducing 3-`Id` gates with a delay of $0.4\\times 3=1.2$ $\\mu$s. Application of $Z_{\\pi}$ pulse will take another $0.4\\mu$s. Similarly, the second set of 5 `Id` gates introduces a delay of $2$ $\\mu$s close to the actual delay of $3.75-1.65=2.10$ microseconds.\n", "\n", - "At the end of each circuit, we place a `measurement` ($M$) operator to read out the result." + "At the end of the circuit, we placed a `measurement` ($M$) operator to read out the result." ] }, { @@ -230,16 +235,16 @@ "name": "stdout", "output_type": "stream", "text": [ - " ┌ ┐ ┌ ┐\n", - "0: ───│0.707+0.j 0. -0.707j│───I───I───I───I───Rz(π)───I───I───I───I───I───Rz(π)───I───I───Rx(π)───I───I───I───I───I───Rz(π)───I───I───I───I───I───I───I───I───I───I───I───Rz(π)───I───I───I───I───I───Rx(π)───I───I───Rz(π)───I───I───I───I───I───Rz(π)───I───I───I───│0.707+0.j 0. -0.707j│───M('qubit-0')───\n", - " │0. -0.707j 0.707+0.j │ │0. -0.707j 0.707+0.j │\n", - " └ ┘ └ ┘\n" + " ┌ ┐ ┌ ┐\n", + "0: ─│0.707+0.j 0. -0.707j│─I─I─I─I─Rz(π)─I─I─I─I─I─Rz(π)─I─I─Rx(π)─I─I─I─I─I─Rz(π)─I─I─I─I─I─I─I─I─I─I─I─Rz(π)─I─I─I─I─I─Rx(π)─I─I─Rz(π)─I─I─I─I─I─Rz(π)─I─I─I─│0.707+0.j 0. -0.707j│─M('qubit-0')─\n", + " │0. -0.707j 0.707+0.j │ │0. -0.707j 0.707+0.j │\n", + " └ ┘ └ ┘\n" ] } ], "source": [ - "##Printing the Quadratic Circuit\n", - "print(quadratic_cirq_circuit)" + "##Drawing the Quadratic Circuit\n", + "print(quadratic_cirq_circuit.to_text_diagram_drawer().render())" ] }, { @@ -248,7 +253,7 @@ "source": [ "### Run the Circuit on Cirq Simulator using Cirq API\n", "\n", - "Consult [Simulation](https://cirq.readthedocs.io/en/stable/simulation.html) for a description of available simulation APIs and their respective properties. Here, we will use the `run` method of `cirq.Simulator` to run the circuit. The circuit is run multiple times upto `repetitions` times. The result is printed after the simulation." + "Consult [Simulation](https://cirq.readthedocs.io/en/stable/simulation.html) for a description of available simulation APIs and their properties. Here, we will use the `run` method of `cirq.Simulator` to run the circuit. The circuit is run upto `repetitions` times. The result is printed after the simulation." ] }, { @@ -266,14 +271,17 @@ } ], "source": [ - "## Prepares the simulator parameters\n", + "##### Set the simulator parameters\n", "'''\n", "repetitions : int\n", " The number of times the circuit will be executed\n", "'''\n", "repetitions = 100\n", "\n", + "## Create the simulator\n", "simulator = cirq.Simulator()\n", + "\n", + "#Run the simulator and collect result\n", "result = simulator.run(quadratic_cirq_circuit, repetitions=repetitions)\n", "\n", "#print the outcome of each repetition\n", diff --git a/tests/test_cirq_circuits.py b/tests/test_cirq_circuits.py index e7cbc9ba..b88797eb 100644 --- a/tests/test_cirq_circuits.py +++ b/tests/test_cirq_circuits.py @@ -27,7 +27,7 @@ def _create_test_sequence(sequence_scheme): - """Create a DD sequence of choice''' + """Create a DD sequence of choice Parameters ---------- @@ -77,7 +77,7 @@ def _create_test_sequence(sequence_scheme): def _check_circuit_output(pre_post_gate_unitary_matrix, circuit_type, expected_result): - """Check the unitary of a dynamic decoupling operation + """Check the outcome of a circuit against expected outcome """ simulator = cirq.Simulator() @@ -95,10 +95,10 @@ def _check_circuit_output(pre_post_gate_unitary_matrix, assert results.measurements['qubit-0'] == expected_result -def test_identity_operation(): +def test_cirq_circuit_operation(): """Tests if the Dynamic Decoupling Sequence gives rise to expected - state with different pre-post gates + state with different pre-post gates parameters in cirq circuits """ _check_circuit_output(None, 'scheduled circuit', 0) pre_post_gate_unitary_matrix = (1. / np.power(2, 0.5)) * np.array( From c0e332f3f726ce962c55472d10dea1acc538880c Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Wed, 22 May 2019 17:55:32 +1000 Subject: [PATCH 09/42] section for schedule added --- examples/running_a_dds_on_cirq.ipynb | 56 ++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/examples/running_a_dds_on_cirq.ipynb b/examples/running_a_dds_on_cirq.ipynb index f238b023..472c5dd6 100644 --- a/examples/running_a_dds_on_cirq.ipynb +++ b/examples/running_a_dds_on_cirq.ipynb @@ -290,6 +290,62 @@ "#you can also collect the outcome as histogram (calculated as dict)\n", "print(result.histogram(key=['qubit-0']))" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Creating a Schedule and running on Cirq Simulator\n", + "\n", + "We can create a `cirq.Schedule` from the DDS. The steps are exactly similar as shown above for `cirq.Circuit` except the `circuit_type` to be changed." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "qubit-0=1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111\n", + "Counter({1: 100})\n" + ] + } + ], + "source": [ + "## set the circuit type as 'scheduled circuit'\n", + "circuit_type='scheduled circuit'\n", + "\n", + "## convert the quadratic sequence to cirq.Schedule\n", + "quadratic_cirq_circuit = convert_dds_to_cirq_circuit(\n", + " dynamic_decoupling_sequence=quadratic_sequence,\n", + " target_qubits=target_qubits,\n", + " gate_time=gate_time,\n", + " add_measurement=add_measurement,\n", + " circuit_type=circuit_type\n", + ")\n", + "\n", + "##### Set the simulator parameters\n", + "'''\n", + "repetitions : int\n", + " The number of times the circuit will be executed\n", + "'''\n", + "repetitions = 100\n", + "\n", + "## Create the simulator\n", + "simulator = cirq.Simulator()\n", + "\n", + "#Run the simulator and collect result\n", + "result = simulator.run(quadratic_cirq_circuit, repetitions=repetitions)\n", + "\n", + "#print the outcome of each repetition\n", + "print(result)\n", + "\n", + "#you can also collect the outcome as histogram (calculated as dict)\n", + "print(result.histogram(key=['qubit-0']))" + ] } ], "metadata": { From be172b0e7b039f5fe34213973268fff43faa482e Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Thu, 23 May 2019 10:22:15 +1000 Subject: [PATCH 10/42] Cirq docstring fixed --- qctrlopencontrols/cirq/cirq_circuit.py | 17 ++++--- qctrlopencontrols/qiskit/quantum_circuit.py | 52 ++++++++++----------- tests/test_qiskit_sequence.py | 14 +++--- 3 files changed, 43 insertions(+), 40 deletions(-) diff --git a/qctrlopencontrols/cirq/cirq_circuit.py b/qctrlopencontrols/cirq/cirq_circuit.py index 49dcbec4..a0f46f06 100644 --- a/qctrlopencontrols/cirq/cirq_circuit.py +++ b/qctrlopencontrols/cirq/cirq_circuit.py @@ -13,9 +13,9 @@ # limitations under the License. """ -====================== +================= cirq.cirq_circuit -====================== +================= """ import numpy as np @@ -166,6 +166,7 @@ def _get_scheduled_circuit(dynamic_decoupling_sequence, If there is rotations around more than one axis at any of the offsets """ + # time in nano seconds gate_time = gate_time * 1e9 rabi_rotations = dynamic_decoupling_sequence.rabi_rotations @@ -181,6 +182,7 @@ def _get_scheduled_circuit(dynamic_decoupling_sequence, operations = np.vstack((rabi_rotations, azimuthal_angles, detuning_rotations)) offsets = dynamic_decoupling_sequence.offsets + # offsets in nano seconds offsets = offsets * 1e9 circuit_operations = [] @@ -376,8 +378,8 @@ def convert_dds_to_cirq_circuit( circuit_type=STANDARD_CIRCUIT, device=None): - """Converts a Dynamic Decoupling Sequence into QuantumCircuit - as defined in Qiskit + """Converts a Dynamic Decoupling Sequence into quantum circuit + as defined in cirq Parameters ---------- @@ -386,7 +388,7 @@ def convert_dds_to_cirq_circuit( target_qubits : list, optional List of target qubits for the sequence operation; the qubits must be cirq.Qid type; defaults to None in which case a 1-D lattice of one - qubit is used. + qubit is used (indexed as 0). gate_time : float, optional Time (in seconds) delay introduced by a gate; defaults to 0.1 pre_post_gate_unitary_matrix : numpy.ndarray or None, optional @@ -395,8 +397,9 @@ def convert_dds_to_cirq_circuit( X-axis. If None, pre-post gate is omitted from the circuit. add_measurement : bool, optional If True, the circuit contains a measurement operation for each of the - target qubits. Each measurement will have a string as the key. The string - is formatted as 'qubit-X' where X is a numeral between 0 and len(target_qubits). + target qubits. Measurement from each of the qubits is associated + with a string as key. The string is formatted as 'qubit-X' where + X is a number between 0 and len(target_qubits). circuit_type : str, optional One of 'scheduled circuit' or 'standard circuit'. In the case of 'standard circuit', the circuit will be a sequence of desired operations diff --git a/qctrlopencontrols/qiskit/quantum_circuit.py b/qctrlopencontrols/qiskit/quantum_circuit.py index 0b0c6e32..548b12c1 100644 --- a/qctrlopencontrols/qiskit/quantum_circuit.py +++ b/qctrlopencontrols/qiskit/quantum_circuit.py @@ -27,8 +27,7 @@ from qctrlopencontrols.dynamic_decoupling_sequences import DynamicDecouplingSequence from qctrlopencontrols.exceptions import ArgumentsValueError -from .constants import (FIX_DURATION_UNITARY, INSTANT_UNITARY, - DEFAULT_PRE_POST_GATE_PARAMETERS) +from .constants import (FIX_DURATION_UNITARY, INSTANT_UNITARY) def _get_circuit_gate_list(dynamic_decoupling_sequence, @@ -132,7 +131,7 @@ def convert_dds_to_quantum_circuit( dynamic_decoupling_sequence, target_qubits=None, gate_time=0.1, - pre_post_gate_parameters=DEFAULT_PRE_POST_GATE_PARAMETERS, + pre_post_gate_parameters=None, add_measurement=True, algorithm=FIX_DURATION_UNITARY, quantum_registers=None, @@ -149,14 +148,13 @@ 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 : 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 + 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 Date: Thu, 23 May 2019 10:36:28 +1000 Subject: [PATCH 11/42] a link from cirq_circuit docstring removed --- qctrlopencontrols/cirq/cirq_circuit.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qctrlopencontrols/cirq/cirq_circuit.py b/qctrlopencontrols/cirq/cirq_circuit.py index a0f46f06..3a09a5a5 100644 --- a/qctrlopencontrols/cirq/cirq_circuit.py +++ b/qctrlopencontrols/cirq/cirq_circuit.py @@ -408,8 +408,8 @@ def convert_dds_to_cirq_circuit( will return a 'cirq.Circuit'. In the case of 'scheduled circuit', the desired operations will be scheduled at offsets specified by the dynamic decoupling sequence; in this case a 'cirq.Schedule' object is returned. Both `cirq.Circuit` - and 'cirq.Schedule' can be used with 'cirq.Simulator'; see example usage in - [XXXXX]. See `Circuits ` _, + and 'cirq.Schedule' can be used with 'cirq.Simulator'. + See `Circuits ` _, `Schedules ` _ and `Simulation ` _. device : cirq.Device, optional From c452889d61941c49f12081c02ae1a2fd0610d383 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Thu, 23 May 2019 11:29:52 +1000 Subject: [PATCH 12/42] typos corrected --- qctrlopencontrols/cirq/cirq_circuit.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qctrlopencontrols/cirq/cirq_circuit.py b/qctrlopencontrols/cirq/cirq_circuit.py index 3a09a5a5..258be354 100644 --- a/qctrlopencontrols/cirq/cirq_circuit.py +++ b/qctrlopencontrols/cirq/cirq_circuit.py @@ -102,7 +102,7 @@ def _get_circuit_gate_list(dynamic_decoupling_sequence, def _get_rotations(operation): - """Returns the pulses based of the rotation operation + """Returns the pulses based on the rotation operation Parameters ---------- @@ -114,7 +114,7 @@ def _get_rotations(operation): ------- numpy.ndarray A 1-D array of length 3 containing x_rotation, y_rotation and z-rotation - calculate from sequence operation + calculated from sequence operation """ x_rotation = operation[0] * np.cos(operation[1]) From 6ab61edfd730b6d1e08ee405ea55d1cf617fca8a Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Thu, 23 May 2019 11:33:42 +1000 Subject: [PATCH 13/42] Return docstring fixed --- qctrlopencontrols/cirq/cirq_circuit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qctrlopencontrols/cirq/cirq_circuit.py b/qctrlopencontrols/cirq/cirq_circuit.py index 258be354..51f77446 100644 --- a/qctrlopencontrols/cirq/cirq_circuit.py +++ b/qctrlopencontrols/cirq/cirq_circuit.py @@ -113,7 +113,7 @@ def _get_rotations(operation): Returns ------- numpy.ndarray - A 1-D array of length 3 containing x_rotation, y_rotation and z-rotation + A 1-D array of length 3 containing x_rotation, y_rotation and z_rotation calculated from sequence operation """ From 176b10780bd95343429da55266fffe1cdf35e8d9 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Thu, 23 May 2019 18:04:48 +1000 Subject: [PATCH 14/42] pre-post gate behaviour changed; tests modified and all pass --- .../driven_controls.py | 17 ++ .../dynamic_decoupling_sequence.py | 37 --- .../predefined.py | 256 ++++++++++++++---- qctrlopencontrols/qiskit/__init__.py | 3 +- qctrlopencontrols/qiskit/quantum_circuit.py | 39 +-- tests/test_dynamical_decoupling.py | 155 ++++------- tests/test_predefined_dynamical_decoupling.py | 139 ++++++---- tests/test_qiskit_sequence.py | 16 +- 8 files changed, 375 insertions(+), 287 deletions(-) diff --git a/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py b/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py index efec0122..63c8e820 100644 --- a/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py +++ b/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py @@ -185,6 +185,23 @@ def convert_dds_to_driven_controls( 'maximum_detuning_rate': maximum_detuning_rate}, extras={'maximum_rabi_rate': maximum_rabi_rate}) + if offsets.size == 0: + offsets = np.array([0, sequence_duration]) + rabi_rotations = np.array([0, 0]) + azimuthal_angles = np.array([0, 0]) + detuning_rotations = np.array([0, 0]) + + if offsets[0] != 0: + offsets = np.append([0], offsets) + rabi_rotations = np.append([0], rabi_rotations) + azimuthal_angles = np.append([0], azimuthal_angles) + detuning_rotations = np.append([0], detuning_rotations) + if offsets[-1] != sequence_duration: + offsets = np.append(offsets, [sequence_duration]) + rabi_rotations = np.append(rabi_rotations, [0]) + azimuthal_angles = np.append(azimuthal_angles, [0]) + detuning_rotations = np.append(detuning_rotations, [0]) + offsets = offsets[np.newaxis, :] rabi_rotations = rabi_rotations[np.newaxis, :] azimuthal_angles = azimuthal_angles[np.newaxis, :] diff --git a/qctrlopencontrols/dynamic_decoupling_sequences/dynamic_decoupling_sequence.py b/qctrlopencontrols/dynamic_decoupling_sequences/dynamic_decoupling_sequence.py index b4d6ecc8..3fc10d32 100644 --- a/qctrlopencontrols/dynamic_decoupling_sequences/dynamic_decoupling_sequence.py +++ b/qctrlopencontrols/dynamic_decoupling_sequences/dynamic_decoupling_sequence.py @@ -55,13 +55,6 @@ class DynamicDecouplingSequence(QctrlObject): #pylint: disable=too-few-public- Default to None. The detuning rotations at each time offset. If None, defaults to 0 at each time offset. - pre_post_rotation : bool - If True, the sequence will have a :math:`X_{\\pi/2}` - rotations at start (offset=0) and end(offset=duration); - this will overwrite any operation at the start and the end (if provided). - If False, it either uses rotations at the start and end (if those are - supplied) or inserts '0' (no operation) at the start and end - (if no operation ar those offsets is supplied). Defaults to False. name : str Name of the sequence; Defaults to None @@ -77,7 +70,6 @@ def __init__(self, rabi_rotations=None, azimuthal_angles=None, detuning_rotations=None, - pre_post_rotation=False, name=None ): @@ -87,7 +79,6 @@ def __init__(self, 'rabi_rotations', 'azimuthal_angles', 'detuning_rotations', - 'pre_post_rotation', 'name']) self.duration = duration @@ -126,34 +117,6 @@ def __init__(self, self.azimuthal_angles = np.array(azimuthal_angles, dtype=np.float) self.detuning_rotations = np.array(detuning_rotations, dtype=np.float) - self.pre_post_rotation = pre_post_rotation - - if self.offsets[0] != 0.: - self.offsets = np.append([0], self.offsets) - if self.pre_post_rotation: - self.rabi_rotations = np.append([np.pi/2], self.rabi_rotations) - else: - self.rabi_rotations = np.append([0], self.rabi_rotations) - - self.azimuthal_angles = np.append([0], self.azimuthal_angles) - self.detuning_rotations = np.append([0], self.detuning_rotations) - else: - if self.pre_post_rotation: - self.rabi_rotations[0] = np.pi/2 - - if self.offsets[-1] != self.duration: - self.offsets = np.append(self.offsets, [self.duration]) - if self.pre_post_rotation: - self.rabi_rotations = np.append(self.rabi_rotations, [np.pi/2]) - else: - self.rabi_rotations = np.append(self.rabi_rotations, [0]) - - self.azimuthal_angles = np.append(self.azimuthal_angles, [0]) - self.detuning_rotations = np.append(self.detuning_rotations, [0]) - else: - if self.pre_post_rotation: - self.rabi_rotations[-1] = np.pi/2 - self.number_of_offsets = len(self.offsets) if len(self.rabi_rotations) != self.number_of_offsets: diff --git a/qctrlopencontrols/dynamic_decoupling_sequences/predefined.py b/qctrlopencontrols/dynamic_decoupling_sequences/predefined.py index 482a5030..18abf173 100644 --- a/qctrlopencontrols/dynamic_decoupling_sequences/predefined.py +++ b/qctrlopencontrols/dynamic_decoupling_sequences/predefined.py @@ -106,7 +106,9 @@ def new_predefined_dds(scheme=SPIN_ECHO, **kwargs): return sequence -def new_ramsey_sequence(duration=None, **kwargs): +def new_ramsey_sequence(duration=None, + pre_post_rotation=False, + **kwargs): """Ramsey sequence @@ -114,6 +116,9 @@ def new_ramsey_sequence(duration=None, **kwargs): ---------- duration : float, optional Total duration of the sequence. Defaults to None + pre_post_rotation : bool, optional + If True, a :math:`\\pi.2` rotation is added at the + start and end of the sequence. kwargs : dict Additional keywords required by qctrlopencontrols.sequences.DynamicDecouplingSequence @@ -136,10 +141,17 @@ def new_ramsey_sequence(duration=None, **kwargs): 'Sequence duration must be above zero:', {'duration': duration}) - offsets = np.array([0.0, duration]) - rabi_rotations = np.zeros(offsets.shape) - azimuthal_angles = np.zeros(offsets.shape) - detuning_rotations = np.zeros(offsets.shape) + if pre_post_rotation: + offsets = duration * np.array([0.0, 1.]) + rabi_rotations = np.array([np.pi/2, np.pi/2]) + azimuthal_angles = np.zeros(offsets.shape) + detuning_rotations = np.zeros(offsets.shape) + + else: + offsets = [] + rabi_rotations = [] + azimuthal_angles = [] + detuning_rotations = [] return DynamicDecouplingSequence( duration=duration, offsets=offsets, @@ -149,7 +161,9 @@ def new_ramsey_sequence(duration=None, **kwargs): **kwargs) -def new_spin_echo_sequence(duration=None, **kwargs): +def new_spin_echo_sequence(duration=None, + pre_post_rotation=False, + **kwargs): """Spin Echo Sequence. @@ -157,6 +171,9 @@ def new_spin_echo_sequence(duration=None, **kwargs): --------- duration : float, optional Total duration of the sequence. Defaults to None + pre_post_rotation : bool, optional + If True, a :math:`\\pi.2` rotation is added at the + start and end of the sequence. kwargs : dict Additional keywords required by qctrlopencontrols.sequences.DynamicDecouplingSequence @@ -179,10 +196,16 @@ def new_spin_echo_sequence(duration=None, **kwargs): 'Sequence duration must be above zero:', {'duration': duration}) - offsets = duration * np.array([0.5]) - rabi_rotations = np.array([np.pi]) - azimuthal_angles = np.zeros(offsets.shape) - detuning_rotations = np.zeros(offsets.shape) + if pre_post_rotation: + offsets = duration * np.array([0., 0.5, 1.]) + rabi_rotations = np.array([np.pi/2, np.pi, np.pi/2]) + azimuthal_angles = np.zeros(offsets.shape) + detuning_rotations = np.zeros(offsets.shape) + else: + offsets = duration * np.array([0.5]) + rabi_rotations = np.array([np.pi]) + azimuthal_angles = np.zeros(offsets.shape) + detuning_rotations = np.zeros(offsets.shape) return DynamicDecouplingSequence( duration=duration, offsets=offsets, @@ -192,7 +215,10 @@ def new_spin_echo_sequence(duration=None, **kwargs): **kwargs) -def new_carr_purcell_sequence(duration=None, number_of_offsets=None, **kwargs): +def new_carr_purcell_sequence(duration=None, + number_of_offsets=None, + pre_post_rotation=False, + **kwargs): """Carr-Purcell Sequence. @@ -202,6 +228,9 @@ def new_carr_purcell_sequence(duration=None, number_of_offsets=None, **kwargs): Total duration of the sequence. Defaults to None number_of_offsets : int, optional Number of offsets. Defaults to None + pre_post_rotation : bool, optional + If True, a :math:`\\pi.2` rotation is added at the + start and end of the sequence. kwargs : dict Additional keywords required by qctrlopencontrols.sequences.DynamicDecouplingSequence @@ -232,12 +261,26 @@ def new_carr_purcell_sequence(duration=None, number_of_offsets=None, **kwargs): {'number_of_offsets': number_of_offsets}) offsets = _carr_purcell_meiboom_gill_offsets(duration, number_of_offsets) - rabi_rotations = np.zeros(offsets.shape) - azimuthal_angles = np.zeros(offsets.shape) - detuning_rotations = np.zeros(offsets.shape) - # set all as X_pi - rabi_rotations[0:] = np.pi + if pre_post_rotation: + offsets = np.append([0], offsets) + offsets = np.append(offsets, [duration]) + + rabi_rotations = np.zeros(offsets.shape) + azimuthal_angles = np.zeros(offsets.shape) + detuning_rotations = np.zeros(offsets.shape) + + rabi_rotations[0] = np.pi/2 + rabi_rotations[-1] = np.pi/2 + rabi_rotations[1:-1] = np.pi + else: + + rabi_rotations = np.zeros(offsets.shape) + azimuthal_angles = np.zeros(offsets.shape) + detuning_rotations = np.zeros(offsets.shape) + + # set all as X_pi + rabi_rotations[0:] = np.pi return DynamicDecouplingSequence( duration=duration, offsets=offsets, @@ -247,6 +290,7 @@ def new_carr_purcell_sequence(duration=None, number_of_offsets=None, **kwargs): def new_carr_purcell_meiboom_gill_sequence(duration=None, # pylint: disable=invalid-name number_of_offsets=None, + pre_post_rotation=False, **kwargs): """Carr-Purcell-Meiboom-Gill Sequences. @@ -256,6 +300,9 @@ def new_carr_purcell_meiboom_gill_sequence(duration=None, # pylint: disable=inv Total duration of the sequence. Defaults to None number_of_offsets : int, optional Number of offsets. Defaults to None + pre_post_rotation : bool, optional + If True, a :math:`\\pi.2` rotation is added at the + start and end of the sequence. kwargs : dict Additional keywords required by qctrlopencontrols.sequences.DynamicDecouplingSequence @@ -287,13 +334,27 @@ def new_carr_purcell_meiboom_gill_sequence(duration=None, # pylint: disable=inv offsets = _carr_purcell_meiboom_gill_offsets(duration, number_of_offsets) - rabi_rotations = np.zeros(offsets.shape) - azimuthal_angles = np.zeros(offsets.shape) - detuning_rotations = np.zeros(offsets.shape) + if pre_post_rotation: + offsets = np.append([0], offsets) + offsets = np.append(offsets, [duration]) + + rabi_rotations = np.zeros(offsets.shape) + azimuthal_angles = np.zeros(offsets.shape) + detuning_rotations = np.zeros(offsets.shape) + + rabi_rotations[0] = np.pi/2 + rabi_rotations[-1] = np.pi/2 + rabi_rotations[1:-1] = np.pi + azimuthal_angles[1:-1] = np.pi/2 + else: + + rabi_rotations = np.zeros(offsets.shape) + azimuthal_angles = np.zeros(offsets.shape) + detuning_rotations = np.zeros(offsets.shape) - # set all azimuthal_angles=pi/2, rabi_rotations = pi - rabi_rotations[0:] = np.pi - azimuthal_angles[0:] = np.pi/2 + # set all azimuthal_angles=pi/2, rabi_rotations = pi + rabi_rotations[0:] = np.pi + azimuthal_angles[0:] = np.pi/2 return DynamicDecouplingSequence( duration=duration, offsets=offsets, @@ -303,7 +364,9 @@ def new_carr_purcell_meiboom_gill_sequence(duration=None, # pylint: disable=inv **kwargs) -def new_uhrig_single_axis_sequence(duration=None, number_of_offsets=None, **kwargs): +def new_uhrig_single_axis_sequence(duration=None, number_of_offsets=None, + pre_post_rotation=False, + **kwargs): """Uhrig Single Axis Sequence. @@ -313,6 +376,9 @@ def new_uhrig_single_axis_sequence(duration=None, number_of_offsets=None, **kwar Total duration of the sequence. Defaults to None number_of_offsets : int, optional Number of offsets. Defaults to None + pre_post_rotation : bool, optional + If True, a :math:`\\pi.2` rotation is added at the + start and end of the sequence. kwargs : dict Additional keywords required by qctrlopencontrols.sequences.DynamicDecouplingSequence @@ -344,13 +410,27 @@ def new_uhrig_single_axis_sequence(duration=None, number_of_offsets=None, **kwar offsets = _uhrig_single_axis_offsets(duration, number_of_offsets) - rabi_rotations = np.zeros(offsets.shape) - azimuthal_angles = np.zeros(offsets.shape) - detuning_rotations = np.zeros(offsets.shape) + if pre_post_rotation: + offsets = np.append([0], offsets) + offsets = np.append(offsets, [duration]) - # set all the azimuthal_angles as pi/2, rabi_rotations = pi - rabi_rotations[0:] = np.pi - azimuthal_angles[0:] = np.pi/2 + rabi_rotations = np.zeros(offsets.shape) + azimuthal_angles = np.zeros(offsets.shape) + detuning_rotations = np.zeros(offsets.shape) + + rabi_rotations[0] = np.pi/2 + rabi_rotations[-1] = np.pi/2 + rabi_rotations[1:-1] = np.pi + azimuthal_angles[1:-1] = np.pi/2 + else: + + rabi_rotations = np.zeros(offsets.shape) + azimuthal_angles = np.zeros(offsets.shape) + detuning_rotations = np.zeros(offsets.shape) + + # set all azimuthal_angles=pi/2, rabi_rotations = pi + rabi_rotations[0:] = np.pi + azimuthal_angles[0:] = np.pi/2 return DynamicDecouplingSequence( duration=duration, offsets=offsets, @@ -361,7 +441,9 @@ def new_uhrig_single_axis_sequence(duration=None, number_of_offsets=None, **kwar def new_periodic_single_axis_sequence(duration=None, # pylint: disable=invalid-name - number_of_offsets=None, **kwargs): + number_of_offsets=None, + pre_post_rotation=False, + **kwargs): """Periodic Single Axis Sequence. @@ -371,6 +453,9 @@ def new_periodic_single_axis_sequence(duration=None, # pylint: disable=invali Total duration of the sequence. Defaults to None number_of_offsets : int, optional Number of offsets. Defaults to None + pre_post_rotation : bool, optional + If True, a :math:`\\pi.2` rotation is added at the + start and end of the sequence. kwargs : dict Additional keywords required by qctrlopencontrols.sequences.DynamicDecouplingSequence @@ -406,12 +491,24 @@ def new_periodic_single_axis_sequence(duration=None, # pylint: disable=invali deltas = np.array(deltas) offsets = duration * deltas - rabi_rotations = np.zeros(offsets.shape) - azimuthal_angles = np.zeros(offsets.shape) - detuning_rotations = np.zeros(offsets.shape) + if pre_post_rotation: + offsets = np.append([0], offsets) + offsets = np.append(offsets, [duration]) + + rabi_rotations = np.zeros(offsets.shape) + azimuthal_angles = np.zeros(offsets.shape) + detuning_rotations = np.zeros(offsets.shape) - # set all the rabi_rotations to X_pi - rabi_rotations[0:] = np.pi + rabi_rotations[0] = np.pi/2 + rabi_rotations[-1] = np.pi/2 + rabi_rotations[1:-1] = np.pi + else: + + rabi_rotations = np.zeros(offsets.shape) + azimuthal_angles = np.zeros(offsets.shape) + detuning_rotations = np.zeros(offsets.shape) + + rabi_rotations[0:] = np.pi return DynamicDecouplingSequence( duration=duration, offsets=offsets, @@ -423,6 +520,7 @@ def new_periodic_single_axis_sequence(duration=None, # pylint: disable=invali def new_walsh_single_axis_sequence(duration=None, paley_order=None, + pre_post_rotation=False, **kwargs): """Welsh Single Axis Sequence. @@ -433,6 +531,9 @@ def new_walsh_single_axis_sequence(duration=None, Total duration of the sequence. Defaults to None paley_order : int, optional Defaults to 1. The paley order of the walsh sequence. + pre_post_rotation : bool, optional + If True, a :math:`\\pi.2` rotation is added at the + start and end of the sequence. kwargs : dict Additional keywords required by qctrlopencontrols.sequences.DynamicDecouplingSequence @@ -482,12 +583,24 @@ def new_walsh_single_axis_sequence(duration=None, walsh_relative_offsets = np.array(walsh_relative_offsets, dtype=np.float) offsets = duration * walsh_relative_offsets - rabi_rotations = np.zeros(offsets.shape) - azimuthal_angles = np.zeros(offsets.shape) - detuning_rotations = np.zeros(offsets.shape) + if pre_post_rotation: + offsets = np.append([0], offsets) + offsets = np.append(offsets, [duration]) + + rabi_rotations = np.zeros(offsets.shape) + azimuthal_angles = np.zeros(offsets.shape) + detuning_rotations = np.zeros(offsets.shape) - # set the rabi_rotations to X_pi - rabi_rotations[0:] = np.pi + rabi_rotations[0] = np.pi/2 + rabi_rotations[-1] = np.pi/2 + rabi_rotations[1:-1] = np.pi + else: + + rabi_rotations = np.zeros(offsets.shape) + azimuthal_angles = np.zeros(offsets.shape) + detuning_rotations = np.zeros(offsets.shape) + + rabi_rotations[0:] = np.pi return DynamicDecouplingSequence( duration=duration, offsets=offsets, @@ -498,7 +611,9 @@ def new_walsh_single_axis_sequence(duration=None, def new_quadratic_sequence(duration=None, - number_inner_offsets=None, number_outer_offsets=None, + number_inner_offsets=None, + number_outer_offsets=None, + pre_post_rotation=False, **kwargs): """Quadratic Decoupling Sequence @@ -514,6 +629,9 @@ def new_quadratic_sequence(duration=None, number_inner_offsets : int, optional Number of inner Z-pi Pulses. Defaults to None. Not used if number_of_offsets is supplied + pre_post_rotation : bool, optional + If True, a :math:`\\pi.2` rotation is added at the + start and end of the sequence. kwargs : dict Additional keywords required by qctrlopencontrols.sequences.DynamicDecouplingSequence @@ -585,6 +703,16 @@ def new_quadratic_sequence(duration=None, rabi_rotations = rabi_rotations[0:-1] detuning_rotations = detuning_rotations[0:-1] + if pre_post_rotation: + offsets = np.append([0], offsets) + offsets = np.append(offsets, [duration]) + + rabi_rotations = np.append([np.pi/2], rabi_rotations) + detuning_rotations = np.append([0.], detuning_rotations) + + rabi_rotations = np.append(rabi_rotations, [np.pi/2]) + detuning_rotations = np.append(detuning_rotations, [0.]) + # finally create the azimuthal angles as all zeros azimuthal_angles = np.zeros(offsets.shape) @@ -596,7 +724,10 @@ def new_quadratic_sequence(duration=None, **kwargs) -def new_x_concatenated_sequence(duration=1.0, concatenation_order=None, **kwargs): +def new_x_concatenated_sequence(duration=1.0, + concatenation_order=None, + pre_post_rotation=False, + **kwargs): """X-Concatenated Dynamic Decoupling Sequence Concatenation of base sequence C(\tau/2)XC(\tau/2)X @@ -609,6 +740,9 @@ def new_x_concatenated_sequence(duration=1.0, concatenation_order=None, **kwargs concatenation_order : int, optional defaults to None The number of concatenation of base sequence + pre_post_rotation : bool, optional + If True, a :math:`\\pi.2` rotation is added at the + start and end of the sequence. kwargs : dict Additional keywords required by qctrlopencontrols.sequences.DynamicDecouplingSequence @@ -654,9 +788,24 @@ def new_x_concatenated_sequence(duration=1.0, concatenation_order=None, **kwargs offsets = np.array(offsets) - rabi_rotations = np.pi * np.ones(offsets.shape) - azimuthal_angles = np.zeros(offsets.shape) - detuning_rotations = np.zeros(offsets.shape) + if pre_post_rotation: + offsets = np.append([0], offsets) + offsets = np.append(offsets, [duration]) + + rabi_rotations = np.zeros(offsets.shape) + azimuthal_angles = np.zeros(offsets.shape) + detuning_rotations = np.zeros(offsets.shape) + + rabi_rotations[0] = np.pi/2 + rabi_rotations[-1] = np.pi/2 + rabi_rotations[1:-1] = np.pi + else: + + rabi_rotations = np.zeros(offsets.shape) + azimuthal_angles = np.zeros(offsets.shape) + detuning_rotations = np.zeros(offsets.shape) + + rabi_rotations[0:] = np.pi return DynamicDecouplingSequence( duration=duration, offsets=offsets, @@ -666,7 +815,10 @@ def new_x_concatenated_sequence(duration=1.0, concatenation_order=None, **kwargs **kwargs) -def new_xy_concatenated_sequence(duration=1.0, concatenation_order=None, **kwargs): +def new_xy_concatenated_sequence(duration=1.0, + concatenation_order=None, + pre_post_rotation=False, + **kwargs): """XY-Concatenated Dynamic Decoupling Sequence Concatenation of base sequence C(\tau/4)XC(\tau/4)YC(\tau/4)XC(\tau/4)Y @@ -679,6 +831,9 @@ def new_xy_concatenated_sequence(duration=1.0, concatenation_order=None, **kwarg concatenation_order : int, optional defaults to None The number of concatenation of base sequence + pre_post_rotation : bool, optional + If True, a :math:`\\pi.2` rotation is added at the + start and end of the sequence. kwargs : dict Additional keywords required by qctrlopencontrols.sequences.DynamicDecouplingSequence @@ -800,6 +955,15 @@ def new_xy_concatenated_sequence(duration=1.0, concatenation_order=None, **kwarg if z_idx >= len(detuning_offsets): break + if pre_post_rotation: + offsets = np.insert(offsets, [0, offsets.shape[0]], [0, duration]) + rabi_rotations = np.insert(rabi_rotations, [0, rabi_rotations.shape[0]], + [np.pi / 2, np.pi / 2]) + azimuthal_angles = np.insert(azimuthal_angles, [0, azimuthal_angles.shape[0]], + [0, 0]) + detuning_rotations = np.insert(detuning_rotations, [0, detuning_rotations.shape[0]], + [0, 0]) + return DynamicDecouplingSequence( duration=duration, offsets=offsets, rabi_rotations=rabi_rotations, diff --git a/qctrlopencontrols/qiskit/__init__.py b/qctrlopencontrols/qiskit/__init__.py index 5c968758..062224f0 100644 --- a/qctrlopencontrols/qiskit/__init__.py +++ b/qctrlopencontrols/qiskit/__init__.py @@ -18,6 +18,5 @@ ============= """ -from .constants import (FIX_DURATION_UNITARY, INSTANT_UNITARY, - DEFAULT_PRE_POST_GATE_PARAMETERS) +from .constants import (FIX_DURATION_UNITARY, INSTANT_UNITARY) from .quantum_circuit import convert_dds_to_quantum_circuit diff --git a/qctrlopencontrols/qiskit/quantum_circuit.py b/qctrlopencontrols/qiskit/quantum_circuit.py index 0b0c6e32..1354ffb4 100644 --- a/qctrlopencontrols/qiskit/quantum_circuit.py +++ b/qctrlopencontrols/qiskit/quantum_circuit.py @@ -27,8 +27,7 @@ from qctrlopencontrols.dynamic_decoupling_sequences import DynamicDecouplingSequence from qctrlopencontrols.exceptions import ArgumentsValueError -from .constants import (FIX_DURATION_UNITARY, INSTANT_UNITARY, - DEFAULT_PRE_POST_GATE_PARAMETERS) +from .constants import (FIX_DURATION_UNITARY, INSTANT_UNITARY) def _get_circuit_gate_list(dynamic_decoupling_sequence, @@ -132,7 +131,6 @@ def convert_dds_to_quantum_circuit( dynamic_decoupling_sequence, target_qubits=None, gate_time=0.1, - pre_post_gate_parameters=DEFAULT_PRE_POST_GATE_PARAMETERS, add_measurement=True, algorithm=FIX_DURATION_UNITARY, quantum_registers=None, @@ -149,16 +147,6 @@ 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 : 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 - Date: Thu, 23 May 2019 20:45:51 +1000 Subject: [PATCH 15/42] notebooks checked and updated --- examples/creating_a_dds.ipynb | 112 +++++----- examples/running_a_dds_on_ibm_q.ipynb | 284 ++++++++++++-------------- 2 files changed, 197 insertions(+), 199 deletions(-) diff --git a/examples/creating_a_dds.ipynb b/examples/creating_a_dds.ipynb index 0f2d9b75..c7ca9f63 100644 --- a/examples/creating_a_dds.ipynb +++ b/examples/creating_a_dds.ipynb @@ -75,10 +75,10 @@ "text": [ "SE DDS:\n", "Duration = 1e-05\n", - "Offsets = [0.0,0.5,1.0] x 1e-05\n", - "Rabi Rotations = [0.0,1.0,0.0] x pi\n", - "Azimuthal Angles = [0.0,0.0,0.0] x pi\n", - "Detuning Rotations = [0.0,0.0,0.0] x pi\n" + "Offsets = [0.5] x 1e-05\n", + "Rabi Rotations = [1.0] x pi\n", + "Azimuthal Angles = [0.0] x pi\n", + "Detuning Rotations = [0.0] x pi\n" ] } ], @@ -99,10 +99,10 @@ "text": [ "CP DDS:\n", "Duration = 1e-05\n", - "Offsets = [0.0,0.125,0.375,0.625,0.875,1.0] x 1e-05\n", - "Rabi Rotations = [0.0,1.0,1.0,1.0,1.0,0.0] x pi\n", - "Azimuthal Angles = [0.0,0.0,0.0,0.0,0.0,0.0] x pi\n", - "Detuning Rotations = [0.0,0.0,0.0,0.0,0.0,0.0] x pi\n" + "Offsets = [0.125,0.375,0.625,0.875] x 1e-05\n", + "Rabi Rotations = [1.0,1.0,1.0,1.0] x pi\n", + "Azimuthal Angles = [0.0,0.0,0.0,0.0] x pi\n", + "Detuning Rotations = [0.0,0.0,0.0,0.0] x pi\n" ] } ], @@ -128,10 +128,10 @@ "text": [ "Walsh DDS:\n", "Duration = 1e-05\n", - "Offsets = [0.0,0.125,0.25,0.375,0.5,0.625,0.75,0.875,1.0] x 1e-05\n", - "Rabi Rotations = [0.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,0.0] x pi\n", - "Azimuthal Angles = [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0] x pi\n", - "Detuning Rotations = [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0] x pi\n" + "Offsets = [0.125,0.25,0.375,0.5,0.625,0.75,0.875] x 1e-05\n", + "Rabi Rotations = [1.0,1.0,1.0,1.0,1.0,1.0,1.0] x pi\n", + "Azimuthal Angles = [0.0,0.0,0.0,0.0,0.0,0.0,0.0] x pi\n", + "Detuning Rotations = [0.0,0.0,0.0,0.0,0.0,0.0,0.0] x pi\n" ] } ], @@ -156,10 +156,10 @@ "text": [ "Quadratic DDS:\n", "Duration = 1e-05\n", - "Offsets = [0.0,0.06249999999999998,0.18749999999999994,0.24999999999999994,0.37499999999999994,0.6249999999999999,0.7499999999999999,0.8124999999999999,0.9375,1.0] x 1e-05\n", - "Rabi Rotations = [0.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,0.0] x pi\n", - "Azimuthal Angles = [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0] x pi\n", - "Detuning Rotations = [0.0,1.0,1.0,0.0,1.0,1.0,0.0,1.0,1.0,0.0] x pi\n" + "Offsets = [0.06249999999999998,0.18749999999999994,0.24999999999999994,0.37499999999999994,0.6249999999999999,0.7499999999999999,0.8124999999999999,0.9375] x 1e-05\n", + "Rabi Rotations = [0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0] x pi\n", + "Azimuthal Angles = [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0] x pi\n", + "Detuning Rotations = [1.0,1.0,0.0,1.0,1.0,0.0,1.0,1.0] x pi\n" ] } ], @@ -185,10 +185,10 @@ "text": [ "XC DDS:\n", "Duration = 1e-05\n", - "Offsets = [0.0,0.25,0.75,1.0] x 1e-05\n", - "Rabi Rotations = [0.0,1.0,1.0,0.0] x pi\n", - "Azimuthal Angles = [0.0,0.0,0.0,0.0] x pi\n", - "Detuning Rotations = [0.0,0.0,0.0,0.0] x pi\n" + "Offsets = [0.25,0.75] x 1e-05\n", + "Rabi Rotations = [1.0,1.0] x pi\n", + "Azimuthal Angles = [0.0,0.0] x pi\n", + "Detuning Rotations = [0.0,0.0] x pi\n" ] } ], @@ -214,10 +214,10 @@ "text": [ "Ramsey DDS:\n", "Duration = 1e-06\n", - "Offsets = [0.0,1.0] x 1e-06\n", - "Rabi Rotations = [0.0,0.0] x pi\n", - "Azimuthal Angles = [0.0,0.0] x pi\n", - "Detuning Rotations = [0.0,0.0] x pi\n" + "Offsets = [] x 1e-06\n", + "Rabi Rotations = [] x pi\n", + "Azimuthal Angles = [] x pi\n", + "Detuning Rotations = [] x pi\n" ] } ], @@ -238,27 +238,42 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 20, "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CP DDS:\n", + "Duration = 1e-05\n", + "Offsets = [0.125,0.375,0.625,0.875] x 1e-05\n", + "Rabi Rotations = [1.0,1.0,1.0,1.0] x pi\n", + "Azimuthal Angles = [0.0,0.0,0.0,0.0] x pi\n", + "Detuning Rotations = [0.0,0.0,0.0,0.0] x pi\n", + "1e-06\n" + ] + }, { "data": { "text/plain": [ - "Text(0, 0.5, 'Detuning Rotation (rad)')" + "Text(0,0.5,'Detuning Rotation (rad)')" ] }, - "execution_count": 8, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] }, - "metadata": {}, + "metadata": { + "needs_background": "light" + }, "output_type": "display_data" } ], @@ -272,22 +287,18 @@ "# prepare the axes\n", "figure, (rabi_plot_axis, azimuth_plot_axis, detuning_plot_axis) = plt.subplots(\n", " 1, 3, figsize=(20,5))\n", - "\n", "rabi_plot_axis.plot(times, rabi_rotations)\n", "rabi_plot_axis.ticklabel_format(style='sci', axis='x', scilimits=(0, 2))\n", - "rabi_plot_axis.set_xlim([0, max(times)])\n", "rabi_plot_axis.set_xlabel('Time (s)')\n", "rabi_plot_axis.set_ylabel('Rabi Rotations (rad)')\n", "\n", "azimuth_plot_axis.plot(times, azimuthal_angles)\n", "azimuth_plot_axis.ticklabel_format(style='sci', axis='x', scilimits=(0, 2))\n", - "azimuth_plot_axis.set_xlim([0, max(times)])\n", "azimuth_plot_axis.set_xlabel('Time (s)')\n", "azimuth_plot_axis.set_ylabel('Azimuthal Angle (rad)')\n", "\n", "detuning_plot_axis.plot(times, detuning_rotations)\n", "detuning_plot_axis.ticklabel_format(style='sci', axis='x', scilimits=(0, 2))\n", - "detuning_plot_axis.set_xlim([0, max(times)])\n", "detuning_plot_axis.set_xlabel('Time (s)')\n", "detuning_plot_axis.set_ylabel('Detuning Rotation (rad)')\n" ] @@ -404,36 +415,38 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "Text(0, 0.5, 'Detuning Rotation (rad)')" + "Text(0,0.5,'Detuning Rotation (rad)')" ] }, - "execution_count": 11, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] }, - "metadata": {}, + "metadata": { + "needs_background": "light" + }, "output_type": "display_data" } ], "source": [ "_duration = 1.50\n", - "_rabi_rotations = [0., np.pi, np.pi, 0., np.pi, np.pi, 0.]\n", - "_azimuthal_angles = [0., np.pi/2, 0., 0., 0., np.pi/2, 0.]\n", - "_detuning_rotations = [0., 0., 0., np.pi, 0., 0., 0.]\n", - "_offsets = [0., 0.25, 0.50, 0.75, 1.00, 1.25, 1.50]\n", + "_rabi_rotations = [np.pi, np.pi, 0., np.pi, np.pi]\n", + "_azimuthal_angles = [np.pi/2, 0., 0., 0., np.pi/2]\n", + "_detuning_rotations = [0., 0., np.pi, 0., 0.]\n", + "_offsets = [0.25, 0.50, 0.75, 1.00, 1.25]\n", "_name = 'Custom DDS'\n", "\n", "custom_dds = DynamicDecouplingSequence(duration=_duration,\n", @@ -455,22 +468,29 @@ "\n", "rabi_plot_axis.plot(times, rabi_rotations)\n", "rabi_plot_axis.ticklabel_format(style='sci', axis='x', scilimits=(0, 2))\n", - "rabi_plot_axis.set_xlim([0, max(times)])\n", + "rabi_plot_axis.set_xlim([0, _duration])\n", "rabi_plot_axis.set_xlabel('Time (sec)')\n", "rabi_plot_axis.set_ylabel('Rabi Rotations (rad)')\n", "\n", "azimuth_plot_axis.plot(times, azimuthal_angles)\n", "azimuth_plot_axis.ticklabel_format(style='sci', axis='x', scilimits=(0, 2))\n", - "azimuth_plot_axis.set_xlim([0, max(times)])\n", + "azimuth_plot_axis.set_xlim([0, _duration])\n", "azimuth_plot_axis.set_xlabel('Time (sec)')\n", "azimuth_plot_axis.set_ylabel('Azimuthal Angle (rad)')\n", "\n", "detuning_plot_axis.plot(times, detuning_rotations)\n", "detuning_plot_axis.ticklabel_format(style='sci', axis='x', scilimits=(0, 2))\n", - "detuning_plot_axis.set_xlim([0, max(times)])\n", + "detuning_plot_axis.set_xlim([0, _duration])\n", "detuning_plot_axis.set_xlabel('Time (sec)')\n", "detuning_plot_axis.set_ylabel('Detuning Rotation (rad)')\n" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -489,7 +509,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.7" + "version": "3.6.8" } }, "nbformat": 4, diff --git a/examples/running_a_dds_on_ibm_q.ipynb b/examples/running_a_dds_on_ibm_q.ipynb index 8afce442..7c219939 100755 --- a/examples/running_a_dds_on_ibm_q.ipynb +++ b/examples/running_a_dds_on_ibm_q.ipynb @@ -20,7 +20,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -64,7 +64,7 @@ "\n", "Converting a DDS into a Qiskit circuit is an approximate process where the instantaneous unitaries are replaced with finite duration gates and the pauses in-between unitaries are replaced with the closest integer number of identity gates. The exact algorithm used to make this approximation is documented in the [source code](https://github.com/qctrl/python-open-controls/blob/master/qctrlopencontrols/qiskit/quantum_circuit.py).\n", "\n", - "In this example we will define a Quadratic DDS and convert it into a circuit that we can later run on a simulator and on a real device. See [creating_a_DDS.ipynb](creating_a_DDS.ipynb) to see how other sequences can be created. We also create a Ramsey DDS of the same duration to compare as a benchmark." + "In this example we will define a Quadratic DDS and convert it into a circuit that we can later run on a simulator and on a real device. See [creating_a_DDS.ipynb](creating_a_DDS.ipynb) to see how other sequences can be created. We also create a Ramsey DDS of the same duration to compare as a benchmark. For both the sequences, we add a $X_{\\pi/2}$ rotation on either end of the sequence." ] }, { @@ -76,7 +76,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -86,13 +86,13 @@ "Quadratic sequence:\n", "Duration = 2e-05\n", "Offsets = [0.0,0.06249999999999998,0.18749999999999994,0.24999999999999994,0.37499999999999994,0.6249999999999999,0.7499999999999999,0.8124999999999999,0.9375,1.0] x 2e-05\n", - "Rabi Rotations = [0.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,0.0] x pi\n", + "Rabi Rotations = [0.5,0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,0.5] x pi\n", "Azimuthal Angles = [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0] x pi\n", "Detuning Rotations = [0.0,1.0,1.0,0.0,1.0,1.0,0.0,1.0,1.0,0.0] x pi\n", "Ramsey sequence:\n", "Duration = 2e-05\n", "Offsets = [0.0,1.0] x 2e-05\n", - "Rabi Rotations = [0.0,0.0] x pi\n", + "Rabi Rotations = [0.5,0.5] x pi\n", "Azimuthal Angles = [0.0,0.0] x pi\n", "Detuning Rotations = [0.0,0.0] x pi\n" ] @@ -105,12 +105,14 @@ " duration=20e-6, \n", " number_inner_offsets=2,\n", " number_outer_offsets=2,\n", + " pre_post_rotation=True,\n", " name='Quadratic sequence')\n", "\n", "# Ramsey sequence, total duration: 20us\n", "ramsey_sequence = new_predefined_dds(\n", " scheme='Ramsey',\n", " duration=20e-6,\n", + " pre_post_rotation=True,\n", " name='Ramsey sequence')\n", "\n", "print(quadratic_sequence)\n", @@ -132,7 +134,7 @@ }, { "cell_type": "code", - "execution_count": 50, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -205,12 +207,12 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 4, "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -255,14 +257,14 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 5, "metadata": { "scrolled": true }, "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -320,11 +322,11 @@ "source": [ "#### Drawing the Quadratic DDS Circuit\n", "\n", - "Note that both DDS will be applied with $X_{\\pi/2}$ rotations at beginning and end, that is, at offsets of $[0, 20]$ $\\mu$s, to create the desired superposition state. The $X_{\\pi/2}$ rotations are not part of the DDS objects but are added to the circuits in the form of pre-post-gates that are implemented via Qiskit's $U3(\\pi/2, -\\pi/2, \\pi/2)$ gate.\n", + "Note that both DDS will be applied with $X_{\\pi/2}$ rotations at beginning and end, that is, at offsets of $[0, 20]$ $\\mu$s, to create the desired superposition state. The $X_{\\pi/2}$ rotations are added to the circuits in the form of pre-post-gates that are implemented via Qiskit's $U3(\\pi/2, -\\pi/2, \\pi/2)$ gate.\n", "\n", "The $U1(\\pi)$ gates are $Z_\\pi$ pulses (a $\\pi$ rotation around $Z$-axis) and $U3(\\pi, -\\pi/2, \\pi/2)$ gates correspond to $X_{\\pi}$ pulses (a $\\pi$ rotation around $X$-axis). The gates match the pulses in the DDS.\n", "\n", - "The `Id` in the drawing corresponds to the `identity` gate. In the DDS, the first $Z_{\\pi}$-pulse is applied at a delay of $1.25$ $\\mu$s. This is approximated by introducing 2-`Id` gates with a delay of $0.4\\times 3=1.2$ $\\mu$s. Similarly, the second set of 6 `Id` gates introduces a delay of $2.4$ $\\mu$s close to the actual delay of $3.75-1.25=2.50$ microseconds.\n", + "The `Id` in the drawing corresponds to the `identity` gate. In the DDS, the first $Z_{\\pi}$-pulse is applied at a delay of $1.25$ $\\mu$s. This is approximated by introducing 3-`Id` gates with a delay of $0.4\\times 3=1.2$ $\\mu$s. Similarly, the second set of 6 `Id` gates introduces a delay of $2.4$ $\\mu$s close to the actual delay of $3.75-1.25=2.50$ microseconds.\n", "\n", "The `barrier` gates are special gates that tell the Qiskit compilers not to simplify a circuit at the specified positions.\n", "\n", @@ -333,73 +335,68 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
         ┌───────────────────────────┐ ░ ┌───────────┐ ░ ┌────┐ ░ ┌────┐ ░ »\n",
-       "q8_0: |0>┤ U3(1.5708,-1.5708,1.5708) ├─░─┤ U3(0,0,0) ├─░─┤ Id ├─░─┤ Id ├─░─»\n",
-       "         └───────────────────────────┘ ░ └───────────┘ ░ └────┘ ░ └────┘ ░ »\n",
-       " c8_0: 0 ══════════════════════════════════════════════════════════════════»\n",
-       "                                                                           »\n",
-       "«      ┌────┐ ░ ┌────────────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ »\n",
-       "«q8_0: ┤ Id ├─░─┤ U1(3.1416) ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─»\n",
-       "«      └────┘ ░ └────────────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ »\n",
-       "«c8_0: ═══════════════════════════════════════════════════════════════════════»\n",
+       "
         ┌───────────────────────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────────────┐»\n",
+       "q0_0: |0>┤ U3(1.5708,-pi/2,pi/2) ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ U1(3.1416) ├»\n",
+       "         └───────────────────────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────────────┘»\n",
+       " c0_0: 0 ═════════════════════════════════════════════════════════════════════»\n",
+       "                                                                              »\n",
+       "«       ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────────────┐»\n",
+       "«q0_0: ─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ U1(3.1416) ├»\n",
+       "«       ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────────────┘»\n",
+       "«c0_0: ═══════════════════════════════════════════════════════════════════════»\n",
        "«                                                                             »\n",
-       "«      ┌────┐ ░ ┌────────────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ »\n",
-       "«q8_0: ┤ Id ├─░─┤ U1(3.1416) ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─»\n",
-       "«      └────┘ ░ └────────────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ »\n",
-       "«c8_0: ═════════════════════════════════════════════════════»\n",
-       "«                                                           »\n",
-       "«      ┌───────────────────────────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ »\n",
-       "«q8_0: ┤ U3(3.1416,-1.5708,1.5708) ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─»\n",
-       "«      └───────────────────────────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ »\n",
-       "«c8_0: ════════════════════════════════════════════════════════════════════»\n",
-       "«                                                                          »\n",
-       "«      ┌────┐ ░ ┌────┐ ░ ┌────────────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ »\n",
-       "«q8_0: ┤ Id ├─░─┤ Id ├─░─┤ U1(3.1416) ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─»\n",
-       "«      └────┘ ░ └────┘ ░ └────────────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ »\n",
-       "«c8_0: ═══════════════════════════════════════════════════════════════════════»\n",
+       "«       ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌───────────────────────┐ ░ ┌────┐ ░ »\n",
+       "«q0_0: ─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ U3(3.1416,-pi/2,pi/2) ├─░─┤ Id ├─░─»\n",
+       "«       ░ └────┘ ░ └────┘ ░ └────┘ ░ └───────────────────────┘ ░ └────┘ ░ »\n",
+       "«c0_0: ═══════════════════════════════════════════════════════════════════»\n",
+       "«                                                                         »\n",
+       "«      ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────────────┐ ░ ┌────┐ ░ »\n",
+       "«q0_0: ┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ U1(3.1416) ├─░─┤ Id ├─░─»\n",
+       "«      └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────────────┘ ░ └────┘ ░ »\n",
+       "«c0_0: ═══════════════════════════════════════════════════════════════════════»\n",
        "«                                                                             »\n",
        "«      ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ »\n",
-       "«q8_0: ┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─»\n",
+       "«q0_0: ┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─»\n",
        "«      └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ »\n",
-       "«c8_0: ════════════════════════════════════════════════════════════════════════»\n",
+       "«c0_0: ════════════════════════════════════════════════════════════════════════»\n",
        "«                                                                              »\n",
-       "«      ┌────────────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ »\n",
-       "«q8_0: ┤ U1(3.1416) ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─»\n",
-       "«      └────────────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ »\n",
-       "«c8_0: ═══════════════════════════════════════════════════════════════════════»\n",
+       "«      ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────────────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ »\n",
+       "«q0_0: ┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ U1(3.1416) ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─»\n",
+       "«      └────┘ ░ └────┘ ░ └────┘ ░ └────────────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ »\n",
+       "«c0_0: ═══════════════════════════════════════════════════════════════════════»\n",
        "«                                                                             »\n",
-       "«      ┌───────────────────────────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ »\n",
-       "«q8_0: ┤ U3(3.1416,-1.5708,1.5708) ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─»\n",
-       "«      └───────────────────────────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ »\n",
-       "«c8_0: ═══════════════════════════════════════════════════════════»\n",
-       "«                                                                 »\n",
-       "«      ┌────────────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ »\n",
-       "«q8_0: ┤ U1(3.1416) ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─»\n",
-       "«      └────────────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ »\n",
-       "«c8_0: ═══════════════════════════════════════════════════════════════════════»\n",
+       "«      ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌───────────────────────┐ ░ ┌────┐ ░ ┌────┐»\n",
+       "«q0_0: ┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ U3(3.1416,-pi/2,pi/2) ├─░─┤ Id ├─░─┤ Id ├»\n",
+       "«      └────┘ ░ └────┘ ░ └────┘ ░ └───────────────────────┘ ░ └────┘ ░ └────┘»\n",
+       "«c0_0: ══════════════════════════════════════════════════════════════════════»\n",
+       "«                                                                            »\n",
+       "«       ░ ┌────┐ ░ ┌────────────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐»\n",
+       "«q0_0: ─░─┤ Id ├─░─┤ U1(3.1416) ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├»\n",
+       "«       ░ └────┘ ░ └────────────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘»\n",
+       "«c0_0: ═══════════════════════════════════════════════════════════════════════»\n",
        "«                                                                             »\n",
-       "«      ┌────────────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌───────────┐ ░ »\n",
-       "«q8_0: ┤ U1(3.1416) ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ U3(0,0,0) ├─░─»\n",
-       "«      └────────────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └───────────┘ ░ »\n",
-       "«c8_0: ════════════════════════════════════════════════════════════»\n",
-       "«                                                                  »\n",
-       "«      ┌───────────────────────────┐ ░ ┌─┐\n",
-       "«q8_0: ┤ U3(1.5708,-1.5708,1.5708) ├─░─┤M├\n",
-       "«      └───────────────────────────┘ ░ └╥┘\n",
-       "«c8_0: ═════════════════════════════════╩═\n",
-       "«                                         
" + "« ░ ┌────┐ ░ ┌────────────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ »\n", + "«q0_0: ─░─┤ Id ├─░─┤ U1(3.1416) ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─»\n", + "« ░ └────┘ ░ └────────────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ »\n", + "«c0_0: ════════════════════════════════════════════════════════»\n", + "« »\n", + "« ┌───────────────────────┐ ░ ┌─┐\n", + "«q0_0: ┤ U3(1.5708,-pi/2,pi/2) ├─░─┤M├\n", + "« └───────────────────────┘ ░ └╥┘\n", + "«c0_0: ═════════════════════════════╩═\n", + "«
" ], "text/plain": [ - "" + "" ] }, - "execution_count": 28, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } @@ -420,63 +417,58 @@ }, { "cell_type": "code", - "execution_count": 51, + "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
          ┌───────────────────────────┐ ░ ┌───────────┐ ░ ┌────┐ ░ ┌────┐ ░ »\n",
-       "q13_0: |0>┤ U3(1.5708,-1.5708,1.5708) ├─░─┤ U3(0,0,0) ├─░─┤ Id ├─░─┤ Id ├─░─»\n",
-       "          └───────────────────────────┘ ░ └───────────┘ ░ └────┘ ░ └────┘ ░ »\n",
-       " c13_0: 0 ══════════════════════════════════════════════════════════════════»\n",
-       "                                                                            »\n",
-       "«       ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐»\n",
-       "«q13_0: ┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├»\n",
-       "«       └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘»\n",
-       "«c13_0: ═════════════════════════════════════════════════════════════════════»\n",
-       "«                                                                            »\n",
-       "«        ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ »\n",
-       "«q13_0: ─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─»\n",
-       "«        ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ »\n",
-       "«c13_0: ══════════════════════════════════════════════════════════════════»\n",
-       "«                                                                         »\n",
-       "«       ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐»\n",
-       "«q13_0: ┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├»\n",
-       "«       └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘»\n",
-       "«c13_0: ═════════════════════════════════════════════════════════════════════»\n",
-       "«                                                                            »\n",
-       "«        ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ »\n",
-       "«q13_0: ─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─»\n",
-       "«        ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ »\n",
-       "«c13_0: ══════════════════════════════════════════════════════════════════»\n",
-       "«                                                                         »\n",
-       "«       ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐»\n",
-       "«q13_0: ┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├»\n",
-       "«       └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘»\n",
-       "«c13_0: ═════════════════════════════════════════════════════════════════════»\n",
-       "«                                                                            »\n",
-       "«        ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ »\n",
-       "«q13_0: ─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─»\n",
-       "«        ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ »\n",
-       "«c13_0: ══════════════════════════════════════════════════════════════════»\n",
-       "«                                                                         »\n",
-       "«       ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌───────────┐ ░ »\n",
-       "«q13_0: ┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ U3(0,0,0) ├─░─»\n",
-       "«       └────┘ ░ └────┘ ░ └────┘ ░ └───────────┘ ░ »\n",
-       "«c13_0: ═══════════════════════════════════════════»\n",
-       "«                                                  »\n",
-       "«       ┌───────────────────────────┐ ░ ┌─┐\n",
-       "«q13_0: ┤ U3(1.5708,-1.5708,1.5708) ├─░─┤M├\n",
-       "«       └───────────────────────────┘ ░ └╥┘\n",
-       "«c13_0: ═════════════════════════════════╩═\n",
-       "«                                          
" + "
         ┌───────────────────────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐»\n",
+       "q1_0: |0>┤ U3(1.5708,-pi/2,pi/2) ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├»\n",
+       "         └───────────────────────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘»\n",
+       " c1_0: 0 ══════════════════════════════════════════════════════════════════════»\n",
+       "                                                                               »\n",
+       "«       ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐»\n",
+       "«q1_0: ─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├»\n",
+       "«       ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘»\n",
+       "«c1_0: ════════════════════════════════════════════════════════════════════════»\n",
+       "«                                                                              »\n",
+       "«       ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐»\n",
+       "«q1_0: ─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├»\n",
+       "«       ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘»\n",
+       "«c1_0: ════════════════════════════════════════════════════════════════════════»\n",
+       "«                                                                              »\n",
+       "«       ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐»\n",
+       "«q1_0: ─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├»\n",
+       "«       ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘»\n",
+       "«c1_0: ════════════════════════════════════════════════════════════════════════»\n",
+       "«                                                                              »\n",
+       "«       ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐»\n",
+       "«q1_0: ─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├»\n",
+       "«       ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘»\n",
+       "«c1_0: ════════════════════════════════════════════════════════════════════════»\n",
+       "«                                                                              »\n",
+       "«       ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐»\n",
+       "«q1_0: ─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├»\n",
+       "«       ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘»\n",
+       "«c1_0: ════════════════════════════════════════════════════════════════════════»\n",
+       "«                                                                              »\n",
+       "«       ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ ┌────┐ ░ »\n",
+       "«q1_0: ─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─┤ Id ├─░─»\n",
+       "«       ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ └────┘ ░ »\n",
+       "«c1_0: ════════════════════════════════════════════════»\n",
+       "«                                                      »\n",
+       "«      ┌───────────────────────┐ ░ ┌─┐\n",
+       "«q1_0: ┤ U3(1.5708,-pi/2,pi/2) ├─░─┤M├\n",
+       "«      └───────────────────────┘ ░ └╥┘\n",
+       "«c1_0: ═════════════════════════════╩═\n",
+       "«                                     
" ], "text/plain": [ - "" + "" ] }, - "execution_count": 51, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -494,7 +486,7 @@ }, { "cell_type": "code", - "execution_count": 49, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -524,7 +516,7 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -547,17 +539,17 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 10, "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] }, - "execution_count": 38, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -572,17 +564,17 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 11, "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] }, - "execution_count": 39, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -617,14 +609,14 @@ }, { "cell_type": "code", - "execution_count": 41, + "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Least busy device is ibmqx4\n" + "Least busy device is ibmqx2\n" ] } ], @@ -634,7 +626,7 @@ "account_token : str\n", " Token to enable IBM Q device access\n", "'''\n", - "account_token = 'insert-your-ibmq-token-here'\n", + "account_token = 'insert_your_ibm_token_here'\n", "IBMQ.enable_account(account_token)\n", "available_devices = IBMQ.backends(\n", " filters=lambda x: not x.configuration().simulator and x.status().operational is True\n", @@ -652,31 +644,24 @@ }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 13, "metadata": {}, "outputs": [ { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "1b8554d668c34b11adb77a12256dc387", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HTML(value=\"

Job Status: job is being initialized

\")" - ] - }, - "metadata": {}, - "output_type": "display_data" + "name": "stdout", + "output_type": "stream", + "text": [ + "Job Status: job has successfully run\n" + ] }, { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAccAAAE1CAYAAACSpiugAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAHnVJREFUeJzt3XuYnWV57/HvTU4mNMHMMA0TQhJi6HRycBxOoogEAUW71RSp0dKitZYdsXRT7MbDZSO03ekWgcJW2So9cNIWFDR4oAKNNipWNInTHIYR9piEkCEOQwwxCUkY7v3HWkmHlwwzgzNrJTPfz3WtK+t93udZ615ZLH55T88bmYkkSfovR1S7AEmSDjWGoyRJBYajJEkFhqMkSQWGoyRJBYajJEkFhqMkSQWGoyRJBYajJEkFo6tdwFCpra3N6dOnV7sMSdIh5Kc//emTmVnXV79hG47Tp09n+fLl1S5DknQIqamp2diffu5WlSSpwHCUJKnAcJQkqcBwlCSpwHCUJKnAcJQkqcBwlCSpwHCUJKnAcJQkqcBwlCSpwHCUJKnAcJQkqcBwlCSpwHCUJKnAcJQkqcBwlCSpwHCUJKnAcJQkqcBwlCSpwHCUJKnAcJQkqcBwlCSpwHCUJKnAcJSkQ8ADDzzAqaeeykknncT111//gvWbN2/mbW97G2eeeSave93ruP/++wH4zne+w1lnncXpp5/OWWedxYoVKw6M2bt3L5dddhmnnHIKr371q7nnnnsq9nkOd6OrXYAkjXTd3d1cccUV3H333UydOpWzzz6b8847j9/+7d8+0Oeaa65h4cKFvO997+Phhx9m0aJFtLS0UFtby5e+9CXq6+tZv349v/d7v8e6desAuPbaa6mrq+PHP/4xzz33HNu2bavWRzzsGI6SVGUrV67k+OOPZ+bMmQCcf/753Hvvvc8Lx4hgx44dADz99NMcc8wxALzyla880KexsZHdu3ezZ88exo0bxxe/+EV+9KMfAXDEEUdQW1tboU90+HO3qiRVWUdHB8cee+yB5alTp9LR0fG8Ph/+8Ie58847mTt3LosWLeKTn/zkC17nnnvuoampiXHjxrF9+3YAli5dyoIFC3jve9/LL37xi6H9IMOI4ShJh4G77rqLd7/73axbt4477riDxYsX89xzzx1Y39raylVXXcV1110HwLPPPsuWLVs49dRT+e53v8spp5zCkiVLqlX+YcdwlKQqq6+v5/HHHz+wvGXLFurr65/X5/bbb2fhwoUAnHrqqezZs4euri4AHn/8cS666CJuvPFGjj/+eABqamqYMGECb33rWwF4+9vfTktLSyU+zrBgOEpSlZ144om0t7ezceNG9u7dy91338155533vD7Tpk07cCZqW1sbe/bs4eijj2b79u28613vYsmSJZx22mkH+kcEb3rTm/j+978PwIoVK2hoaKjchzrMRWZWu4Yh0dzcnMuXL692GZLUL/fffz8f+9jH6O7u5sILL+RDH/oQS5cupbm5mTe/+c08/PDDXHbZZezcuZOI4Morr+QNb3gD11xzDddffz2zZs068Fp33XUXdXV1PPbYYyxevJjt27dz9NFH85nPfIZp06ZV8VNWX01NzcrMPLmvfoajJGnE6G84ultVkqQCw1GSpALDUZKkAsNRkqQCw1GSpALDUZKkAsNRkqQCw1GSpALDUZKkAsNRkqQCw1GSpILR1S5AkgbTFbdMrnYJGgJXv2dbRd/PLUdJkgoMR0mSCgxHSZIKKh6OEXFJRPw8Ip6JiJURcUYf/X8/In4aEbsi4omIuD0ijqlUvZKkkaei4RgRi4AbgKVAM/AgcG9ETO+l/+nAbcAtwFxgITAH+GJFCpYkjUiV3nK8HLg5M2/KzNbMvBToAD7QS//XAJsz8+8y8+eZ+R/Ap4FXV6heSdIIVLFLOSJiLHAScE1h1X3Aa3sZ9gNgaUS8FfgGUAu8C/hWL+9xMXAxQH19PatWrQJg6tSpTJgwgUcffRSAo446ilmzZrF69WoARo0aRVNTE21tbezcuROAxsZGnnrqKbZu3QrAtGnTGDt2LO3t7QBMnjyZ6dOn09LSAsCYMWOYP38+ra2t7N69G4A5c+bQ2dlJZ2cnADNmzCAi2LBhAwC1tbXU19ezdu1aAMaNG8fcuXNZt24de/bsAWDevHl0dHTQ1dUFwMyZM8lMNm7cCEBdXR11dXWsX78egPHjx9PY2MiaNWvYt28fAE1NTWzatIlt20qnQs+aNYu9e/eyefNmAKZMmUJNTQ2tra0AHHnkkTQ0NNDS0kJ3dzcAzc3NtLe3s337dgBmz57Nrl272LJlC/v/vidNmkRbWxsAEydO5IQTTmD16tVkJhFBc3MzjzzyCDt27ACgoaGBp59+mo6ODr8nv6dB+540PHV1dQ3K76m/IjMH+SP08kYRU4HHgTMzc0WP9iXAhZnZ0Mu484GbgfGUwvx+4O2ZufvF3q+5uTmXL18+SNVLOlx4nePwNFjXOdbU1KzMzJP76ndIn60aEXMo7Ub9a0pbnecBxwCfr2ZdkqThrZIz5DwJdANTCu1TgCd6GfNR4KHM/FR5+T8jYifwvYj4WGZuHppSJUkjWcW2HDNzL7ASOLew6lxKZ60ezARKgdrT/uVDeqtXknT4qvTcqtcBt0XEQ5ROtlkMTAU+BxARtwJk5kXl/l8HboqIDwDfBuqB64FVmbmpwrVLkkaIioZjZt4REbXAxykF3VrgLZm5sdxleqH/zRExEfhT4FpgO7Ac+HDlqpYkjTQVvytHZt4I3NjLugUHafs0pZNyJEmqCI/bSZJUYDhKklRgOEqSVGA4SpJUYDhKklRgOEqSVGA4SpJUYDhKklRgOEqSVGA4SpJUYDhKklRgOEqSVGA4SpJUYDhKklRgOEqSVGA4SpJUYDhKklRgOEqSVGA4SpJUYDhKklRgOEqSVGA4SpJUYDhKklRgOEqSVGA4SpJUYDhKklRgOEqSVGA4SpJUYDhKklRgOEqSVGA4SpJUYDhKklRgOEqSVGA4SpJUYDhKklRgOEqSVGA4SpJUMKBwjIh3RsQbeywviYjNEfHtiKgf/PIkSaq8gW45Xrn/SUScCHwM+D/AGODawStLkqTqGT3A/jOAtvLz3wW+lplXR8R9wLcHtTJJkqpkoFuOzwATy8/PBh4oP9/eo12SpMPaQLccvwdcGxHfB04GLii3/xbw2GAWJklStQx0y/FPgb2UQnFxZm4pt78Zd6tKkoaJAW05ZuZm4K0Hab9s0CqSJKnKBnydY0S8LCIuiIgPR8TLy22viIiafo6/JCJ+HhHPRMTKiDijj/5jI+KvymP2RMSmiPizgdYtSVJ/DWjLMSJmUzoJ5zeAlwNfBn4JfKC8/P4+xi8CbgAuAb5f/vPeiJiTmZt6GfYvwDTgYuARYAowfiB1S5I0EAPdcrweuI9SQO3u0X4PcFY/xl8O3JyZN2Vma2ZeCnRQCtcXKE84cDbwlsy8PzM3ZOaPMvO7A6xbkqR+G+jZqq8FTsvM7ojo2b4JmPpiAyNiLHAScE1h1X3l1z2YhcCPgcsj4iJKgXwv8LHM/NVB3uNiSluY1NfXs2rVKgCmTp3KhAkTePTRRwE46qijmDVrFqtXrwZg1KhRNDU10dbWxs6dOwFobGzkqaeeYuvWrQBMmzaNsWPH0t7eDsDkyZOZPn06LS0tAIwZM4b58+fT2trK7t2lfzfMmTOHzs5OOjs7AZgxYwYRwYYNGwCora2lvr6etWvXAjBu3Djmzp3LunXr2LNnDwDz5s2jo6ODrq4uAGbOnElmsnHjRgDq6uqoq6tj/fr1AIwfP57GxkbWrFnDvn37AGhqamLTpk1s27YNgFmzZrF37142b94MwJQpU6ipqaG1tRWAI488koaGBlpaWuju7gagubmZ9vZ2tm/fDsDs2bPZtWsXW7aUzsmqr69n0qRJtLWVLoOdOHEiJ5xwAqtXryYziQiam5t55JFH2LFjBwANDQ08/fTTdHR0+D35PQ3a96Thqaura1B+T/0Vmdn/zhFPAWdk5rqI2AE0ZWZ7RLweuDMzj3mRsVOBx4EzM3NFj/YlwIWZ2XCQMf8KLAD+DfgrSrtuPw38Z2ZeUOzfU3Nzcy5fvrzfn03S8HDFLZOrXYKGwNXv2TYor1NTU7MyM0/uq99Ad6veR2nX6H4ZEZOAq4BvDvC1+uMIIIHfL+9O/Taly0neERFThuD9JEka8G7Vy4HvREQb8DLgDmA2sBV4Zx9jnwS6KR2v7GkK8EQvYzqAxzNze4+21vKf08vvK0nSoBrQlmP5ov9XAZ8EPg/8BLgCODEzO/sYuxdYCZxbWHUu8GAvw34ATI2I3+jR9lvlPzcOpHZJkvproFuOZOZu4B/Lj4G6DrgtIh6iFHyLKZ3I8zmAiLi1/B4Xlft/CfhL4J8i4kpKxxxvAL6Smb94Ce8vSVKf+gzHiDgf+Hpm7is/71Vm3t3H+jsiohb4OFAPrKV0mcb+rcDphf6/iohzKJ2E82NgG/A14CN91S1J0kvVny3HrwDHAL8oP+9NAqP6erHMvBG4sZd1Cw7S1ga88YW9JUkaGn2GY2YecbDnkiQNVwMKu4h4fUS8IFAjYlT5WkdJkg57A90S/A5wsAnGX15eJ0nSYW+g4RiUji0W1QI7f/1yJEmqvn5dyhER95SfJnB7ROzpsXoUMI/er1WUJOmw0t/rHLvKfwalyyl63pFjL6XbT900iHVJklQ1/QrHzPwjgIjYAFyTme5ClSQNWwOaISczrxqqQiRJOlT0Z4ac/6R0m6ltEbGGg5+QA0BmvnIwi5MkqRr6s+V4F7D/BJwXmyFHkqRhoT8z5Fx1sOeSJA1XTgcnSVJBf445vuhxxp485ihJGg76e1cOSZJGjAEdc5QkaSTwmKMkSQVe5yhJUoHXOUqSVOB1jpIkFQxobtX9IuIVQGN5sTUz/9/glSRJUnUNKBwjohb4B+BtwHP/1RzfAN6XmV29DpYk6TAx0LNV/x6YDZwBvKz8eD1wPN7PUZI0TAx0t+qbgLMz84c92n4QEf8deGDwypIkqXoGuuXYCRzsRse7AHepSpKGhYGG418B10fEsfsbys+vLa+TJOmw91ImHj8e2BARj5eXjwWeAX6T0jFJSZIOa048LklSgROPS5JU4MTjkiQVDCgcI2JsRFwVET+LiGciorvnY6iKlCSpkga65fjXwHsonZ36HPA/gc9SuozjksEtTZKk6hhoOL4TWJyZnwe6gWWZ+WfAJ4BzB7s4SZKqYaDhOAVYX37+K+Dl5ef/CrxxsIqSJKmaBhqOm4Cp5eePUppODuA1wO7BKkqSpGoaaDh+FTi7/PwG4KqI+DlwM04AIEkaJgY08XhmfrTH869ExGbgtcDPMvMbg12cJEnV8JJudrxfZv4H8B+DVIskSYeEAU8CEBEnRsStEfGT8uO2iDhxKIqTJKkaBjoJwIXAj4F64FvlxxTgoYj4g8EvT5KkyhvobtX/BfxlZi7t2RgRHwX+Brh9sAqTJKlaBrpbtQ648yDtX6Z0yypJkg57Aw3H7wALDtK+APj3X7cYSZIOBf252fH5PRbvBf42Ik7mv85SPQ04H7hy0KuTJKkKXurNji8uP3r6NHBjXy8WEZdQmrC8HlgHXJaZ3+vHuNcB3wUezsx5ffWXJOml6nO3amYe0c/HqL5eKyIWUZpZZynQDDwI3BsR0/sYNxm4Ffi3fn0qSZJ+DZW+2fHlwM2ZeVNmtmbmpUAH8IE+xv0DcAvww6EuUJKklzIJwO9ExIqIeDIiOiPi3yPiLf0YNxY4CbivsOo+SlPQ9TbuEkrXUv7NQGuVJOmlGNB1jhHxfkrHFb9IaUsO4AzgqxHxgcz8xxcZfjQwCthaaN8KnNPL+82ndK/I0zKzOyL6qu/AsdD6+npWrVoFwNSpU5kwYQKPPvooAEcddRSzZs1i9erVAIwaNYqmpiba2trYuXMnAI2NjTz11FNs3Voqd9q0aYwdO5b29nYAJk+ezPTp02lpaQFgzJgxzJ8/n9bWVnbvLt2gZM6cOXR2dtLZ2QnAjBkziAg2bNgAQG1tLfX19axduxaAcePGMXfuXNatW8eePXsAmDdvHh0dHXR1dQEwc+ZMMpONGzcCUFdXR11dHevXl+4kNn78eBobG1mzZg379u0DoKmpiU2bNrFt2zYAZs2axd69e9m8eTMAU6ZMoaamhtbWVgCOPPJIGhoaaGlpobu7G4Dm5mba29vZvn07ALNnz2bXrl1s2bKF/X/fkyZNoq2tDYCJEydywgknsHr1ajKTiKC5uZlHHnmEHTt2ANDQ0MDTTz9NR0eH35Pf06B9Txqeurq6BuX31F+Rmf3vHPEIcENmfqbQfilwaWb+1ouMnQo8DpyZmSt6tC8BLszMhkL/ccBq4G8z87Zy25XABf05Iae5uTmXL1/e788maXi44pbJ1S5BQ+Dq92wblNepqalZmZkn99VvoLtVp1O6sXHRvcCMPsY+CXRT2kXa0xTgiYP0rwcagX+KiGcj4llgCTC3vOzNlSVJQ+Kl3Oz43IO0vxHY+GIDM3MvsPIg48+ldNZq0ePAfOBVPR6fo3ST5Vf1MkaSpF/bQOdWvQb4dPkuHPvD6XTgD4FL+zH+OuC2iHgI+AGwGJhKKfSIiFsBMvOizNwHrO05OCJ+AezJzOe1S5I0mAZ6s+PPlwPqQ5RmxQFoBd6Zmcv6Mf6OiKgFPk5pt+la4C2ZuX+r80Wvd5QkqRL6HY4RMZrS7tMVmfnVl/qGmXkjvcykk5kL+hh7JU5TJ0kaYv0+5piZzwJ3AxOHrhxJkqpvoCfktACzh6IQSZIOFQMNxyuBayNiYUQcFxE1PR9DUJ8kSRU30LNVv1n+826g5+wBUV7uc/JxSZIOdQMNx7OGpApJkg4h/QrHiJgAfApYCIwBHgD+LDOfHMLaJEmqiv4ec7wKeC+l3ar/TGlWm/87RDVJklRV/d2tej7wx5n5LwAR8UXgBxExKjO7h6w6SZKqoL9bjscB39u/kJkPAc9SmvpNkqRhpb/hOAoo3gjrWQZ+Qo8kSYe8/oZbALdHxJ4ebS8DboqIXfsbMvNtg1mcJEnV0N9wvOUgbbcPZiGSJB0q+hWOmflHQ12IJEmHioFOHydJ0rBnOEqSVGA4SpJUYDhKklRgOEqSVGA4SpJUYDhKklRgOEqSVGA4SpJUYDhKklRgOEqSVGA4SpJUYDhKklRgOEqSVGA4SpJUYDhKklRgOEqSVGA4SpJUYDhKklRgOEqSVGA4SpJUYDhKklRgOEqSVGA4SpJUYDhKklRgOEqSVGA4SpJUYDhKklRgOEqSVGA4SpJUYDgOYw888ACnnnoqJ510Etdff/0L1j/44IMsWLCAuro6li1bdqD9e9/7Hq9//esPPOrr6/nmN7/5vLEf+chHOO6444b8M0hSNVQ8HCPikoj4eUQ8ExErI+KMF+l7fkTcFxGdEbEjIn4UEW+rZL2Hq+7ubq644gruvPNOfvjDH3LXXXfx8MMPP6/PtGnT+OxnP8sFF1zwvPYzzjiDFStWsGLFCpYtW8b48eM566yzDqxfvXo1v/zlLyvyOSSpGioajhGxCLgBWAo0Aw8C90bE9F6GnAksB36n3P9bwFdfLFBVsnLlSo4//nhmzpzJ2LFjOf/887n33nuf12f69OnMnTuXI47o/T+DZcuWcc455zBhwgSgFLqf+MQnuPLKK4eyfEmqqkpvOV4O3JyZN2Vma2ZeCnQAHzhY58z8H5n5vzPzocx8NDOvAlYCCytY82Gpo6ODY4899sDy1KlT6ejoGPDrfPWrX+Ud73jHgeWbbrqJ8847j2OOOWZQ6pSkQ9HoSr1RRIwFTgKuKay6D3jtAF5qIrBtsOpS75544gnWr1/PG97wBqAUuMuWLePrX/96lSuTpKFVsXAEjgZGAVsL7VuBc/rzAhHxQWAacFsv6y8GLgaor69n1apVQGmracKECTz66KMAHHXUUcyaNYvVq1cDMGrUKJqammhra2Pnzp0ANDY28tRTT7F1a6ncadOmMXbsWNrb2wGYPHky06dPp6WlBYAxY8Ywf/58Wltb2b17NwBz5syhs7OTzs5OAGbMmEFEsGHDBgBqa2upr69n7dq1AIwbN465c+eybt069uzZA8C8efPo6Oigq6sLgJkzZ5KZbNy4EYC6ujrq6upYv349AOPHj6exsZFdu3bR2trKqlWraGpqYu3atTz33HOsWrWKWbNmsXfvXjZv3gzAzp072bt374G/ryOPPJKGhgY++9nP8upXv5o1a9bQ3NzMfffdx89+9jPmz5/P6NGj2bVrF/PmzePWW2+lvr6eSZMm0dbWBsDEiRM54YQTWL16NZlJRNDc3MwjjzzCjh07AGhoaODpp58+sEU7Er+nNWvWsG/fPgCamprYtGkT27aV/u1X/J6mTJlCTU0Nra2tz/ueWlpa6O7uBqC5uZn29na2b98OwOzZs9m1axdbtmxh/+9iuH9PGp66uroG5ffUX5GZg/wRenmjiKnA48CZmbmiR/sS4MLMbOhj/DsoheKizOxz06W5uTmXL1/+a1Z9+Hr22Wc55ZRT+NrXvkZ9fT1nn302X/jCF2hsbHxB3w9+8IO88Y1v5O1vf/vz2s8991yWLFnCGWcc/BDvcccdx2OPPTYk9Usv1RW3TK52CRoCV79ncHYY1tTUrMzMk/vqV8ljjk8C3cCUQvsU4IkXGxgRF1AKxov6E4yC0aNHc/XVV3PBBRdw2mmnsXDhQhobG1m6dOmBE3NWrVrF3LlzWbZsGZdffjmvec1rDozftGkTW7Zs4fTTT6/WR5CkqqnYliNARPwIaMnMi3u0/Qy4KzM/2suYdwK3AO/JzDv7+14jfctRGqncchyeKr3lWMljjgDXAbdFxEPAD4DFwFTgcwARcStAZl5UXn4XpS3GvwBWRMT+UyT3ZuZTFa5dkjRCVDQcM/OOiKgFPg7UA2uBt2TmxnKX4vWOiynVeH35sd+/AwuGtlpJ0khV6S1HMvNG4MZe1i14sWVJkiqh4uF4uPH4xfA0WMcvJA1PTjwuSVKB4ShJUoHhKElSgeEoSVKB4ShJUoHhKElSgeEoSVKB4ShJUoHhKElSgeEoSVKB4ShJUoHhKElSgeEoSVKB4ShJUoHhKElSgeEoSVKB4ShJUoHhKElSgeEoSVKB4ShJUoHhKElSgeEoSVKB4ShJUoHhKElSgeEoSVKB4ShJUoHhKElSgeEoSVKB4ShJUoHhKElSgeEoSVKB4ShJUoHhKElSgeEoSVKB4ShJUoHhKElSgeEoSVKB4ShJUoHhKElSgeEoSVKB4ShJUoHhKElSgeEoSVJBxcMxIi6JiJ9HxDMRsTIizuij/5nlfs9ERHtELK5UrZKkkami4RgRi4AbgKVAM/AgcG9ETO+l//HAt8r9moG/BT4dEe+oTMWSpJGo0luOlwM3Z+ZNmdmamZcCHcAHeum/GNiSmZeW+98E3AL8RYXqlSSNQBULx4gYC5wE3FdYdR/w2l6GveYg/b8NnBwRYwa3QkmSSkZX8L2OBkYBWwvtW4FzehlzDPDAQfqPLr9eR88VEXExcHF58Vc1NTVtv07BI9DRwJPVLqIS/v7Pq12BNCj8zQ7cjP50qmQ4DrnM/ALwhWrXcbiKiJ9k5snVrkNS//ibHTqVPOb4JNANTCm0TwGe6GXME730f5YR8q8lSVLlVSwcM3MvsBI4t7DqXEpnox7MD3vp/5PM3De4FUqSVFLps1WvA94bEe+PiMaIuAGYCnwOICJujYhbe/T/HHBsRFxf7v9+4L3ANRWue6Rwl7R0ePE3O0QiMyv7hhGXAFcA9cBa4M8zc0V53XcBMnNBj/5nAn8HzAW2AJ/MzM9VtGhJ0ohS8XCUJOlQ59yqkiQVGI6SJBUYjiNcRJwQEcXLZSRpRPOY4wgUEb8J/CHw50AnpetGO4CvAHdl5s4qlidJVWc4jkARcTMwB/gG0AXUAq8CGoHNwNWZeX/VCpSkKjMcR5iICGAH8JYel9AEMA04DfgTSnMPLsrMn1atUEnPExGTgB3p/7QrwmOOI88c4OfA3v0NWfJYZn4Z+G+UwnNRleqTdHCfAt4XEfPLQfkCEVFb4ZqGLcNx5GkHfgH8XflknOf9N1Ce5u8W4M3VKE7SC0XEuynt1bkWWAZ8KiJ+NyJeERHjy33GA/8QEfOrWOqw4W7VESgiTqM0Nd9u4PPAvwHbMvNXETEBuBV4JjP/oIplSiqLiJso3bjhauB84D3AK4A24FuUfsMNwA2ZObZadQ4nhuMIFRHzgL8E3gbspDTJeyele2t2AO/PzDXVq1ASQESMpjTl5qTM/EiP9rmUtiYvAF4GvBy4JTP/uCqFDjOG4whXvqzjd4CFwDOU5rv9cmY+XNXCJB0QEZOBKZn5cESMBfb1PDEnIhYB/wyc6Il0g8Nw1AERcURmPlftOiT1rXy+QGRmd0T8CaVdqhOqXddwMbraBejQYTBKh4/C73Ui8Ilq1TIcueUoSYe5iBgDdPsP3MFjOEqSVOB1jpIkFRiOkiQVGI6SJBUYjpIkFRiOkiQV/H+GV4eYgr5OeAAAAABJRU5ErkJggg==\n", + "image/png": "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q+dn5kkH69fVu3ALi4jzgJuAC/aGJ0BmzgPmteg3l9JW6CeBv+rqOiVJvUNXnkT0ItAMDG/VPhw44PHLiDgf+B5wSWY+cKC+mdkMPAWMK16qJEkH1mUBmpm7gPnAjFazZlA6G7dNEfEBSuF5WWbec7DPiYgA/gxoLF6tJEkH1tW7cG8GvhcRvwaeBK4ARgDfAoiI7wJk5iXl6Qsphef/AuZExLHlcXZl5oZyn78FfgksAwZT2m37Z5TO7JUkqVN0aYBm5l0RMRT4G0rXay4GzmpxTLP19aBXUKrxlvJrr18Ap5XfHwPcBhwLbAIWAKdk5q87Yx0kSYJuOIkoM78JfHM/80470PR+lrkauLojapMkqb28F64kSQUYoJIkFWCASpJUgAEqSVIBBqgkSQUYoJIkFWCASpJUgAEqSVIBBqgkSQUYoJIkFWCASpJUgAEqSVIBBqgkSQUYoJIkFWCASpJUgAEqSVIBBqgkSQUYoJIkFWCASpJUgAEqSVIBBqgkSQUYoJIkFWCASpJUgAEqSVIBBqgkSQUYoJIkFWCASpJUgAHayz366KO89a1vZerUqdxyyy2vmr9z504+/OEPM3XqVN71rnexevXqffOWLFnCGWecwbRp03j729/Ojh07ADj//POZPn0606ZN45prrqG5ubnL1keSuooB2os1Nzdz7bXXcvfddzNv3jzuvfdennnmmVf0+f73v88xxxzD/PnzufLKK/niF78IwJ49e/jYxz7GzTffzLx583jggQfo168fAN/5znd4/PHHmTt3Li+++CL3339/V6+aJHU6A7QXmz9/PieccAKjR4+mqqqKc889l4ceeugVfWbNmsWFF14IwPvf/37mzJlDZvLYY48xceJEJk2aBEB1dTV9+vQBYPDgwUApZHfv3k1EdOFaSVLXMEB7scbGRo477rh90yNGjKCxsXG/ffr27cvgwYPZsGEDy5cvJyI477zzOO200/j617/+iuXOO+883vjGN/K6172O97///Z2/MpLUxQxQFbJnzx5++ctfcttttzFr1iwefPBBfvGLX+ybf++991JfX8/OnTuZM2dON1YqSZ3DAO3FampqeO655/ZNr127lpqamv322bNnD5s3b6a6upoRI0Zw8sknM3ToUAYOHMiMGTNYuHDhK5Y98sgjOeuss161W1iSDgcGaC/25je/mRUrVrBq1Sp27drFfffdx7vf/e5X9DnzzDP50Y9+BMBPf/pTpk+fTkRw+umns3TpUrZt28aePXuYO3cub3rTm3jppZd4/vnngVLgPvLII4wbN67L102SOlvf7i5A3adv377MnDmT888/n+bmZi666CJqa2u58cYbqaur48wzz+Tiiy/miiuuYOrUqQwZMoRvf/vbABxzzDFcddVVnH766UQEM2bM4IwzzuCFF17goosuYufOnbz88stMnz6dD33oQ928ppLU8SIzu7uGblNXV5ezZ8/u7jIkdbFr7xzS3SWoE8y8dGOHjFNdXT0/M086WD934UqSVIC7cDuAf80enjrqr1lJhye3QCVJKsAAlSSpAANUkqQCDFBJkgowQCVJKsAAlSSpAANUkqQCDFBJkgowQCVJKsAAlSSpAANUkqQCujxAI+KqiHg2InZExPyImH6Q/qeW++2IiBURccVrHVOSpNeqSwM0Ii4AbgVuBOqAucBDETFqP/1PAGaV+9UBfwd8IyLOKzqmJEkdoau3QK8B7sjM2zOzPjM/CTQCV+6n/xXA2sz8ZLn/7cCdwP96DWNKkvSadVmARkQVMBV4pNWsR4CT97PYtDb6PwycFBH9Co4pSdJr1pXPA/0ToA+wrlX7OuBd+1nmWODRNvr3LY8XlY4ZEZcDl5cnX6qurm5oT/Ha50+AF7u7iK7w7au7uwKpQ/g7W7nj29Op1z1QOzNvA27r7joOVRHxVGae1N11SGoff2c7T1cG6ItAMzC8Vftw4Pn9LPP8fvrvKY8XBcaUJOk167JjoJm5C5gPzGg1awalM2fbMm8//Z/KzN0Fx5Qk6TXr6l24NwPfi4hfA09SOst2BPAtgIj4LkBmXlLu/y3gExFxC/BPwNuBy4APtndMdTh3f0uHFn9nO0lkZtd+YMRVwLVADbAYuDoz55Tn/RwgM09r0f9U4B+AicBa4O8z81vtHVOSpM7Q5QEqSdLhwHvhSpJUgAEqSVIBBqgOKiLGRUTrS4UkqVfzGKjaFBF/CvwFcDXQROna20bgHuDezNzajeVJUrczQNWmiLgDmAA8CKwHhgInArXAGmBmZv6s2wqUpG5mgOpVIiKALcBZLS4xCmAk8Dbgo5TuFXlBZv6m2wqV9AoRMRjYkv6PvUt4DFRtmQA8C+za25Alv8/MHwP/g1LAXtBN9Ulq203AhyNicjlMXyUihnZxTYctA1RtWQG8APxD+QSiV/x3Ur6F4p3Amd1RnKRXi4gPUto79DXgp8BNEXFORLwhIgaU+wwA/jkiJndjqYcNd+GqTRHxNkq3Q9xO6TaK/wFszMyXImIg8F1gR2Ze3I1lSiqLiNspPVxjJnAucCnwBqABmEXpd3g8cGtmVnVXnYcTA1T7FRGTgOuA9wFbKd3cv4nSs1YbgY9k5qLuq1ASQET0pXQ708GZ+dkW7RMpbZWeDxwJHAPcmZl/2S2FHmYMUB1U+ZKW9wBnAzso3W/4x5n5TLcWJmmfiBgCDM/MZyKiCtjd8mSiiLgA+FdW9rhEAAAAcElEQVTgzZ781zEMUFUkIo7IzJe7uw5JB1c+fyEyszkiPkpp9+3A7q7rcNHVjzPTIc7wlA4drX5fBwF/2121HI7cApWkXiAi+gHN/hHccQxQSZIK8DpQSZIKMEAlSSrAAJUkqQADVJKkAgxQSZIK+P/6pPSmsTQnSQAAAABJRU5ErkJggg==\n", "text/plain": [ "
" ] }, - "execution_count": 43, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -700,31 +685,24 @@ }, { "cell_type": "code", - "execution_count": 45, + "execution_count": 14, "metadata": {}, "outputs": [ { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "a13e1c509c7d4dd7986063e220c23c26", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HTML(value=\"

Job Status: job is being initialized

\")" - ] - }, - "metadata": {}, - "output_type": "display_data" + "name": "stdout", + "output_type": "stream", + "text": [ + "Job Status: job has successfully run\n" + ] }, { "data": { - "image/png": "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KElShuEoSVKG4ShJUobhKElShuEoSVKG4ShJx4DHHnuMM844g9NPP53Fixe/a/ktt9zCmWeeycc+9jEuuugiXn311YPL7r//fqZPn8706dO5//77AdizZw/z5s3jIx/5CB/96Ee56aabivZd+gLDUZJKrKOjg+uuu44HH3yQp59+moceeogXX3zxHX1OPfVUVqxYwVNPPcWFF17IDTfcAMD27dtZuHAhjz76KI899hgLFy7kjTfeAODzn/88zzzzDE8++STPPPMMjz76aNG/2/HKcJSkElu1ahUnn3wy48aNo6ysjLlz57Js2bJ39DnrrLMYOnQoANOnT2fz5s0ArFixglmzZlFeXs7IkSOZNWsWjz/+OEOHDuWss84CoKysjFNPPfXgOjoyw1GSSqy1tZWTTjrp4Ovq6mpaW1u77H/vvfdy3nnnAbB58+Z3rZsNwR07dvDII49w9tln93DlfdfAUhcgSeq+Bx98kIaGBn74wx92q/9bb73F/Pnzufzyyxk3blzvFteHuOcoSSVWVVXFpk2bDr7evHkzVVVV7+r34x//mEWLFnHfffcxePBgILenmF23urr64OsvfvGLnHLKKVx55ZW9+A36HsNRkkrstNNOo6WlhfXr19Pe3s7SpUuZM2fOO/o8//zzXHPNNdx3331UVlYebD/nnHN44okneOONN3jjjTd44oknOOeccwD4+te/zs6dO1mwYEFRv09f4GFVSSqxgQMHsnDhQi6++GI6Ojq45JJLqKurY8GCBdTX13P++edzww03sHv3bj73uc8BMGbMGO677z7Ky8u59tprOffccwH48pe/THl5OZs2bWLRokVMnDiRWbNmATB//nwuvfTSUn3N40qklEpdQ6+or69PK1asOOr3ue6u8h6oRseahZdtL3UJkkqgoqJiVUpp+pH6Ff2wakRcFRGvRMSbEbEqIs46TN+5EbE8ItoiYldEPBMRFxazXklS/1PUcIyIecASYAFQD/wMWBYRNV2scjawAvhkvv+PgIcPF6iSJB2tYp9zvAa4M6V0e/711RExB7gS+Eq2c0rpC5mmmyLik8BFwE96tVJJUr9VtHCMiDLgdOCbmUXLgRkFvNVwwBNGkg7JcQJ9U7HHCRRzz/H9wABgS6Z9C3Bed94gIv4XMAa4p4vllwOXQ+66oeeeew7IXQc0dOhQXn75ZQBOPPFE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\n", + "image/png": "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\n", "text/plain": [ "
" ] }, - "execution_count": 45, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -757,7 +735,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 15, "metadata": { "scrolled": true }, From 22b0cdc7ebe39ec94886b996bf7c6fe32fa344e8 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Thu, 23 May 2019 20:47:34 +1000 Subject: [PATCH 16/42] notebooks checked and updated --- examples/creating_a_dds.ipynb | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/examples/creating_a_dds.ipynb b/examples/creating_a_dds.ipynb index c7ca9f63..bbd0d8d7 100644 --- a/examples/creating_a_dds.ipynb +++ b/examples/creating_a_dds.ipynb @@ -238,35 +238,22 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 8, "metadata": {}, "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CP DDS:\n", - "Duration = 1e-05\n", - "Offsets = [0.125,0.375,0.625,0.875] x 1e-05\n", - "Rabi Rotations = [1.0,1.0,1.0,1.0] x pi\n", - "Azimuthal Angles = [0.0,0.0,0.0,0.0] x pi\n", - "Detuning Rotations = [0.0,0.0,0.0,0.0] x pi\n", - "1e-06\n" - ] - }, { "data": { "text/plain": [ "Text(0,0.5,'Detuning Rotation (rad)')" ] }, - "execution_count": 20, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -415,7 +402,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 11, "metadata": {}, "outputs": [ { @@ -424,7 +411,7 @@ "Text(0,0.5,'Detuning Rotation (rad)')" ] }, - "execution_count": 13, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" }, From 133b91b743f132748ad63f5f1a11d662fd9b4875 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Thu, 23 May 2019 20:56:59 +1000 Subject: [PATCH 17/42] module docstring fixed --- qctrlopencontrols/driven_controls/driven_control.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qctrlopencontrols/driven_controls/driven_control.py b/qctrlopencontrols/driven_controls/driven_control.py index 7a593537..18043bb3 100644 --- a/qctrlopencontrols/driven_controls/driven_control.py +++ b/qctrlopencontrols/driven_controls/driven_control.py @@ -13,9 +13,9 @@ # limitations under the License. """ -====================== +=============================== driven_controls.driven_controls -====================== +=============================== """ import json import numpy as np From ac5e0e7c021fa4d46d3f826894910269cfe59f09 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Thu, 23 May 2019 22:04:29 +1000 Subject: [PATCH 18/42] cirq conversion method update with new changes of pre-post gate behaviour --- qctrlopencontrols/cirq/cirq_circuit.py | 50 -------------------------- tests/test_cirq_circuits.py | 43 ++++++++-------------- tests/test_qiskit_sequence.py | 18 +++++++--- 3 files changed, 29 insertions(+), 82 deletions(-) diff --git a/qctrlopencontrols/cirq/cirq_circuit.py b/qctrlopencontrols/cirq/cirq_circuit.py index 51f77446..664bcfd0 100644 --- a/qctrlopencontrols/cirq/cirq_circuit.py +++ b/qctrlopencontrols/cirq/cirq_circuit.py @@ -129,7 +129,6 @@ def _get_rotations(operation): def _get_scheduled_circuit(dynamic_decoupling_sequence, target_qubits, gate_time, - pre_post_gate, add_measurement, device): @@ -145,9 +144,6 @@ def _get_scheduled_circuit(dynamic_decoupling_sequence, cirq.Qid type gate_time : float, optional Time (in seconds) delay introduced by a gate; defaults to 0.1 - pre_post_gate : SingleQubitGate - A SingleQubitGate type (defined in cirq package) defined by a 2x2 - unitary matrix. add_measurement : bool If True, a measurement operation is added to each of the qubits. device : cirq.Device @@ -186,15 +182,6 @@ def _get_scheduled_circuit(dynamic_decoupling_sequence, offsets = offsets * 1e9 circuit_operations = [] - if pre_post_gate is not None: - for qubit in target_qubits: - operation = cirq.ScheduledOperation( - time=cirq.Timestamp(nanos=0), - duration=cirq.Duration(nanos=gate_time), - operation=pre_post_gate(qubit)) - circuit_operations.append(operation) - offsets = offsets + gate_time - offset_count = 0 for op_idx in range(operations.shape[1]): instance_operation = np.array([dynamic_decoupling_sequence.rabi_rotations[op_idx], @@ -240,15 +227,6 @@ def _get_scheduled_circuit(dynamic_decoupling_sequence, offset_count += 1 circuit_operations.append(operation) - if pre_post_gate is not None: - for qubit in target_qubits: - operation = cirq.ScheduledOperation( - time=cirq.Timestamp(nanos=offsets[-1] + gate_time), - duration=cirq.Duration(nanos=gate_time), - operation=pre_post_gate(qubit)) - circuit_operations.append(operation) - offsets = offsets + gate_time - if add_measurement: for idx, qubit in enumerate(target_qubits): operation = cirq.ScheduledOperation( @@ -265,7 +243,6 @@ def _get_scheduled_circuit(dynamic_decoupling_sequence, def _get_standard_circuit(dynamic_decoupling_sequence, target_qubits, gate_time, - pre_post_gate, add_measurement): """Returns a standard circuit constructed from dynamic @@ -280,9 +257,6 @@ def _get_standard_circuit(dynamic_decoupling_sequence, cirq.Qid type gate_time : float, optional Time (in seconds) delay introduced by a gate; defaults to 0.1 - pre_post_gate : SingleQubitGate - A SingleQubitGate type (defined in cirq package) defined by a 2x2 - unitary matrix. add_measurement : bool If True, a measurement operation is added to each of the qubits. @@ -307,12 +281,6 @@ def _get_standard_circuit(dynamic_decoupling_sequence, circuit = cirq.Circuit() - if pre_post_gate is not None: - gate_list = [] - for qubit in target_qubits: - gate_list.append(pre_post_gate(qubit)) - circuit.append(gate_list) - offset_count = 0 for gate in circuit_gate_list: @@ -354,12 +322,6 @@ def _get_standard_circuit(dynamic_decoupling_sequence, offset_count += 1 circuit.append(gate_list) - if pre_post_gate is not None: - gate_list = [] - for qubit in target_qubits: - gate_list.append(pre_post_gate(qubit)) - circuit.append(gate_list) - if add_measurement: gate_list = [] for idx, qubit in enumerate(target_qubits): @@ -373,7 +335,6 @@ def convert_dds_to_cirq_circuit( dynamic_decoupling_sequence, target_qubits=None, gate_time=0.1, - pre_post_gate_unitary_matrix=DEFAULT_PRE_POST_ROTATION_MATRIX, add_measurement=True, circuit_type=STANDARD_CIRCUIT, device=None): @@ -391,10 +352,6 @@ def convert_dds_to_cirq_circuit( qubit is used (indexed as 0). gate_time : float, optional Time (in seconds) delay introduced by a gate; defaults to 0.1 - pre_post_gate_unitary_matrix : numpy.ndarray or None, optional - A 2x2 unitary matrix as pre-post gate operations. Defaults to - the unitary matrix corresponding to a rotation of :math:'\\pi/2' around - X-axis. If None, pre-post gate is omitted from the circuit. add_measurement : bool, optional If True, the circuit contains a measurement operation for each of the target qubits. Measurement from each of the qubits is associated @@ -474,11 +431,6 @@ def convert_dds_to_cirq_circuit( if target_qubits is None: target_qubits = [cirq.LineQubit(0)] - if pre_post_gate_unitary_matrix is None: - pre_post_gate = None - else: - pre_post_gate = cirq.SingleQubitMatrixGate(pre_post_gate_unitary_matrix) - if circuit_type not in [SCHEDULED_CIRCUIT, STANDARD_CIRCUIT]: raise ArgumentsValueError('Circuit type must be one of {} or {}'.format( SCHEDULED_CIRCUIT, STANDARD_CIRCUIT), {'algorithm': circuit_type}) @@ -487,7 +439,6 @@ def convert_dds_to_cirq_circuit( return _get_standard_circuit(dynamic_decoupling_sequence=dynamic_decoupling_sequence, target_qubits=target_qubits, gate_time=gate_time, - pre_post_gate=pre_post_gate, add_measurement=add_measurement) if device is None: @@ -500,6 +451,5 @@ def convert_dds_to_cirq_circuit( return _get_scheduled_circuit(dynamic_decoupling_sequence=dynamic_decoupling_sequence, target_qubits=target_qubits, gate_time=gate_time, - pre_post_gate=pre_post_gate, add_measurement=add_measurement, device=device) diff --git a/tests/test_cirq_circuits.py b/tests/test_cirq_circuits.py index b88797eb..bfe7e3bc 100644 --- a/tests/test_cirq_circuits.py +++ b/tests/test_cirq_circuits.py @@ -25,9 +25,9 @@ new_predefined_dds, convert_dds_to_cirq_circuit) -def _create_test_sequence(sequence_scheme): +def _create_test_sequence(sequence_scheme, pre_post_rotation): - """Create a DD sequence of choice + """Create a DD sequence of choice''' Parameters ---------- @@ -36,6 +36,8 @@ def _create_test_sequence(sequence_scheme): 'Uhrig single-axis', 'Periodic single-axis', 'Walsh single-axis', 'Quadratic', 'X concatenated', 'XY concatenated' + pre_post_rotation : bool + If True, adds a :math:`X_{\\pi/2}` gate on either ends Returns ------- @@ -47,6 +49,7 @@ def _create_test_sequence(sequence_scheme): dd_sequence_params = dict() dd_sequence_params['scheme'] = sequence_scheme dd_sequence_params['duration'] = 4 + dd_sequence_params['pre_post_rotation'] = pre_post_rotation # 'spin_echo' does not need any additional parameter @@ -75,8 +78,8 @@ def _create_test_sequence(sequence_scheme): return sequence -def _check_circuit_output(pre_post_gate_unitary_matrix, - circuit_type, expected_result): +def _check_circuit_output(pre_post_rotation, + circuit_type, expected_state): """Check the outcome of a circuit against expected outcome """ @@ -85,14 +88,13 @@ def _check_circuit_output(pre_post_gate_unitary_matrix, 'Uhrig single-axis', 'periodic single-axis', 'Walsh single-axis', 'quadratic', 'X concatenated', 'XY concatenated']: - sequence = _create_test_sequence(sequence_scheme) + sequence = _create_test_sequence(sequence_scheme, pre_post_rotation) cirq_circuit = convert_dds_to_cirq_circuit( dynamic_decoupling_sequence=sequence, - pre_post_gate_unitary_matrix=pre_post_gate_unitary_matrix, add_measurement=True, circuit_type=circuit_type) results = simulator.run(cirq_circuit) - assert results.measurements['qubit-0'] == expected_result + assert results.measurements['qubit-0'] == expected_state def test_cirq_circuit_operation(): @@ -100,27 +102,12 @@ def test_cirq_circuit_operation(): """Tests if the Dynamic Decoupling Sequence gives rise to expected state with different pre-post gates parameters in cirq circuits """ - _check_circuit_output(None, 'scheduled circuit', 0) - pre_post_gate_unitary_matrix = (1. / np.power(2, 0.5)) * np.array( - [[1, -1j], [-1j, 1]], dtype='complex') - _check_circuit_output(pre_post_gate_unitary_matrix, - 'scheduled circuit', 1) - - pre_post_gate_unitary_matrix = np.array( - [[1, 0], [0, 1]], dtype='complex') - _check_circuit_output(pre_post_gate_unitary_matrix, - 'scheduled circuit', 0) - - _check_circuit_output(None, 'standard circuit', 0) - pre_post_gate_unitary_matrix = (1. / np.power(2, 0.5)) * np.array( - [[1, -1j], [-1j, 1]], dtype='complex') - _check_circuit_output(pre_post_gate_unitary_matrix, - 'standard circuit', 1) - - pre_post_gate_unitary_matrix = np.array( - [[1, 0], [0, 1]], dtype='complex') - _check_circuit_output(pre_post_gate_unitary_matrix, - 'standard circuit', 0) + _check_circuit_output(False, 'scheduled circuit', 0) + _check_circuit_output(True, 'scheduled circuit', 1) + + _check_circuit_output(False, 'standard circuit', 0) + _check_circuit_output(True, 'standard circuit', 1) + if __name__ == '__main__': pass diff --git a/tests/test_qiskit_sequence.py b/tests/test_qiskit_sequence.py index 01125901..c4c95fde 100644 --- a/tests/test_qiskit_sequence.py +++ b/tests/test_qiskit_sequence.py @@ -66,19 +66,21 @@ def _create_test_sequence(sequence_scheme, pre_post_rotation): elif dd_sequence_params['scheme'] in ['quadratic']: + dd_sequence_params['duration'] = 16 dd_sequence_params['number_outer_offsets'] = 4 dd_sequence_params['number_inner_offsets'] = 4 elif dd_sequence_params['scheme'] in ['X concatenated', 'XY concatenated']: + dd_sequence_params['duration'] = 16 dd_sequence_params['concatenation_order'] = 2 sequence = new_predefined_dds(**dd_sequence_params) return sequence -def _check_circuit_unitary(pre_post_rotation, multiplier): +def _check_circuit_unitary(pre_post_rotation, multiplier, algorithm): """Check the unitary of a dynamic decoupling operation """ @@ -93,7 +95,7 @@ def _check_circuit_unitary(pre_post_rotation, multiplier): sequence = _create_test_sequence(sequence_scheme, pre_post_rotation) quantum_circuit = convert_dds_to_quantum_circuit( dynamic_decoupling_sequence=sequence, - add_measurement=False, algorithm='instant unitary') + add_measurement=False, algorithm=algorithm) job = execute(quantum_circuit, backend_simulator, @@ -113,10 +115,18 @@ def test_identity_operation(): operation in Qiskit """ _multiplier = np.array([[1, 0], [0, 1]]) - _check_circuit_unitary(False, _multiplier) + _check_circuit_unitary(False, _multiplier, 'instant unitary') _multiplier = (1. / np.power(2, 0.5)) * np.array([[1, -1j], [-1j, 1]], dtype='complex') - _check_circuit_unitary(True, _multiplier) + _check_circuit_unitary(True, _multiplier, 'instant unitary') + + _multiplier = np.array([[1, 0], [0, 1]]) + _check_circuit_unitary(False, _multiplier, 'fixed duration unitary') + + _multiplier = (1. / np.power(2, 0.5)) * np.array([[1, -1j], [-1j, 1]], dtype='complex') + _check_circuit_unitary(True, _multiplier, 'fixed duration unitary') + + if __name__ == '__main__': pass From b59cab6d65d5ae883e143d278300495bb3a4cbc3 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Thu, 23 May 2019 22:11:47 +1000 Subject: [PATCH 19/42] cirq example notebook updated with pre-post gate behaviour --- examples/running_a_dds_on_cirq.ipynb | 33 ++++++++++++++++------------ 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/examples/running_a_dds_on_cirq.ipynb b/examples/running_a_dds_on_cirq.ipynb index 472c5dd6..2104297c 100644 --- a/examples/running_a_dds_on_cirq.ipynb +++ b/examples/running_a_dds_on_cirq.ipynb @@ -20,7 +20,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -50,7 +50,7 @@ "\n", "Converting a DDS into a `cirq.Circuit` or `cirq.Schedule` is an approximate process where the instantaneous unitaries are replaced with finite duration gates. Moreover, in `cirq.Circuit`, the pauses in-between unitaries are replaced with the closest integer number of identity gates. The exact algorithm used to make this approximation is documented in the [source code](../qctrlopencontrols/cirq/cirq_circuit.py).\n", "\n", - "In this example we will define a Quadratic DDS and convert it into a circuit that we can later run on a simulator. See [creating_a_DDS.ipynb](creating_a_DDS.ipynb) to see how other sequences can be created." + "In this example we will define a Quadratic DDS and convert it into a circuit that we can later run on a simulator. We add a $X_{\\pi/2}$ rotation at either end of the sequence. See [creating_a_DDS.ipynb](creating_a_DDS.ipynb) to see how other sequences can be created." ] }, { @@ -62,7 +62,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -72,7 +72,7 @@ "Quadratic sequence:\n", "Duration = 2e-05\n", "Offsets = [0.0,0.06249999999999998,0.18749999999999994,0.24999999999999994,0.37499999999999994,0.6249999999999999,0.7499999999999999,0.8124999999999999,0.9375,1.0] x 2e-05\n", - "Rabi Rotations = [0.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,0.0] x pi\n", + "Rabi Rotations = [0.5,0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,0.5] x pi\n", "Azimuthal Angles = [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0] x pi\n", "Detuning Rotations = [0.0,1.0,1.0,0.0,1.0,1.0,0.0,1.0,1.0,0.0] x pi\n" ] @@ -85,6 +85,7 @@ " duration=20e-6, \n", " number_inner_offsets=2,\n", " number_outer_offsets=2,\n", + " pre_post_rotation=True,\n", " name='Quadratic sequence')\n", "print(quadratic_sequence)" ] @@ -104,7 +105,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -160,12 +161,12 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 5, "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -228,17 +229,14 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - " ┌ ┐ ┌ ┐\n", - "0: ─│0.707+0.j 0. -0.707j│─I─I─I─I─Rz(π)─I─I─I─I─I─Rz(π)─I─I─Rx(π)─I─I─I─I─I─Rz(π)─I─I─I─I─I─I─I─I─I─I─I─Rz(π)─I─I─I─I─I─Rx(π)─I─I─Rz(π)─I─I─I─I─I─Rz(π)─I─I─I─│0.707+0.j 0. -0.707j│─M('qubit-0')─\n", - " │0. -0.707j 0.707+0.j │ │0. -0.707j 0.707+0.j │\n", - " └ ┘ └ ┘\n" + "0: ─Rx(0.5π)─I─I─Rz(π)─I─I─I─I─I─Rz(π)─I─I─Rx(π)─I─I─I─I─I─Rz(π)─I─I─I─I─I─I─I─I─I─I─I─Rz(π)─I─I─I─I─I─Rx(π)─I─I─Rz(π)─I─I─I─I─I─Rz(π)─I─I─Rx(0.5π)─M('qubit-0')─\n" ] } ], @@ -258,7 +256,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -302,7 +300,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -346,6 +344,13 @@ "#you can also collect the outcome as histogram (calculated as dict)\n", "print(result.histogram(key=['qubit-0']))" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { From 0f03a7dc57ed37a056272375991214ea91ee41dc Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Thu, 23 May 2019 22:51:27 +1000 Subject: [PATCH 20/42] linted --- examples/running_a_dds_on_cirq.ipynb | 14 +- qctrlopencontrols/cirq/__init__.py | 3 +- qctrlopencontrols/cirq/cirq_circuit.py | 3 +- qctrlopencontrols/cirq/constants.py | 7 - .../predefined.py | 335 +++++++----------- qctrlopencontrols/qiskit/constants.py | 5 - tests/test_cirq_circuits.py | 1 - tests/test_dynamical_decoupling.py | 2 +- 8 files changed, 131 insertions(+), 239 deletions(-) diff --git a/examples/running_a_dds_on_cirq.ipynb b/examples/running_a_dds_on_cirq.ipynb index 2104297c..88f61ef1 100644 --- a/examples/running_a_dds_on_cirq.ipynb +++ b/examples/running_a_dds_on_cirq.ipynb @@ -20,7 +20,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -62,7 +62,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -105,7 +105,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -161,7 +161,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -229,7 +229,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "metadata": {}, "outputs": [ { @@ -256,7 +256,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -300,7 +300,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 7, "metadata": {}, "outputs": [ { diff --git a/qctrlopencontrols/cirq/__init__.py b/qctrlopencontrols/cirq/__init__.py index 381efad9..08a16ea0 100644 --- a/qctrlopencontrols/cirq/__init__.py +++ b/qctrlopencontrols/cirq/__init__.py @@ -18,6 +18,5 @@ ============= """ -from .constants import (SCHEDULED_CIRCUIT, STANDARD_CIRCUIT, - DEFAULT_PRE_POST_ROTATION_MATRIX) +from .constants import (SCHEDULED_CIRCUIT, STANDARD_CIRCUIT) from .cirq_circuit import convert_dds_to_cirq_circuit diff --git a/qctrlopencontrols/cirq/cirq_circuit.py b/qctrlopencontrols/cirq/cirq_circuit.py index 664bcfd0..3f53eb4a 100644 --- a/qctrlopencontrols/cirq/cirq_circuit.py +++ b/qctrlopencontrols/cirq/cirq_circuit.py @@ -25,8 +25,7 @@ from qctrlopencontrols.dynamic_decoupling_sequences import DynamicDecouplingSequence from qctrlopencontrols.exceptions import ArgumentsValueError -from .constants import (SCHEDULED_CIRCUIT, STANDARD_CIRCUIT, - DEFAULT_PRE_POST_ROTATION_MATRIX) +from .constants import (SCHEDULED_CIRCUIT, STANDARD_CIRCUIT) def _get_circuit_gate_list(dynamic_decoupling_sequence, diff --git a/qctrlopencontrols/cirq/constants.py b/qctrlopencontrols/cirq/constants.py index 437f61c6..42c292b2 100644 --- a/qctrlopencontrols/cirq/constants.py +++ b/qctrlopencontrols/cirq/constants.py @@ -18,8 +18,6 @@ ===================== """ -import numpy as np - SCHEDULED_CIRCUIT = 'scheduled circuit' """Constructs the circuit as schedule of rotation operations at specified offsets. Scheduled circuit @@ -30,8 +28,3 @@ """Constructs the circuit as a series of operations that include identity gates between desired rotation operations. """ - -DEFAULT_PRE_POST_ROTATION_MATRIX = (1. / np.power(2, 0.5)) * np.array( - [[1, -1j], [-1j, 1]], dtype='complex') -"""Unitary matrix for a :math:`\\pi/2` rotation around X-axis. -""" diff --git a/qctrlopencontrols/dynamic_decoupling_sequences/predefined.py b/qctrlopencontrols/dynamic_decoupling_sequences/predefined.py index 18abf173..9eb04741 100644 --- a/qctrlopencontrols/dynamic_decoupling_sequences/predefined.py +++ b/qctrlopencontrols/dynamic_decoupling_sequences/predefined.py @@ -22,7 +22,6 @@ from qctrlopencontrols.exceptions import ArgumentsValueError - from .constants import (RAMSEY, SPIN_ECHO, CARR_PURCELL, CARR_PURCELL_MEIBOOM_GILL, UHRIG_SINGLE_AXIS, @@ -106,6 +105,32 @@ def new_predefined_dds(scheme=SPIN_ECHO, **kwargs): return sequence +def _check_duration(duration): + + """Validates sequence duration + Parameters + ---------- + duration : float, optional + Total duration of the sequence. Defaults to None + + Returns + ------- + float + The validated duration + + Raises + ------ + ArgumentsValueError + If the duration is negative + """ + if duration is None: + duration = 1. + if duration <= 0.: + raise ArgumentsValueError('Sequence duration must be above zero:', + {'duration': duration}) + return duration + + def new_ramsey_sequence(duration=None, pre_post_rotation=False, **kwargs): @@ -134,12 +159,11 @@ def new_ramsey_sequence(duration=None, Raised when an argument is invalid. """ - if duration is None: - duration = 1. - if duration <= 0.: - raise ArgumentsValueError( - 'Sequence duration must be above zero:', - {'duration': duration}) + duration = _check_duration(duration) + offsets = [] + rabi_rotations = [] + azimuthal_angles = [] + detuning_rotations = [] if pre_post_rotation: offsets = duration * np.array([0.0, 1.]) @@ -147,12 +171,6 @@ def new_ramsey_sequence(duration=None, azimuthal_angles = np.zeros(offsets.shape) detuning_rotations = np.zeros(offsets.shape) - else: - offsets = [] - rabi_rotations = [] - azimuthal_angles = [] - detuning_rotations = [] - return DynamicDecouplingSequence( duration=duration, offsets=offsets, rabi_rotations=rabi_rotations, @@ -189,23 +207,17 @@ def new_spin_echo_sequence(duration=None, Raised when an argument is invalid. """ - if duration is None: - duration = 1. - if duration <= 0.: - raise ArgumentsValueError( - 'Sequence duration must be above zero:', - {'duration': duration}) + duration = _check_duration(duration) + offsets = duration * np.array([0.5]) + rabi_rotations = np.array([np.pi]) if pre_post_rotation: - offsets = duration * np.array([0., 0.5, 1.]) - rabi_rotations = np.array([np.pi/2, np.pi, np.pi/2]) - azimuthal_angles = np.zeros(offsets.shape) - detuning_rotations = np.zeros(offsets.shape) - else: - offsets = duration * np.array([0.5]) - rabi_rotations = np.array([np.pi]) - azimuthal_angles = np.zeros(offsets.shape) - detuning_rotations = np.zeros(offsets.shape) + offsets = np.insert(offsets, [0, offsets.shape[0]], [0, duration]) + rabi_rotations = np.insert(rabi_rotations, [0, rabi_rotations.shape[0]], + [np.pi/2, np.pi/2]) + + azimuthal_angles = np.zeros(offsets.shape) + detuning_rotations = np.zeros(offsets.shape) return DynamicDecouplingSequence( duration=duration, offsets=offsets, @@ -245,13 +257,7 @@ def new_carr_purcell_sequence(duration=None, ArgumentsValueError Raised when an argument is invalid. """ - if duration is None: - duration = 1. - if duration <= 0.: - raise ArgumentsValueError( - 'Sequence duration must be above zero:', - {'duration': duration}) - + duration = _check_duration(duration) if number_of_offsets is None: number_of_offsets = 1 number_of_offsets = int(number_of_offsets) @@ -262,25 +268,16 @@ def new_carr_purcell_sequence(duration=None, offsets = _carr_purcell_meiboom_gill_offsets(duration, number_of_offsets) - if pre_post_rotation: - offsets = np.append([0], offsets) - offsets = np.append(offsets, [duration]) - - rabi_rotations = np.zeros(offsets.shape) - azimuthal_angles = np.zeros(offsets.shape) - detuning_rotations = np.zeros(offsets.shape) - - rabi_rotations[0] = np.pi/2 - rabi_rotations[-1] = np.pi/2 - rabi_rotations[1:-1] = np.pi - else: - - rabi_rotations = np.zeros(offsets.shape) - azimuthal_angles = np.zeros(offsets.shape) - detuning_rotations = np.zeros(offsets.shape) + rabi_rotations = np.zeros(offsets.shape) + # set all as X_pi + rabi_rotations[0:] = np.pi - # set all as X_pi - rabi_rotations[0:] = np.pi + if pre_post_rotation: + offsets = np.insert(offsets, [0, offsets.shape[0]], [0, duration]) + rabi_rotations = np.insert(rabi_rotations, [0, rabi_rotations.shape[0]], + [np.pi/2, np.pi/2]) + azimuthal_angles = np.zeros(offsets.shape) + detuning_rotations = np.zeros(offsets.shape) return DynamicDecouplingSequence( duration=duration, offsets=offsets, @@ -317,13 +314,7 @@ def new_carr_purcell_meiboom_gill_sequence(duration=None, # pylint: disable=inv ArgumentsValueError Raised when an argument is invalid. """ - if duration is None: - duration = 1. - if duration <= 0.: - raise ArgumentsValueError( - 'Sequence duration must be above zero:', - {'duration': duration}) - + duration = _check_duration(duration) if number_of_offsets is None: number_of_offsets = 1 number_of_offsets = int(number_of_offsets) @@ -333,28 +324,20 @@ def new_carr_purcell_meiboom_gill_sequence(duration=None, # pylint: disable=inv {'number_of_offsets': number_of_offsets}) offsets = _carr_purcell_meiboom_gill_offsets(duration, number_of_offsets) + rabi_rotations = np.zeros(offsets.shape) + azimuthal_angles = np.zeros(offsets.shape) - if pre_post_rotation: - offsets = np.append([0], offsets) - offsets = np.append(offsets, [duration]) - - rabi_rotations = np.zeros(offsets.shape) - azimuthal_angles = np.zeros(offsets.shape) - detuning_rotations = np.zeros(offsets.shape) - - rabi_rotations[0] = np.pi/2 - rabi_rotations[-1] = np.pi/2 - rabi_rotations[1:-1] = np.pi - azimuthal_angles[1:-1] = np.pi/2 - else: - - rabi_rotations = np.zeros(offsets.shape) - azimuthal_angles = np.zeros(offsets.shape) - detuning_rotations = np.zeros(offsets.shape) + # set all azimuthal_angles=pi/2, rabi_rotations = pi + rabi_rotations[0:] = np.pi + azimuthal_angles[0:] = np.pi / 2 - # set all azimuthal_angles=pi/2, rabi_rotations = pi - rabi_rotations[0:] = np.pi - azimuthal_angles[0:] = np.pi/2 + if pre_post_rotation: + offsets = np.insert(offsets, [0, offsets.shape[0]], [0, duration]) + rabi_rotations = np.insert(rabi_rotations, [0, rabi_rotations.shape[0]], + [np.pi/2, np.pi/2]) + azimuthal_angles = np.insert(azimuthal_angles, [0, azimuthal_angles.shape[0]], + [0, 0]) + detuning_rotations = np.zeros(offsets.shape) return DynamicDecouplingSequence( duration=duration, offsets=offsets, @@ -393,44 +376,29 @@ def new_uhrig_single_axis_sequence(duration=None, number_of_offsets=None, ArgumentsValueError Raised when an argument is invalid. """ - if duration is None: - duration = 1. - if duration <= 0.: - raise ArgumentsValueError( - 'Sequence duration must be above zero:', - {'duration': duration}) - + duration = _check_duration(duration) if number_of_offsets is None: number_of_offsets = 1 number_of_offsets = int(number_of_offsets) if number_of_offsets <= 0.: - raise ArgumentsValueError( - 'Number of offsets must be above zero:', - {'number_of_offsets': number_of_offsets}) + raise ArgumentsValueError('Number of offsets must be above zero:', + {'number_of_offsets': number_of_offsets}) offsets = _uhrig_single_axis_offsets(duration, number_of_offsets) + rabi_rotations = np.zeros(offsets.shape) + azimuthal_angles = np.zeros(offsets.shape) - if pre_post_rotation: - offsets = np.append([0], offsets) - offsets = np.append(offsets, [duration]) - - rabi_rotations = np.zeros(offsets.shape) - azimuthal_angles = np.zeros(offsets.shape) - detuning_rotations = np.zeros(offsets.shape) - - rabi_rotations[0] = np.pi/2 - rabi_rotations[-1] = np.pi/2 - rabi_rotations[1:-1] = np.pi - azimuthal_angles[1:-1] = np.pi/2 - else: - - rabi_rotations = np.zeros(offsets.shape) - azimuthal_angles = np.zeros(offsets.shape) - detuning_rotations = np.zeros(offsets.shape) + # set all azimuthal_angles=pi/2, rabi_rotations = pi + rabi_rotations[0:] = np.pi + azimuthal_angles[0:] = np.pi / 2 - # set all azimuthal_angles=pi/2, rabi_rotations = pi - rabi_rotations[0:] = np.pi - azimuthal_angles[0:] = np.pi/2 + if pre_post_rotation: + offsets = np.insert(offsets, [0, offsets.shape[0]], [0, duration]) + rabi_rotations = np.insert(rabi_rotations, [0, rabi_rotations.shape[0]], + [np.pi/2, np.pi/2]) + azimuthal_angles = np.insert(azimuthal_angles, [0, azimuthal_angles.shape[0]], + [0, 0]) + detuning_rotations = np.zeros(offsets.shape) return DynamicDecouplingSequence( duration=duration, offsets=offsets, @@ -470,45 +438,27 @@ def new_periodic_single_axis_sequence(duration=None, # pylint: disable=invali ArgumentsValueError Raised when an argument is invalid. """ - if duration is None: - duration = 1. - if duration <= 0.: - raise ArgumentsValueError( - 'Sequence duration must be above zero:', - {'duration': duration}) - + duration = _check_duration(duration) if number_of_offsets is None: number_of_offsets = 1 number_of_offsets = int(number_of_offsets) if number_of_offsets <= 0.: - raise ArgumentsValueError( - 'Number of offsets must be above zero:', - {'number_of_offsets': number_of_offsets}) + raise ArgumentsValueError('Number of offsets must be above zero:', + {'number_of_offsets': number_of_offsets}) spacing = 1./(number_of_offsets+1) - # prepare the offsets for delta comb deltas = [k*spacing for k in range(1, number_of_offsets+1)] deltas = np.array(deltas) offsets = duration * deltas + rabi_rotations = np.zeros(offsets.shape) + rabi_rotations[0:] = np.pi if pre_post_rotation: - offsets = np.append([0], offsets) - offsets = np.append(offsets, [duration]) - - rabi_rotations = np.zeros(offsets.shape) - azimuthal_angles = np.zeros(offsets.shape) - detuning_rotations = np.zeros(offsets.shape) - - rabi_rotations[0] = np.pi/2 - rabi_rotations[-1] = np.pi/2 - rabi_rotations[1:-1] = np.pi - else: - - rabi_rotations = np.zeros(offsets.shape) - azimuthal_angles = np.zeros(offsets.shape) - detuning_rotations = np.zeros(offsets.shape) - - rabi_rotations[0:] = np.pi + offsets = np.insert(offsets, [0, offsets.shape[0]], [0, duration]) + rabi_rotations = np.insert(rabi_rotations, [0, rabi_rotations.shape[0]], + [np.pi / 2, np.pi / 2]) + azimuthal_angles = np.zeros(offsets.shape) + detuning_rotations = np.zeros(offsets.shape) return DynamicDecouplingSequence( duration=duration, offsets=offsets, @@ -548,13 +498,7 @@ def new_walsh_single_axis_sequence(duration=None, ArgumentsValueError Raised when an argument is invalid. """ - if duration is None: - duration = 1. - if duration <= 0.: - raise ArgumentsValueError( - 'Sequence duration must be above zero:', - {'duration': duration}) - + duration = _check_duration(duration) if paley_order is None: paley_order = 1 paley_order = int(paley_order) @@ -582,25 +526,17 @@ def new_walsh_single_axis_sequence(duration=None, walsh_relative_offsets.append((i + 1) * (1. / samples)) walsh_relative_offsets = np.array(walsh_relative_offsets, dtype=np.float) offsets = duration * walsh_relative_offsets + rabi_rotations = np.zeros(offsets.shape) - if pre_post_rotation: - offsets = np.append([0], offsets) - offsets = np.append(offsets, [duration]) - - rabi_rotations = np.zeros(offsets.shape) - azimuthal_angles = np.zeros(offsets.shape) - detuning_rotations = np.zeros(offsets.shape) - - rabi_rotations[0] = np.pi/2 - rabi_rotations[-1] = np.pi/2 - rabi_rotations[1:-1] = np.pi - else: + rabi_rotations[0:] = np.pi - rabi_rotations = np.zeros(offsets.shape) - azimuthal_angles = np.zeros(offsets.shape) - detuning_rotations = np.zeros(offsets.shape) + if pre_post_rotation: + offsets = np.insert(offsets, [0, offsets.shape[0]], [0, duration]) + rabi_rotations = np.insert(rabi_rotations, [0, rabi_rotations.shape[0]], + [np.pi / 2, np.pi / 2]) - rabi_rotations[0:] = np.pi + azimuthal_angles = np.zeros(offsets.shape) + detuning_rotations = np.zeros(offsets.shape) return DynamicDecouplingSequence( duration=duration, offsets=offsets, @@ -646,31 +582,25 @@ def new_quadratic_sequence(duration=None, ArgumentsValueError Raised when an argument is invalid. """ - - if duration is None: - duration = 1. - if duration <= 0.: - raise ArgumentsValueError( - 'Sequence duration must be above zero:', - {'duration': duration}) + duration = _check_duration(duration) if number_inner_offsets is None: number_inner_offsets = 1 number_inner_offsets = int(number_inner_offsets) if number_inner_offsets <= 0.: - raise ArgumentsValueError( - 'Number of offsets of inner pulses must be above zero:', - {'number_inner_offsets': number_inner_offsets}, - extras={'duration': duration, 'number_outer_offsets': number_outer_offsets}) + raise ArgumentsValueError('Number of offsets of inner pulses must be above zero:', + {'number_inner_offsets': number_inner_offsets}, + extras={'duration': duration, + 'number_outer_offsets': number_outer_offsets}) if number_outer_offsets is None: number_outer_offsets = 1 number_outer_offsets = int(number_outer_offsets) if number_outer_offsets <= 0.: - raise ArgumentsValueError( - 'Number of offsets of outer pulses must be above zero:', - {'number_inner_offsets': number_outer_offsets}, - extras={'duration': duration, 'number_inner_offsets': number_inner_offsets}) + raise ArgumentsValueError('Number of offsets of outer pulses must be above zero:', + {'number_inner_offsets': number_outer_offsets}, + extras={'duration': duration, + 'number_inner_offsets': number_inner_offsets}) outer_offsets = _uhrig_single_axis_offsets(duration, number_outer_offsets) outer_offsets = np.insert(outer_offsets, [0, outer_offsets.shape[0]], [0, duration]) @@ -678,7 +608,6 @@ def new_quadratic_sequence(duration=None, ends = outer_offsets[1:] inner_durations = ends - starts - # inner_offsets = np.zeros((number_outer_offsets + 1, number_inner_offsets)) offsets = np.zeros((inner_durations.shape[0], number_inner_offsets + 1)) for inner_duration_idx in range(inner_durations.shape[0]): inn_off = _uhrig_single_axis_offsets(inner_durations[inner_duration_idx], @@ -693,7 +622,6 @@ def new_quadratic_sequence(duration=None, rabi_rotations[0:number_outer_offsets, -1] = np.pi detuning_rotations[0:(number_outer_offsets + 1), 0:number_inner_offsets] = np.pi - # make all the arrays 1D; offsets = np.reshape(offsets, (-1,)) rabi_rotations = np.reshape(rabi_rotations, (-1,)) detuning_rotations = np.reshape(detuning_rotations, (-1,)) @@ -704,14 +632,11 @@ def new_quadratic_sequence(duration=None, detuning_rotations = detuning_rotations[0:-1] if pre_post_rotation: - offsets = np.append([0], offsets) - offsets = np.append(offsets, [duration]) - - rabi_rotations = np.append([np.pi/2], rabi_rotations) - detuning_rotations = np.append([0.], detuning_rotations) - - rabi_rotations = np.append(rabi_rotations, [np.pi/2]) - detuning_rotations = np.append(detuning_rotations, [0.]) + offsets = np.insert(offsets, [0, offsets.shape[0]], [0, duration]) + rabi_rotations = np.insert(rabi_rotations, [0, rabi_rotations.shape[0]], + [np.pi / 2, np.pi / 2]) + detuning_rotations = np.insert(detuning_rotations, [0, detuning_rotations.shape[0]], + [0, 0]) # finally create the azimuthal angles as all zeros azimuthal_angles = np.zeros(offsets.shape) @@ -757,12 +682,7 @@ def new_x_concatenated_sequence(duration=1.0, ArgumentsValueError Raised when an argument is invalid. """ - if duration is None: - duration = 1. - if duration <= 0.: - raise ArgumentsValueError( - 'Sequence duration must be above zero:', - {'duration': duration}) + duration = _check_duration(duration) if concatenation_order is None: concatenation_order = 1 @@ -787,25 +707,17 @@ def new_x_concatenated_sequence(duration=1.0, offsets = offsets[0:-1] offsets = np.array(offsets) + rabi_rotations = np.zeros(offsets.shape) + rabi_rotations[0:] = np.pi if pre_post_rotation: - offsets = np.append([0], offsets) - offsets = np.append(offsets, [duration]) - - rabi_rotations = np.zeros(offsets.shape) - azimuthal_angles = np.zeros(offsets.shape) - detuning_rotations = np.zeros(offsets.shape) - - rabi_rotations[0] = np.pi/2 - rabi_rotations[-1] = np.pi/2 - rabi_rotations[1:-1] = np.pi - else: - - rabi_rotations = np.zeros(offsets.shape) - azimuthal_angles = np.zeros(offsets.shape) - detuning_rotations = np.zeros(offsets.shape) + offsets = np.insert(offsets, [0, offsets.shape[0]], + [0, duration]) + rabi_rotations = np.insert(rabi_rotations, [0, rabi_rotations.shape[0]], + [np.pi / 2, np.pi / 2]) - rabi_rotations[0:] = np.pi + azimuthal_angles = np.zeros(offsets.shape) + detuning_rotations = np.zeros(offsets.shape) return DynamicDecouplingSequence( duration=duration, offsets=offsets, @@ -848,12 +760,7 @@ def new_xy_concatenated_sequence(duration=1.0, ArgumentsValueError Raised when an argument is invalid. """ - if duration is None: - duration = 1. - if duration <= 0.: - raise ArgumentsValueError( - 'Sequence duration must be above zero:', - {'duration': duration}) + duration = _check_duration(duration) if concatenation_order is None: concatenation_order = 1 diff --git a/qctrlopencontrols/qiskit/constants.py b/qctrlopencontrols/qiskit/constants.py index 91618fcd..dba899b3 100644 --- a/qctrlopencontrols/qiskit/constants.py +++ b/qctrlopencontrols/qiskit/constants.py @@ -18,7 +18,6 @@ ================ """ -import numpy as np FIX_DURATION_UNITARY = 'fixed duration unitary' """Algorithm to convert a DDS to Quantum circuit @@ -29,7 +28,3 @@ """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. -""" diff --git a/tests/test_cirq_circuits.py b/tests/test_cirq_circuits.py index bfe7e3bc..289fdf5e 100644 --- a/tests/test_cirq_circuits.py +++ b/tests/test_cirq_circuits.py @@ -18,7 +18,6 @@ =================================== """ -import numpy as np import cirq from qctrlopencontrols import ( diff --git a/tests/test_dynamical_decoupling.py b/tests/test_dynamical_decoupling.py index 96c27468..b0666dc4 100644 --- a/tests/test_dynamical_decoupling.py +++ b/tests/test_dynamical_decoupling.py @@ -377,7 +377,7 @@ def test_free_evolution_conversion(): _rabi_rates = np.array([_maximum_rabi_rate, 0., _maximum_rabi_rate]) _azimuthal_angles = np.array([0, 0, 0]) _detunings = np.array([0, 0, 0]) - _durations = np.array([0.025, 9.95, 0.025]) + _durations = np.array([0.025, 9.95, 0.025]) assert np.allclose(driven_control.rabi_rates, _rabi_rates) assert np.allclose(driven_control.azimuthal_angles, _azimuthal_angles) assert np.allclose(driven_control.detunings, _detunings) From 3c867546c29ddf4f229bb9a86ddd85cc55d5f0e8 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Fri, 24 May 2019 12:00:17 +1000 Subject: [PATCH 21/42] cirq conversion method fixed according to updated behaviour wrt pre-post-gate --- examples/running_a_dds_on_cirq.ipynb | 18 ++++++++++---- examples/running_a_dds_on_ibm_q.ipynb | 21 ++++++++-------- qctrlopencontrols/cirq/cirq_circuit.py | 27 +++++++++++++++++++-- qctrlopencontrols/cirq/constants.py | 10 ++++++++ qctrlopencontrols/qiskit/quantum_circuit.py | 10 ++++---- 5 files changed, 64 insertions(+), 22 deletions(-) diff --git a/examples/running_a_dds_on_cirq.ipynb b/examples/running_a_dds_on_cirq.ipynb index 88f61ef1..95b8554d 100644 --- a/examples/running_a_dds_on_cirq.ipynb +++ b/examples/running_a_dds_on_cirq.ipynb @@ -139,6 +139,14 @@ "'''\n", "circuit_type = 'standard circuit'\n", "\n", + "'''\n", + "algorithm : str\n", + " An optional string to specify the algorithm used to place identity gates.\n", + " Can be 'instant unitary' or 'fixed duration unitary'. See source code\n", + " documentation for more details.\n", + "'''\n", + "algorithm = 'instant unitary'\n", + "\n", "\n", "## convert the quadratic sequence to cirq.Circuit\n", "quadratic_cirq_circuit = convert_dds_to_cirq_circuit(\n", @@ -146,7 +154,8 @@ " target_qubits=target_qubits,\n", " gate_time=gate_time,\n", " add_measurement=add_measurement,\n", - " circuit_type=circuit_type\n", + " circuit_type=circuit_type,\n", + " algorithm=algorithm\n", ")" ] }, @@ -217,12 +226,11 @@ "\n", "We can draw a text diagram of the `cirq.Circuit` generated by Q-CTRL Open Controls.\n", "\n", - "Note that a $X_{\\pi/2}$ rotation will be added at beginning and end, that is, at offsets of $[0, 20]$ $\\mu$s, to create the desired superposition state. The $X_{\\pi/2}$ rotations are not part of the DDS objects but are added to the circuits in the form of pre-post-gates that are implemented via `cirq.SingleQubitGate`. The `SingleQubitGate` is specified by a $2\\times 2$ unitary matrix. In this case, the unitary matrix $\n", - "\\frac{1}{\\sqrt{2}}\\times\\begin{bmatrix}1 & -1j\\\\-1j & 1\\end{bmatrix}$ (corresponding to $X_{\\pi/2}$ rotation) is supplied as default by the conversion method.\n", + "Note that a $X_{\\pi/2}$ rotation will be added at beginning and end, that is, at offsets of $[0, 20]$ $\\mu$s, to create the desired superposition state. The $X_{\\pi/2}$ rotations are implemented using $Rx($0.5\\pi$)$ gate.\n", "\n", "The $Rz(\\pi)$ gates are $Z_\\pi$ pulses (a $\\pi$ rotation around $Z$-axis) and $Rx(\\pi)$ gates correspond to $X_{\\pi}$ pulses (a $\\pi$ rotation around $X$-axis). The gates match the pulses in the DDS.\n", "\n", - "The `I` in the drawing corresponds to the `identity` gate. In the DDS, the first $Z_{\\pi}$-pulse is applied at a delay of $1.25$ $\\mu$s. This is approximated by introducing 3-`Id` gates with a delay of $0.4\\times 3=1.2$ $\\mu$s. Application of $Z_{\\pi}$ pulse will take another $0.4\\mu$s. Similarly, the second set of 5 `Id` gates introduces a delay of $2$ $\\mu$s close to the actual delay of $3.75-1.65=2.10$ microseconds.\n", + "The `I` in the drawing corresponds to the `identity` gate. In the DDS, the first $Z_{\\pi}$-pulse is applied at a delay of $1.25$ $\\mu$s. This is approximated by introducing 3-`Id` gates with a delay of $0.4\\times 3=1.2$ $\\mu$s. Similarly, the second set of 6 Id gates introduces a delay of 2.4 𝜇 s close to the actual delay of 3.75−1.25=2.50 microseconds.\n", "\n", "At the end of the circuit, we placed a `measurement` ($M$) operator to read out the result." ] @@ -236,7 +244,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "0: ─Rx(0.5π)─I─I─Rz(π)─I─I─I─I─I─Rz(π)─I─I─Rx(π)─I─I─I─I─I─Rz(π)─I─I─I─I─I─I─I─I─I─I─I─Rz(π)─I─I─I─I─I─Rx(π)─I─I─Rz(π)─I─I─I─I─I─Rz(π)─I─I─Rx(0.5π)─M('qubit-0')─\n" + "0: ─Rx(0.5π)─I─I─I─Rz(π)─I─I─I─I─I─I─Rz(π)─I─I─I─Rx(π)─I─I─I─I─I─I─Rz(π)─I─I─I─I─I─I─I─I─I─I─I─I─Rz(π)─I─I─I─I─I─I─Rx(π)─I─I─I─Rz(π)─I─I─I─I─I─I─Rz(π)─I─I─I─Rx(0.5π)─M('qubit-0')─\n" ] } ], diff --git a/examples/running_a_dds_on_ibm_q.ipynb b/examples/running_a_dds_on_ibm_q.ipynb index 7c219939..c8bae29c 100755 --- a/examples/running_a_dds_on_ibm_q.ipynb +++ b/examples/running_a_dds_on_ibm_q.ipynb @@ -393,7 +393,7 @@ "« " ], "text/plain": [ - "" + "" ] }, "execution_count": 6, @@ -465,7 +465,7 @@ "« " ], "text/plain": [ - "" + "" ] }, "execution_count": 7, @@ -626,11 +626,12 @@ "account_token : str\n", " Token to enable IBM Q device access\n", "'''\n", - "account_token = 'insert_your_ibm_token_here'\n", + "account_token = 'insert-your-ibmq-token-here'\n", "IBMQ.enable_account(account_token)\n", "available_devices = IBMQ.backends(\n", " filters=lambda x: not x.configuration().simulator and x.status().operational is True\n", ")\n", + "#print(available_devices)\n", "backend = least_busy(available_devices)\n", "print('Least busy device is {}'.format(backend.name()))" ] @@ -644,7 +645,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -656,12 +657,12 @@ }, { "data": { - "image/png": "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q+dn5kkH69fVu3ALi4jzgJuAC/aGJ0BmzgPmteg3l9JW6CeBv+rqOiVJvUNXnkT0ItAMDG/VPhw44PHLiDgf+B5wSWY+cKC+mdkMPAWMK16qJEkH1mUBmpm7gPnAjFazZlA6G7dNEfEBSuF5WWbec7DPiYgA/gxoLF6tJEkH1tW7cG8GvhcRvwaeBK4ARgDfAoiI7wJk5iXl6Qsphef/AuZExLHlcXZl5oZyn78FfgksAwZT2m37Z5TO7JUkqVN0aYBm5l0RMRT4G0rXay4GzmpxTLP19aBXUKrxlvJrr18Ap5XfHwPcBhwLbAIWAKdk5q87Yx0kSYJuOIkoM78JfHM/80470PR+lrkauLojapMkqb28F64kSQUYoJIkFWCASpJUgAEqSVIBBqgkSQUYoJIkFWCASpJUgAEqSVIBBqgkSQUYoJIkFWCASpJUgAEqSVIBBqgkSQUYoJIkFWCASpJUgAEqSVIBBqgkSQUYoJIkFWCASpJUgAEqSVIBBqgkSQUYoJIkFWCASpJUgAEqSVIBBqgkSQUYoJIkFWCASpJUgAHayz366KO89a1vZerUqdxyyy2vmr9z504+/OEPM3XqVN71rnexevXqffOWLFnCGWecwbRp03j729/Ojh07ADj//POZPn0606ZN45prrqG5ubnL1keSuooB2os1Nzdz7bXXcvfddzNv3jzuvfdennnmmVf0+f73v88xxxzD/PnzufLKK/niF78IwJ49e/jYxz7GzTffzLx583jggQfo168fAN/5znd4/PHHmTt3Li+++CL3339/V6+aJHU6A7QXmz9/PieccAKjR4+mqqqKc889l4ceeugVfWbNmsWFF14IwPvf/37mzJlDZvLYY48xceJEJk2aBEB1dTV9+vQBYPDgwUApZHfv3k1EdOFaSVLXMEB7scbGRo477rh90yNGjKCxsXG/ffr27cvgwYPZsGEDy5cvJyI477zzOO200/j617/+iuXOO+883vjGN/K6172O97///Z2/MpLUxQxQFbJnzx5++ctfcttttzFr1iwefPBBfvGLX+ybf++991JfX8/OnTuZM2dON1YqSZ3DAO3FampqeO655/ZNr127lpqamv322bNnD5s3b6a6upoRI0Zw8sknM3ToUAYOHMiMGTNYuHDhK5Y98sgjOeuss161W1iSDgcGaC/25je/mRUrVrBq1Sp27drFfffdx7vf/e5X9DnzzDP50Y9+BMBPf/pTpk+fTkRw+umns3TpUrZt28aePXuYO3cub3rTm3jppZd4/vnngVLgPvLII4wbN67L102SOlvf7i5A3adv377MnDmT888/n+bmZi666CJqa2u58cYbqaur48wzz+Tiiy/miiuuYOrUqQwZMoRvf/vbABxzzDFcddVVnH766UQEM2bM4IwzzuCFF17goosuYufOnbz88stMnz6dD33oQ928ppLU8SIzu7uGblNXV5ezZ8/u7jIkdbFr7xzS3SWoE8y8dGOHjFNdXT0/M086WD934UqSVIC7cDuAf80enjrqr1lJhye3QCVJKsAAlSSpAANUkqQCDFBJkgowQCVJKsAAlSSpAANUkqQCDFBJkgowQCVJKsAAlSSpAANUkqQCujxAI+KqiHg2InZExPyImH6Q/qeW++2IiBURccVrHVOSpNeqSwM0Ii4AbgVuBOqAucBDETFqP/1PAGaV+9UBfwd8IyLOKzqmJEkdoau3QK8B7sjM2zOzPjM/CTQCV+6n/xXA2sz8ZLn/7cCdwP96DWNKkvSadVmARkQVMBV4pNWsR4CT97PYtDb6PwycFBH9Co4pSdJr1pXPA/0ToA+wrlX7OuBd+1nmWODRNvr3LY8XlY4ZEZcDl5cnX6qurm5oT/Ha50+AF7u7iK7w7au7uwKpQ/g7W7nj29Op1z1QOzNvA27r7joOVRHxVGae1N11SGoff2c7T1cG6ItAMzC8Vftw4Pn9LPP8fvrvKY8XBcaUJOk167JjoJm5C5gPzGg1awalM2fbMm8//Z/KzN0Fx5Qk6TXr6l24NwPfi4hfA09SOst2BPAtgIj4LkBmXlLu/y3gExFxC/BPwNuBy4APtndMdTh3f0uHFn9nO0lkZtd+YMRVwLVADbAYuDoz55Tn/RwgM09r0f9U4B+AicBa4O8z81vtHVOSpM7Q5QEqSdLhwHvhSpJUgAEqSVIBBqgOKiLGRUTrS4UkqVfzGKjaFBF/CvwFcDXQROna20bgHuDezNzajeVJUrczQNWmiLgDmAA8CKwHhgInArXAGmBmZv6s2wqUpG5mgOpVIiKALcBZLS4xCmAk8Dbgo5TuFXlBZv6m2wqV9AoRMRjYkv6PvUt4DFRtmQA8C+za25Alv8/MHwP/g1LAXtBN9Ulq203AhyNicjlMXyUihnZxTYctA1RtWQG8APxD+QSiV/x3Ur6F4p3Amd1RnKRXi4gPUto79DXgp8BNEXFORLwhIgaU+wwA/jkiJndjqYcNd+GqTRHxNkq3Q9xO6TaK/wFszMyXImIg8F1gR2Ze3I1lSiqLiNspPVxjJnAucCnwBqABmEXpd3g8cGtmVnVXnYcTA1T7FRGTgOuA9wFbKd3cv4nSs1YbgY9k5qLuq1ASQET0pXQ708GZ+dkW7RMpbZWeDxwJHAPcmZl/2S2FHmYMUB1U+ZKW9wBnAzso3W/4x5n5TLcWJmmfiBgCDM/MZyKiCtjd8mSiiLgA+FdW9rhEAAAAcElEQVTgzZ781zEMUFUkIo7IzJe7uw5JB1c+fyEyszkiPkpp9+3A7q7rcNHVjzPTIc7wlA4drX5fBwF/2121HI7cApWkXiAi+gHN/hHccQxQSZIK8DpQSZIKMEAlSSrAAJUkqQADVJKkAgxQSZIK+P/6pPSmsTQnSQAAAABJRU5ErkJggg==\n", + "image/png": "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\n", "text/plain": [ "
" ] }, - "execution_count": 13, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -685,7 +686,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -697,12 +698,12 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] }, - "execution_count": 14, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -735,7 +736,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 16, "metadata": { "scrolled": true }, diff --git a/qctrlopencontrols/cirq/cirq_circuit.py b/qctrlopencontrols/cirq/cirq_circuit.py index 3f53eb4a..6027acdd 100644 --- a/qctrlopencontrols/cirq/cirq_circuit.py +++ b/qctrlopencontrols/cirq/cirq_circuit.py @@ -25,7 +25,8 @@ from qctrlopencontrols.dynamic_decoupling_sequences import DynamicDecouplingSequence from qctrlopencontrols.exceptions import ArgumentsValueError -from .constants import (SCHEDULED_CIRCUIT, STANDARD_CIRCUIT) +from .constants import (SCHEDULED_CIRCUIT, STANDARD_CIRCUIT, + FIX_DURATION_UNITARY, INSTANT_UNITARY) def _get_circuit_gate_list(dynamic_decoupling_sequence, @@ -242,6 +243,7 @@ def _get_scheduled_circuit(dynamic_decoupling_sequence, def _get_standard_circuit(dynamic_decoupling_sequence, target_qubits, gate_time, + algorithm, add_measurement): """Returns a standard circuit constructed from dynamic @@ -256,6 +258,12 @@ def _get_standard_circuit(dynamic_decoupling_sequence, cirq.Qid type gate_time : float, optional Time (in seconds) delay introduced by a gate; defaults to 0.1 + algorithm : str, optional + One of 'fixed duration unitary' or 'instant unitary'; In the case of + 'fixed duration unitary', the operations are assumed to be taking the amount of + gate_time while 'instant unitary' assumes unitaries to be instantaneous; + defaults to 'instant unitary'. Note that this option is only used for + 'standard circuit'; 'scheduled circuit' always contains a 'fixed duration unitary'. add_measurement : bool If True, a measurement operation is added to each of the qubits. @@ -272,7 +280,10 @@ def _get_standard_circuit(dynamic_decoupling_sequence, If there is rotations around more than one axis at any of the offsets """ - unitary_time = gate_time + unitary_time = 0. + if algorithm == FIX_DURATION_UNITARY: + unitary_time = gate_time + circuit_gate_list = _get_circuit_gate_list( dynamic_decoupling_sequence=dynamic_decoupling_sequence, gate_time=gate_time, @@ -336,6 +347,7 @@ def convert_dds_to_cirq_circuit( gate_time=0.1, add_measurement=True, circuit_type=STANDARD_CIRCUIT, + algorithm=INSTANT_UNITARY, device=None): """Converts a Dynamic Decoupling Sequence into quantum circuit @@ -368,6 +380,12 @@ def convert_dds_to_cirq_circuit( See `Circuits ` _, `Schedules ` _ and `Simulation ` _. + algorithm : str, optional + One of 'fixed duration unitary' or 'instant unitary'; In the case of + 'fixed duration unitary', the operations are assumed to be taking the amount of + gate_time while 'instant unitary' assumes unitaries to be instantaneous; + defaults to 'instant unitary'. Note that this option is only used for + 'standard circuit'; 'scheduled circuit' always contains a 'fixed duration unitary'. device : cirq.Device, optional A cirq.Device that specifies hardware constraints for validating circuits and schedules. If None, a unconstrained device is used. See `Cirq Documentation @@ -435,9 +453,14 @@ def convert_dds_to_cirq_circuit( SCHEDULED_CIRCUIT, STANDARD_CIRCUIT), {'algorithm': circuit_type}) if circuit_type == STANDARD_CIRCUIT: + 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}) + return _get_standard_circuit(dynamic_decoupling_sequence=dynamic_decoupling_sequence, target_qubits=target_qubits, gate_time=gate_time, + algorithm=algorithm, add_measurement=add_measurement) if device is None: diff --git a/qctrlopencontrols/cirq/constants.py b/qctrlopencontrols/cirq/constants.py index 42c292b2..9090d599 100644 --- a/qctrlopencontrols/cirq/constants.py +++ b/qctrlopencontrols/cirq/constants.py @@ -28,3 +28,13 @@ """Constructs the circuit as a series of operations that include identity gates between desired rotation operations. """ + +FIX_DURATION_UNITARY = 'fixed duration unitary' +"""Algorithm to convert a DDS to Quantum circuit +where the unitaries are considered as gates with finite duration +""" + +INSTANT_UNITARY = 'instant unitary' +"""Algorithm to convert a DDS to Quantum circuit where the +unitaties are considered as instantaneous operation. +""" diff --git a/qctrlopencontrols/qiskit/quantum_circuit.py b/qctrlopencontrols/qiskit/quantum_circuit.py index 1354ffb4..a7e1ee96 100644 --- a/qctrlopencontrols/qiskit/quantum_circuit.py +++ b/qctrlopencontrols/qiskit/quantum_circuit.py @@ -132,7 +132,7 @@ def convert_dds_to_quantum_circuit( target_qubits=None, gate_time=0.1, add_measurement=True, - algorithm=FIX_DURATION_UNITARY, + algorithm=INSTANT_UNITARY, quantum_registers=None, circuit_name=None): @@ -152,10 +152,10 @@ def convert_dds_to_quantum_circuit( target qubits and a set of ClassicalRegister objects created with length equal to `len(target_qubits)` algorithm : str, optional - One of 'Fixed duration unitary' or 'Instant unitary'; In the case of - 'Fixed duration unitary', the operations are assumed to be taking the amount of - gate_time while 'Instant unitary' assumes unitaries to be instantaneous; - defaults to 'Fixed duration unitary' + One of 'fixed duration unitary' or 'instant unitary'; In the case of + 'fixed duration unitary', the operations are assumed to be taking the amount of + gate_time while 'instant unitary' assumes unitaries to be instantaneous; + defaults to 'instant unitary' quantum_registers : QuantumRegister, optional The set of quantum registers; defaults to None If not None, it must have the target qubit specified in `target_qubit` From 166e897e89ab950c65f3c7e28c88f6f55f77b50e Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Fri, 24 May 2019 12:05:56 +1000 Subject: [PATCH 22/42] algorithm keyword docstring update --- examples/example_sequence.csv | 18 ++++++++++++++++++ qctrlopencontrols/cirq/cirq_circuit.py | 9 +++++---- qctrlopencontrols/qiskit/quantum_circuit.py | 7 ++++--- 3 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 examples/example_sequence.csv diff --git a/examples/example_sequence.csv b/examples/example_sequence.csv new file mode 100644 index 00000000..2f7b4ef8 --- /dev/null +++ b/examples/example_sequence.csv @@ -0,0 +1,18 @@ +rabi_rate,azimuthal_angle,detuning,duration,maximum_rabi_rate +0.0,0.0,0.0,4.999999999999999e-07,6283185.307179586 +0.0,0.0,3.141592653589793,2.4999999999999994e-07,6283185.307179586 +0.0,0.0,0.0,9.999999999999997e-07,6283185.307179586 +0.0,0.0,3.141592653589793,2.4999999999999994e-07,6283185.307179586 +0.0,0.0,0.0,2.5000000000000015e-07,6283185.307179586 +1.0,0.0,0.0,5.000000000000003e-07,6283185.307179586 +0.0,0.0,0.0,8.749999999999997e-07,6283185.307179586 +0.0,0.0,3.141592653589793,2.499999999999997e-07,6283185.307179586 +0.0,0.0,0.0,2.2500000000000005e-06,6283185.307179586 +0.0,0.0,3.141592653589793,2.499999999999993e-07,6283185.307179586 +0.0,0.0,0.0,8.750000000000001e-07,6283185.307179586 +1.0,0.0,0.0,4.999999999999994e-07,6283185.307179586 +0.0,0.0,0.0,2.50000000000001e-07,6283185.307179586 +0.0,0.0,3.141592653589793,2.499999999999993e-07,6283185.307179586 +0.0,0.0,0.0,1.0000000000000023e-06,6283185.307179586 +0.0,0.0,3.141592653589793,2.499999999999993e-07,6283185.307179586 +0.0,0.0,0.0,5.000000000000003e-07,6283185.307179586 \ No newline at end of file diff --git a/qctrlopencontrols/cirq/cirq_circuit.py b/qctrlopencontrols/cirq/cirq_circuit.py index 6027acdd..d208bb45 100644 --- a/qctrlopencontrols/cirq/cirq_circuit.py +++ b/qctrlopencontrols/cirq/cirq_circuit.py @@ -371,7 +371,7 @@ def convert_dds_to_cirq_circuit( circuit_type : str, optional One of 'scheduled circuit' or 'standard circuit'. In the case of 'standard circuit', the circuit will be a sequence of desired operations - at offsets specified by the supplied dynamic decoupling sequence and the + at offsets specified by the dynamic decoupling sequence and the duration between any two offsets will have 'identity' gates; the method will return a 'cirq.Circuit'. In the case of 'scheduled circuit', the desired operations will be scheduled at offsets specified by the dynamic decoupling @@ -382,9 +382,10 @@ def convert_dds_to_cirq_circuit( `Simulation ` _. algorithm : str, optional One of 'fixed duration unitary' or 'instant unitary'; In the case of - 'fixed duration unitary', the operations are assumed to be taking the amount of - gate_time while 'instant unitary' assumes unitaries to be instantaneous; - defaults to 'instant unitary'. Note that this option is only used for + 'fixed duration unitary', the sequence operations are assumed to be + taking the amount of gate_time while 'instant unitary' assumes the sequence + operations are instantaneous (and hence does not contribute to the delay between + offsets). Defaults to 'instant unitary'. Note that this option is only used for 'standard circuit'; 'scheduled circuit' always contains a 'fixed duration unitary'. device : cirq.Device, optional A cirq.Device that specifies hardware constraints for validating circuits diff --git a/qctrlopencontrols/qiskit/quantum_circuit.py b/qctrlopencontrols/qiskit/quantum_circuit.py index a7e1ee96..c0428bde 100644 --- a/qctrlopencontrols/qiskit/quantum_circuit.py +++ b/qctrlopencontrols/qiskit/quantum_circuit.py @@ -153,9 +153,10 @@ def convert_dds_to_quantum_circuit( equal to `len(target_qubits)` algorithm : str, optional One of 'fixed duration unitary' or 'instant unitary'; In the case of - 'fixed duration unitary', the operations are assumed to be taking the amount of - gate_time while 'instant unitary' assumes unitaries to be instantaneous; - defaults to 'instant unitary' + 'fixed duration unitary', the sequence operations are assumed to be + taking the amount of gate_time while 'instant unitary' assumes the sequence + operations are instantaneous (and hence does not contribute to the delay between + offsets). Defaults to 'instant unitary'. quantum_registers : QuantumRegister, optional The set of quantum registers; defaults to None If not None, it must have the target qubit specified in `target_qubit` From 31daa261495bb4a4aa91519c5e506c5831a78028 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Fri, 24 May 2019 12:11:26 +1000 Subject: [PATCH 23/42] Update cirq notebook with minor changes in the text --- examples/running_a_dds_on_cirq.ipynb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/running_a_dds_on_cirq.ipynb b/examples/running_a_dds_on_cirq.ipynb index 95b8554d..9a5a98c5 100644 --- a/examples/running_a_dds_on_cirq.ipynb +++ b/examples/running_a_dds_on_cirq.ipynb @@ -6,7 +6,7 @@ "source": [ "# Running a Dynamical Decoupling Sequence on Cirq\n", "\n", - "Q-CTRL Open Controls provides easy-to-use methods to construct Dynamical Decoupling Sequences (DDS) according to well-known dynamical decoupling schemes. This is described in the [creating a DDS notebook](creating_a_dds.ipynb). Here we show how a DDS from Q-CTRL Open Controls can be exported to a `cirq.Circuit` to run in `cirq.Simulator`.\n", + "Q-CTRL Open Controls provides easy-to-use methods to construct Dynamical Decoupling Sequences (DDS) according to well-known dynamical decoupling schemes. This is described in the [creating a DDS notebook](creating_a_dds.ipynb). Here we show how a DDS from Q-CTRL Open Controls can be exported as quantum circuit (`cirq.Circuit` or `cirq.Schedule`) and run in `cirq.Simulator`.\n", "\n", "Note : You can install `cirq` by simply running `pip install cirq`. Please consult [Cirq Documentation](https://cirq.readthedocs.io/en/stable/) for installation instruction and general introduction to `cirq` package." ] @@ -32,7 +32,7 @@ "#Q-CTRL Open Controls\n", "from qctrlopencontrols import new_predefined_dds, convert_dds_to_cirq_circuit\n", "\n", - "#Cirq\n", + "#Cirq : to run the circuit on simulator\n", "import cirq" ] }, @@ -50,7 +50,7 @@ "\n", "Converting a DDS into a `cirq.Circuit` or `cirq.Schedule` is an approximate process where the instantaneous unitaries are replaced with finite duration gates. Moreover, in `cirq.Circuit`, the pauses in-between unitaries are replaced with the closest integer number of identity gates. The exact algorithm used to make this approximation is documented in the [source code](../qctrlopencontrols/cirq/cirq_circuit.py).\n", "\n", - "In this example we will define a Quadratic DDS and convert it into a circuit that we can later run on a simulator. We add a $X_{\\pi/2}$ rotation at either end of the sequence. See [creating_a_DDS.ipynb](creating_a_DDS.ipynb) to see how other sequences can be created." + "In this example we will define a Quadratic DDS and convert it into a circuit that we can later run on a simulator. Note that we add a $X_{\\pi/2}$ rotation at both ends of the sequence. See [creating_a_DDS.ipynb](creating_a_DDS.ipynb) to see how other sequences can be created." ] }, { From 9f0b94532bf1d0e82ec85b40910db160ecdb0147 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Fri, 24 May 2019 12:13:46 +1000 Subject: [PATCH 24/42] merged with master --- examples/running_a_dds_on_cirq.ipynb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/running_a_dds_on_cirq.ipynb b/examples/running_a_dds_on_cirq.ipynb index 9a5a98c5..6c9d358b 100644 --- a/examples/running_a_dds_on_cirq.ipynb +++ b/examples/running_a_dds_on_cirq.ipynb @@ -20,7 +20,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 15, "metadata": {}, "outputs": [], "source": [ @@ -62,7 +62,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -105,7 +105,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 17, "metadata": {}, "outputs": [], "source": [ @@ -170,7 +170,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 18, "metadata": {}, "outputs": [ { @@ -237,7 +237,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 19, "metadata": {}, "outputs": [ { @@ -264,7 +264,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 20, "metadata": {}, "outputs": [ { @@ -308,7 +308,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 21, "metadata": {}, "outputs": [ { From 24866444ac8cc9be3085a47a117b2ecf989e791f Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Fri, 24 May 2019 12:50:18 +1000 Subject: [PATCH 25/42] docstring for pre-post rotation modified slightly --- qctrlopencontrols/dynamic_decoupling_sequences/predefined.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qctrlopencontrols/dynamic_decoupling_sequences/predefined.py b/qctrlopencontrols/dynamic_decoupling_sequences/predefined.py index 9eb04741..b4d2e375 100644 --- a/qctrlopencontrols/dynamic_decoupling_sequences/predefined.py +++ b/qctrlopencontrols/dynamic_decoupling_sequences/predefined.py @@ -142,8 +142,8 @@ def new_ramsey_sequence(duration=None, duration : float, optional Total duration of the sequence. Defaults to None pre_post_rotation : bool, optional - If True, a :math:`\\pi.2` rotation is added at the - start and end of the sequence. + If True, a :math:`X_{\\pi.2}` rotation + is added at the start and end of the sequence. kwargs : dict Additional keywords required by qctrlopencontrols.sequences.DynamicDecouplingSequence From 7ea6d1809140f1a77afe1a03de2eb0e45f6a81cf Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Fri, 24 May 2019 12:52:25 +1000 Subject: [PATCH 26/42] harrys comments applied on qiskit method too --- qctrlopencontrols/qiskit/quantum_circuit.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qctrlopencontrols/qiskit/quantum_circuit.py b/qctrlopencontrols/qiskit/quantum_circuit.py index c0428bde..51d1f097 100644 --- a/qctrlopencontrols/qiskit/quantum_circuit.py +++ b/qctrlopencontrols/qiskit/quantum_circuit.py @@ -103,7 +103,7 @@ def _get_circuit_gate_list(dynamic_decoupling_sequence, def _get_rotations(operation): - """Returns the pulses based of the rotation operation + """Returns the pulses based on the rotation operation Parameters ---------- @@ -114,8 +114,8 @@ def _get_rotations(operation): Returns ------- numpy.ndarray - A 1-D array of length 3 containing x_rotation, y_rotation and z-rotation - calculate from sequence operation + A 1-D array of length 3 containing x_rotation, y_rotation and z_rotation + calculated from sequence operation """ x_rotation = operation[0] * np.cos(operation[1]) From 46a94ea02c797bc37c94de74fc035b7f6765ab94 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Fri, 24 May 2019 17:11:59 +1000 Subject: [PATCH 27/42] notebooks renamed, titles updated --- .../{running_a_dds_on_cirq.ipynb => export_a_dds_to_cirq.ipynb} | 2 +- ...unning_a_dds_on_ibm_q.ipynb => export_a_dds_to_qiskit.ipynb} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename examples/{running_a_dds_on_cirq.ipynb => export_a_dds_to_cirq.ipynb} (99%) rename examples/{running_a_dds_on_ibm_q.ipynb => export_a_dds_to_qiskit.ipynb} (99%) diff --git a/examples/running_a_dds_on_cirq.ipynb b/examples/export_a_dds_to_cirq.ipynb similarity index 99% rename from examples/running_a_dds_on_cirq.ipynb rename to examples/export_a_dds_to_cirq.ipynb index 6c9d358b..95652d01 100644 --- a/examples/running_a_dds_on_cirq.ipynb +++ b/examples/export_a_dds_to_cirq.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Running a Dynamical Decoupling Sequence on Cirq\n", + "# Export a Dynamical Decoupling Sequence to Cirq\n", "\n", "Q-CTRL Open Controls provides easy-to-use methods to construct Dynamical Decoupling Sequences (DDS) according to well-known dynamical decoupling schemes. This is described in the [creating a DDS notebook](creating_a_dds.ipynb). Here we show how a DDS from Q-CTRL Open Controls can be exported as quantum circuit (`cirq.Circuit` or `cirq.Schedule`) and run in `cirq.Simulator`.\n", "\n", diff --git a/examples/running_a_dds_on_ibm_q.ipynb b/examples/export_a_dds_to_qiskit.ipynb similarity index 99% rename from examples/running_a_dds_on_ibm_q.ipynb rename to examples/export_a_dds_to_qiskit.ipynb index c8bae29c..2bf90004 100755 --- a/examples/running_a_dds_on_ibm_q.ipynb +++ b/examples/export_a_dds_to_qiskit.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Running a Dynamical Decoupling Sequence on IBM Q\n", + "# Export a Dynamical Decoupling Sequence to Qiskit\n", "\n", "Q-CTRL Open Controls provides easy-to-use methods to construct Dynamical Decoupling Sequences (DDS) according to well-known dynamical decoupling schemes. This is described in the [creating a DDS notebook](creating_a_dds.ipynb). Here we show how a DDS from Q-CTRL Open Controls can be exported to a Qiskit circuit to run on an IBM Q device. We also show how a DDS can decrease the number of errors, when executing a quantum circuit on a real quantum computer, by extending the coherence time.\n", "\n", From 4b295d2fe578c37db8b1ead3d890a1a31933c7b8 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Fri, 24 May 2019 17:17:16 +1000 Subject: [PATCH 28/42] readme file updated with the new names of the notebook files and added description for the cirq notebook --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6afbd6bd..d0ae57bd 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,12 @@ Q-CTRL Open Controls can create a large library of standard DDS which can be exp #### Export a DDS to Qiskit -[`examples/running_a_dds_on_ibm_q.ipynb`](examples/running_a_dds_on_ibm_q.ipynb) demonstrates how to take a DDS and convert it to a Qiskit circuit so it can be run on IBM's quantum computers. It also demonstrates using a DDS to improve the performance of a quantum circuit execution by extending the coherence time of a qubit. +[`examples/export_a_dds_on_qiskit.ipynb`](examples/export_a_dds_on_qiskit.ipynb) demonstrates how to take a DDS and convert it to a Qiskit circuit so it can be run on IBM's quantum computers. It also demonstrates using a DDS to improve the performance of a quantum circuit execution by extending the coherence time of a qubit. + +#### Export a DDS to Cirq + +[`examples/export_a_dds_on_cirq.ipynb`](examples/export_a_dds_on_cirq.ipynb) demonstrates how to take a DDS and convert it to a Cirq circuit or schdule. It also shows how to run a circuit or schedule in a Cirq simulator. + ## Contributing From e2cd20486bbdfd36a22ee1992c0d8e0436d47072 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Mon, 27 May 2019 10:15:12 +1000 Subject: [PATCH 29/42] circuit, schedule separated; tests pass --- qctrlopencontrols/__init__.py | 3 +- qctrlopencontrols/cirq/__init__.py | 4 +- qctrlopencontrols/cirq/circuit.py | 227 ++++++++++ qctrlopencontrols/cirq/cirq_circuit.py | 478 -------------------- qctrlopencontrols/cirq/constants.py | 40 -- qctrlopencontrols/cirq/schedule.py | 235 ++++++++++ qctrlopencontrols/qiskit/__init__.py | 4 +- qctrlopencontrols/qiskit/quantum_circuit.py | 12 +- tests/test_cirq_circuits.py | 19 +- 9 files changed, 485 insertions(+), 537 deletions(-) create mode 100644 qctrlopencontrols/cirq/circuit.py delete mode 100644 qctrlopencontrols/cirq/cirq_circuit.py delete mode 100644 qctrlopencontrols/cirq/constants.py create mode 100644 qctrlopencontrols/cirq/schedule.py diff --git a/qctrlopencontrols/__init__.py b/qctrlopencontrols/__init__.py index c7147ce0..4f5fb900 100644 --- a/qctrlopencontrols/__init__.py +++ b/qctrlopencontrols/__init__.py @@ -23,4 +23,5 @@ convert_dds_to_driven_controls) from .driven_controls import DrivenControl, new_predefined_driven_control from .qiskit import convert_dds_to_quantum_circuit -from .cirq import convert_dds_to_cirq_circuit +from .cirq import (convert_dds_to_cirq_circuit, + convert_dds_to_cirq_schedule) diff --git a/qctrlopencontrols/cirq/__init__.py b/qctrlopencontrols/cirq/__init__.py index 08a16ea0..b003e992 100644 --- a/qctrlopencontrols/cirq/__init__.py +++ b/qctrlopencontrols/cirq/__init__.py @@ -18,5 +18,5 @@ ============= """ -from .constants import (SCHEDULED_CIRCUIT, STANDARD_CIRCUIT) -from .cirq_circuit import convert_dds_to_cirq_circuit +from .circuit import convert_dds_to_cirq_circuit +from .schedule import convert_dds_to_cirq_schedule diff --git a/qctrlopencontrols/cirq/circuit.py b/qctrlopencontrols/cirq/circuit.py new file mode 100644 index 00000000..dac445f6 --- /dev/null +++ b/qctrlopencontrols/cirq/circuit.py @@ -0,0 +1,227 @@ +# Copyright 2019 Q-CTRL Pty Ltd & Q-CTRL Inc +# +# 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. + +""" +================= +cirq.cirq_circuit +================= +""" + +import numpy as np + +import cirq + +from qctrlopencontrols.dynamic_decoupling_sequences import DynamicDecouplingSequence +from qctrlopencontrols.exceptions import ArgumentsValueError + +from qctrlopencontrols.qiskit import ( + FIX_DURATION_UNITARY, INSTANT_UNITARY, + get_circuit_gate_list, get_rotations) + + +def _get_standard_circuit(dynamic_decoupling_sequence, + target_qubits, + gate_time, + algorithm, + add_measurement): + + """Returns a standard circuit constructed from dynamic + decoupling sequence + + Parameters + ---------- + dynamic_decoupling_sequence : DynamicDecouplingSequence + The dynamic decoupling sequence + target_qubits : list + List of target qubits for the sequence operation; the qubits must be + cirq.Qid type + gate_time : float, optional + Time (in seconds) delay introduced by a gate; defaults to 0.1 + algorithm : str, optional + One of 'fixed duration unitary' or 'instant unitary'; In the case of + 'fixed duration unitary', the operations are assumed to be taking the amount of + gate_time while 'instant unitary' assumes unitaries to be instantaneous; + defaults to 'instant unitary'. Note that this option is only used for + 'standard circuit'; 'scheduled circuit' always contains a 'fixed duration unitary'. + add_measurement : bool + If True, a measurement operation is added to each of the qubits. + + Returns + ------- + cirq.Circuit + The circuit prepared from dynamic decoupling sequence. In standard circuit + the desired decoupling pulses are placed at offsets and the duration between + the pulses are constructed from identity gates with delays equal to 'gate_time'. + + Raises + ------ + ArgumentsValueError + If there is rotations around more than one axis at any of the offsets + """ + + unitary_time = 0. + if algorithm == FIX_DURATION_UNITARY: + unitary_time = gate_time + + circuit_gate_list = get_circuit_gate_list( + dynamic_decoupling_sequence=dynamic_decoupling_sequence, + gate_time=gate_time, + unitary_time=unitary_time) + + circuit = cirq.Circuit() + + offset_count = 0 + for gate in circuit_gate_list: + + if gate == 'id': + gate_list = [] + for qubit in target_qubits: + gate_list.append(cirq.I(qubit)) + circuit.append(gate_list) + continue + + instance_operation = np.array( + [dynamic_decoupling_sequence.rabi_rotations[offset_count], + dynamic_decoupling_sequence.azimuthal_angles[offset_count], + dynamic_decoupling_sequence.detuning_rotations[offset_count]]) + + rotations = get_rotations(instance_operation) + nonzero_pulse_counts = 0 + for rotation in rotations: + if not np.isclose(rotation, 0.0): + nonzero_pulse_counts += 1 + if nonzero_pulse_counts > 1: + raise ArgumentsValueError( + 'Open Controls support a sequence with one ' + 'valid pulse at any offset. Found sequence ' + 'with multiple rotation operations at an offset.', + {'dynamic_decoupling_sequence': str(dynamic_decoupling_sequence), + 'instance_operation': instance_operation}) + gate_list = [] + for qubit in target_qubits: + if nonzero_pulse_counts == 0: + gate_list.append(cirq.I(qubit)) + else: + if not np.isclose(rotations[0], 0.0): + gate_list.append(cirq.Rx(rotations[0])(qubit)) + elif not np.isclose(rotations[1], 0.0): + gate_list.append(cirq.Ry(rotations[1])(qubit)) + elif not np.isclose(rotations[2], 0.): + gate_list.append(cirq.Rz(rotations[2])(qubit)) + offset_count += 1 + circuit.append(gate_list) + + if add_measurement: + gate_list = [] + for idx, qubit in enumerate(target_qubits): + gate_list.append(cirq.measure(qubit, key='qubit-{}'.format(idx))) + circuit.append(gate_list) + + return circuit + + +def convert_dds_to_cirq_circuit( + dynamic_decoupling_sequence, + target_qubits=None, + gate_time=0.1, + add_measurement=True, + algorithm=INSTANT_UNITARY): + + """Converts a Dynamic Decoupling Sequence into quantum circuit + as defined in cirq + + Parameters + ---------- + dynamic_decoupling_sequence : DynamicDecouplingSequence + The dynamic decoupling sequence + target_qubits : list, optional + List of target qubits for the sequence operation; the qubits must be + cirq.Qid type; defaults to None in which case a 1-D lattice of one + qubit is used (indexed as 0). + gate_time : float, optional + Time (in seconds) delay introduced by a gate; defaults to 0.1 + add_measurement : bool, optional + If True, the circuit contains a measurement operation for each of the + target qubits. Measurement from each of the qubits is associated + with a string as key. The string is formatted as 'qubit-X' where + X is a number between 0 and len(target_qubits). + algorithm : str, optional + One of 'fixed duration unitary' or 'instant unitary'; In the case of + 'fixed duration unitary', the sequence operations are assumed to be + taking the amount of gate_time while 'instant unitary' assumes the sequence + operations are instantaneous (and hence does not contribute to the delay between + offsets). Defaults to 'instant unitary'. Note that this option is only used for + 'standard circuit'; 'scheduled circuit' always contains a 'fixed duration unitary'. + + Returns + ------- + cirq.Circuit + The circuit containing gates corresponding to sequence operation. + + Raises + ------ + ArgumentsValueError + If any of the input parameters result in an invalid operation. + + Notes + ----- + + Dynamic Decoupling Sequences (DDS) consist of idealized pulse operation. Theoretically, + these operations (pi-pulses in X,Y or Z) occur instantaneously. However, in practice, + pulses require time. Therefore, this method of converting an idealized sequence + results to a circuit that is only an approximate implementation of the idealized sequence. + + In idealized definition of DDS, `offsets` represents the instances within sequence + `duration` where a pulse occurs instantaneously. A series of appropriate circuit components + is placed in order to represent these pulses. + + In 'standard circuit', the `gaps` or idle time in between active pulses are filled up + with `identity` gates. Each identity gate introduces a delay of `gate_time`. In this + implementation, the number of identity gates is determined by + :math:`np.int(np.floor(offset_distance / gate_time))`. As a consequence, + :math:`np.int(np.floor(offset_distance / gate_time))`. As a consequence, + the duration of the real-circuit is :math:`gate_time \\times number_of_identity_gates + + pulse_gate_time \\times number_of_pulses`. + + Q-CTRL Open Controls support operation resulting in rotation around at most one axis at + any offset. + """ + + if dynamic_decoupling_sequence is None: + 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)}) + + if gate_time <= 0: + raise ArgumentsValueError( + 'Time delay of gates must be greater than zero.', + {'gate_time': gate_time}) + + if target_qubits is None: + target_qubits = [cirq.LineQubit(0)] + + 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}) + + return _get_standard_circuit(dynamic_decoupling_sequence=dynamic_decoupling_sequence, + target_qubits=target_qubits, + gate_time=gate_time, + algorithm=algorithm, + add_measurement=add_measurement) diff --git a/qctrlopencontrols/cirq/cirq_circuit.py b/qctrlopencontrols/cirq/cirq_circuit.py deleted file mode 100644 index d208bb45..00000000 --- a/qctrlopencontrols/cirq/cirq_circuit.py +++ /dev/null @@ -1,478 +0,0 @@ -# Copyright 2019 Q-CTRL Pty Ltd & Q-CTRL Inc -# -# 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. - -""" -================= -cirq.cirq_circuit -================= -""" - -import numpy as np - -import cirq - -from qctrlopencontrols.dynamic_decoupling_sequences import DynamicDecouplingSequence -from qctrlopencontrols.exceptions import ArgumentsValueError - -from .constants import (SCHEDULED_CIRCUIT, STANDARD_CIRCUIT, - FIX_DURATION_UNITARY, INSTANT_UNITARY) - - -def _get_circuit_gate_list(dynamic_decoupling_sequence, - gate_time, - unitary_time): - - """Converts the operations in a sequence into list of gates - of a circuit - - Parameters - ---------- - dynamic_decoupling_sequence : DynamicDecouplingSequence - Dynamic decoupling sequence instance - gate_time : float - Indicates the delay time of the identity gates - unitary_time : float - Indicates the delay time introduced by unitary gates - - Returns - ------- - list - A list of circuit components with required parameters - - Raises - ------ - ArgumentsValueError - If the offsets cannot be placed properly - """ - - rabi_rotations = dynamic_decoupling_sequence.rabi_rotations - azimuthal_angles = dynamic_decoupling_sequence.azimuthal_angles - detuning_rotations = dynamic_decoupling_sequence.detuning_rotations - - if len(rabi_rotations.shape) == 1: - rabi_rotations = rabi_rotations[np.newaxis, :] - if len(azimuthal_angles.shape) == 1: - azimuthal_angles = azimuthal_angles[np.newaxis, :] - if len(detuning_rotations.shape) == 1: - detuning_rotations = detuning_rotations[np.newaxis, :] - - operations = np.vstack((rabi_rotations, azimuthal_angles, detuning_rotations)) - offsets = dynamic_decoupling_sequence.offsets - - time_covered = 0 - circuit_operations = [] - for operation_idx in range(operations.shape[1]): - - offset_distance = offsets[operation_idx] - time_covered - - if np.isclose(offset_distance, 0.0): - offset_distance = 0.0 - - if offset_distance < 0: - raise ArgumentsValueError("Offsets cannot be placed properly", - {'sequence_operations': operations}) - if offset_distance == 0: - circuit_operations.append('offset') - if np.isclose(np.sum(operations[:, operation_idx]), 0.0): - time_covered = offsets[operation_idx] - else: - time_covered = offsets[operation_idx] + unitary_time - else: - number_of_id_gates = 0 - while (time_covered + (number_of_id_gates+1) * gate_time) <= \ - offsets[operation_idx]: - circuit_operations.append('id') - number_of_id_gates += 1 - circuit_operations.append('offset') - time_covered = offsets[operation_idx] + unitary_time - - return circuit_operations - - -def _get_rotations(operation): - - """Returns the pulses based on the rotation operation - - Parameters - ---------- - operation : numpy.ndarray - 1-D array (length=3) consisting of rabi rotation, azimuthal_angle - and detuning_rotation at an offset of a sequence - - Returns - ------- - numpy.ndarray - A 1-D array of length 3 containing x_rotation, y_rotation and z_rotation - calculated from sequence operation - """ - - x_rotation = operation[0] * np.cos(operation[1]) - y_rotation = operation[0] * np.sin(operation[1]) - z_rotation = operation[2] - - pulses = np.array([x_rotation, y_rotation, z_rotation]) - - return pulses - - -def _get_scheduled_circuit(dynamic_decoupling_sequence, - target_qubits, - gate_time, - add_measurement, - device): - - """Returns a scheduled circuit operation constructed from - dynamic decoupling sequence - - Parameters - ---------- - dynamic_decoupling_sequence : DynamicDecouplingSequence - The dynamic decoupling sequence - target_qubits : list - List of target qubits for the sequence operation; the qubits must be - cirq.Qid type - gate_time : float, optional - Time (in seconds) delay introduced by a gate; defaults to 0.1 - add_measurement : bool - If True, a measurement operation is added to each of the qubits. - device : cirq.Device - The device where these operations will be running. - - Returns - ------- - cirq.Schedule - The scheduled circuit operations. The Schedule object contains a - series of desired gates at specific times measured from the start - of the duration. - - Raises - ------ - ArgumentsValueError - If there is rotations around more than one axis at any of the offsets - """ - - # time in nano seconds - gate_time = gate_time * 1e9 - - rabi_rotations = dynamic_decoupling_sequence.rabi_rotations - azimuthal_angles = dynamic_decoupling_sequence.azimuthal_angles - detuning_rotations = dynamic_decoupling_sequence.detuning_rotations - - if len(rabi_rotations.shape) == 1: - rabi_rotations = rabi_rotations[np.newaxis, :] - if len(azimuthal_angles.shape) == 1: - azimuthal_angles = azimuthal_angles[np.newaxis, :] - if len(detuning_rotations.shape) == 1: - detuning_rotations = detuning_rotations[np.newaxis, :] - - operations = np.vstack((rabi_rotations, azimuthal_angles, detuning_rotations)) - offsets = dynamic_decoupling_sequence.offsets - # offsets in nano seconds - offsets = offsets * 1e9 - - circuit_operations = [] - offset_count = 0 - for op_idx in range(operations.shape[1]): - instance_operation = np.array([dynamic_decoupling_sequence.rabi_rotations[op_idx], - dynamic_decoupling_sequence.azimuthal_angles[op_idx], - dynamic_decoupling_sequence.detuning_rotations[op_idx] - ]) - - rotations = _get_rotations(instance_operation) - nonzero_pulse_counts = 0 - for rotation in rotations: - if not np.isclose(rotation, 0.0): - nonzero_pulse_counts += 1 - if nonzero_pulse_counts > 1: - raise ArgumentsValueError( - 'Open Controls support a sequence with one ' - 'valid pulse at any offset. Found sequence ' - 'with multiple rotation operations at an offset.', - {'dynamic_decoupling_sequence': str(dynamic_decoupling_sequence), - 'instance_operation': instance_operation}) - - for qubit in target_qubits: - if nonzero_pulse_counts == 0: - operation = cirq.ScheduledOperation( - time=cirq.Timestamp(nanos=offsets[op_idx]), - duration=cirq.Duration(nanos=gate_time), - operation=cirq.I(qubit)) - else: - if not np.isclose(rotations[0], 0.0): - operation = cirq.ScheduledOperation( - time=cirq.Timestamp(nanos=offsets[op_idx]), - duration=cirq.Duration(nanos=gate_time), - operation=cirq.Rx(rotations[0])(qubit)) - elif not np.isclose(rotations[1], 0.0): - operation = cirq.ScheduledOperation( - time=cirq.Timestamp(nanos=offsets[op_idx]), - duration=cirq.Duration(nanos=gate_time), - operation=cirq.Rx(rotations[1])(qubit)) - elif not np.isclose(rotations[2], 0.): - operation = cirq.ScheduledOperation( - time=cirq.Timestamp(nanos=offsets[op_idx]), - duration=cirq.Duration(nanos=gate_time), - operation=cirq.Rx(rotations[2])(qubit)) - offset_count += 1 - circuit_operations.append(operation) - - if add_measurement: - for idx, qubit in enumerate(target_qubits): - operation = cirq.ScheduledOperation( - time=cirq.Timestamp(nanos=offsets[-1] + gate_time), - duration=cirq.Duration(nanos=gate_time), - operation=cirq.MeasurementGate( - 1, key='qubit-{}'.format(idx))(qubit)) - circuit_operations.append(operation) - - schedule = cirq.Schedule(device=device, scheduled_operations=circuit_operations) - return schedule - - -def _get_standard_circuit(dynamic_decoupling_sequence, - target_qubits, - gate_time, - algorithm, - add_measurement): - - """Returns a standard circuit constructed from dynamic - decoupling sequence - - Parameters - ---------- - dynamic_decoupling_sequence : DynamicDecouplingSequence - The dynamic decoupling sequence - target_qubits : list - List of target qubits for the sequence operation; the qubits must be - cirq.Qid type - gate_time : float, optional - Time (in seconds) delay introduced by a gate; defaults to 0.1 - algorithm : str, optional - One of 'fixed duration unitary' or 'instant unitary'; In the case of - 'fixed duration unitary', the operations are assumed to be taking the amount of - gate_time while 'instant unitary' assumes unitaries to be instantaneous; - defaults to 'instant unitary'. Note that this option is only used for - 'standard circuit'; 'scheduled circuit' always contains a 'fixed duration unitary'. - add_measurement : bool - If True, a measurement operation is added to each of the qubits. - - Returns - ------- - cirq.Circuit - The circuit prepared from dynamic decoupling sequence. In standard circuit - the desired decoupling pulses are placed at offsets and the duration between - the pulses are constructed from identity gates with delays equal to 'gate_time'. - - Raises - ------ - ArgumentsValueError - If there is rotations around more than one axis at any of the offsets - """ - - unitary_time = 0. - if algorithm == FIX_DURATION_UNITARY: - unitary_time = gate_time - - circuit_gate_list = _get_circuit_gate_list( - dynamic_decoupling_sequence=dynamic_decoupling_sequence, - gate_time=gate_time, - unitary_time=unitary_time) - - circuit = cirq.Circuit() - - offset_count = 0 - for gate in circuit_gate_list: - - if gate == 'id': - gate_list = [] - for qubit in target_qubits: - gate_list.append(cirq.I(qubit)) - circuit.append(gate_list) - continue - - instance_operation = np.array( - [dynamic_decoupling_sequence.rabi_rotations[offset_count], - dynamic_decoupling_sequence.azimuthal_angles[offset_count], - dynamic_decoupling_sequence.detuning_rotations[offset_count]]) - - rotations = _get_rotations(instance_operation) - nonzero_pulse_counts = 0 - for rotation in rotations: - if not np.isclose(rotation, 0.0): - nonzero_pulse_counts += 1 - if nonzero_pulse_counts > 1: - raise ArgumentsValueError( - 'Open Controls support a sequence with one ' - 'valid pulse at any offset. Found sequence ' - 'with multiple rotation operations at an offset.', - {'dynamic_decoupling_sequence': str(dynamic_decoupling_sequence), - 'instance_operation': instance_operation}) - gate_list = [] - for qubit in target_qubits: - if nonzero_pulse_counts == 0: - gate_list.append(cirq.I(qubit)) - else: - if not np.isclose(rotations[0], 0.0): - gate_list.append(cirq.Rx(rotations[0])(qubit)) - elif not np.isclose(rotations[1], 0.0): - gate_list.append(cirq.Ry(rotations[1])(qubit)) - elif not np.isclose(rotations[2], 0.): - gate_list.append(cirq.Rz(rotations[2])(qubit)) - offset_count += 1 - circuit.append(gate_list) - - if add_measurement: - gate_list = [] - for idx, qubit in enumerate(target_qubits): - gate_list.append(cirq.measure(qubit, key='qubit-{}'.format(idx))) - circuit.append(gate_list) - - return circuit - - -def convert_dds_to_cirq_circuit( - dynamic_decoupling_sequence, - target_qubits=None, - gate_time=0.1, - add_measurement=True, - circuit_type=STANDARD_CIRCUIT, - algorithm=INSTANT_UNITARY, - device=None): - - """Converts a Dynamic Decoupling Sequence into quantum circuit - as defined in cirq - - Parameters - ---------- - dynamic_decoupling_sequence : DynamicDecouplingSequence - The dynamic decoupling sequence - target_qubits : list, optional - List of target qubits for the sequence operation; the qubits must be - cirq.Qid type; defaults to None in which case a 1-D lattice of one - qubit is used (indexed as 0). - gate_time : float, optional - Time (in seconds) delay introduced by a gate; defaults to 0.1 - add_measurement : bool, optional - If True, the circuit contains a measurement operation for each of the - target qubits. Measurement from each of the qubits is associated - with a string as key. The string is formatted as 'qubit-X' where - X is a number between 0 and len(target_qubits). - circuit_type : str, optional - One of 'scheduled circuit' or 'standard circuit'. In the case of - 'standard circuit', the circuit will be a sequence of desired operations - at offsets specified by the dynamic decoupling sequence and the - duration between any two offsets will have 'identity' gates; the method - will return a 'cirq.Circuit'. In the case of 'scheduled circuit', the desired - operations will be scheduled at offsets specified by the dynamic decoupling - sequence; in this case a 'cirq.Schedule' object is returned. Both `cirq.Circuit` - and 'cirq.Schedule' can be used with 'cirq.Simulator'. - See `Circuits ` _, - `Schedules ` _ and - `Simulation ` _. - algorithm : str, optional - One of 'fixed duration unitary' or 'instant unitary'; In the case of - 'fixed duration unitary', the sequence operations are assumed to be - taking the amount of gate_time while 'instant unitary' assumes the sequence - operations are instantaneous (and hence does not contribute to the delay between - offsets). Defaults to 'instant unitary'. Note that this option is only used for - 'standard circuit'; 'scheduled circuit' always contains a 'fixed duration unitary'. - device : cirq.Device, optional - A cirq.Device that specifies hardware constraints for validating circuits - and schedules. If None, a unconstrained device is used. See `Cirq Documentation - ` _. - - Returns - ------- - cirq.Circuit or cirq.Schedule - The circuit or schedule (depending on circuit_type option). - Either of them can be used with cirq.Simulator. - - Raises - ------ - ArgumentsValueError - If any of the input parameters result in an invalid operation. - - Notes - ----- - - Dynamic Decoupling Sequences (DDS) consist of idealized pulse operation. Theoretically, - these operations (pi-pulses in X,Y or Z) occur instantaneously. However, in practice, - pulses require time. Therefore, this method of converting an idealized sequence - results to a circuit that is only an approximate implementation of the idealized sequence. - - In idealized definition of DDS, `offsets` represents the instances within sequence - `duration` where a pulse occurs instantaneously. A series of appropriate circuit components - is placed in order to represent these pulses. - - In 'standard circuit', the `gaps` or idle time in between active pulses are filled up - with `identity` gates. Each identity gate introduces a delay of `gate_time`. In this - implementation, the number of identity gates is determined by - :math:`np.int(np.floor(offset_distance / gate_time))`. As a consequence, - :math:`np.int(np.floor(offset_distance / gate_time))`. As a consequence, - the duration of the real-circuit is :math:`gate_time \\times number_of_identity_gates + - pulse_gate_time \\times number_of_pulses`. - - In 'scheduled circuit', the active pulses are scheduled to be activated at a certain - instant calculated from the start of the sequence. This does not require identity gates - to be placed between offsets. - - Q-CTRL Open Controls support operation resulting in rotation around at most one axis at - any offset. - """ - - if dynamic_decoupling_sequence is None: - 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)}) - - if gate_time <= 0: - raise ArgumentsValueError( - 'Time delay of gates must be greater than zero.', - {'gate_time': gate_time}) - - if target_qubits is None: - target_qubits = [cirq.LineQubit(0)] - - if circuit_type not in [SCHEDULED_CIRCUIT, STANDARD_CIRCUIT]: - raise ArgumentsValueError('Circuit type must be one of {} or {}'.format( - SCHEDULED_CIRCUIT, STANDARD_CIRCUIT), {'algorithm': circuit_type}) - - if circuit_type == STANDARD_CIRCUIT: - 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}) - - return _get_standard_circuit(dynamic_decoupling_sequence=dynamic_decoupling_sequence, - target_qubits=target_qubits, - gate_time=gate_time, - algorithm=algorithm, - add_measurement=add_measurement) - - if device is None: - device = cirq.UnconstrainedDevice - - if not isinstance(device, cirq.Device): - raise ArgumentsValueError('Device must be a cirq.Device type.', - {'device': device}) - - return _get_scheduled_circuit(dynamic_decoupling_sequence=dynamic_decoupling_sequence, - target_qubits=target_qubits, - gate_time=gate_time, - add_measurement=add_measurement, - device=device) diff --git a/qctrlopencontrols/cirq/constants.py b/qctrlopencontrols/cirq/constants.py deleted file mode 100644 index 9090d599..00000000 --- a/qctrlopencontrols/cirq/constants.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2019 Q-CTRL Pty Ltd & Q-CTRL Inc -# -# 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. - -""" -===================== -cirq.constants module -===================== -""" - -SCHEDULED_CIRCUIT = 'scheduled circuit' -"""Constructs the circuit as schedule of rotation -operations at specified offsets. Scheduled circuit -only contains gates specific to desired rotation operations. -""" - -STANDARD_CIRCUIT = 'standard circuit' -"""Constructs the circuit as a series of operations that include -identity gates between desired rotation operations. -""" - -FIX_DURATION_UNITARY = 'fixed duration unitary' -"""Algorithm to convert a DDS to Quantum circuit -where the unitaries are considered as gates with finite duration -""" - -INSTANT_UNITARY = 'instant unitary' -"""Algorithm to convert a DDS to Quantum circuit where the -unitaties are considered as instantaneous operation. -""" diff --git a/qctrlopencontrols/cirq/schedule.py b/qctrlopencontrols/cirq/schedule.py new file mode 100644 index 00000000..49324df4 --- /dev/null +++ b/qctrlopencontrols/cirq/schedule.py @@ -0,0 +1,235 @@ +# Copyright 2019 Q-CTRL Pty Ltd & Q-CTRL Inc +# +# 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. + +""" +================= +cirq.cirq_circuit +================= +""" + +import numpy as np + +import cirq + +from qctrlopencontrols.dynamic_decoupling_sequences import DynamicDecouplingSequence +from qctrlopencontrols.exceptions import ArgumentsValueError + +from qctrlopencontrols.qiskit import get_rotations + + +def _get_scheduled_circuit(dynamic_decoupling_sequence, + target_qubits, + gate_time, + add_measurement, + device): + + """Returns a scheduled circuit operation constructed from + dynamic decoupling sequence + + Parameters + ---------- + dynamic_decoupling_sequence : DynamicDecouplingSequence + The dynamic decoupling sequence + target_qubits : list + List of target qubits for the sequence operation; the qubits must be + cirq.Qid type + gate_time : float, optional + Time (in seconds) delay introduced by a gate; defaults to 0.1 + add_measurement : bool + If True, a measurement operation is added to each of the qubits. + device : cirq.Device + The device where these operations will be running. + + Returns + ------- + cirq.Schedule + The scheduled circuit operations. The Schedule object contains a + series of desired gates at specific times measured from the start + of the duration. + + Raises + ------ + ArgumentsValueError + If there is rotations around more than one axis at any of the offsets + """ + + # time in nano seconds + gate_time = gate_time * 1e9 + + rabi_rotations = dynamic_decoupling_sequence.rabi_rotations + azimuthal_angles = dynamic_decoupling_sequence.azimuthal_angles + detuning_rotations = dynamic_decoupling_sequence.detuning_rotations + + if len(rabi_rotations.shape) == 1: + rabi_rotations = rabi_rotations[np.newaxis, :] + if len(azimuthal_angles.shape) == 1: + azimuthal_angles = azimuthal_angles[np.newaxis, :] + if len(detuning_rotations.shape) == 1: + detuning_rotations = detuning_rotations[np.newaxis, :] + + operations = np.vstack((rabi_rotations, azimuthal_angles, detuning_rotations)) + offsets = dynamic_decoupling_sequence.offsets + # offsets in nano seconds + offsets = offsets * 1e9 + + circuit_operations = [] + offset_count = 0 + for op_idx in range(operations.shape[1]): + instance_operation = np.array([dynamic_decoupling_sequence.rabi_rotations[op_idx], + dynamic_decoupling_sequence.azimuthal_angles[op_idx], + dynamic_decoupling_sequence.detuning_rotations[op_idx] + ]) + + rotations = get_rotations(instance_operation) + nonzero_pulse_counts = 0 + for rotation in rotations: + if not np.isclose(rotation, 0.0): + nonzero_pulse_counts += 1 + if nonzero_pulse_counts > 1: + raise ArgumentsValueError( + 'Open Controls support a sequence with one ' + 'valid pulse at any offset. Found sequence ' + 'with multiple rotation operations at an offset.', + {'dynamic_decoupling_sequence': str(dynamic_decoupling_sequence), + 'instance_operation': instance_operation}) + + for qubit in target_qubits: + if nonzero_pulse_counts == 0: + operation = cirq.ScheduledOperation( + time=cirq.Timestamp(nanos=offsets[op_idx]), + duration=cirq.Duration(nanos=gate_time), + operation=cirq.I(qubit)) + else: + if not np.isclose(rotations[0], 0.0): + operation = cirq.ScheduledOperation( + time=cirq.Timestamp(nanos=offsets[op_idx]), + duration=cirq.Duration(nanos=gate_time), + operation=cirq.Rx(rotations[0])(qubit)) + elif not np.isclose(rotations[1], 0.0): + operation = cirq.ScheduledOperation( + time=cirq.Timestamp(nanos=offsets[op_idx]), + duration=cirq.Duration(nanos=gate_time), + operation=cirq.Rx(rotations[1])(qubit)) + elif not np.isclose(rotations[2], 0.): + operation = cirq.ScheduledOperation( + time=cirq.Timestamp(nanos=offsets[op_idx]), + duration=cirq.Duration(nanos=gate_time), + operation=cirq.Rx(rotations[2])(qubit)) + offset_count += 1 + circuit_operations.append(operation) + + if add_measurement: + for idx, qubit in enumerate(target_qubits): + operation = cirq.ScheduledOperation( + time=cirq.Timestamp(nanos=offsets[-1] + gate_time), + duration=cirq.Duration(nanos=gate_time), + operation=cirq.MeasurementGate( + 1, key='qubit-{}'.format(idx))(qubit)) + circuit_operations.append(operation) + + schedule = cirq.Schedule(device=device, scheduled_operations=circuit_operations) + return schedule + + +def convert_dds_to_cirq_schedule( + dynamic_decoupling_sequence, + target_qubits=None, + gate_time=0.1, + add_measurement=True, + device=None): + + """Converts a Dynamic Decoupling Sequence into quantum circuit + as defined in cirq + + Parameters + ---------- + dynamic_decoupling_sequence : DynamicDecouplingSequence + The dynamic decoupling sequence + target_qubits : list, optional + List of target qubits for the sequence operation; the qubits must be + cirq.Qid type; defaults to None in which case a 1-D lattice of one + qubit is used (indexed as 0). + gate_time : float, optional + Time (in seconds) delay introduced by a gate; defaults to 0.1 + add_measurement : bool, optional + If True, the circuit contains a measurement operation for each of the + target qubits. Measurement from each of the qubits is associated + with a string as key. The string is formatted as 'qubit-X' where + X is a number between 0 and len(target_qubits). + device : cirq.Device, optional + A cirq.Device that specifies hardware constraints for validating circuits + and schedules. If None, a unconstrained device is used. See `Cirq Documentation + ` _. + + Returns + ------- + cirq.Schedule + The schedule of sequence rotation operations. + + + Raises + ------ + ArgumentsValueError + If any of the input parameters result in an invalid operation. + + Notes + ----- + + Dynamic Decoupling Sequences (DDS) consist of idealized pulse operation. Theoretically, + these operations (pi-pulses in X,Y or Z) occur instantaneously. However, in practice, + pulses require time. Therefore, this method of converting an idealized sequence + results to a circuit that is only an approximate implementation of the idealized sequence. + + In idealized definition of DDS, `offsets` represents the instances within sequence + `duration` where a pulse occurs instantaneously. A series of appropriate circuit components + is placed in order to represent these pulses. + + In 'scheduled circuit', the active pulses are scheduled to be activated at a certain + instant calculated from the start of the sequence and continues for a duration + of gate_time. This does not require identity gates to be placed between offsets. + + Q-CTRL Open Controls support operation resulting in rotation around at most one axis at + any offset. + """ + + if dynamic_decoupling_sequence is None: + 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)}) + + if gate_time <= 0: + raise ArgumentsValueError( + 'Time delay of gates must be greater than zero.', + {'gate_time': gate_time}) + + if target_qubits is None: + target_qubits = [cirq.LineQubit(0)] + + if device is None: + device = cirq.UnconstrainedDevice + + if not isinstance(device, cirq.Device): + raise ArgumentsValueError('Device must be a cirq.Device type.', + {'device': device}) + + return _get_scheduled_circuit(dynamic_decoupling_sequence=dynamic_decoupling_sequence, + target_qubits=target_qubits, + gate_time=gate_time, + add_measurement=add_measurement, + device=device) diff --git a/qctrlopencontrols/qiskit/__init__.py b/qctrlopencontrols/qiskit/__init__.py index 062224f0..62df0ae4 100644 --- a/qctrlopencontrols/qiskit/__init__.py +++ b/qctrlopencontrols/qiskit/__init__.py @@ -19,4 +19,6 @@ """ from .constants import (FIX_DURATION_UNITARY, INSTANT_UNITARY) -from .quantum_circuit import convert_dds_to_quantum_circuit +from .quantum_circuit import (convert_dds_to_quantum_circuit, + get_circuit_gate_list, + get_rotations) diff --git a/qctrlopencontrols/qiskit/quantum_circuit.py b/qctrlopencontrols/qiskit/quantum_circuit.py index 51d1f097..7324663a 100644 --- a/qctrlopencontrols/qiskit/quantum_circuit.py +++ b/qctrlopencontrols/qiskit/quantum_circuit.py @@ -30,9 +30,9 @@ from .constants import (FIX_DURATION_UNITARY, INSTANT_UNITARY) -def _get_circuit_gate_list(dynamic_decoupling_sequence, - gate_time, - unitary_time): +def get_circuit_gate_list(dynamic_decoupling_sequence, + gate_time, + unitary_time): """Converts the operations in a sequence into list of gates of a quantum circuit @@ -101,7 +101,7 @@ def _get_circuit_gate_list(dynamic_decoupling_sequence, return circuit_operations -def _get_rotations(operation): +def get_rotations(operation): """Returns the pulses based on the rotation operation @@ -246,7 +246,7 @@ def convert_dds_to_quantum_circuit( if algorithm == FIX_DURATION_UNITARY: unitary_time = gate_time - circuit_gate_list = _get_circuit_gate_list( + circuit_gate_list = get_circuit_gate_list( dynamic_decoupling_sequence=dynamic_decoupling_sequence, gate_time=gate_time, unitary_time=unitary_time) @@ -265,7 +265,7 @@ def convert_dds_to_quantum_circuit( dynamic_decoupling_sequence.detuning_rotations[offset_count] ]) - rotations = _get_rotations(instance_operation) + rotations = get_rotations(instance_operation) nonzero_pulse_counts = 0 for rotation in rotations: if not np.isclose(rotation, 0.0): diff --git a/tests/test_cirq_circuits.py b/tests/test_cirq_circuits.py index 289fdf5e..84a37ad9 100644 --- a/tests/test_cirq_circuits.py +++ b/tests/test_cirq_circuits.py @@ -21,7 +21,8 @@ import cirq from qctrlopencontrols import ( - new_predefined_dds, convert_dds_to_cirq_circuit) + new_predefined_dds, convert_dds_to_cirq_circuit, + convert_dds_to_cirq_schedule) def _create_test_sequence(sequence_scheme, pre_post_rotation): @@ -77,8 +78,8 @@ def _create_test_sequence(sequence_scheme, pre_post_rotation): return sequence -def _check_circuit_output(pre_post_rotation, - circuit_type, expected_state): +def _check_circuit_output(pre_post_rotation, conversion_method, + expected_state): """Check the outcome of a circuit against expected outcome """ @@ -88,9 +89,9 @@ def _check_circuit_output(pre_post_rotation, 'Walsh single-axis', 'quadratic', 'X concatenated', 'XY concatenated']: sequence = _create_test_sequence(sequence_scheme, pre_post_rotation) - cirq_circuit = convert_dds_to_cirq_circuit( + cirq_circuit = conversion_method( dynamic_decoupling_sequence=sequence, - add_measurement=True, circuit_type=circuit_type) + add_measurement=True) results = simulator.run(cirq_circuit) assert results.measurements['qubit-0'] == expected_state @@ -101,11 +102,11 @@ def test_cirq_circuit_operation(): """Tests if the Dynamic Decoupling Sequence gives rise to expected state with different pre-post gates parameters in cirq circuits """ - _check_circuit_output(False, 'scheduled circuit', 0) - _check_circuit_output(True, 'scheduled circuit', 1) + _check_circuit_output(False, convert_dds_to_cirq_circuit, 0) + _check_circuit_output(True, convert_dds_to_cirq_circuit, 1) - _check_circuit_output(False, 'standard circuit', 0) - _check_circuit_output(True, 'standard circuit', 1) + _check_circuit_output(False, convert_dds_to_cirq_schedule, 0) + _check_circuit_output(True, convert_dds_to_cirq_schedule, 1) if __name__ == '__main__': From 228f256f07654c29b038fac775188a861c64f00c Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Mon, 27 May 2019 10:21:21 +1000 Subject: [PATCH 30/42] module dosctring updated --- qctrlopencontrols/cirq/circuit.py | 6 +++--- qctrlopencontrols/cirq/schedule.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/qctrlopencontrols/cirq/circuit.py b/qctrlopencontrols/cirq/circuit.py index dac445f6..7efc6e1f 100644 --- a/qctrlopencontrols/cirq/circuit.py +++ b/qctrlopencontrols/cirq/circuit.py @@ -13,9 +13,9 @@ # limitations under the License. """ -================= -cirq.cirq_circuit -================= +============ +cirq.circuit +============ """ import numpy as np diff --git a/qctrlopencontrols/cirq/schedule.py b/qctrlopencontrols/cirq/schedule.py index 49324df4..16b63894 100644 --- a/qctrlopencontrols/cirq/schedule.py +++ b/qctrlopencontrols/cirq/schedule.py @@ -13,9 +13,9 @@ # limitations under the License. """ -================= -cirq.cirq_circuit -================= +============= +cirq.schedule +============= """ import numpy as np From edd85f2e795f22cda0b6233d0da36ecf6313d363 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Mon, 27 May 2019 11:34:25 +1000 Subject: [PATCH 31/42] cirq notebook updated with separate method for circuit and schedule; algorithm keyword removed from qiskit example --- examples/export_a_dds_to_cirq.ipynb | 51 ++++++++------------------- examples/export_a_dds_to_qiskit.ipynb | 33 ++++++----------- 2 files changed, 25 insertions(+), 59 deletions(-) diff --git a/examples/export_a_dds_to_cirq.ipynb b/examples/export_a_dds_to_cirq.ipynb index 95652d01..76da163b 100644 --- a/examples/export_a_dds_to_cirq.ipynb +++ b/examples/export_a_dds_to_cirq.ipynb @@ -6,7 +6,7 @@ "source": [ "# Export a Dynamical Decoupling Sequence to Cirq\n", "\n", - "Q-CTRL Open Controls provides easy-to-use methods to construct Dynamical Decoupling Sequences (DDS) according to well-known dynamical decoupling schemes. This is described in the [creating a DDS notebook](creating_a_dds.ipynb). Here we show how a DDS from Q-CTRL Open Controls can be exported as quantum circuit (`cirq.Circuit` or `cirq.Schedule`) and run in `cirq.Simulator`.\n", + "Q-CTRL Open Controls provides easy-to-use methods to construct Dynamical Decoupling Sequences (DDS) according to well-known dynamical decoupling schemes. This is described in the [creating a DDS notebook](creating_a_dds.ipynb). Here we show how a DDS from Q-CTRL Open Controls can be exported as `cirq.Circuit` or `cirq.Schedule` and run in `cirq.Simulator`.\n", "\n", "Note : You can install `cirq` by simply running `pip install cirq`. Please consult [Cirq Documentation](https://cirq.readthedocs.io/en/stable/) for installation instruction and general introduction to `cirq` package." ] @@ -20,7 +20,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -30,7 +30,7 @@ "from matplotlib.gridspec import GridSpec\n", "\n", "#Q-CTRL Open Controls\n", - "from qctrlopencontrols import new_predefined_dds, convert_dds_to_cirq_circuit\n", + "from qctrlopencontrols import new_predefined_dds, convert_dds_to_cirq_circuit, convert_dds_to_cirq_schedule\n", "\n", "#Cirq : to run the circuit on simulator\n", "import cirq" @@ -46,7 +46,7 @@ "\n", "Q-CTRL Open Controls defines a DDS as a set of instantaneous unitary operations performed at specific offset times, see the [technical documentation](https://docs.q-ctrl.com/control-library#dynamical-decoupling-sequences) for mathematical details.\n", "\n", - "`cirq` implements quantum operations through a series of [gates](https://cirq.readthedocs.io/en/stable/gates.html). Standard way to create a circuit is through `cirq.Circuit` that accepts a list of valid gates. If a user wants to add pauses (in time) during a computation they can use identity gates. Alternatively, `cirq` provides `ScheduledOperation` that specifies an operation (application of a gate on one more qubits) at a certain instant measured in \"nano-seconds\" or \"pico-seconds\" from the start of the sequence. A list of `ScheduledOperation` is collated by `cirq.Schedule`. Both `cirq.Circuit` and `cirq.Schedule` can be used in `cirq.Simulator` to simulate the circuit. We provide a `circuit_type` option to select between `cirq.Circuit` and `cirq.Schedule` as desired output from the conversion method.\n", + "`cirq` implements quantum operations through a series of [gates](https://cirq.readthedocs.io/en/stable/gates.html). Standard way to create a circuit is through `cirq.Circuit` that accepts a list of valid gates. If a user wants to add pauses (in time) during a computation they can use identity gates. Alternatively, `cirq` provides `ScheduledOperation` that specifies an operation (application of a gate on one more qubits) at a certain instant measured in \"nano-seconds\" or \"pico-seconds\" from the start of the sequence. A list of `ScheduledOperation` is collated by `cirq.Schedule`. Both `cirq.Circuit` and `cirq.Schedule` can be used in `cirq.Simulator` to simulate the circuit. We provide two methods -`convert_dds_to_cirq_ircuit` and `covert_dds_to_cirq_schedule` to select between `cirq.Circuit` and `cirq.Schedule` as desired output from the conversion method.\n", "\n", "Converting a DDS into a `cirq.Circuit` or `cirq.Schedule` is an approximate process where the instantaneous unitaries are replaced with finite duration gates. Moreover, in `cirq.Circuit`, the pauses in-between unitaries are replaced with the closest integer number of identity gates. The exact algorithm used to make this approximation is documented in the [source code](../qctrlopencontrols/cirq/cirq_circuit.py).\n", "\n", @@ -62,7 +62,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -105,7 +105,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -131,31 +131,12 @@ "'''\n", "add_measurement = True\n", "\n", - "'''\n", - "circuit_type : str\n", - " One of 'scheduled circuit' (convert to cirq.Schedule) or \n", - " 'standard circuit' (convert to cirq.Circuit). See source code\n", - " documentation for more details.\n", - "'''\n", - "circuit_type = 'standard circuit'\n", - "\n", - "'''\n", - "algorithm : str\n", - " An optional string to specify the algorithm used to place identity gates.\n", - " Can be 'instant unitary' or 'fixed duration unitary'. See source code\n", - " documentation for more details.\n", - "'''\n", - "algorithm = 'instant unitary'\n", - "\n", - "\n", "## convert the quadratic sequence to cirq.Circuit\n", "quadratic_cirq_circuit = convert_dds_to_cirq_circuit(\n", " dynamic_decoupling_sequence=quadratic_sequence,\n", " target_qubits=target_qubits,\n", " gate_time=gate_time,\n", - " add_measurement=add_measurement,\n", - " circuit_type=circuit_type,\n", - " algorithm=algorithm\n", + " add_measurement=add_measurement\n", ")" ] }, @@ -170,7 +151,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -237,7 +218,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 5, "metadata": {}, "outputs": [ { @@ -264,7 +245,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -303,12 +284,12 @@ "source": [ "### Creating a Schedule and running on Cirq Simulator\n", "\n", - "We can create a `cirq.Schedule` from the DDS. The steps are exactly similar as shown above for `cirq.Circuit` except the `circuit_type` to be changed." + "We can create a `cirq.Schedule` from the DDS using `convert_dds_to_cirq_schedule` method." ] }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -321,16 +302,12 @@ } ], "source": [ - "## set the circuit type as 'scheduled circuit'\n", - "circuit_type='scheduled circuit'\n", - "\n", "## convert the quadratic sequence to cirq.Schedule\n", - "quadratic_cirq_circuit = convert_dds_to_cirq_circuit(\n", + "quadratic_cirq_circuit = convert_dds_to_cirq_schedule(\n", " dynamic_decoupling_sequence=quadratic_sequence,\n", " target_qubits=target_qubits,\n", " gate_time=gate_time,\n", - " add_measurement=add_measurement,\n", - " circuit_type=circuit_type\n", + " add_measurement=add_measurement\n", ")\n", "\n", "##### Set the simulator parameters\n", diff --git a/examples/export_a_dds_to_qiskit.ipynb b/examples/export_a_dds_to_qiskit.ipynb index 2bf90004..f80146f5 100755 --- a/examples/export_a_dds_to_qiskit.ipynb +++ b/examples/export_a_dds_to_qiskit.ipynb @@ -164,15 +164,6 @@ "'''\n", "circuit_name = 'quadratic-sequence-circuit'\n", "\n", - "'''\n", - "algorithm : str\n", - " An optional string to specify the algorithm used to place identity gates.\n", - " Can be 'instant unitary' or 'fixed duration unitary'. See source code\n", - " documentation for more details.\n", - "'''\n", - "algorithm = 'instant unitary'\n", - "\n", - "\n", "## convert the quadratic sequence to QuantumCircuit\n", "\n", "quadratic_quantum_circuit = convert_dds_to_quantum_circuit(\n", @@ -180,8 +171,7 @@ " target_qubits=target_qubits,\n", " gate_time=gate_time,\n", " add_measurement=add_measurement,\n", - " circuit_name=circuit_name,\n", - " algorithm=algorithm\n", + " circuit_name=circuit_name\n", ")\n", "\n", "## convert the ramsey sequence to QuantumCircuit\n", @@ -191,8 +181,7 @@ " target_qubits=target_qubits,\n", " gate_time=gate_time,\n", " add_measurement=add_measurement,\n", - " circuit_name=circuit_name,\n", - " algorithm=algorithm\n", + " circuit_name=circuit_name\n", ")" ] }, @@ -393,7 +382,7 @@ "« " ], "text/plain": [ - "" + "" ] }, "execution_count": 6, @@ -465,7 +454,7 @@ "« " ], "text/plain": [ - "" + "" ] }, "execution_count": 7, @@ -645,7 +634,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -657,12 +646,12 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] }, - "execution_count": 14, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -686,7 +675,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -698,12 +687,12 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] }, - "execution_count": 15, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -736,7 +725,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 15, "metadata": { "scrolled": true }, From b3ffaed07700deae385bbf242b267e89f3b5dbd3 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Mon, 27 May 2019 11:40:55 +1000 Subject: [PATCH 32/42] both notebooks: some latex formatting fixed; qiskit notebook- gate_time in text updated to 0.4 to match the code --- examples/export_a_dds_to_cirq.ipynb | 4 ++-- examples/export_a_dds_to_qiskit.ipynb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/export_a_dds_to_cirq.ipynb b/examples/export_a_dds_to_cirq.ipynb index 76da163b..b1fe8178 100644 --- a/examples/export_a_dds_to_cirq.ipynb +++ b/examples/export_a_dds_to_cirq.ipynb @@ -46,7 +46,7 @@ "\n", "Q-CTRL Open Controls defines a DDS as a set of instantaneous unitary operations performed at specific offset times, see the [technical documentation](https://docs.q-ctrl.com/control-library#dynamical-decoupling-sequences) for mathematical details.\n", "\n", - "`cirq` implements quantum operations through a series of [gates](https://cirq.readthedocs.io/en/stable/gates.html). Standard way to create a circuit is through `cirq.Circuit` that accepts a list of valid gates. If a user wants to add pauses (in time) during a computation they can use identity gates. Alternatively, `cirq` provides `ScheduledOperation` that specifies an operation (application of a gate on one more qubits) at a certain instant measured in \"nano-seconds\" or \"pico-seconds\" from the start of the sequence. A list of `ScheduledOperation` is collated by `cirq.Schedule`. Both `cirq.Circuit` and `cirq.Schedule` can be used in `cirq.Simulator` to simulate the circuit. We provide two methods -`convert_dds_to_cirq_ircuit` and `covert_dds_to_cirq_schedule` to select between `cirq.Circuit` and `cirq.Schedule` as desired output from the conversion method.\n", + "`cirq` implements quantum operations through a series of [gates](https://cirq.readthedocs.io/en/stable/gates.html). Standard way to create a circuit is through `cirq.Circuit` that accepts a list of valid gates. If a user wants to add pauses (in time) during a computation they can use identity gates. Alternatively, `cirq` provides `ScheduledOperation` that specifies an operation (application of a gate on one more qubits) at a certain instant measured in \"nano-seconds\" or \"pico-seconds\" from the start of the sequence. A list of `ScheduledOperation` is collated by `cirq.Schedule`. Both `cirq.Circuit` and `cirq.Schedule` can be used in `cirq.Simulator` to simulate the circuit. We provide two methods -`convert_dds_to_cirq_circuit` and `covert_dds_to_cirq_schedule` to select between `cirq.Circuit` and `cirq.Schedule` as desired output from the conversion method.\n", "\n", "Converting a DDS into a `cirq.Circuit` or `cirq.Schedule` is an approximate process where the instantaneous unitaries are replaced with finite duration gates. Moreover, in `cirq.Circuit`, the pauses in-between unitaries are replaced with the closest integer number of identity gates. The exact algorithm used to make this approximation is documented in the [source code](../qctrlopencontrols/cirq/cirq_circuit.py).\n", "\n", @@ -211,7 +211,7 @@ "\n", "The $Rz(\\pi)$ gates are $Z_\\pi$ pulses (a $\\pi$ rotation around $Z$-axis) and $Rx(\\pi)$ gates correspond to $X_{\\pi}$ pulses (a $\\pi$ rotation around $X$-axis). The gates match the pulses in the DDS.\n", "\n", - "The `I` in the drawing corresponds to the `identity` gate. In the DDS, the first $Z_{\\pi}$-pulse is applied at a delay of $1.25$ $\\mu$s. This is approximated by introducing 3-`Id` gates with a delay of $0.4\\times 3=1.2$ $\\mu$s. Similarly, the second set of 6 Id gates introduces a delay of 2.4 𝜇 s close to the actual delay of 3.75−1.25=2.50 microseconds.\n", + "The `I` in the drawing corresponds to the `identity` gate. In the DDS, the first $Z_{\\pi}$-pulse is applied at a delay of $1.25$ $\\mu$s. This is approximated by introducing 3-`Id` gates with a delay of $0.4\\times 3=1.2$ $\\mu s$. Similarly, the second set of 6 Id gates introduces a delay of 2.4$\\mu s$ close to the actual delay of $3.75−1.25=2.50\\mu s$.\n", "\n", "At the end of the circuit, we placed a `measurement` ($M$) operator to read out the result." ] diff --git a/examples/export_a_dds_to_qiskit.ipynb b/examples/export_a_dds_to_qiskit.ipynb index f80146f5..344206d4 100755 --- a/examples/export_a_dds_to_qiskit.ipynb +++ b/examples/export_a_dds_to_qiskit.ipynb @@ -129,7 +129,7 @@ "\n", "See the [source code](https://github.com/qctrl/python-open-controls/blob/master/qctrlopencontrols/qiskit/quantum_circuit.py) for more information and other parameters that may be useful.\n", "\n", - "In this example, we will use $0$th qubit and specify the `gate_time` to be $0.2$ $\\mu$s. For a quadratic DDS, we will use default $X_{\\pi/2}$ rotation as the pre-post gate (Ramsey DDS has this rotation as part of the sequence definition). Both the DDS will require a measurement operation." + "In this example, we will use $0$th qubit and specify the `gate_time` to be $0.4$ $\\mu$s. For a quadratic DDS, we will use default $X_{\\pi/2}$ rotation as the pre-post gate (Ramsey DDS has this rotation as part of the sequence definition). Both the DDS will require a measurement operation." ] }, { @@ -315,7 +315,7 @@ "\n", "The $U1(\\pi)$ gates are $Z_\\pi$ pulses (a $\\pi$ rotation around $Z$-axis) and $U3(\\pi, -\\pi/2, \\pi/2)$ gates correspond to $X_{\\pi}$ pulses (a $\\pi$ rotation around $X$-axis). The gates match the pulses in the DDS.\n", "\n", - "The `Id` in the drawing corresponds to the `identity` gate. In the DDS, the first $Z_{\\pi}$-pulse is applied at a delay of $1.25$ $\\mu$s. This is approximated by introducing 3-`Id` gates with a delay of $0.4\\times 3=1.2$ $\\mu$s. Similarly, the second set of 6 `Id` gates introduces a delay of $2.4$ $\\mu$s close to the actual delay of $3.75-1.25=2.50$ microseconds.\n", + "The `Id` in the drawing corresponds to the `identity` gate. In the DDS, the first $Z_{\\pi}$-pulse is applied at a delay of $1.25$ $\\mu$s. This is approximated by introducing 3-`Id` gates with a delay of $0.4\\times 3=1.2$ $\\mu s$. Similarly, the second set of 6 `Id` gates introduces a delay of $2.4$ $\\mu s$ close to the actual delay of $3.75-1.25=2.50\\mu s$.\n", "\n", "The `barrier` gates are special gates that tell the Qiskit compilers not to simplify a circuit at the specified positions.\n", "\n", From 25cda21c11111222e7579b7213932bb0965d8146 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Mon, 27 May 2019 12:00:56 +1000 Subject: [PATCH 33/42] cirq files dosctring udpated to only contain either circuit or schedule in respective files --- examples/example_sequence.csv | 18 ----------- qctrlopencontrols/cirq/circuit.py | 26 ++++++++-------- qctrlopencontrols/cirq/schedule.py | 49 +++++++++++++++--------------- 3 files changed, 36 insertions(+), 57 deletions(-) delete mode 100644 examples/example_sequence.csv diff --git a/examples/example_sequence.csv b/examples/example_sequence.csv deleted file mode 100644 index 2f7b4ef8..00000000 --- a/examples/example_sequence.csv +++ /dev/null @@ -1,18 +0,0 @@ -rabi_rate,azimuthal_angle,detuning,duration,maximum_rabi_rate -0.0,0.0,0.0,4.999999999999999e-07,6283185.307179586 -0.0,0.0,3.141592653589793,2.4999999999999994e-07,6283185.307179586 -0.0,0.0,0.0,9.999999999999997e-07,6283185.307179586 -0.0,0.0,3.141592653589793,2.4999999999999994e-07,6283185.307179586 -0.0,0.0,0.0,2.5000000000000015e-07,6283185.307179586 -1.0,0.0,0.0,5.000000000000003e-07,6283185.307179586 -0.0,0.0,0.0,8.749999999999997e-07,6283185.307179586 -0.0,0.0,3.141592653589793,2.499999999999997e-07,6283185.307179586 -0.0,0.0,0.0,2.2500000000000005e-06,6283185.307179586 -0.0,0.0,3.141592653589793,2.499999999999993e-07,6283185.307179586 -0.0,0.0,0.0,8.750000000000001e-07,6283185.307179586 -1.0,0.0,0.0,4.999999999999994e-07,6283185.307179586 -0.0,0.0,0.0,2.50000000000001e-07,6283185.307179586 -0.0,0.0,3.141592653589793,2.499999999999993e-07,6283185.307179586 -0.0,0.0,0.0,1.0000000000000023e-06,6283185.307179586 -0.0,0.0,3.141592653589793,2.499999999999993e-07,6283185.307179586 -0.0,0.0,0.0,5.000000000000003e-07,6283185.307179586 \ No newline at end of file diff --git a/qctrlopencontrols/cirq/circuit.py b/qctrlopencontrols/cirq/circuit.py index 7efc6e1f..368dd9f2 100644 --- a/qctrlopencontrols/cirq/circuit.py +++ b/qctrlopencontrols/cirq/circuit.py @@ -30,11 +30,11 @@ get_circuit_gate_list, get_rotations) -def _get_standard_circuit(dynamic_decoupling_sequence, - target_qubits, - gate_time, - algorithm, - add_measurement): +def _get_cirq_circuit(dynamic_decoupling_sequence, + target_qubits, + gate_time, + algorithm, + add_measurement): """Returns a standard circuit constructed from dynamic decoupling sequence @@ -52,8 +52,7 @@ def _get_standard_circuit(dynamic_decoupling_sequence, One of 'fixed duration unitary' or 'instant unitary'; In the case of 'fixed duration unitary', the operations are assumed to be taking the amount of gate_time while 'instant unitary' assumes unitaries to be instantaneous; - defaults to 'instant unitary'. Note that this option is only used for - 'standard circuit'; 'scheduled circuit' always contains a 'fixed duration unitary'. + defaults to 'instant unitary'. add_measurement : bool If True, a measurement operation is added to each of the qubits. @@ -161,8 +160,7 @@ def convert_dds_to_cirq_circuit( 'fixed duration unitary', the sequence operations are assumed to be taking the amount of gate_time while 'instant unitary' assumes the sequence operations are instantaneous (and hence does not contribute to the delay between - offsets). Defaults to 'instant unitary'. Note that this option is only used for - 'standard circuit'; 'scheduled circuit' always contains a 'fixed duration unitary'. + offsets). Defaults to 'instant unitary'. Returns ------- @@ -220,8 +218,8 @@ def convert_dds_to_cirq_circuit( raise ArgumentsValueError('Algorithm must be one of {} or {}'.format( INSTANT_UNITARY, FIX_DURATION_UNITARY), {'algorithm': algorithm}) - return _get_standard_circuit(dynamic_decoupling_sequence=dynamic_decoupling_sequence, - target_qubits=target_qubits, - gate_time=gate_time, - algorithm=algorithm, - add_measurement=add_measurement) + return _get_cirq_circuit(dynamic_decoupling_sequence=dynamic_decoupling_sequence, + target_qubits=target_qubits, + gate_time=gate_time, + algorithm=algorithm, + add_measurement=add_measurement) diff --git a/qctrlopencontrols/cirq/schedule.py b/qctrlopencontrols/cirq/schedule.py index 16b63894..3e0ce360 100644 --- a/qctrlopencontrols/cirq/schedule.py +++ b/qctrlopencontrols/cirq/schedule.py @@ -28,14 +28,13 @@ from qctrlopencontrols.qiskit import get_rotations -def _get_scheduled_circuit(dynamic_decoupling_sequence, - target_qubits, - gate_time, - add_measurement, - device): +def _get_cirq_schedule(dynamic_decoupling_sequence, + target_qubits, + gate_time, + add_measurement, + device): - """Returns a scheduled circuit operation constructed from - dynamic decoupling sequence + """Returns a scheduled operations constructed from dynamic decoupling sequence Parameters ---------- @@ -54,7 +53,7 @@ def _get_scheduled_circuit(dynamic_decoupling_sequence, Returns ------- cirq.Schedule - The scheduled circuit operations. The Schedule object contains a + The scheduled rotation operations. The Schedule object contains a series of desired gates at specific times measured from the start of the duration. @@ -83,7 +82,7 @@ def _get_scheduled_circuit(dynamic_decoupling_sequence, # offsets in nano seconds offsets = offsets * 1e9 - circuit_operations = [] + scheduled_operations = [] offset_count = 0 for op_idx in range(operations.shape[1]): instance_operation = np.array([dynamic_decoupling_sequence.rabi_rotations[op_idx], @@ -127,7 +126,7 @@ def _get_scheduled_circuit(dynamic_decoupling_sequence, duration=cirq.Duration(nanos=gate_time), operation=cirq.Rx(rotations[2])(qubit)) offset_count += 1 - circuit_operations.append(operation) + scheduled_operations.append(operation) if add_measurement: for idx, qubit in enumerate(target_qubits): @@ -136,9 +135,9 @@ def _get_scheduled_circuit(dynamic_decoupling_sequence, duration=cirq.Duration(nanos=gate_time), operation=cirq.MeasurementGate( 1, key='qubit-{}'.format(idx))(qubit)) - circuit_operations.append(operation) + scheduled_operations.append(operation) - schedule = cirq.Schedule(device=device, scheduled_operations=circuit_operations) + schedule = cirq.Schedule(device=device, scheduled_operations=scheduled_operations) return schedule @@ -149,7 +148,7 @@ def convert_dds_to_cirq_schedule( add_measurement=True, device=None): - """Converts a Dynamic Decoupling Sequence into quantum circuit + """Converts a Dynamic Decoupling Sequence into schedule as defined in cirq Parameters @@ -163,13 +162,13 @@ def convert_dds_to_cirq_schedule( gate_time : float, optional Time (in seconds) delay introduced by a gate; defaults to 0.1 add_measurement : bool, optional - If True, the circuit contains a measurement operation for each of the + If True, the schedule contains a measurement operation for each of the target qubits. Measurement from each of the qubits is associated with a string as key. The string is formatted as 'qubit-X' where X is a number between 0 and len(target_qubits). device : cirq.Device, optional - A cirq.Device that specifies hardware constraints for validating circuits - and schedules. If None, a unconstrained device is used. See `Cirq Documentation + A cirq.Device that specifies hardware constraints for validating operations. + If None, a unconstrained device is used. See `Cirq Documentation ` _. Returns @@ -189,13 +188,13 @@ def convert_dds_to_cirq_schedule( Dynamic Decoupling Sequences (DDS) consist of idealized pulse operation. Theoretically, these operations (pi-pulses in X,Y or Z) occur instantaneously. However, in practice, pulses require time. Therefore, this method of converting an idealized sequence - results to a circuit that is only an approximate implementation of the idealized sequence. + results to a schedule that is only an approximate implementation of the idealized sequence. In idealized definition of DDS, `offsets` represents the instances within sequence - `duration` where a pulse occurs instantaneously. A series of appropriate circuit components - is placed in order to represent these pulses. + `duration` where a pulse occurs instantaneously. A series of appropriate rotation + operations is placed in order to represent these pulses. - In 'scheduled circuit', the active pulses are scheduled to be activated at a certain + In cirq.schedule, the active pulses are scheduled to be activated at a certain instant calculated from the start of the sequence and continues for a duration of gate_time. This does not require identity gates to be placed between offsets. @@ -228,8 +227,8 @@ def convert_dds_to_cirq_schedule( raise ArgumentsValueError('Device must be a cirq.Device type.', {'device': device}) - return _get_scheduled_circuit(dynamic_decoupling_sequence=dynamic_decoupling_sequence, - target_qubits=target_qubits, - gate_time=gate_time, - add_measurement=add_measurement, - device=device) + return _get_cirq_schedule(dynamic_decoupling_sequence=dynamic_decoupling_sequence, + target_qubits=target_qubits, + gate_time=gate_time, + add_measurement=add_measurement, + device=device) From ef9511958ee73c8140667856532599f8a915edbe Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Wed, 29 May 2019 20:47:59 +1000 Subject: [PATCH 34/42] Minor text correction in qiskit --- examples/export_a_dds_to_qiskit.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/export_a_dds_to_qiskit.ipynb b/examples/export_a_dds_to_qiskit.ipynb index 344206d4..a5c254fd 100755 --- a/examples/export_a_dds_to_qiskit.ipynb +++ b/examples/export_a_dds_to_qiskit.ipynb @@ -129,7 +129,7 @@ "\n", "See the [source code](https://github.com/qctrl/python-open-controls/blob/master/qctrlopencontrols/qiskit/quantum_circuit.py) for more information and other parameters that may be useful.\n", "\n", - "In this example, we will use $0$th qubit and specify the `gate_time` to be $0.4$ $\\mu$s. For a quadratic DDS, we will use default $X_{\\pi/2}$ rotation as the pre-post gate (Ramsey DDS has this rotation as part of the sequence definition). Both the DDS will require a measurement operation." + "In this example, we will use $0$th qubit and specify the `gate_time` to be $0.4$ $\\mu$s. Both the DDS will require a measurement operation." ] }, { From f27def87ea11f4d95fafa6c2b6fd81afdd16af6e Mon Sep 17 00:00:00 2001 From: michaelhush Date: Thu, 30 May 2019 11:42:47 +1000 Subject: [PATCH 35/42] Minor link fix in notebook --- examples/export_a_dds_to_cirq.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/export_a_dds_to_cirq.ipynb b/examples/export_a_dds_to_cirq.ipynb index b1fe8178..efada7c0 100644 --- a/examples/export_a_dds_to_cirq.ipynb +++ b/examples/export_a_dds_to_cirq.ipynb @@ -50,7 +50,7 @@ "\n", "Converting a DDS into a `cirq.Circuit` or `cirq.Schedule` is an approximate process where the instantaneous unitaries are replaced with finite duration gates. Moreover, in `cirq.Circuit`, the pauses in-between unitaries are replaced with the closest integer number of identity gates. The exact algorithm used to make this approximation is documented in the [source code](../qctrlopencontrols/cirq/cirq_circuit.py).\n", "\n", - "In this example we will define a Quadratic DDS and convert it into a circuit that we can later run on a simulator. Note that we add a $X_{\\pi/2}$ rotation at both ends of the sequence. See [creating_a_DDS.ipynb](creating_a_DDS.ipynb) to see how other sequences can be created." + "In this example we will define a Quadratic DDS and convert it into a circuit that we can later run on a simulator. Note that we add a $X_{\\pi/2}$ rotation at both ends of the sequence. See [creating_a_dds.ipynb](creating_a_dds.ipynb) to see how other sequences can be created." ] }, { @@ -354,7 +354,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.8" + "version": "3.6.7" } }, "nbformat": 4, From 93558109224f4b875da0820206150c02a54ea44f Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Thu, 30 May 2019 14:01:36 +1000 Subject: [PATCH 36/42] get methods removed from qiskit; all methods are now self contained --- qctrlopencontrols/cirq/circuit.py | 196 +++++++++----------- qctrlopencontrols/cirq/schedule.py | 196 ++++++++------------ qctrlopencontrols/globals/__init__.py | 10 + qctrlopencontrols/qiskit/__init__.py | 4 +- qctrlopencontrols/qiskit/constants.py | 30 --- qctrlopencontrols/qiskit/quantum_circuit.py | 143 +++++++------- 6 files changed, 252 insertions(+), 327 deletions(-) delete mode 100644 qctrlopencontrols/qiskit/constants.py diff --git a/qctrlopencontrols/cirq/circuit.py b/qctrlopencontrols/cirq/circuit.py index 368dd9f2..35dbb369 100644 --- a/qctrlopencontrols/cirq/circuit.py +++ b/qctrlopencontrols/cirq/circuit.py @@ -24,110 +24,7 @@ from qctrlopencontrols.dynamic_decoupling_sequences import DynamicDecouplingSequence from qctrlopencontrols.exceptions import ArgumentsValueError - -from qctrlopencontrols.qiskit import ( - FIX_DURATION_UNITARY, INSTANT_UNITARY, - get_circuit_gate_list, get_rotations) - - -def _get_cirq_circuit(dynamic_decoupling_sequence, - target_qubits, - gate_time, - algorithm, - add_measurement): - - """Returns a standard circuit constructed from dynamic - decoupling sequence - - Parameters - ---------- - dynamic_decoupling_sequence : DynamicDecouplingSequence - The dynamic decoupling sequence - target_qubits : list - List of target qubits for the sequence operation; the qubits must be - cirq.Qid type - gate_time : float, optional - Time (in seconds) delay introduced by a gate; defaults to 0.1 - algorithm : str, optional - One of 'fixed duration unitary' or 'instant unitary'; In the case of - 'fixed duration unitary', the operations are assumed to be taking the amount of - gate_time while 'instant unitary' assumes unitaries to be instantaneous; - defaults to 'instant unitary'. - add_measurement : bool - If True, a measurement operation is added to each of the qubits. - - Returns - ------- - cirq.Circuit - The circuit prepared from dynamic decoupling sequence. In standard circuit - the desired decoupling pulses are placed at offsets and the duration between - the pulses are constructed from identity gates with delays equal to 'gate_time'. - - Raises - ------ - ArgumentsValueError - If there is rotations around more than one axis at any of the offsets - """ - - unitary_time = 0. - if algorithm == FIX_DURATION_UNITARY: - unitary_time = gate_time - - circuit_gate_list = get_circuit_gate_list( - dynamic_decoupling_sequence=dynamic_decoupling_sequence, - gate_time=gate_time, - unitary_time=unitary_time) - - circuit = cirq.Circuit() - - offset_count = 0 - for gate in circuit_gate_list: - - if gate == 'id': - gate_list = [] - for qubit in target_qubits: - gate_list.append(cirq.I(qubit)) - circuit.append(gate_list) - continue - - instance_operation = np.array( - [dynamic_decoupling_sequence.rabi_rotations[offset_count], - dynamic_decoupling_sequence.azimuthal_angles[offset_count], - dynamic_decoupling_sequence.detuning_rotations[offset_count]]) - - rotations = get_rotations(instance_operation) - nonzero_pulse_counts = 0 - for rotation in rotations: - if not np.isclose(rotation, 0.0): - nonzero_pulse_counts += 1 - if nonzero_pulse_counts > 1: - raise ArgumentsValueError( - 'Open Controls support a sequence with one ' - 'valid pulse at any offset. Found sequence ' - 'with multiple rotation operations at an offset.', - {'dynamic_decoupling_sequence': str(dynamic_decoupling_sequence), - 'instance_operation': instance_operation}) - gate_list = [] - for qubit in target_qubits: - if nonzero_pulse_counts == 0: - gate_list.append(cirq.I(qubit)) - else: - if not np.isclose(rotations[0], 0.0): - gate_list.append(cirq.Rx(rotations[0])(qubit)) - elif not np.isclose(rotations[1], 0.0): - gate_list.append(cirq.Ry(rotations[1])(qubit)) - elif not np.isclose(rotations[2], 0.): - gate_list.append(cirq.Rz(rotations[2])(qubit)) - offset_count += 1 - circuit.append(gate_list) - - if add_measurement: - gate_list = [] - for idx, qubit in enumerate(target_qubits): - gate_list.append(cirq.measure(qubit, key='qubit-{}'.format(idx))) - circuit.append(gate_list) - - return circuit +from qctrlopencontrols.globals import (FIX_DURATION_UNITARY, INSTANT_UNITARY) def convert_dds_to_cirq_circuit( @@ -218,8 +115,89 @@ def convert_dds_to_cirq_circuit( raise ArgumentsValueError('Algorithm must be one of {} or {}'.format( INSTANT_UNITARY, FIX_DURATION_UNITARY), {'algorithm': algorithm}) - return _get_cirq_circuit(dynamic_decoupling_sequence=dynamic_decoupling_sequence, - target_qubits=target_qubits, - gate_time=gate_time, - algorithm=algorithm, - add_measurement=add_measurement) + unitary_time = 0. + if algorithm == FIX_DURATION_UNITARY: + unitary_time = gate_time + + rabi_rotations = dynamic_decoupling_sequence.rabi_rotations + azimuthal_angles = dynamic_decoupling_sequence.azimuthal_angles + detuning_rotations = dynamic_decoupling_sequence.detuning_rotations + + if len(rabi_rotations.shape) == 1: + rabi_rotations = rabi_rotations[np.newaxis, :] + if len(azimuthal_angles.shape) == 1: + azimuthal_angles = azimuthal_angles[np.newaxis, :] + if len(detuning_rotations.shape) == 1: + detuning_rotations = detuning_rotations[np.newaxis, :] + + operations = np.vstack((rabi_rotations, azimuthal_angles, detuning_rotations)) + offsets = dynamic_decoupling_sequence.offsets + + time_covered = 0 + circuit = cirq.Circuit() + for operation_idx in range(operations.shape[1]): + + offset_distance = offsets[operation_idx] - time_covered + + if np.isclose(offset_distance, 0.0): + offset_distance = 0.0 + + if offset_distance < 0: + raise ArgumentsValueError("Offsets cannot be placed properly", + {'sequence_operations': operations}) + + if offset_distance > 0: + while (time_covered <= offsets[operation_idx]): + gate_list = [] + for qubit in target_qubits: + gate_list.append(cirq.I(qubit)) + time_covered += gate_time + circuit.append(gate_list) + + rabi_rotation = operations[0, operation_idx] + azimuthal_angle = operations[1, operation_idx] + x_rotation = rabi_rotation * np.cos(azimuthal_angle) + y_rotation = rabi_rotation * np.sin(azimuthal_angle) + z_rotation = operations[2, operation_idx] + + rotations = np.array([x_rotation, y_rotation, z_rotation]) + zero_pulses = np.isclose(rotations, 0.0).astype(np.int) + nonzero_pulse_counts = 3 - np.sum(zero_pulses) + if nonzero_pulse_counts > 1: + raise ArgumentsValueError( + 'Open Controls support a sequence with one ' + 'valid pulse at any offset. Found sequence ' + 'with multiple rotation operations at an offset.', + {'dynamic_decoupling_sequence': str(dynamic_decoupling_sequence), + 'offset': dynamic_decoupling_sequence.offsets[operation_idx], + 'rabi_rotation': dynamic_decoupling_sequence.rabi_rotations[ + operation_idx], + 'azimuthal_angle': dynamic_decoupling_sequence.azimuthal_angles[ + operation_idx], + 'detuning_rotaion': dynamic_decoupling_sequence.detuning_rotations[ + operation_idx]} + ) + + gate_list = [] + for qubit in target_qubits: + if nonzero_pulse_counts == 0: + gate_list.append(cirq.I(qubit)) + else: + if not np.isclose(rotations[0], 0.0): + gate_list.append(cirq.Rx(rotations[0])(qubit)) + elif not np.isclose(rotations[1], 0.0): + gate_list.append(cirq.Ry(rotations[1])(qubit)) + elif not np.isclose(rotations[2], 0.): + gate_list.append(cirq.Rz(rotations[2])(qubit)) + circuit.append(gate_list) + if np.isclose(np.sum(rotations), 0.0): + time_covered = offsets[operation_idx] + else: + time_covered = offsets[operation_idx] + unitary_time + if add_measurement: + gate_list = [] + for idx, qubit in enumerate(target_qubits): + gate_list.append(cirq.measure(qubit, key='qubit-{}'.format(idx))) + circuit.append(gate_list) + + return circuit diff --git a/qctrlopencontrols/cirq/schedule.py b/qctrlopencontrols/cirq/schedule.py index 3e0ce360..33261a3f 100644 --- a/qctrlopencontrols/cirq/schedule.py +++ b/qctrlopencontrols/cirq/schedule.py @@ -25,44 +25,93 @@ from qctrlopencontrols.dynamic_decoupling_sequences import DynamicDecouplingSequence from qctrlopencontrols.exceptions import ArgumentsValueError -from qctrlopencontrols.qiskit import get_rotations +def convert_dds_to_cirq_schedule( + dynamic_decoupling_sequence, + target_qubits=None, + gate_time=0.1, + add_measurement=True, + device=None): -def _get_cirq_schedule(dynamic_decoupling_sequence, - target_qubits, - gate_time, - add_measurement, - device): - - """Returns a scheduled operations constructed from dynamic decoupling sequence + """Converts a Dynamic Decoupling Sequence into schedule + as defined in cirq Parameters ---------- dynamic_decoupling_sequence : DynamicDecouplingSequence The dynamic decoupling sequence - target_qubits : list + target_qubits : list, optional List of target qubits for the sequence operation; the qubits must be - cirq.Qid type + cirq.Qid type; defaults to None in which case a 1-D lattice of one + qubit is used (indexed as 0). gate_time : float, optional Time (in seconds) delay introduced by a gate; defaults to 0.1 - add_measurement : bool - If True, a measurement operation is added to each of the qubits. - device : cirq.Device - The device where these operations will be running. + add_measurement : bool, optional + If True, the schedule contains a measurement operation for each of the + target qubits. Measurement from each of the qubits is associated + with a string as key. The string is formatted as 'qubit-X' where + X is a number between 0 and len(target_qubits). + device : cirq.Device, optional + A cirq.Device that specifies hardware constraints for validating operations. + If None, a unconstrained device is used. See `Cirq Documentation + ` _. Returns ------- cirq.Schedule - The scheduled rotation operations. The Schedule object contains a - series of desired gates at specific times measured from the start - of the duration. + The schedule of sequence rotation operations. + Raises ------ ArgumentsValueError - If there is rotations around more than one axis at any of the offsets + If any of the input parameters result in an invalid operation. + + Notes + ----- + + Dynamic Decoupling Sequences (DDS) consist of idealized pulse operation. Theoretically, + these operations (pi-pulses in X,Y or Z) occur instantaneously. However, in practice, + pulses require time. Therefore, this method of converting an idealized sequence + results to a schedule that is only an approximate implementation of the idealized sequence. + + In idealized definition of DDS, `offsets` represents the instances within sequence + `duration` where a pulse occurs instantaneously. A series of appropriate rotation + operations is placed in order to represent these pulses. + + In cirq.schedule, the active pulses are scheduled to be activated at a certain + instant calculated from the start of the sequence and continues for a duration + of gate_time. This does not require identity gates to be placed between offsets. + + Q-CTRL Open Controls support operation resulting in rotation around at most one axis at + any offset. """ + if dynamic_decoupling_sequence is None: + 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)}) + + if gate_time <= 0: + raise ArgumentsValueError( + 'Time delay of gates must be greater than zero.', + {'gate_time': gate_time}) + + if target_qubits is None: + target_qubits = [cirq.LineQubit(0)] + + if device is None: + device = cirq.UnconstrainedDevice + + if not isinstance(device, cirq.Device): + raise ArgumentsValueError('Device must be a cirq.Device type.', + {'device': device}) + # time in nano seconds gate_time = gate_time * 1e9 @@ -85,12 +134,14 @@ def _get_cirq_schedule(dynamic_decoupling_sequence, scheduled_operations = [] offset_count = 0 for op_idx in range(operations.shape[1]): - instance_operation = np.array([dynamic_decoupling_sequence.rabi_rotations[op_idx], - dynamic_decoupling_sequence.azimuthal_angles[op_idx], - dynamic_decoupling_sequence.detuning_rotations[op_idx] - ]) - rotations = get_rotations(instance_operation) + rabi_rotation = dynamic_decoupling_sequence.rabi_rotations[offset_count] + azimuthal_angle = dynamic_decoupling_sequence.azimuthal_angles[offset_count] + x_rotation = rabi_rotation * np.cos(azimuthal_angle) + y_rotation = rabi_rotation * np.sin(azimuthal_angle) + z_rotation = dynamic_decoupling_sequence.detuning_rotations[offset_count] + + rotations = np.array([x_rotation, y_rotation, z_rotation]) nonzero_pulse_counts = 0 for rotation in rotations: if not np.isclose(rotation, 0.0): @@ -101,7 +152,11 @@ def _get_cirq_schedule(dynamic_decoupling_sequence, 'valid pulse at any offset. Found sequence ' 'with multiple rotation operations at an offset.', {'dynamic_decoupling_sequence': str(dynamic_decoupling_sequence), - 'instance_operation': instance_operation}) + 'offset': dynamic_decoupling_sequence.offsets[offset_count], + 'rabi_rotation': dynamic_decoupling_sequence.rabi_rotations[offset_count], + 'azimuthal_angle': dynamic_decoupling_sequence.azimuthal_angles[offset_count], + 'detuning_rotaion': dynamic_decoupling_sequence.detuning_rotations[offset_count]} + ) for qubit in target_qubits: if nonzero_pulse_counts == 0: @@ -139,96 +194,3 @@ def _get_cirq_schedule(dynamic_decoupling_sequence, schedule = cirq.Schedule(device=device, scheduled_operations=scheduled_operations) return schedule - - -def convert_dds_to_cirq_schedule( - dynamic_decoupling_sequence, - target_qubits=None, - gate_time=0.1, - add_measurement=True, - device=None): - - """Converts a Dynamic Decoupling Sequence into schedule - as defined in cirq - - Parameters - ---------- - dynamic_decoupling_sequence : DynamicDecouplingSequence - The dynamic decoupling sequence - target_qubits : list, optional - List of target qubits for the sequence operation; the qubits must be - cirq.Qid type; defaults to None in which case a 1-D lattice of one - qubit is used (indexed as 0). - gate_time : float, optional - Time (in seconds) delay introduced by a gate; defaults to 0.1 - add_measurement : bool, optional - If True, the schedule contains a measurement operation for each of the - target qubits. Measurement from each of the qubits is associated - with a string as key. The string is formatted as 'qubit-X' where - X is a number between 0 and len(target_qubits). - device : cirq.Device, optional - A cirq.Device that specifies hardware constraints for validating operations. - If None, a unconstrained device is used. See `Cirq Documentation - ` _. - - Returns - ------- - cirq.Schedule - The schedule of sequence rotation operations. - - - Raises - ------ - ArgumentsValueError - If any of the input parameters result in an invalid operation. - - Notes - ----- - - Dynamic Decoupling Sequences (DDS) consist of idealized pulse operation. Theoretically, - these operations (pi-pulses in X,Y or Z) occur instantaneously. However, in practice, - pulses require time. Therefore, this method of converting an idealized sequence - results to a schedule that is only an approximate implementation of the idealized sequence. - - In idealized definition of DDS, `offsets` represents the instances within sequence - `duration` where a pulse occurs instantaneously. A series of appropriate rotation - operations is placed in order to represent these pulses. - - In cirq.schedule, the active pulses are scheduled to be activated at a certain - instant calculated from the start of the sequence and continues for a duration - of gate_time. This does not require identity gates to be placed between offsets. - - Q-CTRL Open Controls support operation resulting in rotation around at most one axis at - any offset. - """ - - if dynamic_decoupling_sequence is None: - 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)}) - - if gate_time <= 0: - raise ArgumentsValueError( - 'Time delay of gates must be greater than zero.', - {'gate_time': gate_time}) - - if target_qubits is None: - target_qubits = [cirq.LineQubit(0)] - - if device is None: - device = cirq.UnconstrainedDevice - - if not isinstance(device, cirq.Device): - raise ArgumentsValueError('Device must be a cirq.Device type.', - {'device': device}) - - return _get_cirq_schedule(dynamic_decoupling_sequence=dynamic_decoupling_sequence, - target_qubits=target_qubits, - gate_time=gate_time, - add_measurement=add_measurement, - device=device) diff --git a/qctrlopencontrols/globals/__init__.py b/qctrlopencontrols/globals/__init__.py index 78ccdc81..d3d25a39 100644 --- a/qctrlopencontrols/globals/__init__.py +++ b/qctrlopencontrols/globals/__init__.py @@ -39,3 +39,13 @@ CYLINDRICAL = 'cylindrical' """Defines Cylindrical coordinate system """ + +FIX_DURATION_UNITARY = 'fixed duration unitary' +"""Algorithm to convert a DDS to Quantum circuit +where the unitaries are considered as gates with finite duration +""" + +INSTANT_UNITARY = 'instant unitary' +"""Algorithm to convert a DDS to Quantum circuit where the +unitaties are considered as instantaneous operation. +""" diff --git a/qctrlopencontrols/qiskit/__init__.py b/qctrlopencontrols/qiskit/__init__.py index 62df0ae4..b9945374 100644 --- a/qctrlopencontrols/qiskit/__init__.py +++ b/qctrlopencontrols/qiskit/__init__.py @@ -18,7 +18,5 @@ ============= """ -from .constants import (FIX_DURATION_UNITARY, INSTANT_UNITARY) from .quantum_circuit import (convert_dds_to_quantum_circuit, - get_circuit_gate_list, - get_rotations) + get_circuit_gate_list) diff --git a/qctrlopencontrols/qiskit/constants.py b/qctrlopencontrols/qiskit/constants.py deleted file mode 100644 index dba899b3..00000000 --- a/qctrlopencontrols/qiskit/constants.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2019 Q-CTRL Pty Ltd & Q-CTRL Inc -# -# 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. - -""" -================ -qiskit.constants -================ -""" - - -FIX_DURATION_UNITARY = 'fixed duration unitary' -"""Algorithm to convert a DDS to Quantum circuit -where the unitaries are considered as gates with finite duration -""" - -INSTANT_UNITARY = 'instant unitary' -"""Algorithm to convert a DDS to Quantum circuit where the -unitaties are considered as instantaneous operation. -""" diff --git a/qctrlopencontrols/qiskit/quantum_circuit.py b/qctrlopencontrols/qiskit/quantum_circuit.py index 7324663a..13062231 100644 --- a/qctrlopencontrols/qiskit/quantum_circuit.py +++ b/qctrlopencontrols/qiskit/quantum_circuit.py @@ -26,8 +26,7 @@ from qctrlopencontrols.dynamic_decoupling_sequences import DynamicDecouplingSequence from qctrlopencontrols.exceptions import ArgumentsValueError - -from .constants import (FIX_DURATION_UNITARY, INSTANT_UNITARY) +from qctrlopencontrols.globals import (FIX_DURATION_UNITARY, INSTANT_UNITARY) def get_circuit_gate_list(dynamic_decoupling_sequence, @@ -101,32 +100,6 @@ def get_circuit_gate_list(dynamic_decoupling_sequence, return circuit_operations -def get_rotations(operation): - - """Returns the pulses based on the rotation operation - - Parameters - ---------- - operation : numpy.ndarray - 1-D array (length=3) consisting of rabi rotation, azimuthal_angle - and detuning_rotation at an offset of a sequence - - Returns - ------- - numpy.ndarray - A 1-D array of length 3 containing x_rotation, y_rotation and z_rotation - calculated from sequence operation - """ - - x_rotation = operation[0] * np.cos(operation[1]) - y_rotation = operation[0] * np.sin(operation[1]) - z_rotation = operation[2] - - pulses = np.array([x_rotation, y_rotation, z_rotation]) - - return pulses - - def convert_dds_to_quantum_circuit( dynamic_decoupling_sequence, target_qubits=None, @@ -246,54 +219,88 @@ def convert_dds_to_quantum_circuit( if algorithm == FIX_DURATION_UNITARY: unitary_time = gate_time - circuit_gate_list = get_circuit_gate_list( - dynamic_decoupling_sequence=dynamic_decoupling_sequence, - gate_time=gate_time, - unitary_time=unitary_time) - - offset_count = 0 - for gate in circuit_gate_list: - - if gate == 'id': - 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 - continue - - instance_operation = np.array([dynamic_decoupling_sequence.rabi_rotations[offset_count], - dynamic_decoupling_sequence.azimuthal_angles[offset_count], - dynamic_decoupling_sequence.detuning_rotations[offset_count] - ]) - - rotations = get_rotations(instance_operation) - nonzero_pulse_counts = 0 - for rotation in rotations: - if not np.isclose(rotation, 0.0): - nonzero_pulse_counts += 1 + rabi_rotations = dynamic_decoupling_sequence.rabi_rotations + azimuthal_angles = dynamic_decoupling_sequence.azimuthal_angles + detuning_rotations = dynamic_decoupling_sequence.detuning_rotations + + if len(rabi_rotations.shape) == 1: + rabi_rotations = rabi_rotations[np.newaxis, :] + if len(azimuthal_angles.shape) == 1: + azimuthal_angles = azimuthal_angles[np.newaxis, :] + if len(detuning_rotations.shape) == 1: + detuning_rotations = detuning_rotations[np.newaxis, :] + + operations = np.vstack((rabi_rotations, azimuthal_angles, detuning_rotations)) + offsets = dynamic_decoupling_sequence.offsets + + time_covered = 0 + for operation_idx in range(operations.shape[1]): + + offset_distance = offsets[operation_idx] - time_covered + + if np.isclose(offset_distance, 0.0): + offset_distance = 0.0 + + if offset_distance < 0: + raise ArgumentsValueError("Offsets cannot be placed properly", + {'sequence_operations': operations}) + + if offset_distance > 0: + while (time_covered <= offsets[operation_idx]): + 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 + time_covered += gate_time + # circuit_operations.append('offset') + + rabi_rotation = operations[0, operation_idx] + azimuthal_angle = operations[1, operation_idx] + x_rotation = rabi_rotation * np.cos(azimuthal_angle) + y_rotation = rabi_rotation * np.sin(azimuthal_angle) + z_rotation = operations[2, operation_idx] + + rotations = np.array([x_rotation, y_rotation, z_rotation]) + zero_pulses = np.isclose(rotations, 0.0).astype(np.int) + nonzero_pulse_counts = 3 - np.sum(zero_pulses) if nonzero_pulse_counts > 1: - raise ArgumentsValueError('Open Controls support a sequence with one ' - 'valid pulse at any offset. Found sequence ' - 'with multiple rotation operations at an offset.', - {'dynamic_decoupling_sequence': str( - dynamic_decoupling_sequence), - 'instance_operation': instance_operation}) + raise ArgumentsValueError( + 'Open Controls support a sequence with one ' + 'valid pulse at any offset. Found sequence ' + 'with multiple rotation operations at an offset.', + {'dynamic_decoupling_sequence': str(dynamic_decoupling_sequence), + 'offset': dynamic_decoupling_sequence.offsets[operation_idx], + 'rabi_rotation': dynamic_decoupling_sequence.rabi_rotations[ + operation_idx], + 'azimuthal_angle': dynamic_decoupling_sequence.azimuthal_angles[ + operation_idx], + 'detuning_rotaion': dynamic_decoupling_sequence.detuning_rotations[ + operation_idx]} + ) + for qubit in target_qubits: if nonzero_pulse_counts == 0: - quantum_circuit.u3(0., 0., 0., #pylint: disable=no-member - quantum_registers[qubit]) + quantum_circuit.u3( + 0., 0., 0., # pylint: disable=no-member + quantum_registers[qubit]) 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]) + quantum_circuit.u3( + 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]) + quantum_circuit.u3( + rotations[1], 0., 0., # pylint: disable=no-member + quantum_registers[qubit]) elif not np.isclose(rotations[2], 0.): - quantum_circuit.u1(rotations[2], #pylint: disable=no-member - quantum_registers[qubit]) - quantum_circuit.barrier(quantum_registers[qubit]) #pylint: disable=no-member + quantum_circuit.u1( + rotations[2], # pylint: disable=no-member + quantum_registers[qubit]) + quantum_circuit.barrier(quantum_registers[qubit]) # pylint: disable=no-member - offset_count += 1 + if np.isclose(np.sum(rotations), 0.0): + time_covered = offsets[operation_idx] + else: + time_covered = offsets[operation_idx] + unitary_time if add_measurement: for q_index, qubit in enumerate(target_qubits): From 8dc92940de2febacb6566e476fd0797d2f2bb90c Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Thu, 30 May 2019 14:20:30 +1000 Subject: [PATCH 37/42] minor text changes in cirq --- examples/export_a_dds_to_cirq.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/export_a_dds_to_cirq.ipynb b/examples/export_a_dds_to_cirq.ipynb index b1fe8178..fa526d35 100644 --- a/examples/export_a_dds_to_cirq.ipynb +++ b/examples/export_a_dds_to_cirq.ipynb @@ -100,7 +100,7 @@ "\n", "See the [source code](../qctrlopencontrols/cirq/cirq_circuit.py) for more information and other parameters that may be useful.\n", "\n", - "In this example, we will use a single qubit on 1-D lattice and $X_{\\pi/2}$ rotation as the pre-post gate. We specify the `gate_time` to be $0.4$ $\\mu$s. Finally we will add a measurement operation. In this example we will convert the DDS into a `cirq.Circuit`." + "In this example, we will use a single qubit on 1-D lattice. We specify the `gate_time` to be $0.4$ $\\mu$s. Finally we will add a measurement operation. In this example we will convert the DDS into a `cirq.Circuit`." ] }, { @@ -225,7 +225,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "0: ─Rx(0.5π)─I─I─I─Rz(π)─I─I─I─I─I─I─Rz(π)─I─I─I─Rx(π)─I─I─I─I─I─I─Rz(π)─I─I─I─I─I─I─I─I─I─I─I─I─Rz(π)─I─I─I─I─I─I─Rx(π)─I─I─I─Rz(π)─I─I─I─I─I─I─Rz(π)─I─I─I─Rx(0.5π)─M('qubit-0')─\n" + "0: ─Rx(0.5π)─I─I─I─I─Rz(π)─I─I─I─I─I─I─I─Rz(π)─I─I─I─I─Rx(π)─I─I─I─I─I─I─I─Rz(π)─I─I─I─I─I─I─I─I─I─I─I─I─I─Rz(π)─I─I─I─I─I─I─I─Rx(π)─I─I─I─I─Rz(π)─I─I─I─I─I─I─I─Rz(π)─I─I─I─I─Rx(0.5π)─M('qubit-0')─\n" ] } ], From 529507a9562e876028add31cb6159930a2680a6d Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Thu, 30 May 2019 14:25:49 +1000 Subject: [PATCH 38/42] linted --- qctrlopencontrols/cirq/circuit.py | 2 +- qctrlopencontrols/cirq/schedule.py | 17 +++++++++-------- qctrlopencontrols/qiskit/quantum_circuit.py | 3 +-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/qctrlopencontrols/cirq/circuit.py b/qctrlopencontrols/cirq/circuit.py index 35dbb369..3776a729 100644 --- a/qctrlopencontrols/cirq/circuit.py +++ b/qctrlopencontrols/cirq/circuit.py @@ -147,7 +147,7 @@ def convert_dds_to_cirq_circuit( {'sequence_operations': operations}) if offset_distance > 0: - while (time_covered <= offsets[operation_idx]): + while time_covered <= offsets[operation_idx]: gate_list = [] for qubit in target_qubits: gate_list.append(cirq.I(qubit)) diff --git a/qctrlopencontrols/cirq/schedule.py b/qctrlopencontrols/cirq/schedule.py index 33261a3f..00360b6b 100644 --- a/qctrlopencontrols/cirq/schedule.py +++ b/qctrlopencontrols/cirq/schedule.py @@ -142,20 +142,21 @@ def convert_dds_to_cirq_schedule( z_rotation = dynamic_decoupling_sequence.detuning_rotations[offset_count] rotations = np.array([x_rotation, y_rotation, z_rotation]) - nonzero_pulse_counts = 0 - for rotation in rotations: - if not np.isclose(rotation, 0.0): - nonzero_pulse_counts += 1 + zero_pulses = np.isclose(rotations, 0.0).astype(np.int) + nonzero_pulse_counts = 3 - np.sum(zero_pulses) if nonzero_pulse_counts > 1: raise ArgumentsValueError( 'Open Controls support a sequence with one ' 'valid pulse at any offset. Found sequence ' 'with multiple rotation operations at an offset.', {'dynamic_decoupling_sequence': str(dynamic_decoupling_sequence), - 'offset': dynamic_decoupling_sequence.offsets[offset_count], - 'rabi_rotation': dynamic_decoupling_sequence.rabi_rotations[offset_count], - 'azimuthal_angle': dynamic_decoupling_sequence.azimuthal_angles[offset_count], - 'detuning_rotaion': dynamic_decoupling_sequence.detuning_rotations[offset_count]} + 'offset': dynamic_decoupling_sequence.offsets[op_idx], + 'rabi_rotation': dynamic_decoupling_sequence.rabi_rotations[ + op_idx], + 'azimuthal_angle': dynamic_decoupling_sequence.azimuthal_angles[ + op_idx], + 'detuning_rotaion': dynamic_decoupling_sequence.detuning_rotations[ + op_idx]} ) for qubit in target_qubits: diff --git a/qctrlopencontrols/qiskit/quantum_circuit.py b/qctrlopencontrols/qiskit/quantum_circuit.py index 13062231..05dec421 100644 --- a/qctrlopencontrols/qiskit/quantum_circuit.py +++ b/qctrlopencontrols/qiskit/quantum_circuit.py @@ -246,12 +246,11 @@ def convert_dds_to_quantum_circuit( {'sequence_operations': operations}) if offset_distance > 0: - while (time_covered <= offsets[operation_idx]): + while time_covered <= offsets[operation_idx]: 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 time_covered += gate_time - # circuit_operations.append('offset') rabi_rotation = operations[0, operation_idx] azimuthal_angle = operations[1, operation_idx] From 7f9d2a2f12fa80b326634e8c8782406b6b38e926 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Thu, 30 May 2019 14:32:33 +1000 Subject: [PATCH 39/42] id gate insert logic fixed --- qctrlopencontrols/cirq/circuit.py | 2 +- qctrlopencontrols/qiskit/quantum_circuit.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/qctrlopencontrols/cirq/circuit.py b/qctrlopencontrols/cirq/circuit.py index 35dbb369..cb54e9f6 100644 --- a/qctrlopencontrols/cirq/circuit.py +++ b/qctrlopencontrols/cirq/circuit.py @@ -147,7 +147,7 @@ def convert_dds_to_cirq_circuit( {'sequence_operations': operations}) if offset_distance > 0: - while (time_covered <= offsets[operation_idx]): + while (time_covered+gate_time) <= offsets[operation_idx]: gate_list = [] for qubit in target_qubits: gate_list.append(cirq.I(qubit)) diff --git a/qctrlopencontrols/qiskit/quantum_circuit.py b/qctrlopencontrols/qiskit/quantum_circuit.py index 13062231..e8251c7e 100644 --- a/qctrlopencontrols/qiskit/quantum_circuit.py +++ b/qctrlopencontrols/qiskit/quantum_circuit.py @@ -246,7 +246,7 @@ def convert_dds_to_quantum_circuit( {'sequence_operations': operations}) if offset_distance > 0: - while (time_covered <= offsets[operation_idx]): + while (time_covered+gate_time) <= offsets[operation_idx]: 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 From ab842fe2de270dcab096f38284a769cc7897c8cc Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Thu, 30 May 2019 14:37:50 +1000 Subject: [PATCH 40/42] cirq notebook run again after fixing the id gate insert logic --- examples/export_a_dds_to_cirq.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/export_a_dds_to_cirq.ipynb b/examples/export_a_dds_to_cirq.ipynb index fa526d35..e442df48 100644 --- a/examples/export_a_dds_to_cirq.ipynb +++ b/examples/export_a_dds_to_cirq.ipynb @@ -225,7 +225,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "0: ─Rx(0.5π)─I─I─I─I─Rz(π)─I─I─I─I─I─I─I─Rz(π)─I─I─I─I─Rx(π)─I─I─I─I─I─I─I─Rz(π)─I─I─I─I─I─I─I─I─I─I─I─I─I─Rz(π)─I─I─I─I─I─I─I─Rx(π)─I─I─I─I─Rz(π)─I─I─I─I─I─I─I─Rz(π)─I─I─I─I─Rx(0.5π)─M('qubit-0')─\n" + "0: ─Rx(0.5π)─I─I─I─Rz(π)─I─I─I─I─I─I─Rz(π)─I─I─I─Rx(π)─I─I─I─I─I─I─Rz(π)─I─I─I─I─I─I─I─I─I─I─I─I─Rz(π)─I─I─I─I─I─I─Rx(π)─I─I─I─Rz(π)─I─I─I─I─I─I─Rz(π)─I─I─I─Rx(0.5π)─M('qubit-0')─\n" ] } ], From 6f04813c49bb3004c27632ae666ecdf9f27534a2 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Thu, 30 May 2019 14:39:56 +1000 Subject: [PATCH 41/42] cirq notebook synced with remote --- examples/export_a_dds_to_cirq.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/export_a_dds_to_cirq.ipynb b/examples/export_a_dds_to_cirq.ipynb index 9486ddeb..71f908ad 100644 --- a/examples/export_a_dds_to_cirq.ipynb +++ b/examples/export_a_dds_to_cirq.ipynb @@ -354,7 +354,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.7" + "version": "3.6.8" } }, "nbformat": 4, From f22f5eeb7fdca758bd73f11102240545892f0ea2 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Thu, 30 May 2019 14:47:48 +1000 Subject: [PATCH 42/42] get_circuit_list finally removed from all files --- qctrlopencontrols/qiskit/__init__.py | 3 +- qctrlopencontrols/qiskit/quantum_circuit.py | 71 --------------------- 2 files changed, 1 insertion(+), 73 deletions(-) diff --git a/qctrlopencontrols/qiskit/__init__.py b/qctrlopencontrols/qiskit/__init__.py index b9945374..899a7499 100644 --- a/qctrlopencontrols/qiskit/__init__.py +++ b/qctrlopencontrols/qiskit/__init__.py @@ -18,5 +18,4 @@ ============= """ -from .quantum_circuit import (convert_dds_to_quantum_circuit, - get_circuit_gate_list) +from .quantum_circuit import (convert_dds_to_quantum_circuit) diff --git a/qctrlopencontrols/qiskit/quantum_circuit.py b/qctrlopencontrols/qiskit/quantum_circuit.py index e64f35d2..913f8f4f 100644 --- a/qctrlopencontrols/qiskit/quantum_circuit.py +++ b/qctrlopencontrols/qiskit/quantum_circuit.py @@ -29,77 +29,6 @@ from qctrlopencontrols.globals import (FIX_DURATION_UNITARY, INSTANT_UNITARY) -def get_circuit_gate_list(dynamic_decoupling_sequence, - gate_time, - unitary_time): - - """Converts the operations in a sequence into list of gates - of a quantum circuit - - Parameters - ---------- - dynamic_decoupling_sequence : DynamicDecouplingSequence - Dynamic decoupling sequence instance - gate_time : float - Indicates the delay time of the identity gates - unitary_time : float - Indicates the delay time introduced by unitary gates - - Returns - ------- - list - A list of circuit components with required parameters - - Raises - ------ - ArgumentsValueError - If the offsets cannot be placed properly - """ - - rabi_rotations = dynamic_decoupling_sequence.rabi_rotations - azimuthal_angles = dynamic_decoupling_sequence.azimuthal_angles - detuning_rotations = dynamic_decoupling_sequence.detuning_rotations - - if len(rabi_rotations.shape) == 1: - rabi_rotations = rabi_rotations[np.newaxis, :] - if len(azimuthal_angles.shape) == 1: - azimuthal_angles = azimuthal_angles[np.newaxis, :] - if len(detuning_rotations.shape) == 1: - detuning_rotations = detuning_rotations[np.newaxis, :] - - operations = np.vstack((rabi_rotations, azimuthal_angles, detuning_rotations)) - offsets = dynamic_decoupling_sequence.offsets - - time_covered = 0 - circuit_operations = [] - for operation_idx in range(operations.shape[1]): - - offset_distance = offsets[operation_idx] - time_covered - - if np.isclose(offset_distance, 0.0): - offset_distance = 0.0 - - if offset_distance < 0: - raise ArgumentsValueError("Offsets cannot be placed properly", - {'sequence_operations': operations}) - if offset_distance == 0: - circuit_operations.append('offset') - if np.isclose(np.sum(operations[:, operation_idx]), 0.0): - time_covered = offsets[operation_idx] - else: - time_covered = offsets[operation_idx] + unitary_time - else: - number_of_id_gates = 0 - while (time_covered + (number_of_id_gates+1) * gate_time) <= \ - offsets[operation_idx]: - circuit_operations.append('id') - number_of_id_gates += 1 - circuit_operations.append('offset') - time_covered = offsets[operation_idx] + unitary_time - - return circuit_operations - - def convert_dds_to_quantum_circuit( dynamic_decoupling_sequence, target_qubits=None,