Skip to content
23 changes: 22 additions & 1 deletion qiskit_addon_aqc_tensor/ansatz_generation/from_connectivity.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

from __future__ import annotations

import logging
from typing import Sequence

import numpy as np
Expand All @@ -25,9 +26,15 @@
QuantumCircuit,
)
from qiskit.circuit.library import UnitaryGate
from qiskit.compiler import transpile
from qiskit.exceptions import QiskitError
from qiskit.quantum_info import Operator
from qiskit.synthesis import OneQubitEulerDecomposer, TwoQubitWeylDecomposition

logger = logging.getLogger(__name__)
# We'd like the user to actually see warnings from this module by default
logger.setLevel(logging.WARNING)


class AnsatzBlock(Gate):
"""Ansatz block.
Expand Down Expand Up @@ -300,7 +307,21 @@ def perform_separation(q0: int, q1: int):
partner[q1] = None
couple_qc = couples[q0, q1]
mat = Operator(couple_qc).data
d = TwoQubitWeylDecomposition(mat)
try:
d = TwoQubitWeylDecomposition(mat)
except QiskitError as exc:
# Try again with the transpiled circuit. See
# https://github.com/Qiskit/qiskit-addon-aqc-tensor/pull/100
logger.warning(
"M2 diagonalization has failed with the following non-fatal exception:",
exc_info=exc,
)
logger.warning(
"Trying M2 diagonalization again with transpiled 2-qubit circuit.",
)
couple_qc = transpile(couple_qc, basis_gates=["cx", "rx", "ry", "rz"])
mat = Operator(couple_qc).data
d = TwoQubitWeylDecomposition(mat)
singles[q0] = [UnitaryGate(d.K1r)]
singles[q1] = [UnitaryGate(d.K1l)]
fp01 = free_params[q0, q1]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
fixes:
- |
This adds a workaround for an issue sometimes encountered when calling :class:`~qiskit.synthesis.TwoQubitWeylDecomposition` inside
:func:`.generate_ansatz_from_circuit`. Sometimes an error is thrown despite the input matrix
being unitary to numerical precision, and returning :meth:`~qiskit.quantum_info.Operator.is_unitary()`` as ``True``. This is
an ongoing issue in qiskit, see `https://github.com/Qiskit/qiskit/issues/4159` for more details.

With this workaround, any time the error is encountered, it will retry by transpiling the two-qubit circuit (from which the
matrix is derived) prior to passing the matrix to :class:`~qiskit.synthesis.TwoQubitWeylDecomposition`. It should
be noted that this is does not fix the root issue, and is not guaranteed to always work, but has
been observed to work for some instances.
11 changes: 11 additions & 0 deletions test/ansatz_generation/test_from_connectivity.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,14 @@ def test_idle_qubit(self):
qc.x(0)
_, initial_parameters = generate_ansatz_from_circuit(qc)
assert len(initial_parameters) == 3

def test_large_circuit_no_two_qubit_weyl_decomposition_error(self):
qc = QuantumCircuit(50)

for _ in range(10):
for i in range(0, 50, 2):
qc.cx(i, i + 1)
for i in range(1, 49, 2):
qc.cx(i, i + 1)

_, _ = generate_ansatz_from_circuit(qc, qubits_initially_zero=True)