QAOA
In [45]:
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
import pyqtorch.modules as pyq
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
import pyqtorch.modules as pyq
Solve MIS for QAOA¶
In [46]:
Copied!
np.random.seed(0)
n_nodes = 10
graph = nx.gnp_random_graph(n_nodes, .25, seed=42)
nx.draw(graph, with_labels=True)
np.random.seed(0)
n_nodes = 10
graph = nx.gnp_random_graph(n_nodes, .25, seed=42)
nx.draw(graph, with_labels=True)
In [47]:
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(nn.Module):
def __init__(self, n_qubits, n_layers):
super().__init__()
self.n_qubits = n_qubits
self.gamma = nn.Parameter(torch.empty(n_layers,))
self.ansatz = pyq.VariationalLayer(n_qubits, pyq.RX)
self.reset_parameters()
def reset_parameters(self):
init.uniform_(self.gamma, -2 * np.pi, 2 * np.pi)
self.ansatz.reset_parameters()
def forward(self, return_cost=False):
state = pyq.uniform_state(self.n_qubits)
for g in self.gamma:
state = state * torch.exp(-1j * g * ising_matrix)
state = self.ansatz(state)
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(nn.Module):
def __init__(self, n_qubits, n_layers):
super().__init__()
self.n_qubits = n_qubits
self.gamma = nn.Parameter(torch.empty(n_layers,))
self.ansatz = pyq.VariationalLayer(n_qubits, pyq.RX)
self.reset_parameters()
def reset_parameters(self):
init.uniform_(self.gamma, -2 * np.pi, 2 * np.pi)
self.ansatz.reset_parameters()
def forward(self, return_cost=False):
state = pyq.uniform_state(self.n_qubits)
for g in self.gamma:
state = state * torch.exp(-1j * g * ising_matrix)
state = self.ansatz(state)
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 [48]:
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 1.4900727366440991 Epoch 50 | Loss 1.1838491896514012
In [49]:
Copied!
prob = model()
mis = torch.argmax(prob)
format(mis, '010b')
prob = model()
mis = torch.argmax(prob)
format(mis, '010b')
Out[49]:
'1111101000'
In [50]:
Copied!
mis
mis
Out[50]:
tensor(1000)
In [51]:
Copied!
"{0:b}".format(1)
"{0:b}".format(1)
Out[51]:
'1'
In [52]:
Copied!
sum_N(n_nodes)[mis]
sum_N(n_nodes)[mis]
Out[52]:
tensor(6.+0.j, dtype=torch.complex128)