Skip to content

Commit

Permalink
Merge branch 'master' into stabilizers
Browse files Browse the repository at this point in the history
  • Loading branch information
renatomello committed Feb 19, 2024
2 parents 7cd30b2 + 4282655 commit 548f9b0
Show file tree
Hide file tree
Showing 12 changed files with 945 additions and 812 deletions.
3 changes: 0 additions & 3 deletions .github/.codecov.yml

This file was deleted.

8 changes: 8 additions & 0 deletions .github/codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
coverage:
status:
project:
default:
threshold: 0.5%

github_checks:
annotations: false
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ repos:
- id: check-yaml
- id: debug-statements
- repo: https://github.com/psf/black
rev: 24.1.1
rev: 24.2.0
hooks:
- id: black
- repo: https://github.com/pycqa/isort
Expand Down
1,599 changes: 843 additions & 756 deletions poetry.lock

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ cma = "^3.3.0"
joblib = "^1.2.0"
hyperopt = "^0.2.7"
tabulate = "^0.9.0"
numpy = "^1.26.4"
networkx = "^3.2.1"
cvxpy = {version = "^1.4.2", optional = true}
tensorflow = { version = "^2.14.1", markers = "sys_platform == 'linux' or sys_platform == 'darwin'", optional = true}

[tool.poetry.group.dev]
optional = true
Expand Down
116 changes: 74 additions & 42 deletions src/qibo/backends/npmatrices.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,51 +17,53 @@ def _cast(self, x, dtype):

@cached_property
def H(self):
return self.np.array([[1, 1], [1, -1]], dtype=self.dtype) / self.np.sqrt(2)
return self._cast([[1, 1], [1, -1]], dtype=self.dtype) / self.np.sqrt(2)

@cached_property
def X(self):
return self.np.array([[0, 1], [1, 0]], dtype=self.dtype)
return self._cast([[0, 1], [1, 0]], dtype=self.dtype)

@cached_property
def Y(self):
return self.np.array([[0, -1j], [1j, 0]], dtype=self.dtype)
return self._cast([[0j, -1j], [1j, 0j]], dtype=self.dtype)

@cached_property
def Z(self):
return self.np.array([[1, 0], [0, -1]], dtype=self.dtype)
return self._cast([[1, 0], [0, -1]], dtype=self.dtype)

@cached_property
def SX(self):
return self.np.array([[1 + 1j, 1 - 1j], [1 - 1j, 1 + 1j]], dtype=self.dtype) / 2
return self._cast([[1 + 1j, 1 - 1j], [1 - 1j, 1 + 1j]], dtype=self.dtype) / 2

@cached_property
def SXDG(self):
return self.np.transpose(self.np.conj(self.SX))
return self._cast([[1 - 1j, 1 + 1j], [1 + 1j, 1 - 1j]], dtype=self.dtype) / 2

@cached_property
def S(self):
return self.np.array([[1, 0], [0, 1j]], dtype=self.dtype)
return self._cast([[1 + 0j, 0j], [0j, 1j]], dtype=self.dtype)

@cached_property
def SDG(self):
return self.np.conj(self.S)
return self._cast([[1 + 0j, 0j], [0j, -1j]], dtype=self.dtype)

@cached_property
def T(self):
return self.np.array(
return self._cast(
[[1, 0], [0, self.np.exp(1j * self.np.pi / 4.0)]], dtype=self.dtype
)

@cached_property
def TDG(self):
return self.np.conj(self.T)
return self._cast(
[[1, 0], [0, self.np.exp(-1j * self.np.pi / 4.0)]], dtype=self.dtype
)

def I(self, n=2):
return self.np.eye(n, dtype=self.dtype)
return self._cast(self.np.eye(n, dtype=self.dtype), dtype=self.dtype)

def Align(self, n=2):
return self.I(n)
return self._cast(self.I(n), dtype=self.dtype)

def M(self): # pragma: no cover
raise_error(NotImplementedError)
Expand Down Expand Up @@ -98,9 +100,10 @@ def U2(self, phi, lam):
eplus = self.np.exp(1j * (phi + lam) / 2.0)
eminus = self.np.exp(1j * (phi - lam) / 2.0)
return self._cast(
[[self.np.conj(eplus), -self.np.conj(eminus)], [eminus, eplus]],
[[self.np.conj(eplus), -self.np.conj(eminus)], [eminus, eplus]]
/ self.np.sqrt(2),
dtype=self.dtype,
) / self.np.sqrt(2)
)

def U3(self, theta, phi, lam):
cost = self.np.cos(theta / 2)
Expand All @@ -116,32 +119,39 @@ def U3(self, theta, phi, lam):
)

def U1q(self, theta, phi):
return self.U3(theta, phi - self.np.pi / 2, self.np.pi / 2 - phi)
return self._cast(
self.U3(theta, phi - self.np.pi / 2, self.np.pi / 2 - phi), dtype=self.dtype
)

@cached_property
def CNOT(self):
return self.np.array(
return self._cast(
[[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]], dtype=self.dtype
)

@cached_property
def CY(self):
return self.np.array(
[[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, -1j], [0, 0, 1j, 0]],
return self._cast(
[
[1 + 0j, 0j, 0j, 0j],
[0j, 1 + 0j, 0j, 0j],
[0j, 0j, 0j, -1j],
[0j, 0j, 1j, 0j],
],
dtype=self.dtype,
)

@cached_property
def CZ(self):
return self.np.array(
return self._cast(
[[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, -1]], dtype=self.dtype
)

@cached_property
def CSX(self):
a = (1 + 1j) / 2
b = self.np.conj(a)
return self.np.array(
return self._cast(
[
[1, 0, 0, 0],
[0, 1, 0, 0],
Expand All @@ -153,7 +163,17 @@ def CSX(self):

@cached_property
def CSXDG(self):
return self.np.transpose(self.np.conj(self.CSX))
a = (1 - 1j) / 2
b = self.np.conj(a)
return self._cast(
[
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, a, b],
[0, 0, b, a],
],
dtype=self.dtype,
)

def CRX(self, theta):
cos = self.np.cos(theta / 2.0) + 0j
Expand Down Expand Up @@ -218,43 +238,49 @@ def CU3(self, theta, phi, lam):

@cached_property
def SWAP(self):
return self.np.array(
return self._cast(
[[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]], dtype=self.dtype
)

@cached_property
def iSWAP(self):
return self.np.array(
[[1, 0, 0, 0], [0, 0, 1j, 0], [0, 1j, 0, 0], [0, 0, 0, 1]], dtype=self.dtype
return self._cast(
[
[1 + 0j, 0j, 0j, 0j],
[0j, 0j, 1j, 0j],
[0j, 1j, 0j, 0j],
[0j, 0j, 0j, 1 + 0j],
],
dtype=self.dtype,
)

@cached_property
def SiSWAP(self):
return self.np.array(
return self._cast(
[
[1, 0, 0, 0],
[0, 1 / self.np.sqrt(2), 1j / self.np.sqrt(2), 0],
[0, 1j / self.np.sqrt(2), 1 / self.np.sqrt(2), 0],
[0, 0, 0, 1],
[1 + 0j, 0j, 0j, 0j],
[0j, 1 / self.np.sqrt(2) + 0j, 1j / self.np.sqrt(2), 0j],
[0j, 1j / self.np.sqrt(2), 1 / self.np.sqrt(2) + 0j, 0j],
[0j, 0j, 0j, 1 + 0j],
],
dtype=self.dtype,
)

@cached_property
def SiSWAPDG(self):
return self.np.array(
return self._cast(
[
[1, 0, 0, 0],
[0, 1 / self.np.sqrt(2), -1j / self.np.sqrt(2), 0],
[0, -1j / self.np.sqrt(2), 1 / self.np.sqrt(2), 0],
[0, 0, 0, 1],
[1 + 0j, 0j, 0j, 0j],
[0j, 1 / self.np.sqrt(2) + 0j, -1j / self.np.sqrt(2), 0j],
[0j, -1j / self.np.sqrt(2), 1 / self.np.sqrt(2) + 0j, 0j],
[0j, 0j, 0j, 1 + 0j],
],
dtype=self.dtype,
)

@cached_property
def FSWAP(self):
return self.np.array(
return self._cast(
[[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, -1]], dtype=self.dtype
)

Expand All @@ -277,7 +303,7 @@ def SYC(self):
cost = self.np.cos(self.np.pi / 2) + 0j
isint = -1j * self.np.sin(self.np.pi / 2)
phase = self.np.exp(-1j * self.np.pi / 6)
return self.np.array(
return self._cast(
[
[1, 0, 0, 0],
[0, cost, isint, 0],
Expand Down Expand Up @@ -392,14 +418,19 @@ def RBS(self, theta):

@cached_property
def ECR(self):
return self.np.array(
[[0, 0, 1, 1j], [0, 0, 1j, 1], [1, -1j, 0, 0], [-1j, 1, 0, 0]],
return self._cast(
[
[0j, 0j, 1 + 0j, 1j],
[0j, 0j, 1j, 1 + 0j],
[1 + 0j, -1j, 0j, 0j],
[-1j, 1 + 0j, 0j, 0j],
],
dtype=self.dtype,
) / self.np.sqrt(2)

@cached_property
def TOFFOLI(self):
return self.np.array(
return self._cast(
[
[1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0],
Expand All @@ -409,13 +440,14 @@ def TOFFOLI(self):
[0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 0, 1, 0],
]
],
dtype=self.dtype,
)

def DEUTSCH(self, theta):
sin = self.np.sin(theta) + 0j # 0j necessary for right tensorflow dtype
cos = self.np.cos(theta)
return self.np.array(
cos = self.np.cos(theta) + 0j
return self._cast(
[
[1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0],
Expand Down
6 changes: 3 additions & 3 deletions src/qibo/quantum_info/random_ensembles.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ def _ppf(self, theta: float):


def uniform_sampling_U3(ngates: int, seed=None, backend=None):
"""Samples parameters for Haar-random :math:`U_{3}`s (:class:`qibo.gates.U3`).
"""Samples parameters for Haar-random :class:`qibo.gates.U3`.
Args:
ngates (int): Total number of :math:`U_{3}`s to be sampled.
ngates (int): Total number of :math:`U_{3}` gates to be sampled.
seed (int or :class:`numpy.random.Generator`, optional): Either a generator of random
numbers or a fixed seed to initialize a generator. If ``None``, initializes
a generator with a random seed. Default: ``None``.
Expand All @@ -44,7 +44,7 @@ def uniform_sampling_U3(ngates: int, seed=None, backend=None):
Defaults to ``None``.
Returns:
(ndarray): array of shape (``ngates``, :math:`3`).
ndarray: array of shape (``ngates``, :math:`3`).
"""
if not isinstance(ngates, int):
raise_error(
Expand Down
7 changes: 3 additions & 4 deletions src/qibo/transpiler/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,12 +200,11 @@ def block_decomposition(circuit: Circuit, fuse: bool = True):
remove_list = [first_block]
if len(initial_blocks[1:]) > 0:
for second_block in initial_blocks[1:]:
try:
if second_block.qubits == first_block.qubits:
first_block = first_block.fuse(second_block)
remove_list.append(second_block)
except BlockingError:
if not first_block.commute(second_block):
break
elif not first_block.commute(second_block):
break
blocks.append(first_block)
_remove_gates(initial_blocks, remove_list)

Expand Down
8 changes: 6 additions & 2 deletions src/qibo/transpiler/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,9 @@ def __call__(self, circuit: Circuit, initial_layout: dict):
else:
self._find_new_mapping()

routed_circuit = self.circuit.routed_circuit(circuit_kwargs=circuit.init_kwargs)
circuit_kwargs = circuit.init_kwargs
circuit_kwargs["wire_names"] = list(initial_layout.keys())
routed_circuit = self.circuit.routed_circuit(circuit_kwargs=circuit_kwargs)
if self._final_measurements is not None:
routed_circuit = self._append_final_measurements(
routed_circuit=routed_circuit
Expand Down Expand Up @@ -658,7 +660,9 @@ def __call__(self, circuit: Circuit, initial_layout: dict):
else:
self._find_new_mapping()

routed_circuit = self.circuit.routed_circuit(circuit_kwargs=circuit.init_kwargs)
circuit_kwargs = circuit.init_kwargs
circuit_kwargs["wire_names"] = list(initial_layout.keys())
routed_circuit = self.circuit.routed_circuit(circuit_kwargs=circuit_kwargs)
if self._final_measurements is not None:
routed_circuit = self._append_final_measurements(
routed_circuit=routed_circuit
Expand Down
2 changes: 1 addition & 1 deletion src/qibo/transpiler/unroller.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def __call__(self, circuit: Circuit):
Returns:
(:class:`qibo.models.circuit.Circuit`): equivalent circuit with native gates.
"""
translated_circuit = circuit.__class__(circuit.nqubits)
translated_circuit = Circuit(**circuit.init_kwargs)
for gate in circuit.queue:
translated_circuit.add(
translate_gate(
Expand Down
1 change: 1 addition & 0 deletions tests/test_transpiler_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ def test_custom_passes_restict(gates, placer, routing):
final_layout=final_layout,
native_gates=NativeGates.default(),
)
assert transpiled_circ.wire_names == ["q1", "q2", "q3"]


def test_custom_passes_multiple_placer():
Expand Down
1 change: 1 addition & 0 deletions tests/test_transpiler_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ def test_restrict_qubits(router_algorithm):
)
assert_connectivity(restricted_connectivity, routed_circ)
assert_placement(routed_circ, final_layout, connectivity=restricted_connectivity)
assert routed_circ.wire_names == ["q0", "q2", "q3"]


def test_star_error_multi_qubit():
Expand Down

0 comments on commit 548f9b0

Please sign in to comment.