QAOA
In [23]:
Copied!
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.nn.init as init
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
from pyqtorch.core.circuit import QuantumCircuit
from pyqtorch.ansatz import AlternateLayerAnsatz
from pyqtorch.embedding import SingleLayerEncoding
from pyqtorch.core.operation import Z, RX
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.nn.init as init
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
from pyqtorch.core.circuit import QuantumCircuit
from pyqtorch.ansatz import AlternateLayerAnsatz
from pyqtorch.embedding import SingleLayerEncoding
from pyqtorch.core.operation import Z, RX
Solve MIS for QAOA¶
In [24]:
Copied!
np.random.seed(0)
n_nodes = 5
graph = nx.gnp_random_graph(n_nodes, .25, seed=42)
nx.draw(graph, with_labels=True)
np.random.seed(0)
n_nodes = 5
graph = nx.gnp_random_graph(n_nodes, .25, seed=42)
nx.draw(graph, with_labels=True)
In [32]:
Copied!
from pyqtorch.matrices import generate_ising_from_graph, sum_N
ising_matrix = generate_ising_from_graph(graph, type_ising='N')
ising_cost = 1.2*ising_matrix - sum_N(n_nodes)
ising_matrix = ising_matrix.reshape([2] * n_nodes + [1])
ising_cost = ising_cost.reshape([2] * n_nodes + [1])
class MIS(QuantumCircuit):
def __init__(self, n_qubits, n_layers):
super().__init__(n_qubits)
self.beta = nn.Parameter(torch.empty(n_layers,))
self.gamma = nn.Parameter(torch.empty(n_layers,))
self.reset_parameters()
def reset_parameters(self):
init.uniform_(self.beta, -2 * np.pi, 2 * np.pi)
init.uniform_(self.gamma, -2 * np.pi, 2 * np.pi)
def forward(self, return_cost=False):
state = self.uniform_state()
for b, g in zip(self.beta, self.gamma):
state = state * torch.exp(-1j * g * ising_matrix)
for i in range(self.n_qubits):
state = RX(b, state, [i], self.n_qubits)
if return_cost:
return torch.real(torch.sum(torch.abs(state)**2 * ising_cost))
else:
state = state.reshape((2**self.n_qubits,))
return torch.abs(state)**2
from pyqtorch.matrices import generate_ising_from_graph, sum_N
ising_matrix = generate_ising_from_graph(graph, type_ising='N')
ising_cost = 1.2*ising_matrix - sum_N(n_nodes)
ising_matrix = ising_matrix.reshape([2] * n_nodes + [1])
ising_cost = ising_cost.reshape([2] * n_nodes + [1])
class MIS(QuantumCircuit):
def __init__(self, n_qubits, n_layers):
super().__init__(n_qubits)
self.beta = nn.Parameter(torch.empty(n_layers,))
self.gamma = nn.Parameter(torch.empty(n_layers,))
self.reset_parameters()
def reset_parameters(self):
init.uniform_(self.beta, -2 * np.pi, 2 * np.pi)
init.uniform_(self.gamma, -2 * np.pi, 2 * np.pi)
def forward(self, return_cost=False):
state = self.uniform_state()
for b, g in zip(self.beta, self.gamma):
state = state * torch.exp(-1j * g * ising_matrix)
for i in range(self.n_qubits):
state = RX(b, state, [i], self.n_qubits)
if return_cost:
return torch.real(torch.sum(torch.abs(state)**2 * ising_cost))
else:
state = state.reshape((2**self.n_qubits,))
return torch.abs(state)**2
In [33]:
Copied!
model = MIS(n_nodes, 20)
optimizer = torch.optim.Adam(model.parameters(), lr=.02)
epochs = 100
for epoch in range(epochs):
optimizer.zero_grad()
loss = model(True)
loss.backward()
optimizer.step()
if epoch%50 == 0:
print(f"Epoch {epoch} | Loss {loss}")
model = MIS(n_nodes, 20)
optimizer = torch.optim.Adam(model.parameters(), lr=.02)
epochs = 100
for epoch in range(epochs):
optimizer.zero_grad()
loss = model(True)
loss.backward()
optimizer.step()
if epoch%50 == 0:
print(f"Epoch {epoch} | Loss {loss}")
Epoch 0 | Loss -0.5000000000000002 Epoch 50 | Loss -0.5000000000000002
In [27]:
Copied!
prob = model()
mis = torch.argmax(prob)
format(mis, '010b')
prob = model()
mis = torch.argmax(prob)
format(mis, '010b')
Out[27]:
'0011111001'
In [28]:
Copied!
mis
mis
Out[28]:
tensor(249)
In [29]:
Copied!
"{0:b}".format(1)
"{0:b}".format(1)
Out[29]:
'1'
In [30]:
Copied!
sum_N(n_nodes)[mis]
sum_N(n_nodes)[mis]
Out[30]:
tensor(6.+0.j, dtype=torch.complex128)
In [ ]:
Copied!