Skip to content

Commit

Permalink
final layout hack
Browse files Browse the repository at this point in the history
  • Loading branch information
ikkoham committed Jun 29, 2021
1 parent 30b34c6 commit 7418ac2
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 21 deletions.
42 changes: 26 additions & 16 deletions qiskit/opflow/converters/circuit_sampler.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from qiskit.opflow.state_fns.dict_state_fn import DictStateFn
from qiskit.opflow.state_fns.state_fn import StateFn
from qiskit.providers import Backend, BaseBackend
from qiskit.transpiler.layout import Layout
from qiskit.utils.backend_utils import is_aer_provider, is_statevector_backend
from qiskit.utils.quantum_instance import QuantumInstance

Expand Down Expand Up @@ -197,34 +198,41 @@ def convert(
]

common_circuit = operator[1].to_circuit_op().reduce().to_circuit()
len_common_circuit = len(common_circuit)
try:
# 1. transpile a common circuit
common_circuit.measure_all()
transpiled_common_circuit = self.quantum_instance.transpile(common_circuit)[0]
layout = Layout(
{
i: qr[0]
for i, (_, qr, _) in enumerate(
transpiled_common_circuit[-common_circuit.num_qubits :]
)
}
)
transpiled_common_circuit.remove_final_measurements()

# 2. transpile diff circuits
diff_circuits = []
for circuit in circuits:
diff_circuit = circuit.copy()
del diff_circuit.data[0 : len(common_circuit)]
del diff_circuit.data[0 : len_common_circuit]
diff_circuits.append(diff_circuit)

if transpiled_common_circuit._layout is not None:
layout = transpiled_common_circuit._layout.copy()
used_qubits = set(
used_qubit
for diff_circuit in diff_circuits
for used_qubit in diff_circuit.qubits
)
for q in list(layout.get_virtual_bits().keys()):
if q not in used_qubits:
del layout[q]
orig_layout = self.quantum_instance.compile_config["initial_layout"]
self.quantum_instance.compile_config["initial_layout"] = layout
used_qubits = set(
used_qubit
for diff_circuit in diff_circuits
for used_qubit in diff_circuit.qubits
)
for q in list(layout.get_virtual_bits().keys()):
if q not in used_qubits:
del layout[q]
orig_layout = self.quantum_instance.compile_config["initial_layout"]

self.quantum_instance.compile_config["initial_layout"] = layout
diff_circuits = self.quantum_instance.transpile(diff_circuits)

if transpiled_common_circuit._layout is not None:
self.quantum_instance.compile_config["initial_layout"] = orig_layout
self.quantum_instance.compile_config["initial_layout"] = orig_layout

# 3. combine
transpiled_circuits = []
Expand All @@ -240,6 +248,7 @@ def convert(
# 4. set transpiled circuit cache
self._transpiled_circ_cache = transpiled_circuits
self._transpile_before_bind = True

except QiskitError:
logger.debug(
r"CircuitSampler failed to transpile circuits with unbound "
Expand Down Expand Up @@ -375,6 +384,7 @@ def sample_circuits(

try:
self._transpiled_circ_cache = self.quantum_instance.transpile(circuits)

except QiskitError:
logger.debug(
r"CircuitSampler failed to transpile circuits with unbound "
Expand Down
58 changes: 53 additions & 5 deletions test/python/opflow/test_state_op_meas_evals.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,29 @@

import unittest
from test.python.opflow import QiskitOpflowTestCase
from ddt import ddt, data
import numpy

from qiskit.circuit import QuantumCircuit, Parameter
from qiskit.utils import QuantumInstance
from qiskit.opflow import StateFn, Zero, One, H, X, I, Z, Plus, Minus, CircuitSampler, ListOp
import numpy
from ddt import data, ddt

from qiskit import BasicAer
from qiskit.circuit import Parameter, QuantumCircuit
from qiskit.circuit.library import RealAmplitudes
from qiskit.opflow import (
CircuitSampler,
H,
I,
ListOp,
Minus,
One,
PauliExpectation,
Plus,
StateFn,
X,
Z,
Zero,
)
from qiskit.opflow.exceptions import OpflowError
from qiskit.utils import QuantumInstance


@ddt
Expand Down Expand Up @@ -217,6 +233,38 @@ def test_quantum_instance_with_backend_shots(self):
res = sampler.convert(~Plus @ Plus).eval()
self.assertAlmostEqual(res, 1 + 0j, places=2)

def test_split_transpile(self):
"""Test split transpile for CircuitSampler"""
ansatz = StateFn(RealAmplitudes(num_qubits=3, reps=1, entanglement="linear"))
observable = StateFn(X ^ I ^ I, is_measurement=True)
expectation = PauliExpectation(False).convert(observable @ ansatz)
param_bindings = dict(zip(ansatz.parameters, [1] * len(ansatz.parameters)))
sampled = CircuitSampler(
QuantumInstance(
BasicAer.get_backend("qasm_simulator"),
seed_simulator=15,
seed_transpiler=15,
initial_layout=[0, 1, 2],
coupling_map=[[0, 1], [0, 2]],
),
attach_results=True,
split_transpile=False,
).convert(expectation, param_bindings)
counts_expected = sampled[1].execution_results["counts"]
sampled = CircuitSampler(
QuantumInstance(
BasicAer.get_backend("qasm_simulator"),
seed_simulator=15,
seed_transpiler=15,
initial_layout=[0, 1, 2],
coupling_map=[[0, 1], [0, 2]],
),
attach_results=True,
split_transpile=True,
).convert(expectation, param_bindings)
counts_target = sampled[1].execution_results["counts"]
self.assertDictEqual(counts_target, counts_expected)


if __name__ == "__main__":
unittest.main()

0 comments on commit 7418ac2

Please sign in to comment.