Skip to content

Commit d10c1e3

Browse files
authored
Merge pull request #1649 from victor-onofre/graph_state
[unitaryHack 2025] Graph state encoding
2 parents b059919 + 4a680b5 commit d10c1e3

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

src/qibo/models/encodings.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1555,3 +1555,37 @@ def _add_scs_gate(circuit: Circuit, n: int, k: int):
15551555
gates.RY(target_qubit, theta).controlled_by(control_qubit, last_qubit)
15561556
)
15571557
circuit.add(gates.CNOT(target_qubit, last_qubit))
1558+
1559+
1560+
def graph_state(matrix, backend=None, **kwargs):
1561+
"""Create circuit encoding an undirected graph state given its adjacency matrix.
1562+
1563+
Args:
1564+
matrix (ndarray or list): Adjacency matrix of the graph.
1565+
kwargs (dict, optional): Additional arguments used to initialize a Circuit object.
1566+
For details, see the documentation of :class:`qibo.models.circuit.Circuit`.
1567+
1568+
Returns:
1569+
:class:`qibo.models.circuit.Circuit`: Circuit of the graph state with the given Adjacency matrix.
1570+
"""
1571+
backend = _check_backend(backend)
1572+
1573+
if isinstance(matrix, list):
1574+
matrix = backend.cast(matrix, dtype=int)
1575+
1576+
if not backend.np.allclose(matrix, matrix.T):
1577+
raise_error(
1578+
ValueError,
1579+
f"``matrix`` is not symmetric, not representing an undirected graph",
1580+
)
1581+
1582+
nqubits = len(matrix)
1583+
1584+
circuit = Circuit(nqubits, **kwargs)
1585+
circuit.add(gates.H(qubit) for qubit in range(nqubits))
1586+
1587+
# since the matrix is symmetric, we only need the upper triangular part
1588+
rows, columns = backend.np.nonzero(backend.np.triu(matrix))
1589+
circuit.add(gates.CZ(int(ind_r), int(ind_c)) for ind_r, ind_c in zip(rows, columns))
1590+
1591+
return circuit

tests/test_models_encodings.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from functools import reduce
55
from itertools import combinations
66

7+
import networkx as nx
78
import numpy as np
89
import pytest
910
from scipy.optimize import curve_fit
@@ -18,6 +19,7 @@
1819
dicke_state,
1920
entangling_layer,
2021
ghz_state,
22+
graph_state,
2123
hamming_weight_encoder,
2224
phase_encoder,
2325
sparse_encoder,
@@ -493,3 +495,61 @@ def test_dicke_state(backend, nqubits, weight, density_matrix):
493495
target = backend.np.outer(target, backend.np.conj(target.T))
494496

495497
backend.assert_allclose(state, target)
498+
499+
500+
@pytest.mark.parametrize(
501+
"matrix, expects_error, circuit1, circuit2",
502+
[
503+
# Test Case 1: 3-qubit graph
504+
([[0, 1, 0], [1, 0, 1], [0, 1, 0]], False, True, False),
505+
# Test Case 2: 5-qubit graph
506+
(
507+
[
508+
[0, 1, 0, 0, 1],
509+
[1, 0, 1, 0, 0],
510+
[0, 1, 0, 1, 0],
511+
[0, 0, 1, 0, 1],
512+
[1, 0, 0, 1, 0],
513+
],
514+
False,
515+
False,
516+
True,
517+
),
518+
# Test Case 3: Non-symmetric matrix (expected error)
519+
(
520+
[[0, 1, 0], [0, 0, 1], [0, 1, 0]],
521+
True,
522+
False,
523+
False,
524+
), # matrix[1,0] != matrix[0,1]
525+
# Test Case 4: Non-symmetric matrix (expected error)
526+
([[0, 1], [0, 0]], True, False, False), # matrix[1,0] != matrix[0,1]
527+
],
528+
)
529+
def test_graph_state(backend, matrix, expects_error, circuit1, circuit2):
530+
531+
if expects_error:
532+
# We expect a ValueError for non-symmetric matrices
533+
with pytest.raises(ValueError):
534+
graph_state(matrix, backend=backend)
535+
536+
else:
537+
if circuit1:
538+
nqubits = 3
539+
target = Circuit(nqubits)
540+
target.add(gates.H(qubit) for qubit in range(nqubits))
541+
target.add(gates.CZ(0, 1))
542+
target.add(gates.CZ(1, 2))
543+
544+
if circuit2:
545+
nqubits = 5
546+
target = Circuit(nqubits)
547+
target.add(gates.H(qubit) for qubit in range(nqubits))
548+
target.add(gates.CZ(0, 1))
549+
target.add(gates.CZ(0, 4))
550+
target.add(gates.CZ(1, 2))
551+
target.add(gates.CZ(2, 3))
552+
target.add(gates.CZ(3, 4))
553+
554+
circuit = graph_state(matrix)
555+
backend.assert_circuitclose(circuit, target)

0 commit comments

Comments
 (0)