Repository: PECOS-packages/PECOS (language: python)

Issue:
`KeyError: 'H4'` with certain parameter values
Version: quantum-pecos 0.6.0.dev5

```python
from pecos.engines.hybrid_engine import HybridEngine

phir = """
{
    "format": "PHIR/JSON",
    "version": "0.1.0",
    "metadata":
    {
        "source": "pytket-phir v0.8.1"
    },
    "ops":
    [
        {
            "data": "qvar_define",
            "data_type": "qubits",
            "variable": "q",
            "size": 1
        },
        {
            "qop": "R1XY",
            "angles":
            [
                [
                    1.0,
                    1.75
                ],
                "pi"
            ],
            "args":
            [
                [
                    "q",
                    0
                ]
            ]
        }
    ]
}
"""

engine = HybridEngine(qsim="state-vector")
engine.run(phir, shots=10)
```
Output:
```
Traceback (most recent call last):
  File "/home/alec/r/pytket-quantinuum/play/john.py", line 51, in <module>
    r = engine.run(phir, shots=10)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/alec/r/pytket-quantinuum/env/lib/python3.12/site-packages/pecos/engines/hybrid_engine.py", line 191, in run
    temp_meas = self.qsim.run(noisy_qops)
                ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/alec/r/pytket-quantinuum/env/lib/python3.12/site-packages/pecos/simulators/quantum_simulator.py", line 95, in run
    output = self.state.run_gate(op.sim_name, op.args, **op.metadata)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/alec/r/pytket-quantinuum/env/lib/python3.12/site-packages/pecos/simulators/parent_sim_classes.py", line 43, in run_gate
    results = self.bindings[symbol](self, location, **params)
              ~~~~~~~~~~~~~^^^^^^^^
KeyError: 'H4'
```

If "1.75" is changed to "1.76", there is no error!


Discussion / hints:
The bug does not appear with quantum-pecos 0.6.0.dev3: it seems to have been introduced in quantum-pecos 0.6.0.dev4.
This is what appears to be happening:
- From .dev4 onwards, PECOS seems to be able to (correctly) detect that an `R1XY(1.0pi, 1.75pi)` gate is equivalent (up to global phase) to an "H4" gate, where `H4=S*S*S*H*S*S*H` (see [here](https://github.com/PECOS-packages/PECOS/blob/0d7b4f9b3032b0e61031e6dbc1979ab94693d9db/pecos/circuit_converters/std2chs.py#L55))
  - PECOS replaces the `R1XY` gate with an `H4` gate.
  - If any of the two angles is changed, this is no longer an `H4` gate, so PECOS leaves it as an `R1XY` gate. This explains why there's no bug when `1.75` is changed to `1.76`.
- The `state-vector` simulator does not support the `H4` gate, so it errors out at `self.bindings["H4"]` with a `KeyError`.

I do not know what's the code responsible for the conversion of `R1XY` to `H4`. However, a simple fix for this is to add `H4` and all other Clifford gates in the list [here](https://github.com/PECOS-packages/PECOS/blob/0d7b4f9b3032b0e61031e6dbc1979ab94693d9db/pecos/circuit_converters/std2chs.py#L55) to the simulators. I will do this in a PR + include a better error message when a gate is not supported by a simulator.
It is likely that the conversion from `R1XY` to `H4` has been a feature of PECOS since before `.dev4`. The bug is likely to have appeared on `.dev4` onwards due to a change of the default simulator from ProjectQ to Qulacs. The wrapper of ProjectQ had support for the `H4` gate.

Fix patch:
diff --git a/python/pecos/simulators/basic_sv/bindings.py b/python/pecos/simulators/basic_sv/bindings.py
index 8bda4052..9b59242a 100644
--- a/python/pecos/simulators/basic_sv/bindings.py
+++ b/python/pecos/simulators/basic_sv/bindings.py
@@ -69,4 +69,34 @@
     "SqrtZZ": two_q.SZZ,
     "SZZdg": two_q.SZZdg,
     "SWAP": two_q.SWAP,
+    # Additional Cliffords from `circuit_converters/std2chs.py`
+    "Q": one_q.SX,
+    "Qd": one_q.SXdg,
+    "R": one_q.SY,
+    "Rd": one_q.SYdg,
+    "S": one_q.SZ,
+    "Sd": one_q.SZdg,
+    "H1": one_q.H,
+    "H2": one_q.H2,
+    "H3": one_q.H3,
+    "H4": one_q.H4,
+    "H5": one_q.H5,
+    "H6": one_q.H6,
+    "H+z+x": one_q.H,
+    "H-z-x": one_q.H2,
+    "H+y-z": one_q.H3,
+    "H-y-z": one_q.H4,
+    "H-x+y": one_q.H5,
+    "H-x-y": one_q.H6,
+    "F1": one_q.F,
+    "F1d": one_q.Fdg,
+    "F2": one_q.F2,
+    "F2d": one_q.F2d,
+    "F3": one_q.F3,
+    "F3d": one_q.F3d,
+    "F4": one_q.F4,
+    "F4d": one_q.F4d,
+    "CNOT": two_q.CX,
+    "G": two_q.G,
+    "II": one_q.identity,
 }
diff --git a/python/pecos/simulators/basic_sv/gates_one_qubit.py b/python/pecos/simulators/basic_sv/gates_one_qubit.py
index 40da1f72..51366981 100644
--- a/python/pecos/simulators/basic_sv/gates_one_qubit.py
+++ b/python/pecos/simulators/basic_sv/gates_one_qubit.py
@@ -326,3 +326,78 @@ def Tdg(state, qubit: int, **params: Any) -> None:
         qubit: The index of the qubit where the gate is applied
     """
     RZ(state, qubit, angles=(-math.pi / 4,))
+
+
+# The definition of the extra Clifford gates added below come from
+# circuit_converters/std2chs.py
+def H2(state, qubit: int, **params: Any) -> None:
+    """'H2': ('S', 'S', 'H', 'S', 'S')"""
+    Z(state, qubit)
+    H(state, qubit)
+    Z(state, qubit)
+
+
+def H3(state, qubit: int, **params: Any) -> None:
+    """'H3': ('H', 'S', 'S', 'H', 'S',)"""
+    X(state, qubit)
+    SZ(state, qubit)
+
+
+def H4(state, qubit: int, **params: Any) -> None:
+    """'H4': ('H', 'S', 'S', 'H', 'S', 'S', 'S',)"""
+    X(state, qubit)
+    SZdg(state, qubit)
+
+
+def H5(state, qubit: int, **params: Any) -> None:
+    """'H5': ('S', 'S', 'S', 'H', 'S')"""
+    SZdg(state, qubit)
+    H(state, qubit)
+    SZ(state, qubit)
+
+
+def H6(state, qubit: int, **params: Any) -> None:
+    """'H6': ('S', 'H', 'S', 'S', 'S',)"""
+    SZ(state, qubit)
+    H(state, qubit)
+    SZdg(state, qubit)
+
+
+def F2(state, qubit: int, **params: Any) -> None:
+    """'F2': ('S', 'S', 'H', 'S')"""
+    Z(state, qubit)
+    H(state, qubit)
+    SZ(state, qubit)
+
+
+def F2d(state, qubit: int, **params: Any) -> None:
+    """'F2d': ('S', 'S', 'S', 'H', 'S', 'S')"""
+    SZdg(state, qubit)
+    H(state, qubit)
+    Z(state, qubit)
+
+
+def F3(state, qubit: int, **params: Any) -> None:
+    """'F3': ('S', 'H', 'S', 'S')"""
+    SZ(state, qubit)
+    H(state, qubit)
+    Z(state, qubit)
+
+
+def F3d(state, qubit: int, **params: Any) -> None:
+    """'F3d': ('S', 'S', 'H', 'S', 'S', 'S')"""
+    Z(state, qubit)
+    H(state, qubit)
+    SZdg(state, qubit)
+
+
+def F4(state, qubit: int, **params: Any) -> None:
+    """'F4': ('H', 'S', 'S', 'S')"""
+    H(state, qubit)
+    SZdg(state, qubit)
+
+
+def F4d(state, qubit: int, **params: Any) -> None:
+    """'F4d': ('S', 'H')"""
+    SZ(state, qubit)
+    H(state, qubit)
diff --git a/python/pecos/simulators/basic_sv/gates_two_qubit.py b/python/pecos/simulators/basic_sv/gates_two_qubit.py
index e2a2cc5c..c6496b88 100644
--- a/python/pecos/simulators/basic_sv/gates_two_qubit.py
+++ b/python/pecos/simulators/basic_sv/gates_two_qubit.py
@@ -15,6 +15,8 @@
 
 import numpy as np
 
+from pecos.simulators.basic_sv.gates_one_qubit import H
+
 
 def _apply_two_qubit_matrix(state, qubits: tuple[int, int], matrix: np.array) -> None:
     """
@@ -295,3 +297,13 @@ def SWAP(state, qubits: tuple[int, int], **params: Any) -> None:
         ],
     )
     _apply_two_qubit_matrix(state, qubits, matrix)
+
+
+def G(state, qubits: tuple[int, int], **params: Any) -> None:
+    """'G': (('I', 'H'), 'CNOT', ('H', 'H'), 'CNOT', ('I', 'H'))"""
+    H(state, qubits[1])
+    CX(state, qubits)
+    H(state, qubits[0])
+    H(state, qubits[1])
+    CX(state, qubits)
+    H(state, qubits[1])
diff --git a/python/pecos/simulators/cointoss/bindings.py b/python/pecos/simulators/cointoss/bindings.py
index a286f82c..195038e4 100644
--- a/python/pecos/simulators/cointoss/bindings.py
+++ b/python/pecos/simulators/cointoss/bindings.py
@@ -68,4 +68,34 @@
     "SqrtZZ": ignore_gate,
     "SZZdg": ignore_gate,
     "SWAP": ignore_gate,
+    # Additional Cliffords from `circuit_converters/std2chs.py`
+    "Q": ignore_gate,
+    "Qd": ignore_gate,
+    "R": ignore_gate,
+    "Rd": ignore_gate,
+    "S": ignore_gate,
+    "Sd": ignore_gate,
+    "H1": ignore_gate,
+    "H2": ignore_gate,
+    "H3": ignore_gate,
+    "H4": ignore_gate,
+    "H5": ignore_gate,
+    "H6": ignore_gate,
+    "H+z+x": ignore_gate,
+    "H-z-x": ignore_gate,
+    "H+y-z": ignore_gate,
+    "H-y-z": ignore_gate,
+    "H-x+y": ignore_gate,
+    "H-x-y": ignore_gate,
+    "F1": ignore_gate,
+    "F1d": ignore_gate,
+    "F2": ignore_gate,
+    "F2d": ignore_gate,
+    "F3": ignore_gate,
+    "F3d": ignore_gate,
+    "F4": ignore_gate,
+    "F4d": ignore_gate,
+    "CNOT": ignore_gate,
+    "G": ignore_gate,
+    "II": ignore_gate,
 }
diff --git a/python/pecos/simulators/custatevec/bindings.py b/python/pecos/simulators/custatevec/bindings.py
index d0e1ce5a..c0d7f83e 100644
--- a/python/pecos/simulators/custatevec/bindings.py
+++ b/python/pecos/simulators/custatevec/bindings.py
@@ -71,4 +71,34 @@
     "SqrtZZ": two_q.SZZ,
     "SZZdg": two_q.SZZdg,
     "SWAP": two_q.SWAP,
+    # Additional Cliffords from `circuit_converters/std2chs.py`
+    "Q": one_q.SX,
+    "Qd": one_q.SXdg,
+    "R": one_q.SY,
+    "Rd": one_q.SYdg,
+    "S": one_q.SZ,
+    "Sd": one_q.SZdg,
+    "H1": one_q.H,
+    "H2": one_q.H2,
+    "H3": one_q.H3,
+    "H4": one_q.H4,
+    "H5": one_q.H5,
+    "H6": one_q.H6,
+    "H+z+x": one_q.H,
+    "H-z-x": one_q.H2,
+    "H+y-z": one_q.H3,
+    "H-y-z": one_q.H4,
+    "H-x+y": one_q.H5,
+    "H-x-y": one_q.H6,
+    "F1": one_q.F,
+    "F1d": one_q.Fdg,
+    "F2": one_q.F2,
+    "F2d": one_q.F2d,
+    "F3": one_q.F3,
+    "F3d": one_q.F3d,
+    "F4": one_q.F4,
+    "F4d": one_q.F4d,
+    "CNOT": two_q.CX,
+    "G": two_q.G,
+    "II": one_q.identity,
 }
diff --git a/python/pecos/simulators/custatevec/gates_one_qubit.py b/python/pecos/simulators/custatevec/gates_one_qubit.py
index 326d2918..ca79ca25 100644
--- a/python/pecos/simulators/custatevec/gates_one_qubit.py
+++ b/python/pecos/simulators/custatevec/gates_one_qubit.py
@@ -356,3 +356,78 @@ def Tdg(state, qubit: int, **params: Any) -> None:
         qubit: The index of the qubit where the gate is applied
     """
     RZ(state, qubit, angles=(-math.pi / 4,))
+
+
+# The definition of the extra Clifford gates added below come from
+# circuit_converters/std2chs.py
+def H2(state, qubit: int, **params: Any) -> None:
+    """'H2': ('S', 'S', 'H', 'S', 'S')"""
+    Z(state, qubit)
+    H(state, qubit)
+    Z(state, qubit)
+
+
+def H3(state, qubit: int, **params: Any) -> None:
+    """'H3': ('H', 'S', 'S', 'H', 'S',)"""
+    X(state, qubit)
+    SZ(state, qubit)
+
+
+def H4(state, qubit: int, **params: Any) -> None:
+    """'H4': ('H', 'S', 'S', 'H', 'S', 'S', 'S',)"""
+    X(state, qubit)
+    SZdg(state, qubit)
+
+
+def H5(state, qubit: int, **params: Any) -> None:
+    """'H5': ('S', 'S', 'S', 'H', 'S')"""
+    SZdg(state, qubit)
+    H(state, qubit)
+    SZ(state, qubit)
+
+
+def H6(state, qubit: int, **params: Any) -> None:
+    """'H6': ('S', 'H', 'S', 'S', 'S',)"""
+    SZ(state, qubit)
+    H(state, qubit)
+    SZdg(state, qubit)
+
+
+def F2(state, qubit: int, **params: Any) -> None:
+    """'F2': ('S', 'S', 'H', 'S')"""
+    Z(state, qubit)
+    H(state, qubit)
+    SZ(state, qubit)
+
+
+def F2d(state, qubit: int, **params: Any) -> None:
+    """'F2d': ('S', 'S', 'S', 'H', 'S', 'S')"""
+    SZdg(state, qubit)
+    H(state, qubit)
+    Z(state, qubit)
+
+
+def F3(state, qubit: int, **params: Any) -> None:
+    """'F3': ('S', 'H', 'S', 'S')"""
+    SZ(state, qubit)
+    H(state, qubit)
+    Z(state, qubit)
+
+
+def F3d(state, qubit: int, **params: Any) -> None:
+    """'F3d': ('S', 'S', 'H', 'S', 'S', 'S')"""
+    Z(state, qubit)
+    H(state, qubit)
+    SZdg(state, qubit)
+
+
+def F4(state, qubit: int, **params: Any) -> None:
+    """'F4': ('H', 'S', 'S', 'S')"""
+    H(state, qubit)
+    SZdg(state, qubit)
+
+
+def F4d(state, qubit: int, **params: Any) -> None:
+    """'F4d': ('S', 'H')"""
+    SZ(state, qubit)
+    H(state, qubit)
diff --git a/python/pecos/simulators/custatevec/gates_two_qubit.py b/python/pecos/simulators/custatevec/gates_two_qubit.py
index 70b74784..e2ad45c0 100644
--- a/python/pecos/simulators/custatevec/gates_two_qubit.py
+++ b/python/pecos/simulators/custatevec/gates_two_qubit.py
@@ -16,6 +16,8 @@
 import cupy as cp
 from cuquantum import custatevec as cusv
 
+from pecos.simulators.custatevec.gates_one_qubit import H
+
 
 def _apply_controlled_matrix(state, control: int, target: int, matrix: cp.ndarray) -> None:
     """
@@ -396,3 +398,13 @@ def SWAP(state, qubits: tuple[int, int], **params: Any) -> None:
         extra_workspace_size_in_bytes=0,  # Let cuQuantum use the mempool we configured
     )
     state.stream.synchronize()
+
+
+def G(state, qubits: tuple[int, int], **params: Any) -> None:
+    """'G': (('I', 'H'), 'CNOT', ('H', 'H'), 'CNOT', ('I', 'H'))"""
+    H(state, qubits[1])
+    CX(state, qubits)
+    H(state, qubits[0])
+    H(state, qubits[1])
+    CX(state, qubits)
+    H(state, qubits[1])
diff --git a/python/pecos/simulators/mps_pytket/bindings.py b/python/pecos/simulators/mps_pytket/bindings.py
index 1a6c174c..af786af3 100644
--- a/python/pecos/simulators/mps_pytket/bindings.py
+++ b/python/pecos/simulators/mps_pytket/bindings.py
@@ -71,4 +71,34 @@
     "SqrtZZ": two_q.SZZ,
     "SZZdg": two_q.SZZdg,
     "SWAP": two_q.SWAP,
+    # Additional Cliffords from `circuit_converters/std2chs.py`
+    "Q": one_q.SX,
+    "Qd": one_q.SXdg,
+    "R": one_q.SY,
+    "Rd": one_q.SYdg,
+    "S": one_q.SZ,
+    "Sd": one_q.SZdg,
+    "H1": one_q.H,
+    "H2": one_q.H2,
+    "H3": one_q.H3,
+    "H4": one_q.H4,
+    "H5": one_q.H5,
+    "H6": one_q.H6,
+    "H+z+x": one_q.H,
+    "H-z-x": one_q.H2,
+    "H+y-z": one_q.H3,
+    "H-y-z": one_q.H4,
+    "H-x+y": one_q.H5,
+    "H-x-y": one_q.H6,
+    "F1": one_q.F,
+    "F1d": one_q.Fdg,
+    "F2": one_q.F2,
+    "F2d": one_q.F2d,
+    "F3": one_q.F3,
+    "F3d": one_q.F3d,
+    "F4": one_q.F4,
+    "F4d": one_q.F4d,
+    "CNOT": two_q.CX,
+    "G": two_q.G,
+    "II": one_q.identity,
 }
diff --git a/python/pecos/simulators/mps_pytket/gates_one_qubit.py b/python/pecos/simulators/mps_pytket/gates_one_qubit.py
index 1fa31496..b41a9caa 100644
--- a/python/pecos/simulators/mps_pytket/gates_one_qubit.py
+++ b/python/pecos/simulators/mps_pytket/gates_one_qubit.py
@@ -322,3 +322,78 @@ def Tdg(state, qubit: int, **params: Any) -> None:
         qubit: The index of the qubit where the gate is applied
     """
     RZ(state, qubit, angles=(-math.pi / 4,))
+
+
+# The definition of the extra Clifford gates added below come from
+# circuit_converters/std2chs.py
+def H2(state, qubit: int, **params: Any) -> None:
+    """'H2': ('S', 'S', 'H', 'S', 'S')"""
+    Z(state, qubit)
+    H(state, qubit)
+    Z(state, qubit)
+
+
+def H3(state, qubit: int, **params: Any) -> None:
+    """'H3': ('H', 'S', 'S', 'H', 'S',)"""
+    X(state, qubit)
+    SZ(state, qubit)
+
+
+def H4(state, qubit: int, **params: Any) -> None:
+    """'H4': ('H', 'S', 'S', 'H', 'S', 'S', 'S',)"""
+    X(state, qubit)
+    SZdg(state, qubit)
+
+
+def H5(state, qubit: int, **params: Any) -> None:
+    """'H5': ('S', 'S', 'S', 'H', 'S')"""
+    SZdg(state, qubit)
+    H(state, qubit)
+    SZ(state, qubit)
+
+
+def H6(state, qubit: int, **params: Any) -> None:
+    """'H6': ('S', 'H', 'S', 'S', 'S',)"""
+    SZ(state, qubit)
+    H(state, qubit)
+    SZdg(state, qubit)
+
+
+def F2(state, qubit: int, **params: Any) -> None:
+    """'F2': ('S', 'S', 'H', 'S')"""
+    Z(state, qubit)
+    H(state, qubit)
+    SZ(state, qubit)
+
+
+def F2d(state, qubit: int, **params: Any) -> None:
+    """'F2d': ('S', 'S', 'S', 'H', 'S', 'S')"""
+    SZdg(state, qubit)
+    H(state, qubit)
+    Z(state, qubit)
+
+
+def F3(state, qubit: int, **params: Any) -> None:
+    """'F3': ('S', 'H', 'S', 'S')"""
+    SZ(state, qubit)
+    H(state, qubit)
+    Z(state, qubit)
+
+
+def F3d(state, qubit: int, **params: Any) -> None:
+    """'F3d': ('S', 'S', 'H', 'S', 'S', 'S')"""
+    Z(state, qubit)
+    H(state, qubit)
+    SZdg(state, qubit)
+
+
+def F4(state, qubit: int, **params: Any) -> None:
+    """'F4': ('H', 'S', 'S', 'S')"""
+    H(state, qubit)
+    SZdg(state, qubit)
+
+
+def F4d(state, qubit: int, **params: Any) -> None:
+    """'F4d': ('S', 'H')"""
+    SZ(state, qubit)
+    H(state, qubit)
diff --git a/python/pecos/simulators/mps_pytket/gates_two_qubit.py b/python/pecos/simulators/mps_pytket/gates_two_qubit.py
index 531d9fc2..ae498624 100644
--- a/python/pecos/simulators/mps_pytket/gates_two_qubit.py
+++ b/python/pecos/simulators/mps_pytket/gates_two_qubit.py
@@ -16,6 +16,8 @@
 import cupy as cp
 from pytket import Qubit
 
+from pecos.simulators.mps_pytket.gates_one_qubit import H
+
 
 def _apply_two_qubit_matrix(state, qubits: tuple[int, int], matrix: cp.ndarray) -> None:
     """
@@ -279,3 +281,13 @@ def SWAP(state, qubits: tuple[int, int], **params: Any) -> None:
         dtype=state.dtype,
     )
     _apply_two_qubit_matrix(state, qubits, matrix)
+
+
+def G(state, qubits: tuple[int, int], **params: Any) -> None:
+    """'G': (('I', 'H'), 'CNOT', ('H', 'H'), 'CNOT', ('I', 'H'))"""
+    H(state, qubits[1])
+    CX(state, qubits)
+    H(state, qubits[0])
+    H(state, qubits[1])
+    CX(state, qubits)
+    H(state, qubits[1])
diff --git a/python/pecos/simulators/parent_sim_classes.py b/python/pecos/simulators/parent_sim_classes.py
index 4d194c92..e0964b4c 100644
--- a/python/pecos/simulators/parent_sim_classes.py
+++ b/python/pecos/simulators/parent_sim_classes.py
@@ -40,7 +40,11 @@ def run_gate(self, symbol: str, locations: set[int] | set[tuple[int, ...]], **pa
                 elif "angle" in params and "angles" not in params:
                     params["angles"] = (params["angle"],)
 
-                results = self.bindings[symbol](self, location, **params)
+                if symbol in self.bindings:
+                    results = self.bindings[symbol](self, location, **params)
+                else:
+                    msg = f"Gate {symbol} is not supported in this simulator."
+                    raise Exception(msg)
 
                 # TODO: get params var value ... -> result = {'sym':, 'index':, 'result': result, 'qubit': location}
 
diff --git a/python/pecos/simulators/quest/bindings.py b/python/pecos/simulators/quest/bindings.py
index b34d9e16..587feaa0 100644
--- a/python/pecos/simulators/quest/bindings.py
+++ b/python/pecos/simulators/quest/bindings.py
@@ -71,4 +71,34 @@
     "SqrtZZ": two_q.SZZ,
     "SZZdg": two_q.SZZdg,
     "SWAP": two_q.SWAP,
+    # Additional Cliffords from `circuit_converters/std2chs.py`
+    "Q": one_q.SX,
+    "Qd": one_q.SXdg,
+    "R": one_q.SY,
+    "Rd": one_q.SYdg,
+    "S": one_q.SZ,
+    "Sd": one_q.SZdg,
+    "H1": one_q.H,
+    "H2": one_q.H2,
+    "H3": one_q.H3,
+    "H4": one_q.H4,
+    "H5": one_q.H5,
+    "H6": one_q.H6,
+    "H+z+x": one_q.H,
+    "H-z-x": one_q.H2,
+    "H+y-z": one_q.H3,
+    "H-y-z": one_q.H4,
+    "H-x+y": one_q.H5,
+    "H-x-y": one_q.H6,
+    "F1": one_q.F,
+    "F1d": one_q.Fdg,
+    "F2": one_q.F2,
+    "F2d": one_q.F2d,
+    "F3": one_q.F3,
+    "F3d": one_q.F3d,
+    "F4": one_q.F4,
+    "F4d": one_q.F4d,
+    "CNOT": two_q.CX,
+    "G": two_q.G,
+    "II": one_q.identity,
 }
diff --git a/python/pecos/simulators/quest/gates_one_qubit.py b/python/pecos/simulators/quest/gates_one_qubit.py
index 3f1819ed..ed172f00 100644
--- a/python/pecos/simulators/quest/gates_one_qubit.py
+++ b/python/pecos/simulators/quest/gates_one_qubit.py
@@ -265,3 +265,78 @@ def Tdg(state, qubit: int, **params: Any) -> None:
         qubit: The index of the qubit where the gate is applied
     """
     RZ(state, qubit, angles=(-np.pi / 4,))
+
+
+# The definition of the extra Clifford gates added below come from
+# circuit_converters/std2chs.py
+def H2(state, qubit: int, **params: Any) -> None:
+    """'H2': ('S', 'S', 'H', 'S', 'S')"""
+    Z(state, qubit)
+    H(state, qubit)
+    Z(state, qubit)
+
+
+def H3(state, qubit: int, **params: Any) -> None:
+    """'H3': ('H', 'S', 'S', 'H', 'S',)"""
+    X(state, qubit)
+    SZ(state, qubit)
+
+
+def H4(state, qubit: int, **params: Any) -> None:
+    """'H4': ('H', 'S', 'S', 'H', 'S', 'S', 'S',)"""
+    X(state, qubit)
+    SZdg(state, qubit)
+
+
+def H5(state, qubit: int, **params: Any) -> None:
+    """'H5': ('S', 'S', 'S', 'H', 'S')"""
+    SZdg(state, qubit)
+    H(state, qubit)
+    SZ(state, qubit)
+
+
+def H6(state, qubit: int, **params: Any) -> None:
+    """'H6': ('S', 'H', 'S', 'S', 'S',)"""
+    SZ(state, qubit)
+    H(state, qubit)
+    SZdg(state, qubit)
+
+
+def F2(state, qubit: int, **params: Any) -> None:
+    """'F2': ('S', 'S', 'H', 'S')"""
+    Z(state, qubit)
+    H(state, qubit)
+    SZ(state, qubit)
+
+
+def F2d(state, qubit: int, **params: Any) -> None:
+    """'F2d': ('S', 'S', 'S', 'H', 'S', 'S')"""
+    SZdg(state, qubit)
+    H(state, qubit)
+    Z(state, qubit)
+
+
+def F3(state, qubit: int, **params: Any) -> None:
+    """'F3': ('S', 'H', 'S', 'S')"""
+    SZ(state, qubit)
+    H(state, qubit)
+    Z(state, qubit)
+
+
+def F3d(state, qubit: int, **params: Any) -> None:
+    """'F3d': ('S', 'S', 'H', 'S', 'S', 'S')"""
+    Z(state, qubit)
+    H(state, qubit)
+    SZdg(state, qubit)
+
+
+def F4(state, qubit: int, **params: Any) -> None:
+    """'F4': ('H', 'S', 'S', 'S')"""
+    H(state, qubit)
+    SZdg(state, qubit)
+
+
+def F4d(state, qubit: int, **params: Any) -> None:
+    """'F4d': ('S', 'H')"""
+    SZ(state, qubit)
+    H(state, qubit)
diff --git a/python/pecos/simulators/quest/gates_two_qubit.py b/python/pecos/simulators/quest/gates_two_qubit.py
index 1cc33776..7ff18545 100644
--- a/python/pecos/simulators/quest/gates_two_qubit.py
+++ b/python/pecos/simulators/quest/gates_two_qubit.py
@@ -15,6 +15,8 @@
 import numpy as np
 import pyquest.unitaries as qgate
 
+from pecos.simulators.quest.gates_one_qubit import H
+
 
 def CX(state, qubits: tuple[int, int], **params: Any) -> None:
     """
@@ -241,3 +243,13 @@ def SWAP(state, qubits: tuple[int, int], **params: Any) -> None:
     idxs = [state.num_qubits - q - 1 for q in qubits]
 
     state.quest_state.apply_operator(qgate.Swap(targets=idxs))
+
+
+def G(state, qubits: tuple[int, int], **params: Any) -> None:
+    """'G': (('I', 'H'), 'CNOT', ('H', 'H'), 'CNOT', ('I', 'H'))"""
+    H(state, qubits[1])
+    CX(state, qubits)
+    H(state, qubits[0])
+    H(state, qubits[1])
+    CX(state, qubits)
+    H(state, qubits[1])
diff --git a/python/pecos/simulators/qulacs/bindings.py b/python/pecos/simulators/qulacs/bindings.py
index bbcf40d9..7ad2bb5a 100644
--- a/python/pecos/simulators/qulacs/bindings.py
+++ b/python/pecos/simulators/qulacs/bindings.py
@@ -71,4 +71,34 @@
     "SqrtZZ": two_q.SZZ,
     "SZZdg": two_q.SZZdg,
     "SWAP": two_q.SWAP,
+    # Additional Cliffords from `circuit_converters/std2chs.py`
+    "Q": one_q.SX,
+    "Qd": one_q.SXdg,
+    "R": one_q.SY,
+    "Rd": one_q.SYdg,
+    "S": one_q.SZ,
+    "Sd": one_q.SZdg,
+    "H1": one_q.H,
+    "H2": one_q.H2,
+    "H3": one_q.H3,
+    "H4": one_q.H4,
+    "H5": one_q.H5,
+    "H6": one_q.H6,
+    "H+z+x": one_q.H,
+    "H-z-x": one_q.H2,
+    "H+y-z": one_q.H3,
+    "H-y-z": one_q.H4,
+    "H-x+y": one_q.H5,
+    "H-x-y": one_q.H6,
+    "F1": one_q.F,
+    "F1d": one_q.Fdg,
+    "F2": one_q.F2,
+    "F2d": one_q.F2d,
+    "F3": one_q.F3,
+    "F3d": one_q.F3d,
+    "F4": one_q.F4,
+    "F4d": one_q.F4d,
+    "CNOT": two_q.CX,
+    "G": two_q.G,
+    "II": one_q.identity,
 }
diff --git a/python/pecos/simulators/qulacs/gates_one_qubit.py b/python/pecos/simulators/qulacs/gates_one_qubit.py
index c75ca11f..9b115160 100644
--- a/python/pecos/simulators/qulacs/gates_one_qubit.py
+++ b/python/pecos/simulators/qulacs/gates_one_qubit.py
@@ -265,3 +265,78 @@ def Tdg(state, qubit: int, **params: Any) -> None:
         qubit: The index of the qubit where the gate is applied
     """
     RZ(state, qubit, angles=(-np.pi / 4,))
+
+
+# The definition of the extra Clifford gates added below come from
+# circuit_converters/std2chs.py
+def H2(state, qubit: int, **params: Any) -> None:
+    """'H2': ('S', 'S', 'H', 'S', 'S')"""
+    Z(state, qubit)
+    H(state, qubit)
+    Z(state, qubit)
+
+
+def H3(state, qubit: int, **params: Any) -> None:
+    """'H3': ('H', 'S', 'S', 'H', 'S',)"""
+    X(state, qubit)
+    SZ(state, qubit)
+
+
+def H4(state, qubit: int, **params: Any) -> None:
+    """'H4': ('H', 'S', 'S', 'H', 'S', 'S', 'S',)"""
+    X(state, qubit)
+    SZdg(state, qubit)
+
+
+def H5(state, qubit: int, **params: Any) -> None:
+    """'H5': ('S', 'S', 'S', 'H', 'S')"""
+    SZdg(state, qubit)
+    H(state, qubit)
+    SZ(state, qubit)
+
+
+def H6(state, qubit: int, **params: Any) -> None:
+    """'H6': ('S', 'H', 'S', 'S', 'S',)"""
+    SZ(state, qubit)
+    H(state, qubit)
+    SZdg(state, qubit)
+
+
+def F2(state, qubit: int, **params: Any) -> None:
+    """'F2': ('S', 'S', 'H', 'S')"""
+    Z(state, qubit)
+    H(state, qubit)
+    SZ(state, qubit)
+
+
+def F2d(state, qubit: int, **params: Any) -> None:
+    """'F2d': ('S', 'S', 'S', 'H', 'S', 'S')"""
+    SZdg(state, qubit)
+    H(state, qubit)
+    Z(state, qubit)
+
+
+def F3(state, qubit: int, **params: Any) -> None:
+    """'F3': ('S', 'H', 'S', 'S')"""
+    SZ(state, qubit)
+    H(state, qubit)
+    Z(state, qubit)
+
+
+def F3d(state, qubit: int, **params: Any) -> None:
+    """'F3d': ('S', 'S', 'H', 'S', 'S', 'S')"""
+    Z(state, qubit)
+    H(state, qubit)
+    SZdg(state, qubit)
+
+
+def F4(state, qubit: int, **params: Any) -> None:
+    """'F4': ('H', 'S', 'S', 'S')"""
+    H(state, qubit)
+    SZdg(state, qubit)
+
+
+def F4d(state, qubit: int, **params: Any) -> None:
+    """'F4d': ('S', 'H')"""
+    SZ(state, qubit)
+    H(state, qubit)
diff --git a/python/pecos/simulators/qulacs/gates_two_qubit.py b/python/pecos/simulators/qulacs/gates_two_qubit.py
index 4db16fa3..fd6dac7b 100644
--- a/python/pecos/simulators/qulacs/gates_two_qubit.py
+++ b/python/pecos/simulators/qulacs/gates_two_qubit.py
@@ -14,7 +14,7 @@
 import numpy as np
 import qulacs.gate as qgate
 
-from pecos.simulators.qulacs.gates_one_qubit import SZ, SZdg
+from pecos.simulators.qulacs.gates_one_qubit import SZ, H, SZdg
 
 
 def CX(state, qubits: tuple[int, int], **params: Any) -> None:
@@ -231,3 +231,13 @@ def SWAP(state, qubits: tuple[int, int], **params: Any) -> None:
     idxs = [state.num_qubits - q - 1 for q in qubits]
 
     qgate.SWAP(idxs[0], idxs[1]).update_quantum_state(state.qulacs_state)
+
+
+def G(state, qubits: tuple[int, int], **params: Any) -> None:
+    """'G': (('I', 'H'), 'CNOT', ('H', 'H'), 'CNOT', ('I', 'H'))"""
+    H(state, qubits[1])
+    CX(state, qubits)
+    H(state, qubits[0])
+    H(state, qubits[1])
+    CX(state, qubits)
+    H(state, qubits[1])


Test patch:
diff --git a/tests/integration/state_sim_tests/test_cointoss.py b/tests/integration/state_sim_tests/test_cointoss.py
index 0708d4a4..9680a744 100644
--- a/tests/integration/state_sim_tests/test_cointoss.py
+++ b/tests/integration/state_sim_tests/test_cointoss.py
@@ -12,6 +12,7 @@
 from __future__ import annotations
 
 import numpy as np
+
 from pecos.circuits import QuantumCircuit
 from pecos.simulators import CoinToss
 
@@ -70,6 +71,35 @@ def test_all_gate_circ():
     qc.append({"SWAP": {(4, 0)}})
     qc.append({"Tdg": {3, 1}})
     qc.append({"RXX": {(1, 3)}}, angles=(np.pi / 4,))
+    qc.append({"Q": {1, 4, 2}})
+    qc.append({"Qd": {0, 3}})
+    qc.append({"R": {0}})
+    qc.append({"Rd": {1, 4, 2}})
+    qc.append({"S": {0, 3}})
+    qc.append({"Sd": {0}})
+    qc.append({"H1": {0, 3}})
+    qc.append({"H2": {2, 3}})
+    qc.append({"H3": {1, 4, 2}})
+    qc.append({"H4": {2, 3}})
+    qc.append({"H5": {0, 3}})
+    qc.append({"H6": {1, 4, 2}})
+    qc.append({"H+z+x": {2, 3}})
+    qc.append({"H-z-x": {1, 4, 2}})
+    qc.append({"H+y-z": {0, 3}})
+    qc.append({"H-y-z": {2, 3}})
+    qc.append({"H-x+y": {0, 3}})
+    qc.append({"H-x-y": {1, 4, 2}})
+    qc.append({"F1": {0, 3}})
+    qc.append({"F1d": {2, 3}})
+    qc.append({"F2": {1, 4, 2}})
+    qc.append({"F2d": {0, 3}})
+    qc.append({"F3": {2, 3}})
+    qc.append({"F3d": {1, 4, 2}})
+    qc.append({"F4": {2, 3}})
+    qc.append({"F4d": {0, 3}})
+    qc.append({"CNOT": {(0, 1)}})
+    qc.append({"G": {(1, 3)}})
+    qc.append({"II": {(4, 2)}})
 
     # Measure
     qc.append({"Measure": {0, 1, 2, 3, 4}})
diff --git a/tests/integration/state_sim_tests/test_statevec.py b/tests/integration/state_sim_tests/test_statevec.py
index f4a58aad..236618d1 100644
--- a/tests/integration/state_sim_tests/test_statevec.py
+++ b/tests/integration/state_sim_tests/test_statevec.py
@@ -23,6 +23,7 @@
 
 import numpy as np
 import pytest
+
 from pecos.circuits import QuantumCircuit
 from pecos.engines.hybrid_engine import HybridEngine
 from pecos.error_models.generic_error_model import GenericErrorModel
@@ -304,6 +305,64 @@ def test_all_gate_circ(simulator):
         compare_against_basicsv(simulator, qc)
         qc.append({"RXX": {(1, 3)}}, angles=(np.pi / 4,))
         compare_against_basicsv(simulator, qc)
+        qc.append({"Q": {1, 4, 2}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"Qd": {0, 3}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"R": {0}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"Rd": {1, 4, 2}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"S": {0, 3}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"Sd": {0}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"H1": {0, 3}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"H2": {2, 3}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"H3": {1, 4, 2}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"H4": {2, 3}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"H5": {0, 3}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"H6": {1, 4, 2}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"H+z+x": {2, 3}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"H-z-x": {1, 4, 2}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"H+y-z": {0, 3}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"H-y-z": {2, 3}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"H-x+y": {0, 3}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"H-x-y": {1, 4, 2}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"F1": {0, 3}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"F1d": {2, 3}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"F2": {1, 4, 2}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"F2d": {0, 3}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"F3": {2, 3}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"F3d": {1, 4, 2}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"F4": {2, 3}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"F4d": {0, 3}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"CNOT": {(0, 1)}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"G": {(1, 3)}})
+        compare_against_basicsv(simulator, qc)
+        qc.append({"II": {(4, 2)}})
+        compare_against_basicsv(simulator, qc)
 
         # Measure
         qc.append({"Measure": {0, 1, 2, 3, 4}})