def test_unsupported_backend_component(self):
        """Test that if an unsupported backend component is input then an error is raised."""
        backend_component = "SomeNonExistentBackend"

        # Fill in workflow template
        with pytest.raises(ValueError, match="The specified backend component is not supported."):
            gw.gen_expval_workflow(
                backend_component,
                backend_specs_default,
                qasm_circuit_default,
                operator_string_default,
            )
Ejemplo n.º 2
0
    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)
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
    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 test_can_yaml(self, tmpdir):
        """Test that filling in the workflow template for getting expectation
        values produces a valid yaml."""
        backend_component = "qe-forest"

        # Fill in workflow template
        workflow = gw.gen_expval_workflow(
            backend_component, backend_specs_default, qasm_circuit_default, operator_string_default
        )

        file_name = tmpdir.join("test_workflow.yaml")

        with open(file_name, "w") as file:
            # Testing that no errors arise here
            yaml.dump(workflow, file)
Ejemplo n.º 6
0
    def test_write_workflow_file(self, tmpdir, monkeypatch):
        """Test that filling in the workflow template for getting expectation
        values produces a valid yaml."""
        backend_component = "qe-forest"

        # Fill in workflow template
        workflow = gw.gen_expval_workflow(backend_component,
                                          backend_specs_default,
                                          qasm_circuit_default,
                                          operator_string_default)

        file_name = "test_workflow.yaml"
        with monkeypatch.context() as m:
            m.setattr(pennylane_orquestra.cli_actions, "user_data_dir",
                      lambda *args: tmpdir)
            write_workflow_file(file_name, workflow)

        with open(tmpdir.join(file_name)) as file:
            loaded_yaml = yaml.load(file, Loader=yaml.FullLoader)

        assert workflow == loaded_yaml
    def test_matches_template(self, resources, test_wf):
        """Test that generating a two-step workflow matches the pre-defined
        template."""
        backend_component = "qe-forest"

        # Fill in workflow template
        circuits = [qasm_circuit_default, qasm_circuit_default]
        workflow = gw.gen_expval_workflow(
            backend_component,
            backend_specs_default,
            circuits,
            operator_string_default,
            resources=resources,
        )

        assert workflow["apiVersion"] == test_wf["apiVersion"]
        assert workflow["name"] == test_wf["name"]
        assert workflow["imports"] == test_wf["imports"]

        compare_two_expval_steps(workflow["steps"][0], test_wf["steps"][0])
        compare_two_expval_steps(workflow["steps"][1], test_wf["steps"][1])
        assert workflow == test_wf
Ejemplo n.º 8
0
    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