Skip to content

Commit ba9892b

Browse files
authored
Feature/documentation (#33)
* Added documentation to the Grover and MaxKCutGrover mixer classes. * Added documentation to the MaxKCutLX class. * Added documentation to the X, XY and XYTensor mixer classes. Also did some refining on the documentation of the mixer classes. * Added documentation to the utility classes and functions. * Added documentation to the OptResults and QAOA classes. * Restore example notebooks to match original main branch. * Fixed spelling errors, removed whitespaces and added some comments to docstring.
1 parent 9370e96 commit ba9892b

File tree

11 files changed

+699
-73
lines changed

11 files changed

+699
-73
lines changed

qaoa/mixers/grover_mixer.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,25 @@
66

77

88
class Grover(Mixer):
9+
"""
10+
Grover mixer.
11+
12+
Subclass of the `Mixer` subclass that implements the Grover mixing operation.
13+
14+
Attributes:
15+
subcircuit (InitialState): The initial state circuit to be tensorized.
16+
circuit (QuantumCircuit): The quantum circuit representing the mixer.
17+
mixer_param (Parameter): The parameter for the mixer.
18+
N_qubits (int): The number of qubits in the mixer circuit.
19+
20+
Methods:
21+
create_circuit(): Constructs the Grover mixer circuit using the subcircuit.
22+
"""
23+
924
def __init__(self, subcircuit: InitialState) -> None:
1025
"""
26+
Initializes the Grover mixer.
27+
1128
Args:
1229
subcircuit (InitialState): the circuit that is to be tensorised
1330
"""
@@ -16,9 +33,13 @@ def __init__(self, subcircuit: InitialState) -> None:
1633
self.N_qubits = subcircuit.N_qubits
1734

1835
def create_circuit(self):
19-
# given feasibel states f \in F,
20-
# Let US the circuit that prepares US = 1/|F| \sum_{f\inF} |f>
21-
# The Grover mixer has the form US^\dagger X^n C^{n-1}Phase X^n US,
36+
"""
37+
Constructs the Grover mixer circuit using the subcircuit.
38+
39+
Given feasible states f \in F,
40+
and let US be the circuit that prepares US = 1/|F| \sum_{f\inF} |f>.
41+
The Grover mixer has the form US^\dagger X^n C^{n-1}Phase X^n US.
42+
"""
2243

2344
self.subcircuit.create_circuit()
2445
US = self.subcircuit.circuit

qaoa/mixers/maxkcut_grover_mixer.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,39 @@
99

1010

1111
class MaxKCutGrover(Mixer):
12+
"""
13+
Grover mixer for the Max K-Cut problem.
14+
15+
Subclass of the `Mixer` subclass that implements the Grover mixing operation for the Max k-cut problem.
16+
17+
Attributes:
18+
k_cuts (int): The number of cuts in the Max k-Cut problem.
19+
problem_encoding (str): The encoding of the problem, either "onehot" or "binary".
20+
color_encoding (str): The encoding of colors, can be "max_balanced", "Dicke1_2", or "LessThanK".
21+
tensorized (bool): Whether to use tensorization for the mixer.
22+
23+
Methods:
24+
is_power_of_two(): Returns True if `k_cuts` is a power of two, False otherwise.
25+
set_numV(k): Sets the number of vertices based on the number of cuts.
26+
create_circuit(): Constructs the Grover mixer circuit for the Max k-Cut problem.
27+
"""
28+
1229
def __init__(
1330
self, k_cuts: int, problem_encoding: str, color_encoding: str, tensorized: bool
1431
) -> None:
32+
"""
33+
Initializes the MaxKCutGrover mixer.
34+
35+
Args:
36+
k_cuts (int): The number of cuts in the Max k-Cut problem.
37+
problem_encoding (str): The encoding of the problem, either "onehot" or "binary".
38+
color_encoding (str): The encoding of colors, can be "max_balanced", "Dicke1_2", or "LessThanK".
39+
tensorized (bool): Whether to use tensorization for the mixer.
40+
41+
Raises:
42+
ValueError: If `k_cuts` is less than 2 or greater than 8, or if `problem_encoding` is not valid.
43+
ValueError: If `color_encoding` is not valid for the given `k_cuts`.
44+
"""
1545
if (k_cuts < 2) or (k_cuts > 8):
1646
raise ValueError(
1747
"k_cuts must be 2 or more, and is not implemented for k_cuts > 8"
@@ -45,6 +75,15 @@ def is_power_of_two(self) -> bool:
4575
return False
4676

4777
def set_numV(self, k):
78+
"""
79+
Set the number of vertices based on the number of cuts.
80+
81+
Args:
82+
k (int): The number of cuts in the Max k-Cut problem.
83+
84+
Raises:
85+
ValueError: If the total number of qubits is not a multiple of k.
86+
"""
4887
num_V = self.N_qubits / k
4988

5089
if not num_V.is_integer():
@@ -55,6 +94,10 @@ def set_numV(self, k):
5594
self.num_V = int(num_V)
5695

5796
def create_circuit(self) -> None:
97+
"""
98+
Constructs the Grover mixer circuit for the Max k-Cut problem.
99+
"""
100+
58101
if self.problem_encoding == "binary":
59102
self.k_bits = int(np.ceil(np.log2(self.k_cuts)))
60103
self.set_numV(self.k_bits)

qaoa/mixers/maxkcut_lx_mixer.py

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,36 @@
1010

1111

1212
class MaxKCutLX(Mixer):
13+
"""
14+
Logical X (LX) mixer for the Max k-Cut problem.
15+
16+
Subclass of the `Mixer` subclass that implements the LX mixing operation for the Max k-Cut problem.
17+
18+
Attributes:
19+
k_cuts (int): The number of cuts in the Max k-Cut problem.
20+
color_encoding (str): The encoding of colors, can be "LessThanK", "Dicke1_2", or "max_balanced".
21+
topology (str): The topology of the mixer, either "standard" or "ring".
22+
23+
Methods:
24+
is_power_of_two(): Returns True if `k_cuts` is a power of two, False otherwise.
25+
create_SparsePauliOp(): Creates the sparse Pauli operator for the given `k_cuts`.
26+
create_circuit(): Constructs the LX mixer circuit for the Max k-Cut problem.
27+
"""
28+
1329
def __init__(self, k_cuts: int, color_encoding: str, topology: str = "standard"):
30+
"""
31+
Initializes the MaxKCutLX mixer.
32+
33+
Args:
34+
k_cuts (int): The number of cuts in the Max k-Cut problem.
35+
color_encoding (str): The encoding of colors, can be "LessThanK", "Dicke1_2", or "max_balanced".
36+
topology (str): The topology of the mixer, either "standard" or "ring".
37+
38+
Raises:
39+
ValueError: If `k_cuts` is a power of two.
40+
ValueError: If `color_encoding` is not specified.
41+
ValueError: If `k_cuts` is 3 and `topology` is not "standard" or "ring".
42+
"""
1443
if (k_cuts < 2) or (k_cuts > 8):
1544
raise ValueError(
1645
"k_cuts must be 2 or more, and is not implemented for k_cuts > 8"
@@ -33,15 +62,16 @@ def __init__(self, k_cuts: int, color_encoding: str, topology: str = "standard")
3362

3463
def is_power_of_two(self) -> bool:
3564
"""
36-
Return True if self.k_cuts is a power of two, False otherwise.
65+
Returns:
66+
bool: True if self.k_cuts is a power of two, False otherwise.
3767
"""
3868
if self.k_cuts > 0 and (self.k_cuts & (self.k_cuts - 1)) == 0:
3969
return True
4070
return False
4171

4272
def create_SparsePauliOp(self) -> None:
4373
"""
44-
Create sparse Pauli operator for given k. Hard coded
74+
Create sparse Pauli operator for given k. Hard coded.
4575
4676
Returns:
4777
None
@@ -108,6 +138,9 @@ def create_SparsePauliOp(self) -> None:
108138
self.op = SparsePauliOp(data, coeffs=coeffs)
109139

110140
def create_circuit(self) -> None:
141+
"""
142+
Constructs the LX mixer circuit for the Max k-Cut problem.
143+
"""
111144
self.num_V = int(self.N_qubits / self.k_bits)
112145
q = QuantumRegister(self.N_qubits)
113146
mixer_param = Parameter("x_beta")

qaoa/mixers/x_mixer.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,30 @@
55

66

77
class X(Mixer):
8+
"""
9+
X mixer.
10+
11+
Subclass of the `Mixer` subclass that implements the X mixing operation.
12+
13+
Attributes:
14+
mixer_param (Parameter): The parameter for the mixer.
15+
N_qubits (int): The number of qubits in the circuit.
16+
circuit (QuantumCircuit): The mixer's quantum circuit.
17+
18+
Methods:
19+
create_circuit(): Constructs the X mixer circuit.
20+
"""
21+
822
def __init__(self) -> None:
23+
"""
24+
Initializes the X mixer.
25+
"""
926
self.mixer_param = Parameter("x_beta")
1027

1128
def create_circuit(self):
29+
"""
30+
Constructs the X mixer circuit.
31+
"""
1232
q = QuantumRegister(self.N_qubits)
1333

1434
self.circuit = QuantumCircuit(q)

qaoa/mixers/xy_mixer.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,38 @@
1111

1212

1313
class XY(Mixer):
14+
"""
15+
XY mixer.
16+
17+
Subclass of the `Mixer` subclass that implements the XY mixing operation.
18+
19+
Attributes:
20+
topology (list): The topology of the mixer, default is None.
21+
mixer_param (Parameter): The parameter for the XY mixer.
22+
N_qubits (int): The number of qubits in the mixer circuit.
23+
circuit (QuantumCircuit): The quantum circuit representing the XY mixer.
24+
25+
Methods:
26+
create_circuit(): Constructs the XY mixer circuit using the specified topology.
27+
generate_pairs(n, case="ring"): Generates pairs of qubits based on the specified topology.
28+
"""
29+
1430
def __init__(self, topology=None) -> None:
31+
"""
32+
Initializes the XY mixer.
33+
34+
Args:
35+
topology (list, optional): The topology of the mixer. If None, defaults to "ring" topology.
36+
"""
1537
self.topology = topology
1638
self.mixer_param = Parameter("x_beta")
1739

1840
def create_circuit(self):
41+
"""
42+
Constructs the XY mixer circuit using the specified topology.
43+
44+
If no topology is specified, it defaults to a "ring" topology.
45+
"""
1946
if not self.topology:
2047
print('No topology specified for the XY-mixer, assuming "ring" topology')
2148
self.topology = XY.generate_pairs(self.N_qubits)
@@ -28,6 +55,15 @@ def create_circuit(self):
2855

2956
@staticmethod
3057
def generate_pairs(n, case="ring"):
58+
"""_summary_
59+
60+
Args:
61+
n (int): The number of qubits.
62+
case (str, optional): Topology. Defaults to "ring".
63+
64+
Returns:
65+
list: A list of pairs of qubit indices based on the specified topology.
66+
"""
3167
# default ring, otherwise "chain"
3268
if n < 2:
3369
return [] # Not enough elements to form any pairs

qaoa/mixers/xy_tensor.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,38 @@
88

99

1010
class XYTensor(Mixer):
11+
"""
12+
XY tensor mixer for the Max k-Cut problem.
13+
14+
Subclass of the `Mixer` class that implements the XY tensor mixing operation for the Max k-Cut problem.
15+
16+
Attributes:
17+
k_cuts (int): The number of cuts in the Max k-Cut problem.
18+
topology (list): The topology of the mixer, default is None.
19+
num_V (int): The number of vertices in the Max k-Cut problem.
20+
21+
Methods:
22+
create_circuit(): Constructs the XY tensor mixer circuit for the Max k-Cut problem.
23+
"""
24+
1125
def __init__(self, k_cuts: int, topology=None) -> None:
26+
"""
27+
Initializes the XYTensor mixer for the Max k-Cut problem.
28+
29+
Args:
30+
k_cuts (int): The number of cuts in the Max k-Cut problem.
31+
topology (list, optional): The topology of the mixer. If None, defaults to "ring" topology.
32+
"""
1233
self.k_cuts = k_cuts
1334
self.topology = topology
1435

1536
def create_circuit(self) -> None:
37+
"""
38+
Constructs the XY tensor mixer circuit for the Max k-Cut problem.
39+
40+
Raises:
41+
ValueError: If the total number of qubits is not a multiple of `k_cuts`.
42+
"""
1643
self.num_V = self.N_qubits / self.k_cuts
1744

1845
if not self.num_V.is_integer():

0 commit comments

Comments
 (0)