Skip to content

Commit

Permalink
estimator_from_aer.py qiskit >=0.46 compatible
Browse files Browse the repository at this point in the history
  • Loading branch information
atlytle committed May 30, 2024
1 parent 647e509 commit cdbe300
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 57 deletions.
48 changes: 10 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,52 +20,24 @@ Install from GitHub:
```bash
pip install git+ssh://[email protected]/atlytle/dense-ev.git
```
To run unit tests,
A test function comparing results using abelian and dense grouping
with exact results is available
```python
from dense_ev._test_ops import run_unit_tests
from dense_ev.test_estimator import test_random

run_unit_tests()
m = 3 # n_qubits
run_unit_tests(m)
```

### Qiskit version compatibility
Note that **dense_ev** specifies `qiskit < 0.43.0`, as the `Opflow` and
`QuantumInstance` packages have been deprecated as of `Qiskit 0.43.0`.
We plan to update the code to function with the new `primitives` as this
migration continues and more documentation becomes available.
**Update 2024-01-07**: Support for dense Pauli grouping
**2024-01-07**: Support for dense Pauli grouping
in the Aer `Estimator` primitive merged to `main` branch.
See usage example below.
See usage example below.
**2024-05-30**: Functionality using `Opflow` and other deprecated classes
has been removed. Package requirements changed from `qiskit < 0.43.0`
to `qiskit` (v1.0). Added `qiskit_aer` requirement.

## Usage
Functionality for naive and QWC groupings is provided in Qiskit
by the `PauliExpectation` class. `DensePauliExpectation` extends the functionality
to dense optimal grouping, and may be used as a replacement for
`PauliExpectation`:
```python
from dense_ev.dense_pauli_expectation import DensePauliExpectation

# Simple expectation values:
...

ev_spec = StateFn(H).compose(psi)
expectation = DensePauliExpectation().convert(ev_spec)

...

# VQE example
...

vqe = VQE(ansatz, optimizer=spsa, quantum_instance=qi,
callback=store_intermediate_result,
expectation=DensePauliExpectation())

result = vqe.compute_minimum_eigenvalue(operator=H)

...


```

### Estimator support
The Aer implementation of `Estimator` is extended to incorporate
dense Pauli grouping, and can be invoked using the keyword
Expand Down
17 changes: 11 additions & 6 deletions src/dense_ev/estimator_from_aer.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import numpy as np
from qiskit.circuit import ParameterExpression, QuantumCircuit
from qiskit.compiler import transpile
from qiskit.opflow import PauliSumOp
#from qiskit.opflow import PauliSumOp
from qiskit.primitives import BaseEstimator, EstimatorResult
from qiskit.primitives.primitive_job import PrimitiveJob
from qiskit.primitives.utils import _circuit_key, _observable_key, init_observable
Expand Down Expand Up @@ -104,9 +104,11 @@ def __init__(
If approximation is True, this parameter is ignored and assumed to be False.
"""
super().__init__(options=run_options)
# if abelian_grouping == "DENSE":
# m = 3
# self.PO = PauliOrganizer(m)
# These three private attributes used to be created by super, but were deprecated in Qiskit
# 0.46. See https://github.com/Qiskit/qiskit/pull/11051
self._circuits = []
self._parameters = []
self._observables = []
backend_options = {} if backend_options is None else backend_options
method = (
"density_matrix"
Expand Down Expand Up @@ -148,7 +150,7 @@ def _call(
def _run(
self,
circuits: Sequence[QuantumCircuit],
observables: Sequence[BaseOperator | PauliSumOp],
observables: Sequence[BaseOperator],
parameter_values: Sequence[Sequence[float]],
**run_options,
) -> PrimitiveJob:
Expand Down Expand Up @@ -185,7 +187,8 @@ def _run(
parameter_values,
**run_options,
)
job.submit()
# The public submit method was removed in Qiskit 0.46
(job.submit if hasattr(job, "submit") else job._submit)() # pylint: disable=no-member
return job

def _compute(self, circuits, observables, parameter_values, run_options):
Expand Down Expand Up @@ -394,6 +397,8 @@ def _combine_circs(circuit: QuantumCircuit, meas_circuits: list[QuantumCircuit])
circs = []
for meas_circuit in meas_circuits:
new_circ = circuit.copy()
#print(f"{new_circ.num_qubits = }")
#print(f"{meas_circuit.num_qubits = }")
for creg in meas_circuit.cregs:
new_circ.add_register(creg)
new_circ.compose(meas_circuit, inplace=True)
Expand Down
8 changes: 4 additions & 4 deletions src/dense_ev/rmatrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@
from numpy.random import normal
from scipy.stats import unitary_group

from qiskit.opflow.primitive_ops import PauliOp
#from qiskit.opflow.primitive_ops import PauliOp
from qiskit.quantum_info import SparsePauliOp
from qiskit.quantum_info.operators import Pauli
from qiskit.opflow.list_ops.summed_op import SummedOp
from qiskit.opflow.primitive_ops.pauli_sum_op import PauliSumOp
from qiskit.opflow.converters import AbelianGrouper
#from qiskit.opflow.list_ops.summed_op import SummedOp
#from qiskit.opflow.primitive_ops.pauli_sum_op import PauliSumOp
#from qiskit.opflow.converters import AbelianGrouper

# from qiskit.opflow.converters.pauli_basis_change import PauliBasisChange
# from qiskit.opflow.state_fns.state_fn import StateFn
Expand Down
19 changes: 10 additions & 9 deletions src/dense_ev/test_estimator.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,15 @@ def test_random(m):
result_exact = estimator.run(state, H, shots=nshots).result().values

# Abelian result.
nshots = 200000
approx = False
grouping = True
run_options = {"shots": nshots, "seed": seed}
estimator = Estimator(
run_options=run_options, abelian_grouping=grouping, approximation=approx
)
result_abelian = estimator.run(state, H, shots=nshots).result().values
# nshots = 200000
# approx = False
# grouping = True
# run_options = {"shots": nshots, "seed": seed}
# estimator = Estimator(
# run_options=run_options, abelian_grouping=grouping,
# approximation=approx
# )
#result_abelian = estimator.run(state, H, shots=nshots).result().values

# Dense result.
nshots = 200000
Expand All @@ -62,7 +63,7 @@ def test_random(m):
result_dense = estimator.run(state, H, shots=nshots).result().values

print(f"{result_exact = }")
print(f"{result_abelian = }")
#print(f"{result_abelian = }")
print(f"{result_dense = }")


Expand Down

0 comments on commit cdbe300

Please sign in to comment.