Exemplo n.º 1
0
    def get_exact_expectation_values(self, circuit, qubit_operator, **kwargs):
        """Run a circuit to prepare a wavefunction and measure the exact
        expectation values with respect to a given operator.

        Args:
            circuit (zquantum.core.circuit.Circuit): the circuit to prepare the state
            qubit_operator (openfermion.ops.QubitOperator): the operator to measure
        Returns:
            zquantum.core.measurement.ExpectationValues: the expectation values
                of each term in the operator
        """
        self.num_circuits_run += 1
        self.num_jobs_run += 1
        wavefunction = self.get_wavefunction(circuit)

        # Pyquil does not support PauliSums with no terms.
        if len(qubit_operator.terms) == 0:
            return ExpectationValues(np.zeros((0, )))

        values = []

        for op in qubit_operator:
            values.append(expectation(op, wavefunction))
        return expectation_values_to_real(ExpectationValues(
            np.asarray(values)))
Exemplo n.º 2
0
    def get_expectation_values(self, circuit, qubit_operator, **kwargs):
        """Run a circuit and measure the expectation values with respect to a
        given operator. Note: the number of bitstrings measured is derived
        from self.n_samples - if self.n_samples = None, then this will use
        self.get_exact_expectation_values

        Args:
            circuit (zquantum.core.circuit.Circuit): the circuit to prepare the state
            qubit_operator (openfermion.ops.QubitOperator): the operator to measure
        Returns:
            zquantum.core.measurement.ExpectationValues: the expectation values
                of each term in the operator
        """
        self.num_circuits_run += 1
        self.num_jobs_run += 1
        if self.n_samples == None:
            return self.get_exact_expectation_values(circuit, qubit_operator,
                                                     **kwargs)
        else:
            operator = change_operator_type(qubit_operator, IsingOperator)
            measurements = self.run_circuit_and_measure(circuit)
            expectation_values = measurements.get_expectation_values(operator)

            expectation_values = expectation_values_to_real(expectation_values)
            return expectation_values
Exemplo n.º 3
0
def evaluate_operator_for_parameter_grid(ansatz,
                                         grid,
                                         backend,
                                         operator,
                                         previous_layer_params=[]):
    """Evaluate the expectation value of an operator for every set of circuit
    parameters in the parameter grid.

    Args:
        ansatz (dict): the ansatz
        grid (zquantum.core.circuit.ParameterGrid): The parameter grid containing
            the parameters for the last layer of the ansatz
        backend (zquantum.core.interfaces.backend.QuantumSimulator): the backend
            to run the circuits on
        operator (openfermion.ops.QubitOperator): the operator
        previous_layer_params (array): A list of the parameters for previous layers
            of the ansatz

    Returns:
        value_estimate (zquantum.core.utils.ValueEstimate): stores the value of the expectation and its
             precision
        optimal_parameters (numpy array): the ansatz parameters representing the ansatz parameters
            resulting in the best minimum evaluation. If multiple sets of parameters evaluate to the same value,
            the first set of parameters is chosen as the optimal.
    """
    parameter_grid_evaluation = []
    circuitset = []
    params_set = []
    for last_layer_params in grid.params_list:
        # Build the ansatz circuit
        params = np.concatenate(
            (np.asarray(previous_layer_params), np.asarray(last_layer_params)))

        # Build the ansatz circuit
        circuitset.append(ansatz.get_executable_circuit(params))
        params_set.append(params)

    expectation_values_set = backend.get_expectation_values_for_circuitset(
        circuitset, operator)

    min_value_estimate = None
    for params, expectation_values in zip(params_set, expectation_values_set):
        expectation_values = expectation_values_to_real(expectation_values)
        value_estimate = ValueEstimate(sum(expectation_values.values))
        parameter_grid_evaluation.append({
            "value": value_estimate,
            "parameter1": params[-2],
            "parameter2": params[-1],
        })

        if min_value_estimate is None:
            min_value_estimate = value_estimate
            optimal_parameters = params
        elif value_estimate.value < min_value_estimate.value:
            min_value_estimate = value_estimate
            optimal_parameters = params

    return parameter_grid_evaluation, optimal_parameters
Exemplo n.º 4
0
    def get_expectation_values(self, circuit, qubit_operator, **kwargs):
        if self.n_samples == None:
            return self.get_exact_expectation_values(circuit, qubit_operator, **kwargs)
        else:
            measurements = self.run_circuit_and_measure(circuit)
            expectation_values = measurements.get_expectation_values(qubit_operator)

            expectation_values = expectation_values_to_real(expectation_values)
            return expectation_values
Exemplo n.º 5
0
    def get_expectation_values(self, circuit, qubit_operator, **kwargs):
        if self.device_name == 'wavefunction-simulator' and self.n_samples==None:
            return self.get_exact_expectation_values(circuit, qubit_operator, **kwargs)
        else:
            measurements = self.run_circuit_and_measure(circuit, nthreads=self.nthreads)
            expectation_values = get_expectation_values_from_measurements(
                                    measurements, qubit_operator)

            expectation_values = expectation_values_to_real(expectation_values)
            return expectation_values
Exemplo n.º 6
0
def test_expectation_values_to_real():
    # Given
    expectation_values = ExpectationValues(
        np.array([0.0 + 0.1j, 0.0 + 1e-10j, -1.0]))
    target_expectation_values = ExpectationValues(np.array([0.0, 0.0, -1.0]))

    # When
    real_expectation_values = expectation_values_to_real(expectation_values)

    # Then
    for value in expectation_values.values:
        assert not isinstance(value, complex)
    np.testing.assert_array_equal(real_expectation_values.values,
                                  target_expectation_values.values)
def _evaluate_solution_for_hamiltonian(solution: Tuple[int],
                                       hamiltonian: QubitOperator) -> float:
    """Evaluates a solution of a hamiltonian by its calculating expectation value.

    Args:
        solution: solution to a problem as a tuple of bits
        hamiltonian: a Hamiltonian representing a problem.

    Returns:
        float: value of a solution.
    """
    hamiltonian = change_operator_type(hamiltonian, IsingOperator)
    expectation_values = expectation_values_to_real(
        Measurements([solution]).get_expectation_values(hamiltonian))
    return sum(expectation_values.values)
Exemplo n.º 8
0
def _get_expval(backend, circuit, ops):
    """Auxiliary function to get the expectation value of a list of operators
    given a quantum circuit and a quantum backend.

    In sampling mode, the same measurement outcomes are post-processed for each
    operator. In exact mode, the statevector prepared by the quantum circuit is
    simulated separately for each operator. This is required so that the
    standard ``get_exact_expectation_values`` method of the ``QuantumBackend``
    interface can be used.

    Args:
        backend (QuantumBackend): the Orquestra quantum backend to use
        circuit (zquantum.core.circuit.Circuit): the circuit represented as an
            OpenQASM 2.0 program
        operators (list): a list of operators as ``openfermion.QubitOperator``
            or ``openfermion.IsingOperator`` objects

    Returns:
        list: list of expectation values for each operator
    """
    results = []

    if backend.n_samples is not None:
        measurements = backend.run_circuit_and_measure(circuit)

        # Iterating through the operators specified e.g., [IsingOperator("[Z0]
        # + [Z1]"), IsingOperator("[Z1]")] to post-process the measurements
        # outcomes
        for op in ops:
            expectation_values = measurements.get_expectation_values(op)
            expectation_values = expectation_values_to_real(expectation_values)

            # Summing the expectation values obtained for each term of the
            # operator yields the expectation value for the operator
            # E.g., <psi|Z0 + Z1|psi> = <psi|Z0|psi> + <psi|Z1|psi>
            val = np.sum(expectation_values.values)
            results.append(val)
    else:
        for op in ops:
            expectation_values = backend.get_exact_expectation_values(
                circuit, op)

            val = np.sum(expectation_values.values)
            results.append(val)

    return results
Exemplo n.º 9
0
    def get_expectation_values_for_circuitset(self, circuitset, operator,
                                              **kwargs):
        """Run a set of circuits and measure the expectation values with respect to a
        given operator.

        Args:
            circuitset (list of zquantum.core.circuit.Circuit objects): the circuits to prepare the states
            operator (openfermion.ops.IsingOperator or openfermion.ops.QubitOperator): the operator to measure
        Returns:
            list of zquantum.core.measurement.ExpectationValues objects: a list of the expectation values of each
                term in the operator with respect to the various state preparation circuits
        """
        self.num_circuits_run += len(circuitset)
        self.num_jobs_run += 1
        operator = change_operator_type(operator, IsingOperator)
        measurements_set = self.run_circuitset_and_measure(circuitset)

        expectation_values_set = []
        for measurements in measurements_set:
            expectation_values = measurements.get_expectation_values(operator)
            expectation_values = expectation_values_to_real(expectation_values)
            expectation_values_set.append(expectation_values)

        return expectation_values_set