-
Notifications
You must be signed in to change notification settings - Fork 24
Expand file tree
/
Copy pathlessthank_initialstate.py
More file actions
152 lines (129 loc) · 4.69 KB
/
lessthank_initialstate.py
File metadata and controls
152 lines (129 loc) · 4.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import numpy as np
from qiskit import QuantumCircuit, QuantumRegister
from qiskit.circuit.library import XXPlusYYGate
from .base_initialstate import InitialState # type: ignore
class LessThanK(InitialState):
"""
LessThanK initial state.
Subclass for the `InitialState` class. Creates a quantum circuit representing the initial state for the for the MAX k-CUT problem.
For k not a power of two, the initial state is a superposition of k feasible states from the computational basis.
Attributes:
k (int): subsets (or "colors") of the vertices in the MAX k-CUT problem is seperated into.
Methods:
create_circuit(): Generates a circuit that creates the initial state from the |0> state.
"""
def __init__(self, k: int) -> None:
"""
Checks that the k-value is valid and initizalizes N qubits and k cuts
Args:
k (int): the number of subsets of the vertices in the MAX k-CUT problem
Raises:
ValueError: if k is neither a power of 2 or between 2 and 8
"""
if not LessThanK.is_power_of_two_or_between_2_and_8(k):
raise ValueError("k must be a power of two or between 2 and 8")
self.k = k
self.N_qubits = int(np.ceil(np.log2(self.k)))
def create_circuit(self) -> None:
"""
Creates a circuit by calling on the methods for different k, following the algorithm from https://arxiv.org/abs/2411.08594.
k is between 2 and 8 or a power of 2.
"""
if self.k == 3:
self.circuit = self.k3()
elif self.k == 5:
self.circuit = self.k5()
elif self.k == 6:
self.circuit = self.k6()
elif self.k == 7:
self.circuit = self.k7()
else:
self.circuit = self.power_of_two()
def is_power_of_two_or_between_2_and_8(k):
"""
Checks the validity of the argument k, so that k is either between 2 and 8 or a power of 2
Returns:
True if k is a power of 2 or between 2 and 8, and False otherwise
"""
# Check if k is between 2 and 8
if 2 <= k <= 8:
return True
# Check if k is a power of two
# A number is a power of two if it has exactly one bit set, i.e., k & (k - 1) == 0 and k > 0
if k > 0 and (k & (k - 1)) == 0:
return True
return False
def power_of_two(self) -> QuantumCircuit:
"""
Creates a circuit for the case where k is a power of two.
Returns:
QuantumCircuit: Quantum circuit.
"""
q = QuantumRegister(self.N_qubits)
circuit = QuantumCircuit(q)
circuit.h(q)
return circuit
def k3(self) -> QuantumCircuit:
"""
Creates a circuit for the case k = 3.
Returns:
QuantumCircuit: Quantum circuit.
"""
q = QuantumRegister(self.N_qubits)
circuit = QuantumCircuit(q)
theta = np.arccos(1 / np.sqrt(3)) * 2
phi = np.pi / 2
beta = -np.pi / 2
circuit.ry(theta, 1)
gate = XXPlusYYGate(phi, beta)
circuit.append(gate, [0, 1])
return circuit
def k5(self) -> QuantumCircuit:
"""
Creates a circuit for the case k = 5.
Returns:
QuantumCircuit: Quantum circuit.
"""
q = QuantumRegister(self.N_qubits)
circuit = QuantumCircuit(q)
theta = np.arcsin(1 / np.sqrt(5)) * 2
circuit.ry(theta, 0)
circuit.ch(0, [1, 2], ctrl_state=0)
return circuit
def k6(self) -> QuantumCircuit:
"""
Creates a circuit for the case k = 6.
Returns:
QuantumCircuit: Quantum circuit.
"""
q = QuantumRegister(self.N_qubits)
circuit = QuantumCircuit(q)
theta = np.pi / 2
phi = np.arccos(1 / np.sqrt(3)) * 2
gamma = np.pi / 2
beta = -np.pi / 2
circuit.ry(theta, 2)
circuit.ry(phi, 1)
gate = XXPlusYYGate(gamma, beta)
circuit.append(gate, [0, 1])
return circuit
def k7(self) -> QuantumCircuit:
"""
Creates a circuit for the case k = 7.
Returns:
QuantumCircuit: uantum circuit.
"""
q = QuantumRegister(self.N_qubits)
circuit = QuantumCircuit(q)
delta = np.arcsin(1 / np.sqrt(7)) * 2
theta = np.pi / 2
phi = np.arccos(1 / np.sqrt(3)) * 2
gamma = np.pi / 2
beta = -np.pi / 2
circuit.ry(delta, 0)
circuit.cx(0, 1)
circuit.cry(theta, 0, 2, ctrl_state=0)
circuit.cry(phi, 0, 1, ctrl_state=0)
gate = XXPlusYYGate(gamma, beta)
circuit.append(gate, [0, 1])
return circuit