def test_submit_raises_no_success(self, monkeypatch): """Test that the qe_submit method raises an error if a success message was not received.""" no_success_msg = "Not a success message." with monkeypatch.context() as m: # Disable submitting to the Orquestra platform by mocking Popen m.setattr(subprocess, "Popen", lambda *args, **kwargs: MockPopen(no_success_msg)) with pytest.raises(ValueError, match=no_success_msg): qe_submit("some_filename")
def test_submit_raises_unexpected_resp(self, monkeypatch, response): """Test that the qe_submit method raises an error if the workflow id could not be obtained.""" unexp_resp_msg = "Received an unexpected response after submitting workflow." with monkeypatch.context() as m: # Disable submitting to the Orquestra platform by mocking Popen m.setattr(subprocess, "Popen", lambda *args, **kwargs: MockPopen(response)) m.setattr(os, "remove", lambda *args, **kwargs: None) with pytest.raises(ValueError, match=unexp_resp_msg): qe_submit("some_filename")
def test_submit_raises(self, backend_component, tmpdir): """Test that submitting a workflow to Orquestra with invalid requirements raises an error.""" # Skip if not logged in to Orquestra try_resp = qe_list_workflow() need_login_msg = "token has expired, please log in again\n" if need_login_msg in try_resp: pytest.skip("Has not logged in to the Orquestra platform.") circuits = [qasm_circuit_default] # This will not be a valid operator: will raise error operator = [] # Fill in workflow template workflow = gw.gen_expval_workflow(backend_component, backend_specs_default, circuits, operator) file_name = tmpdir.join("test_workflow.yaml") with open(file_name, "w") as file: d = yaml.dump(workflow, file) # Submit a workflow --- error due to the operator with pytest.raises(ValueError, match="Error"): workflow_id = qe_submit(file_name)
def test_can_submit_and_query_workflow_details(self, resources, tmpdir): """Test that filling in the workflow template for getting expectation values can be submitted to Orquestra and workflow details can be queried.""" # Skip if not logged in to Orquestra try_resp = qe_list_workflow() need_login_msg = "token has expired, please log in again\n" if need_login_msg in try_resp: pytest.skip("Has not logged in to the Orquestra platform.") backend_component = "qe-forest" op = ['["[Z0]"]'] circuits = [qasm_circuit_default] # Fill in workflow template workflow = gw.gen_expval_workflow(backend_component, backend_specs_default, circuits, op, resources=resources) file_name = tmpdir.join("test_workflow.yaml") with open(file_name, "w") as file: d = yaml.dump(workflow, file) # Submit a workflow workflow_id = qe_submit(file_name) workflow_msg = workflow_details(workflow_id) details_string = "".join(workflow_msg) assert workflow_id in details_string
def execute(self, circuit, **kwargs): # Input checks not_all_expval = any(obs.return_type is not Expectation for obs in circuit.observables) if not_all_expval: raise NotImplementedError( f"The {self.short_name} device only supports returning expectation values." ) self.check_validity(circuit.operations, circuit.observables) qasm_circuit = self.serialize_circuit(circuit) # 2. Create the qubit operators ops, identity_indices = self.process_observables(circuit.observables) if not ops: # All the observables were identity, no workflow submission needed return self._asarray([1] * len(identity_indices)) ops_json = json.dumps(ops) # Single step: need to nest the operators into a list ops = [ops_json] qasm_circuit = [qasm_circuit] # 4-5. Create the backend specs & workflow file workflow = gen_expval_workflow( self.qe_component, self.backend_specs, qasm_circuit, ops, resources=self._resources, **kwargs, ) file_id = str(uuid.uuid4()) filename = f"expval-{file_id}.yaml" filepath = write_workflow_file(filename, workflow) # 6. Submit the workflow workflow_id = qe_submit(filepath, keep_file=self._keep_files) if self._keep_files: self._filenames.append(filename) self._latest_id = workflow_id # 7. Loop until finished results = self.single_step_results(workflow_id) # Insert the theoretical value for the expectation value of the # identity operator for idx in identity_indices: results.insert(idx, 1) res = self._asarray(results) return res
def multi_step_execute(self, circuits, file_id, **kwargs): """Creates a multi-step workflow for executing a batch of circuits. Args: circuits (list[QuantumTape]): circuits to execute on the device file_id (str): the file id to be used for naming the workflow file Returns: list[array[float]]: list of measured value(s) for the batch """ for circuit in circuits: # Input checks not_all_expval = any(obs.return_type is not Expectation for obs in circuit.observables) if not_all_expval: raise NotImplementedError( f"The {self.short_name} device only supports returning expectation values." ) self.check_validity(circuit.operations, circuit.observables) # 1. Create qasm strings from the circuits qasm_circuits = [ self.serialize_circuit(circuit) for circuit in circuits ] # 2. Create the qubit operators of observables for each circuit ops = [] identity_indices = {} empty_obs_list = [] for idx, circuit in enumerate(circuits): processed_observables, current_id_indices = self.process_observables( circuit.observables) ops.append(processed_observables) if not processed_observables: # Keep track of empty observable lists empty_obs_list.append(idx) identity_indices[idx] = current_id_indices if not all(ops): # There were batches which had only identity observables if not any(ops): # All the batches only had identity observables, no workflow submission needed return [ self._asarray([1] * len(circuit.observables)) for circuit in circuits ] # Remove the empty lists so that those are not submitted ops = [o for o in ops if o] # Multiple steps: need to create json strings as elements of the list ops = [json.dumps(o) for o in ops] # 3-4. Create the backend specs & workflow file workflow = gen_expval_workflow( self.qe_component, self.backend_specs, qasm_circuits, ops, resources=self._resources, **kwargs, ) filename = f"expval-{file_id}.yaml" filepath = write_workflow_file(filename, workflow) # 5. Submit the workflow workflow_id = qe_submit(filepath, keep_file=self._keep_files) self._latest_id = workflow_id if self._keep_files: self._filenames.append(filename) # 6. Loop until finished results = self.multiple_steps_results(workflow_id) results = self.insert_identity_res_batch(results, empty_obs_list, identity_indices) results = [self._asarray(res) for res in results] return results