Rotosolve optimizer
Create diagram
[1]:
from lambeq import BobcatParser
parser = BobcatParser()
train_diagram = parser.sentence2diagram('Alice loves Bob')
Create circuits
[2]:
from lambeq import StronglyEntanglingAnsatz, AtomicType
ansatz = StronglyEntanglingAnsatz({AtomicType.NOUN: 1, AtomicType.SENTENCE: 1},
n_layers=2, n_single_qubit_params=3)
train_circuit = ansatz(train_diagram)
train_circuit.draw(figsize=(9, 12))

Parameterise
[3]:
from lambeq import NumpyModel
model = NumpyModel.from_diagrams([train_circuit], use_jit=True)
model.initialise_weights()
model([train_circuit]).shape
[3]:
(1, 2)
Define evaluation metric
[4]:
from jax import jit
@jit
def loss(y_pred, _):
"""The goal is to minimise the expectation value of the Pauli Z operator.
DisCoPy does not provide functionality to directly calculate expectation
values. Therefore, we need to calculate the expectation value from the
measurement probabilities of the Ket(0) and Ket(1) using their
eigenvalues."""
# 0 state probability
p0 = y_pred[:, 0]
# 1 state probability
p1 = y_pred[:, 1]
# expectation value
exp = p0 - p1 # eigenvalues are 1 and -1
return - exp.mean() # minimise expectation of measuring a 1
loss(model([train_circuit]), None)
[4]:
Array(0.35246935, dtype=float32)
[5]:
from lambeq import Dataset
train_dataset = Dataset(
[train_circuit],
[-1])
Initialize trainer
[6]:
from lambeq import QuantumTrainer
from lambeq import RotosolveOptimizer
from tqdm import trange
EPOCHS = 5
losses = []
for i in trange(20): # calculate results for 100 different seeds
trainer = QuantumTrainer(
model,
loss_function=loss,
epochs=EPOCHS,
optimizer=RotosolveOptimizer,
optim_hyperparams={},
evaluate_on_train=True,
verbose = 'suppress',
seed=i
)
initial_loss = loss(trainer.model([train_circuit]), None)
trainer.fit(train_dataset, log_interval=12)
losses.append([initial_loss] + trainer.train_epoch_costs)
100%|██████████| 20/20 [00:04<00:00, 4.17it/s]
Show results
[7]:
# get mean and std of the losses
import numpy as np
mean_losses = np.mean(losses, axis=0)
std_losses = np.std(losses, axis=0)
[8]:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(8, 6))
ax.set_title('Training set')
ax.set_xlabel('Epochs')
ax.set_ylabel('Loss')
colours = iter(plt.rcParams['axes.prop_cycle'].by_key()['color'])
ax.plot(mean_losses, color=next(colours));
ax.fill_between(range(len(mean_losses)), mean_losses-std_losses, mean_losses+std_losses, alpha=0.2, color=next(colours));

Final output
[9]:
model([train_circuit]).round(3)
[9]:
Array([[1., 0.]], dtype=float32)