Repository: Qiskit/qiskit

Issue:
Equivalence library lacks many equivalences in the clifford group
Many equivalences in the clifford group are missing from the equivalence library. Some examples:
 * `sdg == h.z == z.s == s**3`
 *  `sx` == `sdg.h.sdg`
 * `cy == sdg.cx.s`
 * `x`,`y`, and `z` in terms of `h` and `s` (for example, `x == h.s.s.h`)


Discussion:
I opened an [issue](https://quantumcomputing.stackexchange.com/questions/16748/from-logical-universal-gate-set-to-physical-one-qiskit) that may be related to this one.

In brief, the `transpile` method ends the task with error when passing the universal gate set `['h', 's', 't', 'cx']` 

where is the equivalence library? is it the templates library? 
https://github.com/Qiskit/qiskit-terra/tree/master/qiskit/circuit/library/templates/clifford
> where is the equivalence library? is it the templates library?
> https://github.com/Qiskit/qiskit-terra/tree/master/qiskit/circuit/library/templates/clifford

It's not the templates library (that's only used for pattern match in the optimization passes). This is the circuit equivalence library which is used to dynamic build a graph of equivalences between gates: https://github.com/Qiskit/qiskit-terra/blob/master/qiskit/circuit/library/standard_gates/equivalence_library.py which gets used by the `BasisTranslator` pass to search for and convert from an arbitrary circuit to one in the native basis set.

This issue is just about some missing equivalence rules in the library (although I would expect the search to find some of these even if there isn't a direct edge).
>     * `sx` == `sdg.h.sdg`

This is in the equivalence lib already: https://github.com/Qiskit/qiskit-terra/blob/master/qiskit/circuit/library/standard_gates/equivalence_library.py#L391-L399

> 
>     * `cy == sdg.cx.s`

This is in the equivalence lib already:
https://github.com/Qiskit/qiskit-terra/blob/master/qiskit/circuit/library/standard_gates/equivalence_library.py#L713-L721

Resolving patch:
diff --git a/qiskit/circuit/library/standard_gates/equivalence_library.py b/qiskit/circuit/library/standard_gates/equivalence_library.py
--- a/qiskit/circuit/library/standard_gates/equivalence_library.py
+++ b/qiskit/circuit/library/standard_gates/equivalence_library.py
@@ -358,6 +358,34 @@
 def_sdg.append(U1Gate(-pi / 2), [q[0]], [])
 _sel.add_equivalence(SdgGate(), def_sdg)
 
+q = QuantumRegister(1, "q")
+def_sdg = QuantumCircuit(q)
+for inst, qargs, cargs in [
+    (SGate(), [q[0]], []),
+    (ZGate(), [q[0]], []),
+]:
+    def_sdg.append(inst, qargs, cargs)
+_sel.add_equivalence(SdgGate(), def_sdg)
+
+q = QuantumRegister(1, "q")
+def_sdg = QuantumCircuit(q)
+for inst, qargs, cargs in [
+    (ZGate(), [q[0]], []),
+    (SGate(), [q[0]], []),
+]:
+    def_sdg.append(inst, qargs, cargs)
+_sel.add_equivalence(SdgGate(), def_sdg)
+
+q = QuantumRegister(1, "q")
+def_sdg = QuantumCircuit(q)
+for inst, qargs, cargs in [
+    (SGate(), [q[0]], []),
+    (SGate(), [q[0]], []),
+    (SGate(), [q[0]], []),
+]:
+    def_sdg.append(inst, qargs, cargs)
+_sel.add_equivalence(SdgGate(), def_sdg)
+
 # SwapGate
 
 q = QuantumRegister(2, "q")
@@ -543,7 +571,7 @@
     def_cu1.append(inst, qargs, cargs)
 _sel.add_equivalence(CU1Gate(theta), def_cu1)
 
-# U1Gate
+# U2Gate
 
 q = QuantumRegister(1, "q")
 phi = Parameter("phi")
@@ -617,6 +645,18 @@
 def_x.append(U3Gate(pi, 0, pi), [q[0]], [])
 _sel.add_equivalence(XGate(), def_x)
 
+q = QuantumRegister(1, "q")
+def_x = QuantumCircuit(q)
+for inst, qargs, cargs in [
+    (HGate(), [q[0]], []),
+    (SGate(), [q[0]], []),
+    (SGate(), [q[0]], []),
+    (HGate(), [q[0]], []),
+]:
+    def_x.append(inst, qargs, cargs)
+_sel.add_equivalence(XGate(), def_x)
+
+
 # CXGate
 
 for plus_ry in [False, True]:
@@ -696,6 +736,34 @@
 def_y.append(U3Gate(pi, pi / 2, pi / 2), [q[0]], [])
 _sel.add_equivalence(YGate(), def_y)
 
+q = QuantumRegister(1, "q")
+def_y = QuantumCircuit(q)
+def_y.global_phase = 3 * pi / 2
+for inst, qargs, cargs in [
+    (HGate(), [q[0]], []),
+    (SGate(), [q[0]], []),
+    (SGate(), [q[0]], []),
+    (HGate(), [q[0]], []),
+    (SGate(), [q[0]], []),
+    (SGate(), [q[0]], []),
+]:
+    def_y.append(inst, qargs, cargs)
+_sel.add_equivalence(YGate(), def_y)
+
+q = QuantumRegister(1, "q")
+def_y = QuantumCircuit(q)
+def_y.global_phase = pi / 2
+for inst, qargs, cargs in [
+    (SGate(), [q[0]], []),
+    (SGate(), [q[0]], []),
+    (HGate(), [q[0]], []),
+    (SGate(), [q[0]], []),
+    (SGate(), [q[0]], []),
+    (HGate(), [q[0]], []),
+]:
+    def_y.append(inst, qargs, cargs)
+_sel.add_equivalence(YGate(), def_y)
+
 # CYGate
 
 q = QuantumRegister(2, "q")
@@ -715,6 +783,15 @@
 def_z.append(U1Gate(pi), [q[0]], [])
 _sel.add_equivalence(ZGate(), def_z)
 
+q = QuantumRegister(1, "q")
+def_z = QuantumCircuit(q)
+for inst, qargs, cargs in [
+    (SGate(), [q[0]], []),
+    (SGate(), [q[0]], []),
+]:
+    def_z.append(inst, qargs, cargs)
+_sel.add_equivalence(ZGate(), def_z)
+
 # CZGate
 
 q = QuantumRegister(2, "q")


Test patch: