Skip to content

Commit

Permalink
Merge branch 'main' into equiv_stabilizers
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Feb 8, 2023
2 parents 3b20578 + 00b4754 commit 7ad4fde
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 89 deletions.
14 changes: 14 additions & 0 deletions qiskit/circuit/library/standard_gates/x.py
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,20 @@ def _define(self):

self.definition = qc

def qasm(self):
# Gross hack to override the Qiskit name with the name this gate has in Terra's version of
# 'qelib1.inc'. In general, the larger exporter mechanism should know about this to do the
# mapping itself, but right now that's not possible without a complete rewrite of the OQ2
# exporter code (low priority), or we would need to modify 'qelib1.inc' which would be
# needlessly disruptive this late in OQ2's lifecycle. The current OQ2 exporter _always_
# outputs the `include 'qelib1.inc' line. ---Jake, 2022-11-21.
try:
old_name = self.name
self.name = "c3sqrtx"
return super().qasm()
finally:
self.name = old_name


class C3XGate(ControlledGate):
r"""The X gate controlled on 3 qubits.
Expand Down
2 changes: 1 addition & 1 deletion qiskit/circuit/quantumcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -1644,7 +1644,7 @@ def qasm(
"rccx",
"rc3x",
"c3x",
"c3sx",
"c3sx", # This is the Qiskit gate name, but the qelib1.inc name is 'c3sqrtx'.
"c4x",
]

Expand Down
116 changes: 43 additions & 73 deletions qiskit/converters/ast_to_dag.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,42 +25,7 @@
from qiskit.circuit.reset import Reset
from qiskit.circuit.barrier import Barrier
from qiskit.circuit.delay import Delay
from qiskit.circuit.library.standard_gates.x import CCXGate
from qiskit.circuit.library.standard_gates.swap import CSwapGate
from qiskit.circuit.library.standard_gates.x import CXGate
from qiskit.circuit.library.standard_gates.y import CYGate
from qiskit.circuit.library.standard_gates.z import CZGate
from qiskit.circuit.library.standard_gates.swap import SwapGate
from qiskit.circuit.library.standard_gates.h import HGate
from qiskit.circuit.library.standard_gates.i import IGate
from qiskit.circuit.library.standard_gates.s import SGate
from qiskit.circuit.library.standard_gates.s import SdgGate
from qiskit.circuit.library.standard_gates.sx import SXGate
from qiskit.circuit.library.standard_gates.sx import SXdgGate
from qiskit.circuit.library.standard_gates.t import TGate
from qiskit.circuit.library.standard_gates.t import TdgGate
from qiskit.circuit.library.standard_gates.p import PhaseGate
from qiskit.circuit.library.standard_gates.u1 import U1Gate
from qiskit.circuit.library.standard_gates.u2 import U2Gate
from qiskit.circuit.library.standard_gates.u3 import U3Gate
from qiskit.circuit.library.standard_gates.u import UGate
from qiskit.circuit.library.standard_gates.x import XGate
from qiskit.circuit.library.standard_gates.y import YGate
from qiskit.circuit.library.standard_gates.z import ZGate
from qiskit.circuit.library.standard_gates.rx import RXGate
from qiskit.circuit.library.standard_gates.ry import RYGate
from qiskit.circuit.library.standard_gates.rz import RZGate
from qiskit.circuit.library.standard_gates.rxx import RXXGate
from qiskit.circuit.library.standard_gates.rzz import RZZGate
from qiskit.circuit.library.standard_gates.p import CPhaseGate
from qiskit.circuit.library.standard_gates.u import CUGate
from qiskit.circuit.library.standard_gates.u1 import CU1Gate
from qiskit.circuit.library.standard_gates.u3 import CU3Gate
from qiskit.circuit.library.standard_gates.h import CHGate
from qiskit.circuit.library.standard_gates.rx import CRXGate
from qiskit.circuit.library.standard_gates.ry import CRYGate
from qiskit.circuit.library.standard_gates.rz import CRZGate
from qiskit.circuit.library.standard_gates.sx import CSXGate
from qiskit.circuit.library import standard_gates as std


def ast_to_dag(ast):
Expand Down Expand Up @@ -102,43 +67,48 @@ class AstInterpreter:
"""Interprets an OpenQASM by expanding subroutines and unrolling loops."""

standard_extension = {
"u1": U1Gate,
"u2": U2Gate,
"u3": U3Gate,
"u": UGate,
"p": PhaseGate,
"x": XGate,
"y": YGate,
"z": ZGate,
"t": TGate,
"tdg": TdgGate,
"s": SGate,
"sdg": SdgGate,
"sx": SXGate,
"sxdg": SXdgGate,
"swap": SwapGate,
"rx": RXGate,
"rxx": RXXGate,
"ry": RYGate,
"rz": RZGate,
"rzz": RZZGate,
"id": IGate,
"h": HGate,
"cx": CXGate,
"cy": CYGate,
"cz": CZGate,
"ch": CHGate,
"crx": CRXGate,
"cry": CRYGate,
"crz": CRZGate,
"csx": CSXGate,
"cu1": CU1Gate,
"cp": CPhaseGate,
"cu": CUGate,
"cu3": CU3Gate,
"ccx": CCXGate,
"cswap": CSwapGate,
"u1": std.U1Gate,
"u2": std.U2Gate,
"u3": std.U3Gate,
"u": std.UGate,
"p": std.PhaseGate,
"x": std.XGate,
"y": std.YGate,
"z": std.ZGate,
"t": std.TGate,
"tdg": std.TdgGate,
"s": std.SGate,
"sdg": std.SdgGate,
"sx": std.SXGate,
"sxdg": std.SXdgGate,
"swap": std.SwapGate,
"rx": std.RXGate,
"rxx": std.RXXGate,
"ry": std.RYGate,
"rz": std.RZGate,
"rzz": std.RZZGate,
"id": std.IGate,
"h": std.HGate,
"cx": std.CXGate,
"cy": std.CYGate,
"cz": std.CZGate,
"ch": std.CHGate,
"crx": std.CRXGate,
"cry": std.CRYGate,
"crz": std.CRZGate,
"csx": std.CSXGate,
"cu1": std.CU1Gate,
"cp": std.CPhaseGate,
"cu": std.CUGate,
"cu3": std.CU3Gate,
"ccx": std.CCXGate,
"cswap": std.CSwapGate,
"delay": Delay,
"rccx": std.RCCXGate,
"rc3x": std.RC3XGate,
"c3x": std.C3XGate,
"c3sqrtx": std.C3SXGate,
"c4x": std.C4XGate,
}

def __init__(self, dag):
Expand Down Expand Up @@ -263,7 +233,7 @@ def _process_cnot(self, node):
)
maxidx = max([len(id0), len(id1)])
for idx in range(maxidx):
cx_gate = CXGate()
cx_gate = std.CXGate()
cx_gate.condition = self.condition
if len(id0) > 1 and len(id1) > 1:
self.dag.apply_operation_back(cx_gate, [id0[idx], id1[idx]], [])
Expand Down
4 changes: 1 addition & 3 deletions qiskit/providers/fake_provider/fake_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,6 @@ def _get_noise_model_from_backend_v2(
temperature=0,
gate_lengths=None,
gate_length_units="ns",
standard_gates=None,
):
"""Build noise model from BackendV2.
Expand Down Expand Up @@ -406,7 +405,6 @@ def _get_noise_model_from_backend_v2(
gate_lengths=gate_lengths,
gate_length_units=gate_length_units,
temperature=temperature,
standard_gates=standard_gates,
)
for name, qubits, error in gate_errors:
noise_model.add_quantum_error(error, name, qubits)
Expand Down Expand Up @@ -459,7 +457,7 @@ def _setup_sim(self):

self.sim = aer.AerSimulator()
if self.properties():
noise_model = NoiseModel.from_backend(self, warnings=False)
noise_model = NoiseModel.from_backend(self)
self.sim.set_options(noise_model=noise_model)
# Update fake backend default options too to avoid overwriting
# it when run() is called
Expand Down
5 changes: 2 additions & 3 deletions qiskit/quantum_info/states/statevector.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
"""
Statevector quantum state class.
"""

import copy
import re
from numbers import Number
Expand Down Expand Up @@ -225,7 +224,7 @@ def __len__(self):
return len(self._data)

@property
def data(self):
def data(self) -> np.ndarray:
"""Return data."""
return self._data

Expand All @@ -238,7 +237,7 @@ def is_valid(self, atol=None, rtol=None):
norm = np.linalg.norm(self.data)
return np.allclose(norm, 1, rtol=rtol, atol=atol)

def to_operator(self):
def to_operator(self) -> Operator:
"""Convert state to a rank-1 projector operator"""
mat = np.outer(self.data, np.conj(self.data))
return Operator(mat, input_dims=self.dims(), output_dims=self.dims())
Expand Down
20 changes: 11 additions & 9 deletions qiskit/quantum_info/synthesis/xx_decompose/decomposer.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
"""
Driver for a synthesis routine which emits optimal XX-based circuits.
"""

from __future__ import annotations
import heapq
import math
from operator import itemgetter
from typing import Callable, Optional, Union
from typing import Callable

import numpy as np

Expand Down Expand Up @@ -78,10 +78,10 @@ class XXDecomposer:

def __init__(
self,
basis_fidelity: Union[dict, float] = 1.0,
basis_fidelity: dict | float = 1.0,
euler_basis: str = "U",
embodiments: Optional[dict] = None,
backup_optimizer: Optional[Callable] = None,
embodiments: dict[float, QuantumCircuit] | None = None,
backup_optimizer: Callable[..., QuantumCircuit] | None = None,
):
from qiskit.transpiler.passes.optimization.optimize_1q_decomposition import (
Optimize1qGatesDecomposition, # pylint: disable=cyclic-import
Expand All @@ -93,7 +93,9 @@ def __init__(
self.basis_fidelity = basis_fidelity

# expose one of the basis gates so others can know what this decomposer targets
embodiment_circuit = next(iter(self.embodiments.items()), ([], []))[1]
embodiment_circuit: list | QuantumCircuit = next(iter(self.embodiments.items()), ([], []))[
1
]
for instruction in embodiment_circuit:
if len(instruction.qubits) == 2:
self.gate = instruction.operation
Expand Down Expand Up @@ -217,10 +219,10 @@ def _strength_to_infidelity(basis_fidelity, approximate=False):

def __call__(
self,
unitary: Union[Operator, np.ndarray],
basis_fidelity: Optional[Union[dict, float]] = None,
unitary: Operator | np.ndarray,
basis_fidelity: dict | float | None = None,
approximate: bool = True,
):
) -> QuantumCircuit:
"""
Fashions a circuit which (perhaps `approximate`ly) models the special unitary operation
`unitary`, using the circuit templates supplied at initialization as `embodiments`. The
Expand Down
5 changes: 5 additions & 0 deletions releasenotes/notes/fix-qasm2-c3sxgate-47171c9d17876219.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
fixes:
- |
Circuits containing :class:`.C3SXGate` can now be output and read in again safely from the
OpenQASM 2.0 exporter (:meth:`.QuantumCircuit.qasm`) and parser (:meth:`.QuantumCircuit.from_qasm_str`).
17 changes: 17 additions & 0 deletions test/python/circuit/test_circuit_qasm.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
from qiskit.test import QiskitTestCase
from qiskit.circuit import Parameter, Qubit, Clbit, Gate
from qiskit.circuit.library import C3SXGate
from qiskit.qasm.exceptions import QasmError

# Regex pattern to match valid OpenQASM identifiers
Expand Down Expand Up @@ -247,6 +248,22 @@ def test_circuit_qasm_with_composite_circuit_with_many_params_and_qubits(self):

self.assertEqual(original_str, qc.qasm())

def test_c3sxgate_roundtrips(self):
"""Test that C3SXGate correctly round trips. Qiskit gives this gate a different name
('c3sx') to the name in Qiskit's version of qelib1.inc ('c3sqrtx') gate, which can lead to
resolution issues."""
qc = QuantumCircuit(4)
qc.append(C3SXGate(), qc.qubits, [])
qasm = qc.qasm()
expected = """OPENQASM 2.0;
include "qelib1.inc";
qreg q[4];
c3sqrtx q[0],q[1],q[2],q[3];
"""
self.assertEqual(qasm, expected)
parsed = QuantumCircuit.from_qasm_str(qasm)
self.assertIsInstance(parsed.data[0].operation, C3SXGate)

def test_unbound_circuit_raises(self):
"""Test circuits with unbound parameters raises."""
qc = QuantumCircuit(1)
Expand Down

0 comments on commit 7ad4fde

Please sign in to comment.