Skip to content

Commit

Permalink
[SDS-977] Easier handling async jobs (#156)
Browse files Browse the repository at this point in the history
* [SDS-977] Easier handling async jobs

* removed deprecated qiskit stuff and updated python versions

* travis does not support 3.11 yet
  • Loading branch information
QFer committed May 2, 2023
1 parent a1e7be6 commit 81df362
Show file tree
Hide file tree
Showing 10 changed files with 23 additions and 245 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/nightly.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ jobs:
with:
repository: qiskit/qiskit-terra
path: qiskit-terra
- name: Set up Python 3.7
- name: Set up Python 3.8
uses: actions/setup-python@v4
with:
python-version: 3.7
python-version: 3.8
- name: pip install prerequisites
run: pip install --upgrade cython ./qiskit-terra .[dev]
- name: Run examples
Expand Down
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,14 @@ def get_long_description():
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'License :: OSI Approved :: Apache Software License'],
license='Apache 2.0',
packages=['quantuminspire', 'quantuminspire.qiskit', 'quantuminspire.projectq'],
install_requires=['coverage>=4.5.1', 'matplotlib>=2.1', 'pylatexenc', 'coreapi>=2.3.3', 'numpy>=1.20', 'jupyter',
'nbimporter', 'qilib'],
extras_require={
'qiskit': ["qiskit>=0.20.0"],
'qiskit': ["qiskit>=0.40.0"],
'projectq': ["projectq>=0.4"],
'dev': ['pytest>=3.3.1', "pylint", "mypy>=0.670"],
'rtd': ['sphinx', 'sphinx_rtd_theme', 'nbsphinx', 'sphinx-automodapi', 'recommonmark'],
Expand Down
15 changes: 7 additions & 8 deletions src/quantuminspire/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ def get_raw_data_from_result(self, result_id: int) -> List[List[Any]]:
Gets the raw data from the result of the executed job, given the result_id.
The raw data consists of a list of measurements for each shot (job.number_of_shots).
The measurements contains a list of data for each measurement in the job (len(measurement_mask)).
The measurements contain a list of data for each measurement in the job (len(measurement_mask)).
The data consist of integer state values (0 or 1) for each measured qubit, else None (see measurement_mask).
Actual type is: List[List[List[Optional[int]]]] with least significant qubit first.
Expand Down Expand Up @@ -873,10 +873,9 @@ def _create_asset(self, name: str, project: Dict[str, Any], content: str) -> Dic

# other #

@staticmethod
def _wait_for_completed_job(quantum_inspire_job: QuantumInspireJob, collect_max_tries: Optional[int] = None,
sec_retry_delay: float = 0.5) -> Tuple[bool, str]:
"""Wait for job completion.
def wait_for_completed_job(self, quantum_inspire_job: QuantumInspireJob, collect_max_tries: Optional[int] = None,
sec_retry_delay: float = 0.5) -> Tuple[bool, str]:
""" Wait for job completion.
Delays the process and requests the job status. The waiting loop is broken when the job status is
completed or cancelled, or when the maximum number of tries is set and has been reached.
Expand Down Expand Up @@ -937,7 +936,7 @@ def execute_qasm(self, qasm: str, backend_type: Optional[Union[Dict[str, Any], i
:param qasm: The cQASM code as string object.
:param backend_type: The backend_type to execute the algorithm on.
:param number_of_shots: Execution times of the algorithm before collecting the results.
:param collect_tries: The number of times the status of the job is check for completion before returning.
:param collect_tries: The number of times the status of the job is checked for completion before returning.
:param default_number_of_shots: The default used number of shots for the project.
:param identifier: The identifier to generate names for the project, asset and job when necessary.
:param full_state_projection: Do not use full state projection with simulations when set to False (default).
Expand All @@ -958,7 +957,7 @@ def execute_qasm(self, qasm: str, backend_type: Optional[Union[Dict[str, Any], i
full_state_projection=full_state_projection,
user_data=user_data)

has_results, message = self._wait_for_completed_job(quantum_inspire_job, collect_tries)
has_results, message = self.wait_for_completed_job(quantum_inspire_job, collect_tries)
return dict(quantum_inspire_job.retrieve_results()) if has_results else \
dict(self._generate_error_result(message))
except (CoreAPIException, TypeError, ValueError, ApiError) as err_msg:
Expand All @@ -981,7 +980,7 @@ def execute_qasm_async(self, qasm: str, backend_type: Optional[Union[Dict[str, A
the job to finish and returns the result.
To execute a cQASM program a job is scheduled on a backend of type `backend type` as given by the
parameter backend_type. Currently there are 3 backend types available:
parameter backend_type. Currently, there are 3 backend types available:
1. QX single-node simulator (default for anonymous accounts)
2. QX single-node simulator SurfSara (advanced account credentials needed)
Expand Down
2 changes: 1 addition & 1 deletion src/quantuminspire/qiskit/backend_qx.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class QuantumInspireBackend(Backend): # type: ignore
backend_name='qi_simulator',
backend_version=quantum_inspire_version,
n_qubits=26,
basis_gates=['x', 'y', 'z', 'h', 'rx', 'ry', 'rz', 's', 'sdg', 't', 'tdg', 'cx', 'ccx', 'u1', 'p', 'u2', 'u3',
basis_gates=['x', 'y', 'z', 'h', 'rx', 'ry', 'rz', 's', 'sdg', 't', 'tdg', 'cx', 'ccx', 'p',
'id', 'swap', 'cz', 'snapshot', 'delay', 'barrier'],
gates=[GateConfig(name='NotUsed', parameters=['NaN'], qasm_def='NaN')],
local=False,
Expand Down
36 changes: 2 additions & 34 deletions src/quantuminspire/qiskit/circuit_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ def _u1(stream: StringIO, instruction: QasmQobjInstruction) -> None:
""" Translates the U1(lambda) element to U3(0, 0, lambda).
A copy of the circuit is made to prevent
side-effects for the caller.
side effects for the caller.
:param stream: The string-io stream to where the resulting cQASM is written.
:param instruction: The Qiskit instruction to translate to cQASM.
Expand All @@ -468,7 +468,7 @@ def _c_u1(stream: StringIO, instruction: QasmQobjInstruction, binary_control: st
""" Translates the binary-controlled U1(lambda) element to U3(0, 0, lambda).
A copy of the circuit is
made to prevent side-effects for the caller.
made to prevent side effects for the caller.
:param stream: The string-io stream to where the resulting cQASM is written.
:param instruction: The Qiskit instruction to translate to cQASM.
Expand Down Expand Up @@ -502,38 +502,6 @@ def _c_p(stream: StringIO, instruction: QasmQobjInstruction, binary_control: str
"""
CircuitToString._c_u1(stream, instruction, binary_control)

@staticmethod
def _u2(stream: StringIO, instruction: QasmQobjInstruction) -> None:
""" Translates the U2(phi, lambda) element to U3(pi/2, phi, lambda).
A copy of the circuit is made to prevent
side-effects for the caller.
:param stream: The string-io stream to where the resulting cQASM is written.
:param instruction: The Qiskit instruction to translate to cQASM.
"""
temp_instruction = copy.deepcopy(instruction)
temp_instruction.params.insert(0, np.pi/2)
CircuitToString._u3(stream, temp_instruction)

@staticmethod
def _c_u2(stream: StringIO, instruction: QasmQobjInstruction, binary_control: str) -> None:
""" Translates the binary-controlled U2(phi, lambda) element to U3(pi/2, phi, lambda).
A copy of the
circuit is made to prevent side-effects for the caller.
:param stream: The string-io stream to where the resulting cQASM is written.
:param instruction: The Qiskit instruction to translate to cQASM.
:param binary_control: The multi-bits control string. The gate is executed when all specified classical bits
are 1.
"""
temp_instruction = copy.deepcopy(instruction)
temp_instruction.params.insert(0, np.pi/2)
CircuitToString._c_u3(stream, temp_instruction, binary_control)

@staticmethod
def _u3(stream: StringIO, instruction: QasmQobjInstruction) -> None:
""" Translates the U3(theta, phi, lambda) element to 3 rotation gates.
Expand Down
2 changes: 1 addition & 1 deletion src/quantuminspire/qiskit/quantum_inspire_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def _adjust_backend_configuration(config: QasmBackendConfiguration, backend: Dic
elif gate == 'toffoli':
config.basis_gates += ['ccx']
if 'rz' in config.basis_gates and 'ry' in config.basis_gates:
config.basis_gates += ['u1', 'p', 'u2', 'u3']
config.basis_gates += ['p']

config.simulator = not backend['is_hardware_backend']
config.conditional = not backend['is_hardware_backend']
Expand Down
4 changes: 2 additions & 2 deletions src/tests/quantuminspire/qiskit/test_backend_qx.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ def test_backend_default_configuration(self):
backend_name='qi_simulator',
backend_version=quantum_inspire_version,
n_qubits=26,
basis_gates=['x', 'y', 'z', 'h', 'rx', 'ry', 'rz', 's', 'sdg', 't', 'tdg', 'cx', 'ccx', 'u1', 'p', 'u2',
'u3', 'id', 'swap', 'cz', 'snapshot', 'delay', 'barrier'],
basis_gates=['x', 'y', 'z', 'h', 'rx', 'ry', 'rz', 's', 'sdg', 't', 'tdg', 'cx', 'ccx', 'p',
'id', 'swap', 'cz', 'snapshot', 'delay', 'barrier'],
gates=[GateConfig(name='NotUsed', parameters=['NaN'], qasm_def='NaN')],
conditional=True,
simulator=True,
Expand Down
192 changes: 1 addition & 191 deletions src/tests/quantuminspire/qiskit/test_circuit_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def _generate_cqasm_from_instructions(instructions, number_of_qubits=2, full_sta
'memory_slots': number_of_qubits,
'compiled_circuit_qasm': ''},
'config': {'coupling_map': 'all-to-all',
'basis_gates': 'x,y,z,h,rx,ry,rz,s,cx,ccx,u1,p,u2,u3,id,snapshot',
'basis_gates': 'x,y,z,h,rx,ry,rz,s,cx,ccx,p,id,snapshot',
'n_qubits': number_of_qubits}}
experiment = qiskit.qobj.QasmQobjExperiment.from_dict(experiment_dict)
for instruction in experiment.instructions:
Expand Down Expand Up @@ -455,72 +455,6 @@ def test_generate_cqasm_correct_output_conditional_gate_u(self):
self.assertTrue('not b[2,3]\nC-Rz b[0,1,2,3], q[1], -0.333333\nC-Ry b[0,1,2,3], q[1], 0.123456\nC-Rz b[0,1,2,3],'
' q[1], 0.654321\nnot b[2,3]\n' in result)

def test_generate_cqasm_correct_output_gate_u1_deprecated(self):
# Qiskit u1 is deprecated from 0.16.0. u1 -> p
# As long as it is available we need to support it.
qc = QuantumCircuit(2, 2)
qc.u1(np.pi / 2, 0)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('Rz q[0], 1.570796\n' in result)

qc = QuantumCircuit(2, 2)
qc.u1(np.pi / 4, 1)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('Rz q[1], 0.785398\n' in result)

qc = QuantumCircuit(3, 3)
qc.u1(-np.pi / 4, 2)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('Rz q[2], -0.785398\n' in result)

qc = QuantumCircuit(3, 3)
qc.u1(0.123456, 2)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('Rz q[2], 0.123456\n' in result)

qc = QuantumCircuit(2, 2)
qc.u1(0, 0)
result = self._generate_cqasm_from_circuit(qc)
self.assertFalse('q[0]' in result)

def test_generate_cqasm_correct_output_conditional_gate_u1_deprecated(self):
# Qiskit u1 is deprecated from 0.16.0. u1 -> p
# As long as it is available we need to support it.
q = QuantumRegister(4, "q")
c = ClassicalRegister(4, "c")
qc = QuantumCircuit(q, c, name="test")
qc.u1(np.pi / 2, 0).c_if(c, 3)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('not b[2,3]\nC-Rz b[0,1,2,3], q[0], 1.570796\nnot b[2,3]\n' in result)

q = QuantumRegister(4, "q")
c = ClassicalRegister(4, "c")
qc = QuantumCircuit(q, c, name="test")
qc.u1(np.pi / 4, 1).c_if(c, 3)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('not b[2,3]\nC-Rz b[0,1,2,3], q[1], 0.785398\nnot b[2,3]\n' in result)

q = QuantumRegister(4, "q")
c = ClassicalRegister(4, "c")
qc = QuantumCircuit(q, c, name="test")
qc.u1(-np.pi / 4, 2).c_if(c, 3)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('not b[2,3]\nC-Rz b[0,1,2,3], q[2], -0.785398\nnot b[2,3]\n' in result)

q = QuantumRegister(4, "q")
c = ClassicalRegister(4, "c")
qc = QuantumCircuit(q, c, name="test")
qc.u1(0.123456, 2).c_if(c, 3)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('not b[2,3]\nC-Rz b[0,1,2,3], q[2], 0.123456\nnot b[2,3]\n' in result)

q = QuantumRegister(4, "q")
c = ClassicalRegister(4, "c")
qc = QuantumCircuit(q, c, name="test")
qc.u1(0, 0).c_if(c, 3)
result = self._generate_cqasm_from_circuit(qc)
self.assertFalse('q[0]' in result)

def test_generate_cqasm_correct_output_gate_p(self):
qc = QuantumCircuit(2, 2)
qc.p(np.pi / 2, 0)
Expand Down Expand Up @@ -637,62 +571,6 @@ def test_generate_cqasm_correct_output_conditional_gate_u2(self):
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('not b[2,3]\nC-Ry b[0,1,2,3], q[0], 1.570796\nnot b[2,3]\n' in result)

def test_generate_cqasm_correct_output_gate_u2_deprecated(self):
# Qiskit u2 is deprecated from 0.16.0. u2(a, b) -> u(pi/2, a, b)
# As long as it is available we need to support it.
qc = QuantumCircuit(2, 2)
qc.u2(np.pi, np.pi / 2, 0)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('Rz q[0], 1.570796\nRy q[0], 1.570796\nRz q[0], 3.141593\n' in result)

qc = QuantumCircuit(2, 2)
qc.u2(0, np.pi, 1)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('Rz q[1], 3.141593\nRy q[1], 1.570796\n' in result)

qc = QuantumCircuit(3, 3)
qc.u2(0.123456, -0.654321, 2)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('Rz q[2], -0.654321\nRy q[2], 1.570796\nRz q[2], 0.123456\n' in result)

qc = QuantumCircuit(3, 3)
qc.u2(0, 0, 0)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('Ry q[0], 1.570796\n' in result)

def test_generate_cqasm_correct_output_conditional_gate_u2_deprecated(self):
# Qiskit u2 is deprecated from 0.16.0. u2(a, b) -> u(pi/2, a, b)
# As long as it is available we need to support it.
q = QuantumRegister(4, "q")
c = ClassicalRegister(4, "c")
qc = QuantumCircuit(q, c, name="test")
qc.u2(np.pi, np.pi / 2, 0).c_if(c, 3)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('not b[2,3]\nC-Rz b[0,1,2,3], q[0], 1.570796\nC-Ry b[0,1,2,3], q[0], 1.570796\nC-Rz b[0,1,2,3], q[0],'
' 3.141593\nnot b[2,3]\n' in result)

q = QuantumRegister(4, "q")
c = ClassicalRegister(4, "c")
qc = QuantumCircuit(q, c, name="test")
qc.u2(0, np.pi, 1).c_if(c, 3)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('not b[2,3]\nC-Rz b[0,1,2,3], q[1], 3.141593\nC-Ry b[0,1,2,3], q[1], 1.570796\nnot b[2,3]\n' in result)

q = QuantumRegister(4, "q")
c = ClassicalRegister(4, "c")
qc = QuantumCircuit(q, c, name="test")
qc.u2(0.123456, -0.654321, 2).c_if(c, 3)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('not b[2,3]\nC-Rz b[0,1,2,3], q[2], -0.654321\nC-Ry b[0,1,2,3], q[2], 1.570796\nC-Rz b[0,1,2,3], q[2],'
' 0.123456\nnot b[2,3]\n' in result)

q = QuantumRegister(4, "q")
c = ClassicalRegister(4, "c")
qc = QuantumCircuit(q, c, name="test")
qc.u2(0, 0, 0).c_if(c, 3)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('not b[2,3]\nC-Ry b[0,1,2,3], q[0], 1.570796\nnot b[2,3]\n' in result)

def test_generate_cqasm_correct_output_gate_u3(self):
# Qiskit u3 is deprecated from 0.16.0. u3 -> u
qc = QuantumCircuit(2, 2)
Expand Down Expand Up @@ -759,74 +637,6 @@ def test_generate_cqasm_correct_output_conditional_gate_u3(self):
result = self._generate_cqasm_from_circuit(qc)
self.assertFalse('q[0]' in result)

def test_generate_cqasm_correct_output_gate_u3_deprecated(self):
# Qiskit u3 is deprecated from 0.16.0. u3 -> u
# As long as it is available we need to support it.
qc = QuantumCircuit(2, 2)
qc.u3(1, 2, 3, 0)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('Rz q[0], 3.000000\nRy q[0], 1.000000\nRz q[0], 2.000000\n' in result)

qc = QuantumCircuit(2, 2)
qc.u3(0.123456, 0.654321, -0.333333, 1)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('Rz q[1], -0.333333\nRy q[1], 0.123456\nRz q[1], 0.654321\n' in result)

qc = QuantumCircuit(2, 2)
qc.u3(0, 0.654321, 0, 1)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('Rz q[1], 0.654321\n' in result)

qc = QuantumCircuit(3, 3)
qc.u3(0.654321, 0, 0, 2)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('Ry q[2], 0.654321\n' in result)

qc = QuantumCircuit(2, 2)
qc.u3(0, 0, 0, 0)
result = self._generate_cqasm_from_circuit(qc)
self.assertFalse('q[0]' in result)

def test_generate_cqasm_correct_output_conditional_gate_u3_deprecated(self):
# Qiskit u3 is deprecated from 0.16.0. u3 -> u
# As long as it is available we need to support it.
q = QuantumRegister(4, "q")
c = ClassicalRegister(4, "c")
qc = QuantumCircuit(q, c, name="test")
qc.u3(1, 2, 3, 0).c_if(c, 3)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('not b[2,3]\nC-Rz b[0,1,2,3], q[0], 3.000000\nC-Ry b[0,1,2,3], q[0], 1.000000\nC-Rz b[0,1,2,3], q[0],'
' 2.000000\nnot b[2,3]\n' in result)

q = QuantumRegister(4, "q")
c = ClassicalRegister(4, "c")
qc = QuantumCircuit(q, c, name="test")
qc.u3(0.123456, 0.654321, -0.333333, 1).c_if(c, 3)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('not b[2,3]\nC-Rz b[0,1,2,3], q[1], -0.333333\nC-Ry b[0,1,2,3], q[1], 0.123456\nC-Rz b[0,1,2,3], q[1],'
' 0.654321\nnot b[2,3]\n' in result)

q = QuantumRegister(4, "q")
c = ClassicalRegister(4, "c")
qc = QuantumCircuit(q, c, name="test")
qc.u3(0, 0.654321, 0, 1).c_if(c, 3)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('not b[2,3]\nC-Rz b[0,1,2,3], q[1], 0.654321\nnot b[2,3]\n' in result)

q = QuantumRegister(4, "q")
c = ClassicalRegister(4, "c")
qc = QuantumCircuit(q, c, name="test")
qc.u3(0.654321, 0, 0, 2).c_if(c, 3)
result = self._generate_cqasm_from_circuit(qc)
self.assertTrue('not b[2,3]\nC-Ry b[0,1,2,3], q[2], 0.654321\nnot b[2,3]\n' in result)

q = QuantumRegister(4, "q")
c = ClassicalRegister(4, "c")
qc = QuantumCircuit(q, c, name="test")
qc.u3(0, 0, 0, 0).c_if(c, 3)
result = self._generate_cqasm_from_circuit(qc)
self.assertFalse('q[0]' in result)

def test_generate_cqasm_correct_output_sympy_special_cases(self):
# Zero
qc = QuantumCircuit(2, 2)
Expand Down
Loading

0 comments on commit 81df362

Please sign in to comment.