Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix some bugs in loading Solovay Kitaev decompositions (backport #12579) #12664

Merged
merged 1 commit into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def generate_basic_approximations(
data = {}
for sequence in sequences:
gatestring = sequence.name
data[gatestring] = sequence.product
data[gatestring] = (sequence.product, sequence.global_phase)

np.save(filename, data)

Expand Down
24 changes: 18 additions & 6 deletions qiskit/synthesis/discrete_basis/solovay_kitaev.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,19 @@ def __init__(

self.basic_approximations = self.load_basic_approximations(basic_approximations)

def load_basic_approximations(self, data: list | str | dict) -> list[GateSequence]:
@staticmethod
def load_basic_approximations(data: list | str | dict) -> list[GateSequence]:
"""Load basic approximations.

Args:
data: If a string, specifies the path to the file from where to load the data.
If a dictionary, directly specifies the decompositions as ``{gates: matrix}``.
There ``gates`` are the names of the gates producing the SO(3) matrix ``matrix``,
e.g. ``{"h t": np.array([[0, 0.7071, -0.7071], [0, -0.7071, -0.7071], [-1, 0, 0]]}``.
If a dictionary, directly specifies the decompositions as ``{gates: matrix}``
or ``{gates: (matrix, global_phase)}``. There, ``gates`` are the names of the gates
producing the SO(3) matrix ``matrix``, e.g.
``{"h t": np.array([[0, 0.7071, -0.7071], [0, -0.7071, -0.7071], [-1, 0, 0]]}``
and the ``global_phase`` can be given to account for a global phase difference
between the U(2) matrix of the quantum gates and the stored SO(3) matrix.
If not given, the ``global_phase`` will be assumed to be 0.

Returns:
A list of basic approximations as type ``GateSequence``.
Expand All @@ -72,13 +77,20 @@ def load_basic_approximations(self, data: list | str | dict) -> list[GateSequenc

# if a file, load the dictionary
if isinstance(data, str):
data = np.load(data, allow_pickle=True)
data = np.load(data, allow_pickle=True).item()

sequences = []
for gatestring, matrix in data.items():
for gatestring, matrix_and_phase in data.items():
if isinstance(matrix_and_phase, tuple):
matrix, global_phase = matrix_and_phase
else:
matrix, global_phase = matrix_and_phase, 0

sequence = GateSequence()
sequence.gates = [_1q_gates[element] for element in gatestring.split()]
sequence.labels = [gate.name for gate in sequence.gates]
sequence.product = np.asarray(matrix)
sequence.global_phase = global_phase
sequences.append(sequence)

return sequences
Expand Down
10 changes: 10 additions & 0 deletions releasenotes/notes/fix-sk-load-from-file-02c6eabbbd7fcda3.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
fixes:
- |
Fix the :class:`.SolovayKitaev` transpiler pass when loading basic
approximations from an exising ``.npy`` file. Previously, loading
a stored approximation which allowed for further reductions (e.g. due
to gate cancellations) could cause a runtime failure.
Additionally, the global phase difference of the U(2) gate product
and SO(3) representation was lost during a save-reload procedure.
Fixes `Qiskit/qiskit#12576 <https://github.com/Qiskit/qiskit/issues/12576>`_.
31 changes: 31 additions & 0 deletions test/python/transpiler/test_solovay_kitaev.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@

"""Test the Solovay Kitaev transpilation pass."""

import os
import unittest
import math
import tempfile
import numpy as np
import scipy

Expand Down Expand Up @@ -230,6 +232,35 @@ def test_u_gates_work(self):
included_gates = set(discretized.count_ops().keys())
self.assertEqual(set(basis_gates), included_gates)

def test_load_from_file(self):
"""Test loading basic approximations from a file works.

Regression test of Qiskit/qiskit#12576.
"""
filename = "approximations.npy"

with tempfile.TemporaryDirectory() as tmp_dir:
fullpath = os.path.join(tmp_dir, filename)

# dump approximations to file
generate_basic_approximations(basis_gates=["h", "s", "sdg"], depth=3, filename=fullpath)

# circuit to decompose and reference decomp
circuit = QuantumCircuit(1)
circuit.rx(0.8, 0)

reference = QuantumCircuit(1, global_phase=3 * np.pi / 4)
reference.h(0)
reference.s(0)
reference.h(0)

# load the decomp and compare to reference
skd = SolovayKitaev(basic_approximations=fullpath)
# skd = SolovayKitaev(basic_approximations=filename)
discretized = skd(circuit)

self.assertEqual(discretized, reference)


@ddt
class TestGateSequence(QiskitTestCase):
Expand Down
Loading