diff --git a/.idea/.gitignore b/.idea/.gitignore
deleted file mode 100644
index eaf91e2a..00000000
--- a/.idea/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
diff --git a/.idea/OpenSquirrel.iml b/.idea/OpenSquirrel.iml
deleted file mode 100644
index 5625493c..00000000
--- a/.idea/OpenSquirrel.iml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
deleted file mode 100644
index 105ce2da..00000000
--- a/.idea/inspectionProfiles/profiles_settings.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 098984c5..00000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 58c5eb79..00000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100644
index c8397c94..00000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/opensquirrel/squirrel_ir.py b/opensquirrel/squirrel_ir.py
index 56c6ae4d..8cfbf0c1 100644
--- a/opensquirrel/squirrel_ir.py
+++ b/opensquirrel/squirrel_ir.py
@@ -8,7 +8,15 @@
import numpy as np
-from opensquirrel.common import ATOL, X, Y, Z, normalize_angle, normalize_axis
+from opensquirrel.common import (
+ ATOL,
+ X,
+ Y,
+ Z,
+ normalize_angle,
+ normalize_axis,
+ are_matrices_equivalent_up_to_global_phase,
+)
class SquirrelIRVisitor(ABC):
@@ -90,6 +98,11 @@ def __init__(self, generator, arguments):
self.generator = generator
self.arguments = arguments
+ def __eq__(self, other):
+ if not isinstance(other, Gate):
+ return False
+ return _compare_gate_classes(self, other)
+
@property
def name(self) -> Optional[str]:
return self.generator.__name__ if self.generator else ""
@@ -171,13 +184,6 @@ def __init__(self, matrix: np.ndarray, operands: List[Qubit], generator=None, ar
self.matrix = matrix
self.operands = operands
- def __eq__(self, other):
- if not (isinstance(other, ControlledGate) or isinstance(other, MatrixGate)):
- return False
- if isinstance(other, ControlledGate):
- return _compare_gate_classes(self, other)
- return np.allclose(self.matrix, other.matrix)
-
def __repr__(self):
return f"MatrixGate(qubits={self.operands}, matrix={self.matrix})"
@@ -200,17 +206,6 @@ def __init__(self, control_qubit: Qubit, target_gate: Gate, generator=None, argu
self.control_qubit = control_qubit
self.target_gate = target_gate
- def __eq__(self, other):
-
- if not (isinstance(other, ControlledGate) or isinstance(other, MatrixGate)):
- return False
- if isinstance(other, MatrixGate):
- return _compare_gate_classes(self, other)
- if self.control_qubit != other.control_qubit:
- return False
-
- return self.target_gate == other.target_gate
-
def __repr__(self):
return f"ControlledGate(control_qubit={self.control_qubit}, {self.target_gate})"
@@ -225,7 +220,7 @@ def is_identity(self) -> bool:
return self.target_gate.is_identity()
-def _compare_gate_classes(g1: Union[ControlledGate, MatrixGate], g2: Union[ControlledGate, MatrixGate]) -> bool:
+def _compare_gate_classes(g1: Gate, g2: Gate) -> bool:
union_mapping = list(set(g1.get_qubit_operands()) | set(g2.get_qubit_operands()))
@@ -234,7 +229,7 @@ def _compare_gate_classes(g1: Union[ControlledGate, MatrixGate], g2: Union[Contr
matrix_g1 = get_matrix_after_qubit_remapping([g1], union_mapping)
matrix_g2 = get_matrix_after_qubit_remapping([g2], union_mapping)
- return np.allclose(matrix_g1, matrix_g2)
+ return are_matrices_equivalent_up_to_global_phase(matrix_g1, matrix_g2)
def named_gate(gate_generator: Callable[..., Gate]) -> Callable[..., Gate]:
diff --git a/test/test_squirrel_ir.py b/test/test_squirrel_ir.py
index 05ab217d..1ad7b64d 100644
--- a/test/test_squirrel_ir.py
+++ b/test/test_squirrel_ir.py
@@ -80,3 +80,22 @@ def test_inverse_gate(self):
)
self.assertTrue(inverted_matrix_gate == inverted_cnot_gate)
+
+ def test_global_phase(self):
+ inverted_matrix_with_phase = MatrixGate(
+ np.array(
+ [
+ [1j, 0, 0, 0],
+ [0, 0, 0, 1j],
+ [0, 0, 1j, 0],
+ [0, 1j, 0, 0],
+ ]
+ ),
+ operands=[Qubit(0), Qubit(1)],
+ )
+
+ inverted_cnot_gate = ControlledGate(
+ Qubit(1), BlochSphereRotation(qubit=Qubit(0), axis=(1, 0, 0), angle=math.pi, phase=math.pi / 2)
+ )
+
+ self.assertTrue(inverted_matrix_with_phase == inverted_cnot_gate)