Welcome to QuCumber’s documentation!¶
Installation¶
QuCumber only supports Python 3, not Python 2. If you are using Python 2, please update! You will also want to install the following packages, if you have not already.
- Pytorch v0.4.1 (https://pytorch.org/)
- tqdm (https://github.com/tqdm/tqdm)
Github¶
Navigate to the qucumber page on github (https://github.com/PIQuIL/QuCumber) and clone the repository by typing:
git clone https://github.com/PIQuIL/QuCumber.git
Navigate to the main directory and type:
python setup.py install
Windows¶
Navigate to the directory (through command prompt) where pip.exe is installed
(usually C:\Python\Scripts\pip.exe
) and type:
pip.exe install qucumber
Download the tutorials¶
Once you have installed QuCumber, we recommend going through our tutorial that is divided into two parts.
- Training a wave function to reconstruct a positive-real wave function (i.e. no phase) from a transverse-field Ising model (TFIM) and then generating new data.
- Training an wave function to reconstruct a complex wave function (i.e. with a phase) from a simple two qubit random state and then generating new data.
We have made interactive python notebooks that can be downloaded (along with the data required) here. Note that the linked examples are from the most recent stable release (relative to the version of the docs you’re currently viewing), and may not match the examples shown in the following pages. It is recommended that you refer to documentation for the latest stable release: https://qucumber.readthedocs.io/en/stable/.
If you wish to simply view the static, non-interactive notebooks, continue to the next page of the documentation.
Alternatively, you can view interactive notebooks online at: ,
though they may be slow.
This is a static, non-editable tutorial.
We recommend you install QuCumber if you want to run the examples locally.
You can then get an archive file containing the examples from the relevant release
here.
Alternatively, you can launch an interactive online version, though it may be a bit slow:
Reconstruction of a positive-real wavefunction¶
In this tutorial, a walkthrough of how to reconstruct a positive-real wavefunction via training a Restricted Boltzmann Machine (RBM), the neural network behind qucumber, will be presented. The data used for training will be measurements from a one-dimensional transverse-field Ising model (TFIM) with 10 sites at its critical point.
Transverse-field Ising model¶
The example dataset, located in tfim1d_data.txt, comprises of 10,000 measurements from a one-dimensional transverse-field Ising model (TFIM) with 10 sites at its critical point. The Hamiltonian for the transverse-field Ising model (TFIM) is given by
where is the conventional spin-1/2 Pauli operator on site
. At the critical point,
. As per convention, spins are represented in binary notation with zero and one denoting spin-down and spin-up, respectively.
Using qucumber to reconstruct the wavefunction¶
Imports¶
To begin the tutorial, first import the required Python packages.
[1]:
import numpy as np
import matplotlib.pyplot as plt
from qucumber.nn_states import PositiveWaveFunction
from qucumber.callbacks import MetricEvaluator
import qucumber.utils.training_statistics as ts
import qucumber.utils.data as data
The Python class PositiveWaveFunction contains generic properties of a RBM meant to reconstruct a positive-real wavefunction, the most notable one being the gradient function required for stochastic gradient descent.
To instantiate a PositiveWaveFunction object, one needs to specify the number of visible and hidden units in the RBM. The number of visible units, num_visible, is given by the size of the physical system, i.e. the number of spins or qubits (10 in this case), while the number of hidden units, num_hidden, can be varied to change the expressiveness of the neural network.
Note: The optimal num_hidden : num_visible ratio will depend on the system. For the TFIM, having this ratio be equal to 1 leads to good results with reasonable computational effort.
Training¶
To evaluate the training in real time, the fidelity between the true ground-state wavefunction of the system and the wavefunction that qucumber reconstructs, , will be calculated along with the Kullback-Leibler (KL) divergence (the RBM’s cost function). It will also be shown that any custom function can be used to evaluate the training.
First, the training data and the true wavefunction of this system must be loaded using the data utility.
[2]:
psi_path = "tfim1d_psi.txt"
train_path = "tfim1d_data.txt"
train_data, true_psi = data.load_data(train_path, psi_path)
As previously mentioned, to instantiate a PositiveWaveFunction object, one needs to specify the number of visible and hidden units in the RBM. These two quantities equal will be kept equal.
[3]:
nv = train_data.shape[-1]
nh = nv
nn_state = PositiveWaveFunction(num_visible=nv, num_hidden=nh)
# nn_state = PositiveWaveFunction(num_visible=nv, num_hidden=nh, gpu = False)
By default, qucumber will attempt to run on a GPU if one is available (if one is not available, qucumber will default to CPU). If one wishes to run qucumber on a CPU, add the flag “gpu = False” in the PositiveWaveFunction object instantiation (i.e. uncomment the line above).
Now the hyperparameters of the training process can be specified.
epochs: the total number of training cycles that will be performed (default = 100)
pos_batch_size: the number of data points used in the positive phase of the gradient (default = 100)
neg_batch_size: the number of data points used in the negative phase of the gradient (default = pos_batch_size)
k: the number of contrastive divergence steps (default = 1)
lr: the learning rate (default = 0.001)
Note: For more information on the hyperparameters above, it is strongly encouraged that the user to read through the brief, but thorough theory document on RBMs located in the qucumber documentation. One does not have to specify these hyperparameters, as their default values will be used without the user overwriting them. It is recommended to keep with the default values until the user has a stronger grasp on what these hyperparameters mean. The quality and the computational efficiency of the training will highly depend on the choice of hyperparameters. As such, playing around with the hyperparameters is almost always necessary.
For the TFIM with 10 sites, the following hyperparameters give excellent results.
[4]:
epochs = 500
pbs = 100 # pos_batch_size
nbs = 200 # neg_batch_size
lr = 0.01
k = 10
For evaluating the training in real time, the MetricEvaluator will be called in order to calculate the training evaluators every 100 epochs. The MetricEvaluator requires the following arguments.
- log_every: the frequency of the training evaluators being calculated is controlled by the log_every argument (e.g. log_every = 200 means that the MetricEvaluator will update the user every 200 epochs)
- A dictionary of functions you would like to reference to evaluate the training (arguments required for these functions are keyword arguments placed after the dictionary)
The following additional arguments are needed to calculate the fidelity and KL divergence in the training_statistics utility.
- target_psi: the true wavefunction of the system
- space: the hilbert space of the system
The training evaluators can be printed out via the verbose=True statement.
Although the fidelity and KL divergence are excellent training evaluators, they are not practical to calculate in most cases; the user may not have access to the target wavefunction of the system, nor may generating the hilbert space of the system be computationally feasible. However, evaluating the training in real time is extremely convenient.
Any custom function that the user would like to use to evaluate the training can be given to the MetricEvaluator, thus avoiding having to calculate fidelity and/or KL divergence. Any custom function given to MetricEvaluator must take the neural-network state (in this case, the PositiveWaveFunction object) and keyword arguments. As an example, the function to be passed to the MetricEvaluator will be the fifth coefficient of the reconstructed wavefunction multiplied by a parameter, A.
[5]:
def psi_coefficient(nn_state, space, A, **kwargs):
norm = nn_state.compute_normalization(space).sqrt_()
return A * nn_state.psi(space)[0][4] / norm
Now the hilbert space of the system can be generated for the fidelity and KL divergence and the dictionary of functions the user would like to compute every “log_every” epochs can be given to the MetricEvaluator.
[6]:
log_every = 10
space = nn_state.generate_hilbert_space(nv)
Now the training can begin. The PositiveWaveFunction object has a property called fit which takes care of this. MetricEvaluator must be passed to the fit function in a list (callbacks).
[7]:
callbacks = [
MetricEvaluator(
log_every,
{"Fidelity": ts.fidelity, "KL": ts.KL, "A_Ψrbm_5": psi_coefficient},
target_psi=true_psi,
verbose=True,
space=space,
A=3.,
)
]
nn_state.fit(
train_data,
epochs=epochs,
pos_batch_size=pbs,
neg_batch_size=nbs,
lr=lr,
k=k,
callbacks=callbacks,
)
# nn_state.fit(train_data, callbacks=callbacks)
Epoch: 10 Fidelity = 0.524441 KL = 1.311481 A_Ψrbm_5 = 0.102333
Epoch: 20 Fidelity = 0.627167 KL = 0.887134 A_Ψrbm_5 = 0.151670
Epoch: 30 Fidelity = 0.733927 KL = 0.582645 A_Ψrbm_5 = 0.194329
Epoch: 40 Fidelity = 0.794879 KL = 0.445741 A_Ψrbm_5 = 0.221883
Epoch: 50 Fidelity = 0.829248 KL = 0.363647 A_Ψrbm_5 = 0.232239
Epoch: 60 Fidelity = 0.860589 KL = 0.287518 A_Ψrbm_5 = 0.241004
Epoch: 70 Fidelity = 0.886160 KL = 0.231527 A_Ψrbm_5 = 0.244122
Epoch: 80 Fidelity = 0.902777 KL = 0.196992 A_Ψrbm_5 = 0.234641
Epoch: 90 Fidelity = 0.914448 KL = 0.174226 A_Ψrbm_5 = 0.231594
Epoch: 100 Fidelity = 0.923648 KL = 0.156510 A_Ψrbm_5 = 0.234137
Epoch: 110 Fidelity = 0.929855 KL = 0.142626 A_Ψrbm_5 = 0.220506
Epoch: 120 Fidelity = 0.937082 KL = 0.127953 A_Ψrbm_5 = 0.228048
Epoch: 130 Fidelity = 0.943320 KL = 0.114683 A_Ψrbm_5 = 0.225533
Epoch: 140 Fidelity = 0.948913 KL = 0.102805 A_Ψrbm_5 = 0.220003
Epoch: 150 Fidelity = 0.953720 KL = 0.092966 A_Ψrbm_5 = 0.219529
Epoch: 160 Fidelity = 0.957696 KL = 0.085269 A_Ψrbm_5 = 0.219721
Epoch: 170 Fidelity = 0.960716 KL = 0.079273 A_Ψrbm_5 = 0.215919
Epoch: 180 Fidelity = 0.963032 KL = 0.075418 A_Ψrbm_5 = 0.219223
Epoch: 190 Fidelity = 0.965285 KL = 0.071062 A_Ψrbm_5 = 0.217072
Epoch: 200 Fidelity = 0.966294 KL = 0.069517 A_Ψrbm_5 = 0.218791
Epoch: 210 Fidelity = 0.968279 KL = 0.065436 A_Ψrbm_5 = 0.214237
Epoch: 220 Fidelity = 0.969002 KL = 0.063958 A_Ψrbm_5 = 0.208316
Epoch: 230 Fidelity = 0.970735 KL = 0.060499 A_Ψrbm_5 = 0.211827
Epoch: 240 Fidelity = 0.971954 KL = 0.058173 A_Ψrbm_5 = 0.213458
Epoch: 250 Fidelity = 0.972797 KL = 0.056356 A_Ψrbm_5 = 0.216414
Epoch: 260 Fidelity = 0.973940 KL = 0.054098 A_Ψrbm_5 = 0.219072
Epoch: 270 Fidelity = 0.975173 KL = 0.051311 A_Ψrbm_5 = 0.213439
Epoch: 280 Fidelity = 0.976146 KL = 0.049353 A_Ψrbm_5 = 0.214791
Epoch: 290 Fidelity = 0.977626 KL = 0.046184 A_Ψrbm_5 = 0.215294
Epoch: 300 Fidelity = 0.978880 KL = 0.043539 A_Ψrbm_5 = 0.215247
Epoch: 310 Fidelity = 0.979931 KL = 0.041293 A_Ψrbm_5 = 0.211467
Epoch: 320 Fidelity = 0.981140 KL = 0.038849 A_Ψrbm_5 = 0.213601
Epoch: 330 Fidelity = 0.982012 KL = 0.036976 A_Ψrbm_5 = 0.216033
Epoch: 340 Fidelity = 0.982764 KL = 0.035460 A_Ψrbm_5 = 0.217036
Epoch: 350 Fidelity = 0.983499 KL = 0.033983 A_Ψrbm_5 = 0.208566
Epoch: 360 Fidelity = 0.984789 KL = 0.031407 A_Ψrbm_5 = 0.218186
Epoch: 370 Fidelity = 0.985142 KL = 0.030643 A_Ψrbm_5 = 0.215245
Epoch: 380 Fidelity = 0.985985 KL = 0.028931 A_Ψrbm_5 = 0.217562
Epoch: 390 Fidelity = 0.986345 KL = 0.028262 A_Ψrbm_5 = 0.217989
Epoch: 400 Fidelity = 0.986798 KL = 0.027449 A_Ψrbm_5 = 0.215068
Epoch: 410 Fidelity = 0.987459 KL = 0.026076 A_Ψrbm_5 = 0.220650
Epoch: 420 Fidelity = 0.987785 KL = 0.025427 A_Ψrbm_5 = 0.220902
Epoch: 430 Fidelity = 0.988085 KL = 0.024916 A_Ψrbm_5 = 0.217657
Epoch: 440 Fidelity = 0.988270 KL = 0.024565 A_Ψrbm_5 = 0.218701
Epoch: 450 Fidelity = 0.988164 KL = 0.024811 A_Ψrbm_5 = 0.222711
Epoch: 460 Fidelity = 0.988564 KL = 0.024018 A_Ψrbm_5 = 0.212042
Epoch: 470 Fidelity = 0.988859 KL = 0.023432 A_Ψrbm_5 = 0.221610
Epoch: 480 Fidelity = 0.989148 KL = 0.022804 A_Ψrbm_5 = 0.224286
Epoch: 490 Fidelity = 0.989477 KL = 0.022194 A_Ψrbm_5 = 0.223508
Epoch: 500 Fidelity = 0.989738 KL = 0.021626 A_Ψrbm_5 = 0.223838
All of these training evaluators can be accessed after the training has completed, as well. The code below shows this, along with plots of each training evaluator versus the training cycle number (epoch).
[8]:
fidelities = callbacks[0].Fidelity
KLs = callbacks[0].KL
coeffs = callbacks[0].A_Ψrbm_5
# Please note that the key given to the *MetricEvaluator* must be what comes after callbacks[0].
epoch = np.arange(log_every, epochs + 1, log_every)
[9]:
# Some parameters to make the plots look nice
params = {'text.usetex': True,
'font.family': 'serif',
'legend.fontsize': 14,
'figure.figsize': (10, 3),
'axes.labelsize': 16,
'xtick.labelsize':14,
'ytick.labelsize':14,
'lines.linewidth':2,
'lines.markeredgewidth': 0.8,
'lines.markersize': 5,
'lines.marker': "o",
"patch.edgecolor": "black"
}
plt.rcParams.update(params)
plt.style.use('seaborn-deep')
[10]:
# Plotting
fig, axs = plt.subplots(nrows=1, ncols=3, figsize=(14, 3))
ax = axs[0]
ax.plot(epoch, fidelities, "o", color = "C0", markeredgecolor="black")
ax.set_ylabel(r'Fidelity')
ax.set_xlabel(r'Epoch')
ax = axs[1]
ax.plot(epoch, KLs, "o", color = "C1", markeredgecolor="black")
ax.set_ylabel(r'KL Divergence')
ax.set_xlabel(r'Epoch')
ax = axs[2]
ax.plot(epoch, coeffs, "o", color = "C2", markeredgecolor="black")
ax.set_ylabel(r'$A\psi_{RBM}[5]$')
ax.set_xlabel(r'Epoch')
plt.tight_layout()
plt.savefig("fid_KL.pdf")
plt.show()

It should be noted that one could have just ran nn_state.fit(train_samples) and just used the default hyperparameters and no training evaluators.
To demonstrate how important it is to find the optimal hyperparameters for a certain system, restart this notebook and comment out the original fit statement and uncomment the one below. The default hyperparameters will be used instead. Using the non-default hyperparameters yielded a fidelity of approximately 0.994, while the default hyperparameters yielded a fidelity of approximately 0.523!
The RBM’s parameters will also be saved for future use in other tutorials. They can be saved to a pickle file with the name “saved_params.pt” with the code below.
[11]:
nn_state.save("saved_params.pt")
This saves the weights, visible biases and hidden biases as torch tensors with the following keys: “weights”, “visible_bias”, “hidden_bias”.
This is a static, non-editable tutorial.
We recommend you install QuCumber if you want to run the examples locally.
You can then get an archive file containing the examples from the relevant release
here.
Alternatively, you can launch an interactive online version, though it may be a bit slow:
Reconstruction of a complex wavefunction¶
In this tutorial, a walkthrough of how to reconstruct a complex wavefunction via training a Restricted Boltzmann Machine (RBM), the neural network behind qucumber, will be presented.
The wavefunction to be reconstructed¶
The simple wavefunction below describing two qubits (coefficients stored in qubits_psi.txt) will be reconstructed.
where the exact values of and
used for this tutorial are
The example dataset, qubits_train.txt, comprises of 500 measurements made in various bases (X, Y and Z). A corresponding file containing the bases for each data point in qubits_train.txt, qubits_train_bases.txt, is also required. As per convention, spins are represented in binary notation with zero and one denoting spin-down and spin-up, respectively.
Using qucumber to reconstruct the wavefunction¶
Imports¶
To begin the tutorial, first import the required Python packages.
[1]:
import numpy as np
import torch
import matplotlib.pyplot as plt
from qucumber.nn_states import ComplexWaveFunction
from qucumber.callbacks import MetricEvaluator
import qucumber.utils.unitaries as unitaries
import qucumber.utils.cplx as cplx
import qucumber.utils.training_statistics as ts
import qucumber.utils.data as data
The Python class ComplexWaveFunction contains generic properties of a RBM meant to reconstruct a complex wavefunction, the most notable one being the gradient function required for stochastic gradient descent.
To instantiate a ComplexWaveFunction object, one needs to specify the number of visible and hidden units in the RBM. The number of visible units, num_visible, is given by the size of the physical system, i.e. the number of spins or qubits (2 in this case), while the number of hidden units, num_hidden, can be varied to change the expressiveness of the neural network.
Note: The optimal num_hidden : num_visible ratio will depend on the system. For the two-qubit wavefunction described above, good results are yielded when this ratio is 1.
On top of needing the number of visible and hidden units, a ComplexWaveFunction object requires the user to input a dictionary containing the unitary operators (2x2) that will be used to rotate the qubits in and out of the computational basis, Z, during the training process. The unitaries utility will take care of creating this dictionary.
The MetricEvaluator class and training_statistics utility are built-in amenities that will allow the user to evaluate the training in real time.
Lastly, the cplx utility allows qucumber to be able to handle complex numbers. Currently, Pytorch does not support complex numbers.
Training¶
To evaluate the training in real time, the fidelity between the true wavefunction of the system and the wavefunction that qucumber reconstructs, , will be calculated along with the Kullback-Leibler (KL) divergence (the RBM’s cost function). First, the training data and the true wavefunction of this system need to be loaded using the data utility.
[2]:
train_path = "qubits_train.txt"
train_bases_path = "qubits_train_bases.txt"
psi_path = "qubits_psi.txt"
bases_path = "qubits_bases.txt"
train_samples, true_psi, train_bases, bases = data.load_data(
train_path, psi_path, train_bases_path, bases_path
)
The file qubits_bases.txt contains every unique basis in the qubits_train_bases.txt file. Calculation of the full KL divergence in every basis requires the user to specify each unique basis.
As previouosly mentioned, a ComplexWaveFunction object requires a dictionary that contains the unitariy operators that will be used to rotate the qubits in and out of the computational basis, Z, during the training process. In the case of the provided dataset, the unitaries required are the well-known , and
gates. The dictionary needed can be created with the following command.
[3]:
unitary_dict = unitaries.create_dict()
# unitary_dict = unitaries.create_dict(unitary_name=torch.tensor([[real part],
# [imaginary part]],
# dtype=torch.double)
If the user wishes to add their own unitary operators from their experiment to unitary_dict, uncomment the block above. When unitaries.create_dict() is called, it will contain the identity and the and
gates by default with the keys “Z”, “X” and “Y”, respectively.
The number of visible units in the RBM is equal to the number of qubits. The number of hidden units will also be taken to be the number of visible units.
[4]:
nv = train_samples.shape[-1]
nh = nv
nn_state = ComplexWaveFunction(
num_visible=nv, num_hidden=nh, unitary_dict=unitary_dict, gpu=False
)
# nn_state = ComplexWaveFunction(num_visible=nv, num_hidden=nh, unitary_dict=unitary_dict)
By default, qucumber will attempt to run on a GPU if one is available (if one is not available, qucumber will default to CPU). If one wishes to run qucumber on a CPU, add the flag “gpu = False” in the ComplexWaveFunction object instantiation. Uncomment the line above to run this tutorial on a GPU.
Now the hyperparameters of the training process can be specified.
epochs: the total number of training cycles that will be performed (default = 100)
pos_batch_size: the number of data points used in the positive phase of the gradient (default = 100)
neg_batch_size: the number of data points used in the negative phase of the gradient (default = pos_batch_size)
k: the number of contrastive divergence steps (default = 1)
lr: the learning rate (default = 0.001)
Note: For more information on the hyperparameters above, it is strongly encouraged that the user to read through the brief, but thorough theory document on RBMs. One does not have to specify these hyperparameters, as their default values will be used without the user overwriting them. It is recommended to keep with the default values until the user has a stronger grasp on what these hyperparameters mean. The quality and the computational efficiency of the training will highly depend on the choice of hyperparameters. As such, playing around with the hyperparameters is almost always necessary.
The two-qubit example in this tutorial should be extremely easy to train, regardless of the choice of hyperparameters. However, the hyperparameters below will be used.
[5]:
epochs = 100
pbs = 50 # pos_batch_size
nbs = 50 # neg_batch_size
lr = 0.1
k = 5
For evaluating the training in real time, the MetricEvaluator will be called to calculate the training evaluators every 10 epochs. The MetricEvaluator requires the following arguments.
- log_every: the frequency of the training evaluators being calculated is controlled by the log_every argument (e.g. log_every = 200 means that the MetricEvaluator will update the user every 200 epochs)
- A dictionary of functions you would like to reference to evaluate the training (arguments required for these functions are keyword arguments placed after the dictionary)
The following additional arguments are needed to calculate the fidelity and KL divergence in the training_statistics utility.
- target_psi (the true wavefunction of the system)
- space (the hilbert space of the system)
The training evaluators can be printed out via the verbose=True statement.
Although the fidelity and KL divergence are excellent training evaluators, they are not practical to calculate in most cases; the user may not have access to the target wavefunction of the system, nor may generating the hilbert space of the system be computationally feasible. However, evaluating the training in real time is extremely convenient.
Any custom function that the user would like to use to evaluate the training can be given to the MetricEvaluator, thus avoiding having to calculate fidelity and/or KL divergence. As an example, functions that calculate the the norm of each of the reconstructed wavefunction’s coefficients are presented. Any custom function given to MetricEvaluator must take the neural-network state (in this case, the ComplexWaveFunction object) and keyword arguments. Although the given example requires the hilbert space to be computed, the scope of the MetricEvaluator’s ability to be able to handle any function should still be evident.
[6]:
def alpha(nn_state, space, **kwargs):
rbm_psi = nn_state.psi(space)
normalization = nn_state.compute_normalization(space).sqrt_()
alpha_ = cplx.norm(
torch.tensor([rbm_psi[0][0], rbm_psi[1][0]], device=nn_state.device)
/ normalization
)
return alpha_
def beta(nn_state, space, **kwargs):
rbm_psi = nn_state.psi(space)
normalization = nn_state.compute_normalization(space).sqrt_()
beta_ = cplx.norm(
torch.tensor([rbm_psi[0][1], rbm_psi[1][1]], device=nn_state.device)
/ normalization
)
return beta_
def gamma(nn_state, space, **kwargs):
rbm_psi = nn_state.psi(space)
normalization = nn_state.compute_normalization(space).sqrt_()
gamma_ = cplx.norm(
torch.tensor([rbm_psi[0][2], rbm_psi[1][2]], device=nn_state.device)
/ normalization
)
return gamma_
def delta(nn_state, space, **kwargs):
rbm_psi = nn_state.psi(space)
normalization = nn_state.compute_normalization(space).sqrt_()
delta_ = cplx.norm(
torch.tensor([rbm_psi[0][3], rbm_psi[1][3]], device=nn_state.device)
/ normalization
)
return delta_
Now the hilbert space of the system must be generated for the fidelity and KL divergence and the dictionary of functions the user would like to compute every “log_every” epochs must be given to the MetricEvaluator.
[7]:
log_every = 2
space = nn_state.generate_hilbert_space(nv)
callbacks = [
MetricEvaluator(
log_every,
{
"Fidelity": ts.fidelity,
"KL": ts.KL,
"normα": alpha,
# "normβ": beta,
# "normγ": gamma,
# "normδ": delta,
},
target_psi=true_psi,
bases=bases,
verbose=True,
space=space,
)
]
Now the training can begin. The ComplexWaveFunction object has a property called fit which takes care of this.
[8]:
nn_state.fit(
train_samples,
epochs=epochs,
pos_batch_size=pbs,
neg_batch_size=nbs,
lr=lr,
k=k,
input_bases=train_bases,
callbacks=callbacks,
)
Epoch: 2 Fidelity = 0.609290 KL = 0.251365 normα = 0.328561
Epoch: 4 Fidelity = 0.761520 KL = 0.130756 normα = 0.268571
Epoch: 6 Fidelity = 0.838254 KL = 0.082158 normα = 0.253614
Epoch: 8 Fidelity = 0.882321 KL = 0.059876 normα = 0.251210
Epoch: 10 Fidelity = 0.909942 KL = 0.046754 normα = 0.259010
Epoch: 12 Fidelity = 0.929755 KL = 0.036943 normα = 0.258238
Epoch: 14 Fidelity = 0.942398 KL = 0.030965 normα = 0.262524
Epoch: 16 Fidelity = 0.951771 KL = 0.027162 normα = 0.250808
Epoch: 18 Fidelity = 0.958536 KL = 0.023913 normα = 0.257332
Epoch: 20 Fidelity = 0.963766 KL = 0.021570 normα = 0.259561
Epoch: 22 Fidelity = 0.968224 KL = 0.019610 normα = 0.263528
Epoch: 24 Fidelity = 0.970991 KL = 0.018523 normα = 0.256601
Epoch: 26 Fidelity = 0.974414 KL = 0.017127 normα = 0.256168
Epoch: 28 Fidelity = 0.976543 KL = 0.016030 normα = 0.261707
Epoch: 30 Fidelity = 0.977891 KL = 0.015551 normα = 0.254371
Epoch: 32 Fidelity = 0.978768 KL = 0.015847 normα = 0.242762
Epoch: 34 Fidelity = 0.981126 KL = 0.013974 normα = 0.259100
Epoch: 36 Fidelity = 0.981330 KL = 0.013704 normα = 0.262152
Epoch: 38 Fidelity = 0.981989 KL = 0.013495 normα = 0.256111
Epoch: 40 Fidelity = 0.983230 KL = 0.012711 normα = 0.269000
Epoch: 42 Fidelity = 0.984230 KL = 0.012301 normα = 0.273091
Epoch: 44 Fidelity = 0.984190 KL = 0.012178 normα = 0.260481
Epoch: 46 Fidelity = 0.985494 KL = 0.011501 normα = 0.269168
Epoch: 48 Fidelity = 0.985192 KL = 0.011518 normα = 0.269217
Epoch: 50 Fidelity = 0.986754 KL = 0.010896 normα = 0.264035
Epoch: 52 Fidelity = 0.987266 KL = 0.011288 normα = 0.263792
Epoch: 54 Fidelity = 0.987998 KL = 0.010323 normα = 0.268859
Epoch: 56 Fidelity = 0.987993 KL = 0.009957 normα = 0.267215
Epoch: 58 Fidelity = 0.988191 KL = 0.009873 normα = 0.273412
Epoch: 60 Fidelity = 0.988129 KL = 0.009665 normα = 0.264751
Epoch: 62 Fidelity = 0.986891 KL = 0.010557 normα = 0.254349
Epoch: 64 Fidelity = 0.988134 KL = 0.009504 normα = 0.264387
Epoch: 66 Fidelity = 0.987419 KL = 0.009870 normα = 0.263105
Epoch: 68 Fidelity = 0.988299 KL = 0.009280 normα = 0.264269
Epoch: 70 Fidelity = 0.989128 KL = 0.008897 normα = 0.267263
Epoch: 72 Fidelity = 0.989572 KL = 0.008808 normα = 0.268239
Epoch: 74 Fidelity = 0.988996 KL = 0.008901 normα = 0.256966
Epoch: 76 Fidelity = 0.988131 KL = 0.009278 normα = 0.261540
Epoch: 78 Fidelity = 0.989458 KL = 0.008405 normα = 0.263894
Epoch: 80 Fidelity = 0.988967 KL = 0.008628 normα = 0.261319
Epoch: 82 Fidelity = 0.989337 KL = 0.008332 normα = 0.271008
Epoch: 84 Fidelity = 0.989170 KL = 0.008351 normα = 0.270172
Epoch: 86 Fidelity = 0.989256 KL = 0.008291 normα = 0.273329
Epoch: 88 Fidelity = 0.989592 KL = 0.008019 normα = 0.269137
Epoch: 90 Fidelity = 0.989677 KL = 0.007917 normα = 0.266120
Epoch: 92 Fidelity = 0.989260 KL = 0.008174 normα = 0.261290
Epoch: 94 Fidelity = 0.990006 KL = 0.007627 normα = 0.266389
Epoch: 96 Fidelity = 0.989957 KL = 0.007610 normα = 0.270035
Epoch: 98 Fidelity = 0.990623 KL = 0.007506 normα = 0.278505
Epoch: 100 Fidelity = 0.990754 KL = 0.007096 normα = 0.266719
All of these training evaluators can be accessed after the training has completed, as well. The code below shows this, along with plots of each training evaluator versus the training cycle number (epoch).
[9]:
fidelities = callbacks[0].Fidelity
KLs = callbacks[0].KL
coeffs = callbacks[0].normα
# Please note that the key given to the *MetricEvaluator* must be what comes after callbacks[0].
epoch = np.arange(log_every, epochs + 1, log_every)
[10]:
# Some parameters to make the plots look nice
params = {'text.usetex': True,
'font.family': 'serif',
'legend.fontsize': 14,
'figure.figsize': (10, 3),
'axes.labelsize': 16,
'xtick.labelsize':14,
'ytick.labelsize':14,
'lines.linewidth':2,
'lines.markeredgewidth': 0.8,
'lines.markersize': 5,
'lines.marker': "o",
"patch.edgecolor": "black"
}
plt.rcParams.update(params)
plt.style.use('seaborn-deep')
[11]:
fig, axs = plt.subplots(nrows=1, ncols=3, figsize=(14, 3))
ax = axs[0]
ax.plot(epoch, fidelities, "o", color = "C0", markeredgecolor="black")
ax.set_ylabel(r'Fidelity')
ax.set_xlabel(r'Epoch')
ax = axs[1]
ax.plot(epoch, KLs, "o", color = "C1", markeredgecolor="black")
ax.set_ylabel(r'KL Divergence')
ax.set_xlabel(r'Epoch')
ax = axs[2]
ax.plot(epoch, coeffs, "o", color = "C2", markeredgecolor="black")
ax.set_ylabel(r'$\vert\alpha\vert$')
ax.set_xlabel(r'Epoch')
plt.tight_layout()
plt.savefig("complex_fid_KL.pdf")
plt.show()

It should be noted that one could have just ran nn_state.fit(train_samples) and just used the default hyperparameters and no training evaluators.
At the end of the training process, the network parameters (the weights, visible biases and hidden biases) are stored in the ComplexWaveFunction object. One can save them to a pickle file, which will be called saved_params.pt, with the following command.
[12]:
nn_state.save("saved_params.pt")
This saves the weights, visible biases and hidden biases as torch tensors with the following keys: “weights”, “visible_bias”, “hidden_bias”.
This is a static, non-editable tutorial.
We recommend you install QuCumber if you want to run the examples locally.
You can then get an archive file containing the examples from the relevant release
here.
Alternatively, you can launch an interactive online version, though it may be a bit slow:
Sampling and calculating observables¶
Generate new samples¶
Firstly, to generate meaningful data, an RBM needs to be trained. Please refer to the tutorials 1 and 2 on training an RBM if how to train an RBM using qucumber is unclear. An RBM with a positive-real wavefunction describing a transverse-field Ising model (TFIM) with 10 sites has already been trained in the first tutorial, with the parameters of the machine saved here as saved_params.pt. The autoload function can be employed here to instantiate the corresponding PositiveWaveFunction object from the saved RBM parameters.
[1]:
import numpy as np
import matplotlib.pyplot as plt
from qucumber.nn_states import PositiveWaveFunction
from qucumber.observables import ObservableBase
import quantum_ising_chain
from quantum_ising_chain import TFIMChainEnergy
nn_state = PositiveWaveFunction.autoload("saved_params.pt")
A PositiveWaveFunction object has a property called sample that takes in the following arguments.
- k: the number of Gibbs steps to perform to generate the new samples
- num_samples: the number of new data points to be generated
[2]:
new_samples = nn_state.sample(k=100, num_samples=10000)
print(new_samples)
tensor([[1., 1., 1., ..., 1., 0., 0.],
[1., 1., 1., ..., 1., 0., 0.],
[0., 0., 0., ..., 0., 1., 1.],
...,
[1., 1., 1., ..., 1., 1., 1.],
[0., 0., 1., ..., 0., 1., 1.],
[0., 0., 0., ..., 1., 1., 1.]], dtype=torch.float64)
With the newly generated samples, the user can now easliy calculate observables that do not require any details associated with the RBM. A great example of this is the magnetization. To calculate the magnetization, the newly-generated samples must be converted to 1 from 1 and 0, respectively. The function below does the trick.
[3]:
def to_pm1(samples):
return samples.mul(2.).sub(1.)
Now, the magnetization is calculated as follows.
[4]:
def Magnetization(samples):
return to_pm1(samples).mean(1).abs().mean()
magnetization = Magnetization(new_samples).item()
print("Magnetization = %.5f" % magnetization)
Magnetization = 0.54968
The exact value for the magnetization is 0.5610.
The magnetization and the newly-generated samples can also be saved to a pickle file along with the RBM parameters in the PositiveWaveFunction object.
[5]:
nn_state.save(
"saved_params_and_new_data.pt",
metadata={"samples": new_samples, "magnetization": magnetization},
)
The metadata argument in the save function takes in a dictionary of data that you would like to save on top of the RBM parameters.
Calculate an observable using the Observable module¶
Custom observable¶
Qucumber has a built-in module called Observable which makes it easy for the user to compute any arbitrary observable from the RBM. To see the the Observable module in action, an example observable called PIQuIL, which inherits properties from the Observable module, is shown below.
The PIQuIL observable takes an measurement at a site and multiplies it by the measurement two sites from it. There is also a parameter, P, that determines the strength of each of these interactions. For example, for the dataset
and
with P = 2, the PIQuIL for each data point would be
and
, respectively.
[6]:
class PIQuIL(ObservableBase):
def __init__(self, P):
super(PIQuIL, self).__init__()
self.P = P
# Required : function that calculates the PIQuIL. Must be named "apply"
def apply(self, nn_state, samples):
to_pm1(samples)
interaction_ = 0
for i in range(samples.shape[-1]):
if (i + 3) > samples.shape[-1]:
continue
else:
interaction_ += self.P * samples[:, i] * samples[:, i + 2]
return interaction_
P = 0.05
piquil = PIQuIL(P)
The apply function is contained in the Observable module, but is overwritten here. The apply function in Observable will compute the observable itself and must take in the RBM (nn_state) and a batch of samples as arguments. Thus, any new class inheriting from Observables that the user would like to define must contain a function called apply that calculates this new observable.
Although the PIQuIL observable could technically be computed without the use of the Observable module since it does not ever use the RBM (nn_state), it is still nonetheless a constructive example.
The real power in the Observable module is in the ability for the user to easily compute statistics of the observable from the generated sample. Since we have already generated new samples of data, the PIQuIL observable’s mean, standard error and variance on the new data can be calculated with the statistics_from_samples function in the Observable module. The user must simply give the RBM and the samples as arguments.
[7]:
piquil_stats1 = piquil.statistics_from_samples(nn_state, new_samples)
The statistics_from_samples function returns a dictionary containing the mean, standard error and the variance with the keys “mean”, “std_error” and “variance”, respectively.
[8]:
print(
"Mean PIQuIL: %.4f" % piquil_stats1["mean"], "+/- %.4f" % piquil_stats1["std_error"]
)
print("Variance: %.4f" % piquil_stats1["variance"])
Mean PIQuIL: 0.1419 +/- 0.0014
Variance: 0.0188
However, if the user did not have samples generated already, that is no problem. The statistics function in the Observable module will generate new samples internally and compute the mean, standard error and variance on those samples. Since the samples are not an argument in the statistics function, the user must now give the following additional arguments to the statistics function to generate the new samples.
- num_samples: the number of samples to generate internally
- num_chains: the number of Markov chains to run in parallel (default = 0)
- burn_in: the number of Gibbs steps to perform before recording any samples (default = 1000)
- steps: the number of Gibbs steps to perform between each sample (default = 1)
The statistics function will also return a dictionary containing the mean, standard error and the variance with the keys “mean”, “std_error” and “variance”, respectively.
[9]:
num_samples = 10000
burn_in = 100
steps = 100
piquil_stats2 = piquil.statistics(nn_state, num_samples, burn_in=burn_in, steps=steps)
print(
"Mean PIQuIL: %.4f" % piquil_stats2["mean"], "+/- %.4f" % piquil_stats2["std_error"]
)
print("Variance: %.4f" % piquil_stats2["variance"])
Mean PIQuIL: 0.1409 +/- 0.0014
Variance: 0.0186
TFIM Energy¶
Some observables cannot be computed directly from samples, but instead depend on the RBM as previously mentioned. For example, the magnetization of the TFIM simply depends on the samples the user gives as input. Whereas the TFIM energy is much more complicated. An example for the computation of the energy is provided in the python file quantum_ising_chain.py, which takes advantage of qucumber’s Observable module.
quantum_ising_chain.py comprises of a class that computes the energy of a TFIM (TFIMChainEnergy) that inherits properties from the Observable module. To instantiate a TFIMChainEnergy object, the value must be specified. The trained RBM parameters are from the first tutorial, where the example data was from the TFIM with 10 sites at its critical point (
).
[10]:
h = 1
tfim_energy = TFIMChainEnergy(h)
To go ahead and calculate the mean energy and its standard error from the previously generated samples from this tutorial (new_samples), the statistics_from_samples function in the Observable module is called upon.
[11]:
energy_stats = tfim_energy.statistics_from_samples(nn_state, new_samples)
print("Mean: %.4f" % energy_stats["mean"], "+/- %.4f" % energy_stats["std_error"])
print("Variance: %.4f" % energy_stats["variance"])
Mean: -1.2362 +/- 0.0005
Variance: 0.0022
The exact value for the energy is -1.2381.
To illustrate how quickly the energy converges as a function of the sampling step (i.e. the number of Gibbs steps to perform to generate a new batch of samples), steps, the Convergence function in quantum_ising_chain.py will do the trick. Convergence creates a batch of random samples initially, which is then used to generate a new batch of samples from the RBM. The TFIM energy will be calculated at every Gibbs step. Please note that the samples generated previously (new_samples) are not used here; different samples are generated.
[12]:
steps = 200
num_samples = 10000
dict_observables = quantum_ising_chain.Convergence(
nn_state, tfim_energy, num_samples, steps
)
energy = dict_observables["energies"]
err_energy = dict_observables["error"]
step = np.arange(steps + 1)
E0 = -1.2381
ax = plt.axes()
ax.plot(step, abs((energy - E0) / E0) * 100, color="red")
ax.set_xlim(0, steps)
ax.set_ylim(0, 0.6)
ax.set_xlabel("Gibbs Step")
ax.set_ylabel("% Error in Energy")
[12]:
Text(0,0.5,'% Error in Energy')

One can see a brief transient period in the magnetization observable, before the state of the machine “warms up” to equilibrium. After that, the values fluctuate around the calculated mean.
Adding observables¶
One may also add / subtract observables with the new observable also retaining the same properties in the Observables module. For instance, a new observable can be defined by adding the TFIM energy observable multiplied by an arbitrary constant to the PIQuIL observable.
[13]:
new_obs = 0.01 * tfim_energy + piquil
The same statistics of this new observable can also be calculated.
[14]:
new_obs_stats = new_obs.statistics_from_samples(nn_state, new_samples)
print("Mean: %.4f" % new_obs_stats["mean"], "+/- %.4f" % new_obs_stats["std_error"])
print("Variance: %.4f" % new_obs_stats["variance"])
Mean: 0.1295 +/- 0.0014
Variance: 0.0188
Template for your custom observable¶
Here is a generic template for you to try using the Observable module yourself.
[15]:
import torch
from qucumber.observables import ObservableBase
class YourObservable(ObservableBase):
def __init__(self, your_constants):
super(YourObservable, self).__init__()
self.your_constants = your_constants
def apply(self, nn_state, samples):
# arguments of "apply" must be in this order
# calculate your observable for each data point
obs = torch.tensor([42] * len(samples))
# make sure the observables are on the same device and have the
# same dtype as the samples
obs = obs.to(samples)
# return a torch tensor containing the observable values
return obs
This is a static, non-editable tutorial.
We recommend you install QuCumber if you want to run the examples locally.
You can then get an archive file containing the examples from the relevant release
here.
Alternatively, you can launch an interactive online version, though it may be a bit slow:
Training while monitoring observables¶
As seen in the first tutorial that went through reconstructing the wavefunction describing the TFIM with 10 sites at its critical point, the user can evaluate the training in real time with the MetricEvaluator and custom functions. What is most likely more impactful in many cases is to calculate an observable, like the energy, during the training process. This is slightly more computationally involved than using the MetricEvaluator to evaluate functions because observables require that samples be drawn from the RBM.
Luckily, qucumber also has a module very similar to the MetricEvaluator, but for observables. This is called the ObservableEvaluator. The following implements the ObservableEvaluator to calculate the energy during the training on the TFIM data in the first tutorial. We will use the same hyperparameters as before.
It is assumed that the user has worked through tutorial 3 beforehand. Recall that quantum_ising_chain.py contains the TFIMChainEnergy class that inherits from the Observable module. The exact ground-state energy is -1.2381.
[1]:
import os.path
import numpy as np
import matplotlib.pyplot as plt
from qucumber.nn_states import PositiveWaveFunction
from qucumber.callbacks import ObservableEvaluator
import qucumber.utils.data as data
from quantum_ising_chain import TFIMChainEnergy
[2]:
train_data = data.load_data(
os.path.join("..", "Tutorial1_TrainPosRealWaveFunction", "tfim1d_data.txt")
)[0]
nv = train_data.shape[-1]
nh = nv
nn_state = PositiveWaveFunction(num_visible=nv, num_hidden=nh)
epochs = 1000
pbs = 100 # pos_batch_size
nbs = 200 # neg_batch_size
lr = 0.01
k = 10
log_every = 100
h = 1
num_samples = 10000
burn_in = 100
steps = 100
tfim_energy = TFIMChainEnergy(h)
Now, the ObservableEvaluator can be called. The ObservableEvaluator requires the following arguments.
- log_every: the frequency of the training evaluators being calculated is controlled by the log_every argument (e.g. log_every = 200 means that the MetricEvaluator will update the user every 200 epochs)
- A list of Observable objects you would like to reference to evaluate the training (arguments required for generating samples to calculate the observables are keyword arguments placed after the list)
The following additional arguments are needed to calculate the statistics on the generated samples during training (these are the arguments of the statistics function in the Observable module, minus the nn_state argument; this gets passed in as an argument to fit).
- num_samples: the number of samples to generate internally
- num_chains: the number of Markov chains to run in parallel (default = 0)
- burn_in: the number of Gibbs steps to perform before recording any samples (default = 1000)
- steps: the number of Gibbs steps to perform between each sample (default = 1)
The training evaluators can be printed out via the verbose=True statement.
[3]:
callbacks = [
ObservableEvaluator(
log_every,
[tfim_energy],
verbose=True,
num_samples=num_samples,
burn_in=burn_in,
steps=steps,
)
]
nn_state.fit(
train_data,
epochs=epochs,
pos_batch_size=pbs,
neg_batch_size=nbs,
lr=lr,
k=k,
callbacks=callbacks,
)
Epoch: 100
TFIMChainEnergy:
mean: -1.197008 variance: 0.022882 std_error: 0.001513
Epoch: 200
TFIMChainEnergy:
mean: -1.216405 variance: 0.011845 std_error: 0.001088
Epoch: 300
TFIMChainEnergy:
mean: -1.224917 variance: 0.008271 std_error: 0.000909
Epoch: 400
TFIMChainEnergy:
mean: -1.228988 variance: 0.005977 std_error: 0.000773
Epoch: 500
TFIMChainEnergy:
mean: -1.230748 variance: 0.004908 std_error: 0.000701
Epoch: 600
TFIMChainEnergy:
mean: -1.232201 variance: 0.003850 std_error: 0.000620
Epoch: 700
TFIMChainEnergy:
mean: -1.233295 variance: 0.003404 std_error: 0.000583
Epoch: 800
TFIMChainEnergy:
mean: -1.233561 variance: 0.002842 std_error: 0.000533
Epoch: 900
TFIMChainEnergy:
mean: -1.235249 variance: 0.002480 std_error: 0.000498
Epoch: 1000
TFIMChainEnergy:
mean: -1.234220 variance: 0.002232 std_error: 0.000472
The callbacks list returns a list of dictionaries. The mean, standard error and the variance at each epoch can be accessed as follows.
[4]:
energies = callbacks[0].TFIMChainEnergy.mean
errors = callbacks[0].TFIMChainEnergy.std_error
variance = callbacks[0].TFIMChainEnergy.variance
# Please note that the name of the observable class that the user makes must be what comes after callbacks[0].
A plot of the energy as a function of the training cycle is presented below.
[5]:
epoch = np.arange(log_every, epochs + 1, log_every)
E0 = -1.2381
ax = plt.axes()
ax.plot(epoch, energies, color="red")
ax.set_xlim(log_every, epochs)
ax.axhline(E0, color="black")
ax.fill_between(epoch, energies - errors, energies + errors, alpha=0.2, color="black")
ax.set_xlabel("Epoch")
ax.set_ylabel("Energy")
ax.grid()

RBM¶
-
class
qucumber.rbm.
BinaryRBM
(num_visible, num_hidden, zero_weights=False, gpu=True)[source]¶ Bases:
torch.nn.modules.module.Module
-
effective_energy
(v)[source]¶ The effective energies of the given visible states.
Parameters: v (torch.Tensor) – The visible states. Returns: The effective energies of the given visible states. Return type: torch.Tensor
-
effective_energy_gradient
(v)[source]¶ The gradients of the effective energies for the given visible states.
Parameters: v (torch.Tensor) – The visible states. Returns: 1d vector containing the gradients for all parameters (computed on the given visible states v). Return type: torch.Tensor
-
gibbs_steps
(k, initial_state, overwrite=False)[source]¶ Performs k steps of Block Gibbs sampling. One step consists of sampling the hidden state
from the conditional distribution
, and sampling the visible state
from the conditional distribution
.
Parameters: - k (int) – Number of Block Gibbs steps.
- initial_state (torch.Tensor) – The initial state of the Markov Chain. If given, num_samples will be ignored.
- overwrite (bool) – Whether to overwrite the initial_state tensor, if it is provided.
-
partition
(space)[source]¶ Compute the partition function of the RBM.
Parameters: space (torch.Tensor) – A rank 2 tensor of the visible space. Returns: The value of the partition function evaluated at the current state of the RBM. Return type: torch.Tensor
-
prob_h_given_v
(v, out=None)[source]¶ Given a visible unit configuration, compute the probability vector of the hidden units being on.
Parameters: - h (torch.Tensor) – The hidden unit.
- out (torch.Tensor) – The output tensor to write to.
Returns: The probability of hidden units being active given the visible state.
Return type:
-
prob_v_given_h
(h, out=None)[source]¶ Given a hidden unit configuration, compute the probability vector of the visible units being on.
Parameters: - h (torch.Tensor) – The hidden unit
- out (torch.Tensor) – The output tensor to write to.
Returns: The probability of visible units being active given the hidden state.
Return type:
-
sample_h_given_v
(v, out=None)[source]¶ Sample/generate a hidden state given a visible state.
Parameters: - h (torch.Tensor) – The visible state.
- out (torch.Tensor) – The output tensor to write to.
Returns: Tuple containing prob_h_given_v(v) and the sampled hidden state.
Return type:
-
sample_v_given_h
(h, out=None)[source]¶ Sample/generate a visible state given a hidden state.
Parameters: - h (torch.Tensor) – The hidden state.
- out (torch.Tensor) – The output tensor to write to.
Returns: Tuple containing prob_v_given_h(h) and the sampled visible state.
Return type:
-
Quantum States¶
Positive WaveFunction¶
-
class
qucumber.nn_states.
PositiveWaveFunction
(num_visible, num_hidden=None, gpu=True)[source]¶ Bases:
qucumber.nn_states.WaveFunctionBase
Class capable of learning wavefunctions with no phase.
Parameters: -
amplitude
(v)[source]¶ Compute the (unnormalized) amplitude of a given vector/matrix of visible states.
Parameters: v (torch.Tensor) – visible states Returns: Matrix/vector containing the amplitudes of v Return type: torch.Tensor
-
static
autoload
(location, gpu=False)[source]¶ Initializes a WaveFunction from the parameters in the given location.
Parameters: Returns: A new WaveFunction initialized from the given parameters. The returned WaveFunction will be of whichever type this function was called on.
-
compute_batch_gradients
(k, samples_batch, neg_batch)[source]¶ Compute the gradients of a batch of the training data (samples_batch).
Parameters: - k (int) – Number of contrastive divergence steps in training.
- samples_batch (torch.Tensor) – Batch of the input samples.
- neg_batch (torch.Tensor) – Batch of the input samples for computing the negative phase.
Returns: List containing the gradients of the parameters.
Return type:
-
compute_normalization
(space)[source]¶ Compute the normalization constant of the wavefunction.
Parameters: space (torch.Tensor) – A rank 2 tensor of the entire visible space.
-
device
¶ The device that the model is on.
-
fit
(data, epochs=100, pos_batch_size=100, neg_batch_size=None, k=1, lr=0.001, progbar=False, starting_epoch=1, time=False, callbacks=None, optimizer=<class 'torch.optim.sgd.SGD'>, **kwargs)[source]¶ Train the WaveFunction.
Parameters: - data (np.array) – The training samples
- epochs (int) – The number of full training passes through the dataset. Technically, this specifies the index of the last training epoch, which is relevant if starting_epoch is being set.
- pos_batch_size (int) – The size of batches for the positive phase taken from the data.
- neg_batch_size (int) – The size of batches for the negative phase taken from the data. Defaults to pos_batch_size.
- k (int) – The number of contrastive divergence steps.
- lr (float) – Learning rate
- progbar (bool or str) – Whether or not to display a progress bar. If “notebook” is passed, will use a Jupyter notebook compatible progress bar.
- starting_epoch (int) – The epoch to start from. Useful if continuing training from a previous state.
- callbacks (list[qucumber.callbacks.CallbackBase]) – Callbacks to run while training.
- optimizer (torch.optim.Optimizer) – The constructor of a torch optimizer.
- kwargs – Keyword arguments to pass to the optimizer
-
generate_hilbert_space
(size=None, device=None)[source]¶ Generates Hilbert space of dimension
.
Parameters: - size (int) – The size of each element of the Hilbert space. Defaults to the number of visible units.
- device – The device to create the Hilbert space matrix on. Defaults to the device this model is on.
Returns: A tensor with all the basis states of the Hilbert space.
Return type:
-
gradient
(v)[source]¶ Compute the gradient of the effective energy for a batch of states.
Parameters: v (torch.Tensor) – visible states Returns: A single tensor containing all of the parameter gradients. Return type: torch.Tensor
-
load
(location)[source]¶ Loads the WaveFunction parameters from the given location ignoring any metadata stored in the file. Overwrites the WaveFunction’s parameters.
Note
The WaveFunction object on which this function is called must have the same parameter shapes as the one who’s parameters are being loaded.
Parameters: location (str or file) – The location to load the WaveFunction parameters from.
-
max_size
¶ Maximum size of the Hilbert space for full enumeration
-
networks
¶ A list of the names of the internal RBMs.
-
phase
(v)[source]¶ Compute the phase of a given vector/matrix of visible states.
In the case of a PositiveWaveFunction, the phase is just zero.
Parameters: v (torch.Tensor) – visible states Returns: Matrix/vector containing the phases of v Return type: torch.Tensor
-
probability
(v, Z)[source]¶ Evaluates the probability of the given vector(s) of visible states.
Parameters: - v (torch.Tensor) – The visible states.
- Z (float) – The partition function.
Returns: The probability of the given vector(s) of visible units.
Return type:
-
psi
(v)[source]¶ Compute the (unnormalized) wavefunction of a given vector/matrix of visible states.
Parameters: v (torch.Tensor) – visible states Returns: Complex object containing the value of the wavefunction for each visible state Return type: torch.Tensor
-
rbm_am
¶ The RBM to be used to learn the wavefunction amplitude.
-
sample
(k, num_samples=1, initial_state=None, overwrite=False)[source]¶ Performs k steps of Block Gibbs sampling. One step consists of sampling the hidden state
from the conditional distribution
, and sampling the visible state
from the conditional distribution
.
Parameters: - k (int) – Number of Block Gibbs steps.
- num_samples (int) – The number of samples to generate.
- initial_state (torch.Tensor) – The initial state of the Markov Chain. If given, num_samples will be ignored.
- overwrite (bool) – Whether to overwrite the initial_state tensor, if it is provided.
-
save
(location, metadata=None)[source]¶ Saves the WaveFunction parameters to the given location along with any given metadata.
Parameters:
-
stop_training
¶ If True, will not train.
If this property is set to True during the training cycle, training will terminate once the current batch or epoch ends (depending on when stop_training was set).
-
subspace_vector
(num, size=None, device=None)[source]¶ Generates a single vector from the Hilbert space of dimension
.
Parameters: - size (int) – The size of each element of the Hilbert space.
- num (int) – The specific vector to return from the Hilbert space. Since the Hilbert space can be represented by the set of binary strings of length size, num is equivalent to the decimal representation of the returned vector.
- device – The device to create the vector on. Defaults to the device this model is on.
Returns: A state from the Hilbert space.
Return type:
-
Complex WaveFunction¶
-
class
qucumber.nn_states.
ComplexWaveFunction
(num_visible, num_hidden=None, unitary_dict=None, gpu=True)[source]¶ Bases:
qucumber.nn_states.WaveFunctionBase
Class capable of learning wavefunctions with a non-zero phase.
Parameters: - num_visible (int) – The number of visible units, ie. the size of the system being learned.
- num_hidden (int) – The number of hidden units in both internal RBMs. Defaults to the number of visible units.
- unitary_dict (dict[str, torch.Tensor]) – A dictionary mapping unitary names to their matrix representations.
- gpu (bool) – Whether to perform computations on the default gpu.
-
amplitude
(v)[source]¶ Compute the (unnormalized) amplitude of a given vector/matrix of visible states.
Parameters: v (torch.Tensor) – visible states .
Returns: Vector containing the amplitudes of the given states. Return type: torch.Tensor
-
static
autoload
(location, gpu=False)[source]¶ Initializes a WaveFunction from the parameters in the given location.
Parameters: Returns: A new WaveFunction initialized from the given parameters. The returned WaveFunction will be of whichever type this function was called on.
-
compute_batch_gradients
(k, samples_batch, neg_batch, bases_batch=None)[source]¶ Compute the gradients of a batch of the training data (samples_batch).
If measurements are taken in bases other than the reference basis, a list of bases (bases_batch) must also be provided.
Parameters: - k (int) – Number of contrastive divergence steps in training.
- samples_batch (torch.Tensor) – Batch of the input samples.
- neg_batch (torch.Tensor) – Batch of the input samples for computing the negative phase.
- bases_batch (np.array) – Batch of the input bases corresponding to the samples in samples_batch.
Returns: List containing the gradients of the parameters.
Return type:
-
compute_normalization
(space)[source]¶ Compute the normalization constant of the wavefunction.
Parameters: space (torch.Tensor) – A rank 2 tensor of the entire visible space.
-
device
¶ The device that the model is on.
-
fit
(data, epochs=100, pos_batch_size=100, neg_batch_size=None, k=1, lr=0.001, input_bases=None, progbar=False, starting_epoch=1, time=False, callbacks=None, optimizer=<class 'torch.optim.sgd.SGD'>, **kwargs)[source]¶ Train the WaveFunction.
Parameters: - data (np.array) – The training samples
- epochs (int) – The number of full training passes through the dataset. Technically, this specifies the index of the last training epoch, which is relevant if starting_epoch is being set.
- pos_batch_size (int) – The size of batches for the positive phase taken from the data.
- neg_batch_size (int) – The size of batches for the negative phase taken from the data. Defaults to pos_batch_size.
- k (int) – The number of contrastive divergence steps.
- lr (float) – Learning rate
- input_bases (np.array) – The measurement bases for each sample. Must be provided if training a ComplexWaveFunction.
- progbar (bool or str) – Whether or not to display a progress bar. If “notebook” is passed, will use a Jupyter notebook compatible progress bar.
- starting_epoch (int) – The epoch to start from. Useful if continuing training from a previous state.
- callbacks (list[qucumber.callbacks.CallbackBase]) – Callbacks to run while training.
- optimizer (torch.optim.Optimizer) – The constructor of a torch optimizer.
- kwargs – Keyword arguments to pass to the optimizer
-
generate_hilbert_space
(size=None, device=None)[source]¶ Generates Hilbert space of dimension
.
Parameters: - size (int) – The size of each element of the Hilbert space. Defaults to the number of visible units.
- device – The device to create the Hilbert space matrix on. Defaults to the device this model is on.
Returns: A tensor with all the basis states of the Hilbert space.
Return type:
-
gradient
(basis, sample)[source]¶ Compute the gradient of a sample, measured in different bases.
Parameters: - basis (np.array) – A set of bases.
- sample (np.array) – A sample to compute the gradient of.
Returns: A list of 2 tensors containing the parameters of each of the internal RBMs.
Return type:
-
load
(location)[source]¶ Loads the WaveFunction parameters from the given location ignoring any metadata stored in the file. Overwrites the WaveFunction’s parameters.
Note
The WaveFunction object on which this function is called must have the same parameter shapes as the one who’s parameters are being loaded.
Parameters: location (str or file) – The location to load the WaveFunction parameters from.
-
max_size
¶ Maximum size of the Hilbert space for full enumeration
-
networks
¶ A list of the names of the internal RBMs.
-
phase
(v)[source]¶ Compute the phase of a given vector/matrix of visible states.
Parameters: v (torch.Tensor) – visible states .
Returns: Vector containing the phases of the given states. Return type: torch.Tensor
-
probability
(v, Z)[source]¶ Evaluates the probability of the given vector(s) of visible states.
Parameters: - v (torch.Tensor) – The visible states.
- Z (float) – The partition function.
Returns: The probability of the given vector(s) of visible units.
Return type:
-
psi
(v)[source]¶ Compute the (unnormalized) wavefunction of a given vector/matrix of visible states.
Parameters: v (torch.Tensor) – visible states Returns: Complex object containing the value of the wavefunction for each visible state Return type: torch.Tensor
-
rbm_am
¶ The RBM to be used to learn the wavefunction amplitude.
-
rbm_ph
¶ RBM used to learn the wavefunction phase.
-
sample
(k, num_samples=1, initial_state=None, overwrite=False)[source]¶ Performs k steps of Block Gibbs sampling. One step consists of sampling the hidden state
from the conditional distribution
, and sampling the visible state
from the conditional distribution
.
Parameters: - k (int) – Number of Block Gibbs steps.
- num_samples (int) – The number of samples to generate.
- initial_state (torch.Tensor) – The initial state of the Markov Chain. If given, num_samples will be ignored.
- overwrite (bool) – Whether to overwrite the initial_state tensor, if it is provided.
-
save
(location, metadata=None)[source]¶ Saves the WaveFunction parameters to the given location along with any given metadata.
Parameters:
-
stop_training
¶ If True, will not train.
If this property is set to True during the training cycle, training will terminate once the current batch or epoch ends (depending on when stop_training was set).
-
subspace_vector
(num, size=None, device=None)[source]¶ Generates a single vector from the Hilbert space of dimension
.
Parameters: - size (int) – The size of each element of the Hilbert space.
- num (int) – The specific vector to return from the Hilbert space. Since the Hilbert space can be represented by the set of binary strings of length size, num is equivalent to the decimal representation of the returned vector.
- device – The device to create the vector on. Defaults to the device this model is on.
Returns: A state from the Hilbert space.
Return type:
Abstract WaveFunction¶
Note
This is an Abstract Base Class, it is not meant to be used directly. The following API reference is mostly for developers.
-
class
qucumber.nn_states.
WaveFunctionBase
[source]¶ Bases:
abc.ABC
Abstract Base Class for WaveFunctions.
-
amplitude
(v)[source]¶ Compute the (unnormalized) amplitude of a given vector/matrix of visible states.
Parameters: v (torch.Tensor) – visible states Returns: Matrix/vector containing the amplitudes of v Return type: torch.Tensor
-
static
autoload
(location, gpu=False)[source]¶ Initializes a WaveFunction from the parameters in the given location.
Parameters: Returns: A new WaveFunction initialized from the given parameters. The returned WaveFunction will be of whichever type this function was called on.
-
compute_batch_gradients
(k, samples_batch, neg_batch, bases_batch=None)[source]¶ Compute the gradients of a batch of the training data (samples_batch).
If measurements are taken in bases other than the reference basis, a list of bases (bases_batch) must also be provided.
Parameters: - k (int) – Number of contrastive divergence steps in training.
- samples_batch (torch.Tensor) – Batch of the input samples.
- neg_batch (torch.Tensor) – Batch of the input samples for computing the negative phase.
- bases_batch (np.array) – Batch of the input bases corresponding to the samples in samples_batch.
Returns: List containing the gradients of the parameters.
Return type:
-
compute_normalization
(space)[source]¶ Compute the normalization constant of the wavefunction.
Parameters: space (torch.Tensor) – A rank 2 tensor of the entire visible space.
-
device
¶ The device that the model is on.
-
fit
(data, epochs=100, pos_batch_size=100, neg_batch_size=None, k=1, lr=0.001, input_bases=None, progbar=False, starting_epoch=1, time=False, callbacks=None, optimizer=<class 'torch.optim.sgd.SGD'>, **kwargs)[source]¶ Train the WaveFunction.
Parameters: - data (np.array) – The training samples
- epochs (int) – The number of full training passes through the dataset. Technically, this specifies the index of the last training epoch, which is relevant if starting_epoch is being set.
- pos_batch_size (int) – The size of batches for the positive phase taken from the data.
- neg_batch_size (int) – The size of batches for the negative phase taken from the data. Defaults to pos_batch_size.
- k (int) – The number of contrastive divergence steps.
- lr (float) – Learning rate
- input_bases (np.array) – The measurement bases for each sample. Must be provided if training a ComplexWaveFunction.
- progbar (bool or str) – Whether or not to display a progress bar. If “notebook” is passed, will use a Jupyter notebook compatible progress bar.
- starting_epoch (int) – The epoch to start from. Useful if continuing training from a previous state.
- callbacks (list[qucumber.callbacks.CallbackBase]) – Callbacks to run while training.
- optimizer (torch.optim.Optimizer) – The constructor of a torch optimizer.
- kwargs – Keyword arguments to pass to the optimizer
-
generate_hilbert_space
(size=None, device=None)[source]¶ Generates Hilbert space of dimension
.
Parameters: - size (int) – The size of each element of the Hilbert space. Defaults to the number of visible units.
- device – The device to create the Hilbert space matrix on. Defaults to the device this model is on.
Returns: A tensor with all the basis states of the Hilbert space.
Return type:
-
load
(location)[source]¶ Loads the WaveFunction parameters from the given location ignoring any metadata stored in the file. Overwrites the WaveFunction’s parameters.
Note
The WaveFunction object on which this function is called must have the same parameter shapes as the one who’s parameters are being loaded.
Parameters: location (str or file) – The location to load the WaveFunction parameters from.
-
max_size
¶ Maximum size of the Hilbert space for full enumeration
-
networks
¶ A list of the names of the internal RBMs.
-
phase
(v)[source]¶ Compute the phase of a given vector/matrix of visible states.
Parameters: v (torch.Tensor) – visible states Returns: Matrix/vector containing the phases of v Return type: torch.Tensor
-
probability
(v, Z)[source]¶ Evaluates the probability of the given vector(s) of visible states.
Parameters: - v (torch.Tensor) – The visible states.
- Z (float) – The partition function.
Returns: The probability of the given vector(s) of visible units.
Return type:
-
psi
(v)[source]¶ Compute the (unnormalized) wavefunction of a given vector/matrix of visible states.
Parameters: v (torch.Tensor) – visible states Returns: Complex object containing the value of the wavefunction for each visible state Return type: torch.Tensor
-
rbm_am
¶ The RBM to be used to learn the wavefunction amplitude.
-
sample
(k, num_samples=1, initial_state=None, overwrite=False)[source]¶ Performs k steps of Block Gibbs sampling. One step consists of sampling the hidden state
from the conditional distribution
, and sampling the visible state
from the conditional distribution
.
Parameters: - k (int) – Number of Block Gibbs steps.
- num_samples (int) – The number of samples to generate.
- initial_state (torch.Tensor) – The initial state of the Markov Chain. If given, num_samples will be ignored.
- overwrite (bool) – Whether to overwrite the initial_state tensor, if it is provided.
-
save
(location, metadata=None)[source]¶ Saves the WaveFunction parameters to the given location along with any given metadata.
Parameters:
-
stop_training
¶ If True, will not train.
If this property is set to True during the training cycle, training will terminate once the current batch or epoch ends (depending on when stop_training was set).
-
subspace_vector
(num, size=None, device=None)[source]¶ Generates a single vector from the Hilbert space of dimension
.
Parameters: - size (int) – The size of each element of the Hilbert space.
- num (int) – The specific vector to return from the Hilbert space. Since the Hilbert space can be represented by the set of binary strings of length size, num is equivalent to the decimal representation of the returned vector.
- device – The device to create the vector on. Defaults to the device this model is on.
Returns: A state from the Hilbert space.
Return type:
-
Callbacks¶
-
class
qucumber.callbacks.
CallbackBase
[source]¶ Base class for callbacks.
-
on_batch_end
(nn_state, epoch, batch)[source]¶ Called at the end of each batch.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction being trained.
- epoch (int) – The current epoch.
- batch (int) – The current batch index.
-
on_batch_start
(nn_state, epoch, batch)[source]¶ Called at the start of each batch.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction being trained.
- epoch (int) – The current epoch.
- batch (int) – The current batch index.
-
on_epoch_end
(nn_state, epoch)[source]¶ Called at the end of each epoch.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction being trained.
- epoch (int) – The current epoch.
-
on_epoch_start
(nn_state, epoch)[source]¶ Called at the start of each epoch.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction being trained.
- epoch (int) – The current epoch.
-
on_train_end
(nn_state)[source]¶ Called at the end of the training cycle.
Parameters: nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction being trained.
-
on_train_start
(nn_state)[source]¶ Called at the start of the training cycle.
Parameters: nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction being trained.
-
-
class
qucumber.callbacks.
LambdaCallback
(on_train_start=None, on_train_end=None, on_epoch_start=None, on_epoch_end=None, on_batch_start=None, on_batch_end=None)[source]¶ Class for creating simple callbacks.
This callback is constructed using the passed functions that will be called at the appropriate time.
Parameters: - on_train_start (callable or None) – A function to be called at the start of the training
cycle. Must follow the same signature as
CallbackBase.on_train_start
. - on_train_end (callable or None) – A function to be called at the end of the training
cycle. Must follow the same signature as
CallbackBase.on_train_end
. - on_epoch_start (callable or None) – A function to be called at the start of every epoch.
Must follow the same signature as
CallbackBase.on_epoch_start
. - on_epoch_end (callable or None) – A function to be called at the end of every epoch.
Must follow the same signature as
CallbackBase.on_epoch_end
. - on_batch_start (callable or None) – A function to be called at the start of every batch.
Must follow the same signature as
CallbackBase.on_batch_start
. - on_batch_end (callable or None) – A function to be called at the end of every batch.
Must follow the same signature as
CallbackBase.on_batch_end
.
- on_train_start (callable or None) – A function to be called at the start of the training
cycle. Must follow the same signature as
-
class
qucumber.callbacks.
ModelSaver
(period, folder_path, file_name, save_initial=True, metadata=None, metadata_only=False)[source]¶ Callback which allows model parameters (along with some metadata) to be saved to disk at regular intervals.
This callback is called at the end of each epoch. If save_initial is True, will also be called at the start of the training cycle.
Parameters: - period (int) – Frequency of model saving (in epochs).
- folder_path (str) – The directory in which to save the files
- file_name (str) – The name of the output files. Should be a format string with one blank, which will be filled with either the epoch number or the word “initial”.
- save_initial (bool) – Whether to save the initial parameters (and metadata).
- metadata (callable or dict or None) – The metadata to save to disk with the model parameters Can be either a function or a dictionary. In the case of a function, it must take 2 arguments the RBM being trained, and the current epoch number, and then return a dictionary containing the metadata to be saved.
- metadata_only (bool) – Whether to save only the metadata to disk.
-
class
qucumber.callbacks.
Logger
(period, logger_fn=<built-in function print>, msg_gen=None, **msg_gen_kwargs)[source]¶ Callback which logs output at regular intervals.
This callback is called at the end of each epoch.
Parameters: - period (int) – Logging frequency (in epochs).
- logger_fn (callable) – The function used for logging. Must take 1 string as an argument. Defaults to the standard print function.
- msg_gen (callable) – A callable which generates the string to be logged. Must take 2 positional arguments: the RBM being trained and the current epoch. It must also be able to take some keyword arguments.
- **kwargs – Keyword arguments which will be passed to msg_gen.
-
class
qucumber.callbacks.
EarlyStopping
(period, tolerance, patience, evaluator_callback, quantity_name)[source]¶ Stop training once the model stops improving. The specific criterion for stopping is:
where
is the metric value at the current evaluation (time
),
is the “patience” parameter, and
is the tolerance.
This callback is called at the end of each epoch.
Parameters: - period (int) – Frequency with which the callback checks whether training has converged (in epochs).
- tolerance (float) – The maximum relative change required to consider training as having converged.
- patience (int) – How many intervals to wait before claiming the training has converged.
- evaluator_callback (
MetricEvaluator
orObservableEvaluator
) – An instance ofMetricEvaluator
orObservableEvaluator
which computes the metric that we want to check for convergence. - quantity_name (str) – The name of the metric/observable stored in evaluator_callback.
-
class
qucumber.callbacks.
VarianceBasedEarlyStopping
(period, tolerance, patience, evaluator_callback, quantity_name, variance_name)[source]¶ Stop training once the model stops improving. This is a variation on the
EarlyStopping
class which takes the variance of the metric into account. The specific criterion for stopping is:where
is the metric value at the current evaluation (time
),
is the “patience” parameter,
is the variance of the metric, and
is the tolerance.
This callback is called at the end of each epoch.
Parameters: - period (int) – Frequency with which the callback checks whether training has converged (in epochs).
- tolerance (float) – The maximum (standardized) change required to consider training as having converged.
- patience (int) – How many intervals to wait before claiming the training has converged.
- evaluator_callback (
MetricEvaluator
orObservableEvaluator
) – An instance ofMetricEvaluator
orObservableEvaluator
which computes the metric/observable that we want to check for convergence. - quantity_name (str) – The name of the metric/obserable stored in evaluator_callback.
- variance_name (str) – The name of the variance stored in evaluator_callback.
-
class
qucumber.callbacks.
MetricEvaluator
(period, metrics, verbose=False, log=None, **metric_kwargs)[source]¶ Evaluate and hold on to the results of the given metric(s).
This callback is called at the end of each epoch.
Note
Since callbacks are given to
fit
as a list, they will be called in a deterministic order. It is therefore recommended that instances ofMetricEvaluator
be among the first callbacks in the list passed tofit
, as one would often use it in conjunction with other callbacks likeEarlyStopping
which may depend onMetricEvaluator
having been called.Parameters: - period (int) – Frequency with which the callback evaluates the given metric(s).
- metrics (dict(str, callable)) – A dictionary of callables where the keys are the names of the metrics and the callables take the WaveFunction being trained as their positional argument, along with some keyword arguments. The metrics are evaluated and put into an internal dictionary structure resembling the structure of metrics.
- verbose (bool) – Whether to print metrics to stdout.
- log (str) – A filepath to log metric values to in CSV format.
- **metric_kwargs – Keyword arguments to be passed to metrics.
-
__getattr__
(metric)[source]¶ Return an array of all recorded values of the given metric.
Parameters: metric (str) – The metric to retrieve. Returns: The past values of the metric. Return type: np.array
-
__len__
()[source]¶ Return the number of timesteps that metrics have been evaluated for.
Return type: int
-
epochs
¶ Return a list of all epochs that have been recorded.
Return type: np.array
-
class
qucumber.callbacks.
ObservableEvaluator
(period, observables, verbose=False, log=None, **sampling_kwargs)[source]¶ Evaluate and hold on to the results of the given observable(s).
This callback is called at the end of each epoch.
Note
Since callback are given to
fit
as a list, they will be called in a deterministic order. It is therefore recommended that instances ofObservableEvaluator
be among the first callbacks in the list passed tofit
, as one would often use it in conjunction with other callbacks likeEarlyStopping
which may depend onObservableEvaluator
having been called.Parameters: - period (int) – Frequency with which the callback evaluates the given observables(s).
- observables (list(qucumber.observables.ObservableBase)) – A list of Observables. Observable statistics are evaluated by sampling the WaveFunction. Note that observables that have the same name will conflict, and precedence will be given to the right-most observable argument.
- verbose (bool) – Whether to print metrics to stdout.
- log (str) – A filepath to log metric values to in CSV format.
- **sampling_kwargs – Keyword arguments to be passed to Observable.statistics. Ex. num_samples, num_chains, burn_in, steps.
-
__getattr__
(observable)[source]¶ Return an ObservableStatistics containing recorded statistics of the given observable.
Parameters: observable (str) – The observable to retrieve. Returns: The past values of the observable. Return type: ObservableStatistics
-
__len__
()[source]¶ Return the number of timesteps that observables have been evaluated for.
Return type: int
-
epochs
¶ Return a list of all epochs that have been recorded.
Return type: np.array
-
class
qucumber.callbacks.
LivePlotting
(period, evaluator_callback, quantity_name, error_name=None, total_epochs=None, smooth=True)[source]¶ Plots metrics/observables.
This callback is called at the end of each epoch.
Parameters: - period (int) – Frequency with which the callback updates the plots (in epochs).
- evaluator_callback (
MetricEvaluator
orObservableEvaluator
) – An instance ofMetricEvaluator
orObservableEvaluator
which computes the metric/observable that we want to plot. - quantity_name (str) – The name of the metric/observable stored in evaluator_callback.
- error_name (str) – The name of the error stored in evaluator_callback.
-
class
qucumber.callbacks.
Timer
(verbose=True)[source]¶ Callback which records the training time.
This callback is always called at the start and end of training. It will run at the end of an epoch or batch if the given model’s stop_training property is set to True.
Parameters: verbose (bool) – Whether to print the elapsed time at the end of training.
Observables¶
Pauli Operators¶
-
class
qucumber.observables.
SigmaZ
[source]¶ Bases:
qucumber.observables.ObservableBase
The
observable.
Computes the magnetization in the Z direction of a spin chain.
-
apply
(nn_state, samples)[source]¶ Computes the magnetization of each sample given a batch of samples.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction that drew the samples.
- samples (torch.Tensor) – A batch of samples to calculate the observable on.
Must be using the
convention.
-
name
¶ The name of the Observable.
-
sample
(nn_state, k, num_samples=1, initial_state=None, overwrite=False)[source]¶ Draws samples of the observable using the given WaveFunction.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction to draw samples from.
- k (int) – The number of Gibbs Steps to perform before drawing a sample.
- num_samples (int) – The number of samples to draw.
- initial_state (torch.Tensor) – The initial state of the Markov Chain. If given, num_samples will be ignored.
- overwrite (bool) – Whether to overwrite the initial_state tensor, if it is provided, with the updated state of the Markov chain.
-
statistics
(nn_state, num_samples, num_chains=0, burn_in=1000, steps=1)[source]¶ Estimates the expected value, variance, and the standard error of the observable over the distribution defined by the WaveFunction.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction to draw samples from.
- num_samples (int) – The number of samples to draw. The actual number of samples drawn may be slightly higher if num_samples % num_chains != 0.
- num_chains (int) – The number of Markov chains to run in parallel; if 0, will use a number of chains equal to num_samples.
- burn_in (int) – The number of Gibbs Steps to perform before recording any samples.
- steps (int) – The number of Gibbs Steps to take between each sample.
Returns: A dictionary containing the (estimated) expected value (key: “mean”), variance (key: “variance”), and standard error (key: “std_error”) of the observable.
Return type:
-
statistics_from_samples
(nn_state, samples)[source]¶ Estimates the expected value, variance, and the standard error of the observable using the given samples.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction that drew the samples.
- samples (torch.Tensor) – A batch of sample states to calculate the observable on.
-
symbol
¶ The algebraic symbol representing the Observable.
-
-
class
qucumber.observables.
SigmaX
[source]¶ Bases:
qucumber.observables.ObservableBase
The
observable
Computes the magnetization in the X direction of a spin chain.
-
apply
(nn_state, samples)[source]¶ Computes the magnetization along X of each sample in the given batch of samples.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction that drew the samples.
- samples (torch.Tensor) – A batch of samples to calculate the observable on.
Must be using the
convention.
-
name
¶ The name of the Observable.
-
sample
(nn_state, k, num_samples=1, initial_state=None, overwrite=False)[source]¶ Draws samples of the observable using the given WaveFunction.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction to draw samples from.
- k (int) – The number of Gibbs Steps to perform before drawing a sample.
- num_samples (int) – The number of samples to draw.
- initial_state (torch.Tensor) – The initial state of the Markov Chain. If given, num_samples will be ignored.
- overwrite (bool) – Whether to overwrite the initial_state tensor, if it is provided, with the updated state of the Markov chain.
-
statistics
(nn_state, num_samples, num_chains=0, burn_in=1000, steps=1)[source]¶ Estimates the expected value, variance, and the standard error of the observable over the distribution defined by the WaveFunction.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction to draw samples from.
- num_samples (int) – The number of samples to draw. The actual number of samples drawn may be slightly higher if num_samples % num_chains != 0.
- num_chains (int) – The number of Markov chains to run in parallel; if 0, will use a number of chains equal to num_samples.
- burn_in (int) – The number of Gibbs Steps to perform before recording any samples.
- steps (int) – The number of Gibbs Steps to take between each sample.
Returns: A dictionary containing the (estimated) expected value (key: “mean”), variance (key: “variance”), and standard error (key: “std_error”) of the observable.
Return type:
-
statistics_from_samples
(nn_state, samples)[source]¶ Estimates the expected value, variance, and the standard error of the observable using the given samples.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction that drew the samples.
- samples (torch.Tensor) – A batch of sample states to calculate the observable on.
-
symbol
¶ The algebraic symbol representing the Observable.
-
-
class
qucumber.observables.
SigmaY
[source]¶ Bases:
qucumber.observables.ObservableBase
The
observable
Computes the magnetization in the Y direction of a spin chain.
-
apply
(nn_state, samples)[source]¶ Computes the magnetization along Y of each sample in the given batch of samples.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction that drew the samples.
- samples (torch.Tensor) – A batch of samples to calculate the observable on.
Must be using the
convention.
-
name
¶ The name of the Observable.
-
sample
(nn_state, k, num_samples=1, initial_state=None, overwrite=False)[source]¶ Draws samples of the observable using the given WaveFunction.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction to draw samples from.
- k (int) – The number of Gibbs Steps to perform before drawing a sample.
- num_samples (int) – The number of samples to draw.
- initial_state (torch.Tensor) – The initial state of the Markov Chain. If given, num_samples will be ignored.
- overwrite (bool) – Whether to overwrite the initial_state tensor, if it is provided, with the updated state of the Markov chain.
-
statistics
(nn_state, num_samples, num_chains=0, burn_in=1000, steps=1)[source]¶ Estimates the expected value, variance, and the standard error of the observable over the distribution defined by the WaveFunction.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction to draw samples from.
- num_samples (int) – The number of samples to draw. The actual number of samples drawn may be slightly higher if num_samples % num_chains != 0.
- num_chains (int) – The number of Markov chains to run in parallel; if 0, will use a number of chains equal to num_samples.
- burn_in (int) – The number of Gibbs Steps to perform before recording any samples.
- steps (int) – The number of Gibbs Steps to take between each sample.
Returns: A dictionary containing the (estimated) expected value (key: “mean”), variance (key: “variance”), and standard error (key: “std_error”) of the observable.
Return type:
-
statistics_from_samples
(nn_state, samples)[source]¶ Estimates the expected value, variance, and the standard error of the observable using the given samples.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction that drew the samples.
- samples (torch.Tensor) – A batch of sample states to calculate the observable on.
-
symbol
¶ The algebraic symbol representing the Observable.
-
Neighbour Interactions¶
-
class
qucumber.observables.
NeighbourInteraction
(periodic_bcs=False, c=1)[source]¶ Bases:
qucumber.observables.ObservableBase
The
observable
Computes the c-th nearest neighbour interaction for a spin chain with either open or periodic boundary conditions.
Parameters: -
apply
(nn_state, samples)[source]¶ Computes the energy of this neighbour interaction for each sample given a batch of samples.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction that drew the samples.
- samples (torch.Tensor) – A batch of samples to calculate the observable on.
Must be using the
convention.
-
name
¶ The name of the Observable.
-
sample
(nn_state, k, num_samples=1, initial_state=None, overwrite=False)[source]¶ Draws samples of the observable using the given WaveFunction.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction to draw samples from.
- k (int) – The number of Gibbs Steps to perform before drawing a sample.
- num_samples (int) – The number of samples to draw.
- initial_state (torch.Tensor) – The initial state of the Markov Chain. If given, num_samples will be ignored.
- overwrite (bool) – Whether to overwrite the initial_state tensor, if it is provided, with the updated state of the Markov chain.
-
statistics
(nn_state, num_samples, num_chains=0, burn_in=1000, steps=1)[source]¶ Estimates the expected value, variance, and the standard error of the observable over the distribution defined by the WaveFunction.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction to draw samples from.
- num_samples (int) – The number of samples to draw. The actual number of samples drawn may be slightly higher if num_samples % num_chains != 0.
- num_chains (int) – The number of Markov chains to run in parallel; if 0, will use a number of chains equal to num_samples.
- burn_in (int) – The number of Gibbs Steps to perform before recording any samples.
- steps (int) – The number of Gibbs Steps to take between each sample.
Returns: A dictionary containing the (estimated) expected value (key: “mean”), variance (key: “variance”), and standard error (key: “std_error”) of the observable.
Return type:
-
statistics_from_samples
(nn_state, samples)[source]¶ Estimates the expected value, variance, and the standard error of the observable using the given samples.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction that drew the samples.
- samples (torch.Tensor) – A batch of sample states to calculate the observable on.
-
symbol
¶ The algebraic symbol representing the Observable.
-
Abstract Observable¶
Note
This is an Abstract Base Class, it is not meant to be used directly. The following API reference is mostly for developers.
-
class
qucumber.observables.
ObservableBase
[source]¶ Bases:
abc.ABC
Base class for observables.
-
apply
(nn_state, samples)[source]¶ Computes the value of the observable, row-wise, on a batch of samples. Must be implemented by any subclasses.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction that drew the samples.
- samples (torch.Tensor) – A batch of sample states to calculate the observable on.
-
name
¶ The name of the Observable.
-
sample
(nn_state, k, num_samples=1, initial_state=None, overwrite=False)[source]¶ Draws samples of the observable using the given WaveFunction.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction to draw samples from.
- k (int) – The number of Gibbs Steps to perform before drawing a sample.
- num_samples (int) – The number of samples to draw.
- initial_state (torch.Tensor) – The initial state of the Markov Chain. If given, num_samples will be ignored.
- overwrite (bool) – Whether to overwrite the initial_state tensor, if it is provided, with the updated state of the Markov chain.
-
statistics
(nn_state, num_samples, num_chains=0, burn_in=1000, steps=1)[source]¶ Estimates the expected value, variance, and the standard error of the observable over the distribution defined by the WaveFunction.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction to draw samples from.
- num_samples (int) – The number of samples to draw. The actual number of samples drawn may be slightly higher if num_samples % num_chains != 0.
- num_chains (int) – The number of Markov chains to run in parallel; if 0, will use a number of chains equal to num_samples.
- burn_in (int) – The number of Gibbs Steps to perform before recording any samples.
- steps (int) – The number of Gibbs Steps to take between each sample.
Returns: A dictionary containing the (estimated) expected value (key: “mean”), variance (key: “variance”), and standard error (key: “std_error”) of the observable.
Return type:
-
statistics_from_samples
(nn_state, samples)[source]¶ Estimates the expected value, variance, and the standard error of the observable using the given samples.
Parameters: - nn_state (qucumber.nn_states.WaveFunctionBase) – The WaveFunction that drew the samples.
- samples (torch.Tensor) – A batch of sample states to calculate the observable on.
-
symbol
¶ The algebraic symbol representing the Observable.
-
Complex Algebra¶
-
qucumber.utils.cplx.
absolute_value
(x)[source]¶ Computes the complex absolute value elementwise.
Parameters: x (torch.Tensor) – A complex tensor. Returns: A real tensor. Return type: torch.Tensor
-
qucumber.utils.cplx.
conjugate
(x)[source]¶ A function that takes the conjugate transpose of the argument.
Parameters: x (torch.Tensor) – A complex vector or matrix. Returns: The conjugate of x. Return type: torch.Tensor
-
qucumber.utils.cplx.
elementwise_division
(x, y)[source]¶ Elementwise division of x by y.
Parameters: - x (torch.Tensor) – A complex tensor.
- y (torch.Tensor) – A complex tensor.
Return type:
-
qucumber.utils.cplx.
elementwise_mult
(x, y)[source]¶ Alias for
scalar_mult()
.
-
qucumber.utils.cplx.
inner_prod
(x, y)[source]¶ A function that returns the inner product of two complex vectors, x and y (<x|y>).
Parameters: - x (torch.Tensor) – A complex vector.
- y (torch.Tensor) – A complex vector.
Raises: ValueError – If x and y are not complex vectors with their first dimensions being 2, then the function will not execute.
Returns: The inner product,
.
Return type:
-
qucumber.utils.cplx.
kronecker_prod
(x, y)[source]¶ A function that returns the tensor / kronecker product of 2 complex tensors, x and y.
Parameters: - x (torch.Tensor) – A complex matrix.
- y (torch.Tensor) – A complex matrix.
Raises: ValueError – If x and y do not have 3 dimensions or their first dimension is not 2, the function cannot execute.
Returns: The tensorproduct of x and y,
.
Return type:
-
qucumber.utils.cplx.
make_complex
(x, y=None)[source]¶ A function that combines the real (x) and imaginary (y) parts of a vector or a matrix.
Note
x and y must have the same shape. Also, this will not work for rank zero tensors.
Parameters: - x (torch.Tensor) – The real part
- y (torch.Tensor) – The imaginary part. Can be None, in which case, the resulting complex tensor will have imaginary part equal to zero.
Returns: The tensor [x,y] = x + yi.
Return type:
-
qucumber.utils.cplx.
matmul
(x, y)[source]¶ A function that computes complex matrix-matrix and matrix-vector products.
Note
If one wishes to do matrix-vector products, the vector must be the second argument (y).
Parameters: - x (torch.Tensor) – A complex matrix.
- y (torch.Tensor) – A complex vector or matrix.
Returns: The product between x and y.
Return type:
-
qucumber.utils.cplx.
norm
(x)[source]¶ A function that returns the norm of the argument.
Parameters: x (torch.Tensor) – A complex scalar. Returns: .
Return type: torch.Tensor
-
qucumber.utils.cplx.
norm_sqr
(x)[source]¶ A function that returns the squared norm of the argument.
Parameters: x (torch.Tensor) – A complex scalar. Returns: .
Return type: torch.Tensor
-
qucumber.utils.cplx.
outer_prod
(x, y)[source]¶ A function that returns the outer product of two complex vectors, x and y.
Parameters: - x (torch.Tensor) – A complex vector.
- y (torch.Tensor) – A complex vector.
Raises: ValueError – If x and y are not complex vectors with their first dimensions being 2, then the function will not execute.
Returns: The outer product between x and y,
.
Return type:
-
qucumber.utils.cplx.
scalar_divide
(x, y)[source]¶ A function that computes the division of x by y.
Parameters: - x (torch.Tensor) – The numerator (a complex scalar, vector or matrix).
- y (torch.Tensor) – The denominator (a complex scalar).
Returns: x / y
Return type:
-
qucumber.utils.cplx.
scalar_mult
(x, y, out=None)[source]¶ A function that computes the product between complex matrices and scalars, complex vectors and scalars or two complex scalars.
Parameters: - x (torch.Tensor) – A complex scalar, vector or matrix.
- y (torch.Tensor) – A complex scalar, vector or matrix.
- z (torch.Tensor) – The complex tensor to write the output to.
- z – A complex scalar, vector or matrix. Can be None, in which case, a new tensor is created and returned. Otherwise, the method overwrites z.
Returns: The product between x and y. Either overwrites z, or returns a new tensor.
Return type:
Data Handling¶
-
qucumber.utils.data.
extract_refbasis_samples
(train_samples, train_bases)[source]¶ Extract the reference basis samples from the data.
Parameters: - train_samples (numpy.array) – The training samples.
- train_bases (numpy.array) – The bases of the training samples.
Returns: The samples in the data that are only in the reference basis.
Return type: