API Reference

Data

Defines the qbmlib.data package.

class qhbmlib.data.QHBMData(input_qhbm: qhbmlib.inference.qhbm.QHBM)[source]

QuantumData defined by a QHBM.

expectation(observable: Union[tensorflow.python.framework.ops.Tensor, qhbmlib.models.hamiltonian.Hamiltonian])[source]

See base class docstring.

class qhbmlib.data.QuantumData[source]

Interface for quantum datasets.

abstract expectation(observable: Union[tensorflow.python.framework.ops.Tensor, qhbmlib.models.hamiltonian.Hamiltonian])[source]

Take the expectation value of an observable against this dataset.

Parameters

observable – Hermitian operator to measure. If tf.Tensor, it is of type tf.string with shape [1], result of calling tfq.convert_to_tensor on a list of cirq.PauliSum, [op]. Otherwise, a Hamiltonian.

Returns

Scalar tf.Tensor which is the expectation value of observable against

this quantum data source.

Models

Defines the qhbmlib.models package.

class qhbmlib.models.BernoulliEnergy(*args, **kwargs)[source]

Tensor product of coin flip distributions.

Note that we parameterize using the energy of a spin in a magnetic field, which is offset from the log probability of a typical Bernoulli.

property logits

Returns the current logits of the distribution.

For our Bernoulli distribution, let $p$ be the probability of bit being 1. In this case, we have $p = frac{e^{theta}}{{e^{theta}+e^{-theta}}}$. Therefore, each independent logit is: $$logit = logfrac{p}{1-p} = logfrac{e^{theta}}{e^{-theta}}

= log{e^{2*theta}} = 2*theta$$

operator_shards(qubits)[source]

See base class description.

property post_process

See base class description.

class qhbmlib.models.BitstringEnergy(*args, **kwargs)[source]

Class for representing an energy function over bitstrings.

Keras Layer which can be interpreted as outputting an unnormalized log-probability for each given bit-string x, written E(x). Hence, this class implicitly defines a probability distribution over all bit-strings given by $$p(x) = frac{exp(-E(x))}{sum_x exp(-E(x))}.$$

Moving to its use in QHBMs: each bit-string can also be interpreted as an index for an entry of the diagonal eigenvalue matrix in the spectral representation of a density operator. Hence, for a QHBM, inference corresponds to sampling computational basis states $|x><x|$ for $x ~ p$, where $p$ is the probability distribution written above.

property bits

Labels for the bits on which this distribution is supported.

build(input_shape)[source]

Builds all the internal layers.

call(inputs)[source]

Returns the energies corresponding to the input bitstrings.

property energy_layers

List of keras layers which, when stacked, map bitstrings to energies.

This list of layers is where the caller would access model weights to be updated from a secondary model or hypernetwork.

property num_bits

Number of bits on which this layer acts.

class qhbmlib.models.DirectQuantumCircuit(*args, **kwargs)[source]

QuantumCircuit with direct map from model variables to circuit params.

class qhbmlib.models.Hamiltonian(*args, **kwargs)[source]

Diagonalized (spectral) representation of a Hermitian operator.

class qhbmlib.models.KOBE(*args, **kwargs)[source]

Kth Order Binary Energy function.

operator_shards(qubits: List[cirq.devices.grid_qubit.GridQubit])[source]

See base class description.

property post_process

See base class description.

class qhbmlib.models.Parity(*args, **kwargs)[source]

Computes the parities of input spins.

call(inputs)[source]

Returns a batch of parities corresponding to the input bitstrings.

class qhbmlib.models.PauliMixin[source]

Mixin class to add a Pauli Z representation to BitstringEnergy.

operator_expectation(expectation_shards: tensorflow.python.framework.ops.Tensor)[source]

Computes the average energy given operator shard expectation values.

abstract operator_shards(qubits: List[cirq.devices.grid_qubit.GridQubit])[source]

Parameter independent Pauli Z strings to measure.

Parameters

qubits – List of cirq.GridQubits. objects to measure.

Returns

List of PauliSum objects whose expectation values are fed to

operator_expectation to compute average energy.

abstract property post_process

List of keras layers. Concatenation of these layers yields the trainable map from the operator shard expectations to a single scalar which is the average energy.

class qhbmlib.models.QAIA(*args, **kwargs)[source]

Quantum circuit defined by a classical energy and a Hamiltonian.

This circuit model is intended for use with VQT.

class qhbmlib.models.QuantumCircuit(*args, **kwargs)[source]

Class for representing a quantum circuit.

build(input_shape)[source]

Builds the layers which calculate the values.

input_shape is unused because it is known to be the shape of self._value_layers_inputs.

call(inputs)[source]

Inputs are bitstrings prepended as initial states to self.pqc.

property pqc

TFQ tensor representation of the parameterized unitary circuit.

property qubits

Sorted list of the qubits on which this circuit acts.

property symbol_names

1D tensor of strings which are the free parameters of the circuit.

property symbol_values

1D tf.Tensor of floats specifying the current values of the parameters.

This should be structured such that self.symbol_values[i] is the current value of self.symbol_names[i] in self.pqc and self.inverse_pqc.

property value_layers

List of lists of Keras layers which calculate current parameter values.

This property (and value_layers_inputs) is where the caller would access model weights to be updated from a secondary model or hypernetwork.

property value_layers_inputs

List of lists of variables which are inputs to value_layers.

This property (and value_layers) is where the caller would access model weights to be updated from a secondary model or hypernetwork.

class qhbmlib.models.SpinsFromBitstrings(*args, **kwargs)[source]

Simple layer taking bits to spins.

call(inputs)[source]

Returns the spins corresponding to the input bitstrings.

Note that this maps |0> -> +1 and |1> -> -1. This is in accordance with the usual interpretation of the Bloch sphere.

class qhbmlib.models.VariableDot(*args, **kwargs)[source]

Utility layer for dotting input with a same-sized variable.

build(input_shape)[source]

Initializes the internal variables.

call(inputs)[source]

Returns the dot product between the inputs and this layer’s variables.

Inference

Defines the qhbmlib.inference package.

class qhbmlib.inference.AnalyticEnergyInference(*args, **kwargs)[source]

Uses an explicit categorical distribution to implement parent functions.

property all_bitstrings

Returns every bitstring.

property all_energies

Returns the energy of every bitstring.

property distribution

Categorical distribution set during self._ready_inference.

class qhbmlib.inference.AnalyticQuantumInference(*args, **kwargs)[source]

Analytic methods for inference on QuantumCircuit objects.

This class uses the TensorFlow Quantum Expectation layer to compute expectation values of observables. It uses adjoint gradients to compute the derivatives of those expectation values.

Why shouldn’t we use the ParameterShift differentiator with this class? First, in this class expectation values of observables are exact irrespective of the chosen differentiator. Second, parameter shift derivatives are exactly equal to the true derivative in the noiseless, exact-expectation regime. Thus using it would just increase computational overhead without gaining additional accuracy.

class qhbmlib.inference.BernoulliEnergyInference(*args, **kwargs)[source]

Manages inference for a Bernoulli defined by spin energies.

property distribution

Bernoulli distribution set during self._ready_inference.

class qhbmlib.inference.EnergyInference(*args, **kwargs)[source]

Provides some default method implementations.

class qhbmlib.inference.EnergyInferenceBase(*args, **kwargs)[source]

Defines the interface for inference on BitstringEnergy objects.

Let $E$ be the energy function defined by a given BitstringEnergy, and let $X$ be the set of bitstrings in the domain of $E$. Associated with $E$ is a probability distribution $$p(x) = frac{e^{-E(x)}}{sum_{yin X} e^{-E(y)}},$$ which we call the Energy Based Model (EBM) associated with $E$. Inference in this class means estimating quantities of interest relative to the EBM.

call(inputs, *args, **kwargs)[source]

Calls this layer on the given inputs.

property energy

The energy function which sets the probabilities for this EBM.

entropy()[source]

Returns an estimate of the entropy.

expectation(function)[source]

Returns an estimate of the expectation value of the given function.

Parameters

function – Mapping from a 2D tensor of bitstrings to a possibly nested structure. The structure must have atomic elements all of which are float tensors with the same batch size as the input bitstrings.

log_partition()[source]

Returns an estimate of the log partition function.

sample(num_samples: int)[source]

Returns samples from the EBM corresponding to self.energy.

Parameters

num_samples – Number of samples to draw from the EBM.

property seed

Current TFP compatible seed controlling sampling behavior.

PRNG seed; see tfp.random.sanitize_seed for details. This seed will be used in the sample method. If None, the seed is updated after every inference call. Otherwise, the seed is fixed.

property variables_updated

Returns True if tracked variables do not have the checkpointed values.

class qhbmlib.inference.GibbsWithGradientsInference(*args, **kwargs)[source]

Manages inference using a Gibbs With Gradients kernel.

class qhbmlib.inference.QHBM(*args, **kwargs)[source]

Methods for inference involving normalized exponentials of Hamiltonians.

We also call the normalized exponential of a Hamiltonian a “thermal state”. Here we formalize some aspects of thermal states, which will be used later to explain particular methods of this class.

# TODO(#119): add reference to updated QHBM paper.

Each method takes as input some modular Hamiltonian $$K_{thetaphi} = U_phi K_theta U_phi^dagger.$$ The [thermal state][1] corresponding to the model is $$ rho_T = Z^{-1} e^{-beta K_{thetaphi}}.$$ For QHBMs, we assume $beta = 1$, effectively absorbing it into the definition of the modular Hamiltonian. Then $rho_T$ can be expanded as $$rho_T = sum_x p_theta(x)U_phiket{x}bra{x}U_phi^dagger,$$ where the probability is given by $$p_theta(x) = tr[exp(-K_theta)]bra{x}exp(-K_theta)ket{x}$$ for $xin{1, ldots, dim(K_{thetaphi})} = mathcal{X}$. Note that each $U_phiket{x}$ is an eigenvector of both $rho_T$ and $K_{thetaphi}$.

Corresponding to this density operator is an [ensemble of quantum states][2]. Using the terms above, we define the particular ensemble $$mathcal{E} = {p_theta(x), U_phiket{x}}_{xinmathcal{X}},$$ also known as the [canonical ensemble][2] corresponding to $rho_T$. Each method of this class implicitly samples from this ensemble, then post-processes to perform a particular inference task.

#### References [1]: Nielsen, Michael A. and Chuang, Isaac L. (2010).

Quantum Computation and Quantum Information. Cambridge University Press.

[2]: Wilde, Mark M. (2017).

Quantum Information Theory (second edition). Cambridge University Press.

circuits(num_samples: int)[source]

Draws thermally distributed eigenstates from the model Hamiltonian.

Here we explain the algorithm. First, construct $X$ to be a classical random variable with probability distribution $p_theta(x)$ set by model.e_inference.energy. Then, draw $n = $`num_samples` bitstrings, $S={x_1, ldots, x_n}$, from $X$. For each unique $x_iin S$, set states[i] to the TFQ string representation of $U_phiket{x_i}$, where $U_phi$ is set by self.q_inference.circuit. Finally, set counts[i] equal to the number of times $x_i$ occurs in $S$.

Parameters
  • model – The modular Hamiltonian whose normalized exponential is the density operator governing the ensemble of states from which to sample.

  • num_samples – Number of states to draw from the ensemble.

Returns

1D tf.Tensor of dtype tf.string. Each entry is a TFQ string

representation of an eigenstate of self.modular_hamiltonian.

counts: 1D tf.Tensor of dtype tf.int32. counts[i] is the number of

times states[i] was drawn from the ensemble.

Return type

states

property e_inference

The object used for inference on density operator eigenvalues.

expectation(observables: Union[tensorflow.python.framework.ops.Tensor, qhbmlib.models.hamiltonian.Hamiltonian])[source]

Estimates observable expectation values against the density operator.

TODO(#119): add expectation and derivative equations and discussions

from updated paper.

Implicitly sample pure states from the canonical ensemble corresponding to the thermal state defined by self.modular_hamiltonian. For each such state |psi>, estimate the expectation value <psi|op_j|psi> for each ops[j]. Then, average these expectation values over the sampled states.

Parameters
  • model – The modular Hamiltonian whose normalized exponential is the density operator against which expectation values will be estimated.

  • obervables – Hermitian operators to measure. See docstring of QuantumInference.expectation for details.

Returns

tf.Tensor with shape [n_ops] whose entries are are the sample averaged expectation values of each entry in ops.

property modular_hamiltonian

The modular Hamiltonian defining this QHBM.

property q_inference

The object used for inference on density operator eigenvectors.

class qhbmlib.inference.SampledQuantumInference(*args, **kwargs)[source]

Sampling methods for inference on QuantumCircuit objects.

This class uses the TensorFlow Quantum SampledExpectation and Sample layers to compute expectation values of observables. It uses parameter shift gradients to compute derivatives of those expectation values.

qhbmlib.inference.density_matrix(model: qhbmlib.models.hamiltonian.Hamiltonian)[source]

Returns the thermal state corresponding to a modular Hamiltonian.

Given a modular Hamiltonian $K_{thetaphi} = U_phi K_theta U_phi^dagger$, the corresponding thermal state is

begin{align*}

rho &= (text{tr}[e^{-K_{thetaphi}}])^{-1} e^{-K_{thetaphi}} \&= Z_theta^{-1} U_phi e^{-K_theta} U_phi^dagger \&= U_phi P_theta U_phi^dagger

end{align*} where we defined the diagonal matrix $P_theta$ as $$

langle x|P_theta|yrangle = begin{cases}

p_theta(x), & text{if}x = y \ 0, & text{otherwise}

end{cases}

$$ Continuing, using the definition of matrix multiplication, we have begin{align*}

rho &= U_phi sum_{i,k,j} |iranglelangle i|P_theta|krangle

langle k| U_phi^dagger|jranglelangle j|

\&= U_phi sum_{k,j} p_theta(k)|krangle

langle k| U_phi^dagger|jranglelangle j|

\&= sum_{i,k,j} p_theta(k)|iranglelangle i|U_phi|krangle

langle k| U_phi^dagger|jranglelangle j|

end{align*}

Parameters

model – Modular Hamiltonian whose corresponding thermal state is the density matrix to be calculated.

qhbmlib.inference.fidelity(model: qhbmlib.models.hamiltonian.Hamiltonian, sigma: tensorflow.python.framework.ops.Tensor)[source]

Calculate the fidelity between a QHBM and a density matrix.

Definition of the fidelity between two quantum states $rho$ and $sigma$ is $$ F(rho, sigma) = left(text{tr}sqrt{sqrt{rho}sigmasqrt{rho}}right)^2. $$ When the first argument is a QHBM, we can write $$

F(rho, sigma) = left(text{tr}sqrt{

U_phisqrt{K_theta}U_phi^dagger sigma U_phisqrt{K_theta}U_phi^dagger}right)^2.

$$ By the definition of matrix functions, we can pull the unitaries outside the square root, and use cyclicity of trace to remove them. Then we have $$

F(rho, sigma) = left(text{tr}sqrt{

sqrt{K_theta}U_phi^daggersigma U_phisqrt{K_theta}}right)^2.

$$ Let $omega = sqrt{K_theta}U_phi^daggersigma U_phisqrt{K_theta}$, and let $WD W^dagger$ be a unitary diagonalization of $omega$. Note that $U_phi^daggersigma U_phi$ is Hermitian since it is a unitary conjugation of a Hermitian matrix. Also, for Hermitian matrices A and B, we have $$

(ABA)^dagger = (BA)^dagger A^dagger

= A^dagger B^dagger A^dagger = ABA.

$$ Therefore $ABA$ is also Hermitian. Thus $omega$ is Hermitian, which allows the use of faster eigenvalue finding routines. Then we have $$

F(rho, sigma) = left(text{tr}sqrt{D}right)^2

= left(sum_isqrt{D_{ii}}right)^2.

$$

Parameters
  • model – Modular Hamiltonian whose corresponding thermal state is to be compared to sigma, as the left density matrix in fidelity.

  • sigma – 2-D tf.Tensor of a numeric dtype representing the right density matrix in the fidelity calculation.

Returns

A scalar tf.Tensor which is the fidelity between the density matrix

represented by this QHBM and sigma.

qhbmlib.inference.probabilities(input_energy: qhbmlib.models.energy.BitstringEnergy)[source]

Returns the probabilities of the EBM.

Parameters

input_energy – The energy function defining the EBM.

qhbmlib.inference.qmhl(data: qhbmlib.data.quantum_data.QuantumData, input_qhbm: qhbmlib.inference.qhbm.QHBM)[source]

Calculate the QMHL loss of the QHBM against the quantum data.

See equation 21 in the appendix.

Parameters
  • data – The data mixed state to learn.

  • input_qhbm – QHBM being trained to approximate data.

Returns

The quantum cross-entropy between the data and the model.

qhbmlib.inference.unitary(input_circuit: qhbmlib.models.circuit.QuantumCircuit)[source]

Returns the unitary matrix corresponding to the given circuit.

Parameters

input_circuit – Quantum circuit whose unitary matrix is to be calculated.

qhbmlib.inference.vqt(input_qhbm: qhbmlib.inference.qhbm.QHBM, target_hamiltonian: Union[tensorflow.python.framework.ops.Tensor, qhbmlib.models.hamiltonian.Hamiltonian], beta: tensorflow.python.framework.ops.Tensor)[source]

Computes the VQT loss of a given QHBM and Hamiltonian.

This function is differentiable within a tf.GradientTape scope.

Parameters
  • input_qhbm – Inference methods for the model.

  • target_hamiltonian – The Hamiltonian whose thermal state is to be learned. If it is a tf.Tensor, it is of type tf.string with shape [1], result of calling tfq.convert_to_tensor on a list of cirq.PauliSum, [op]. Otherwise, a Hamiltonian.

  • beta – A scalar tf.Tensor which is the inverse temperature at which the loss is calculated.

Returns

The VQT loss.

Utils

Utilities used across more than one file.

class qhbmlib.utils.Squeeze(*args, **kwargs)[source]

Wraps tf.squeeze in a Keras Layer.

call(inputs)[source]

Applies tf.squeeze to the inputs.

qhbmlib.utils.expand_unique_results(y, idx)[source]

Inverse of unique_bitstrings_with_counts.

Parameters
  • y – Values to pick according to idx.

  • idx – The index at which to place each value of y in the output.

Returns

tf.Tensor such that expanded[i] == y[idx[i]].

Return type

expanded

qhbmlib.utils.unique_bitstrings_with_counts(bitstrings, out_idx=tf.int32)[source]

Extract the unique bitstrings in the given bitstring tensor.

Parameters
  • bitstrings – 2-D tf.Tensor, interpreted as a list of bitstrings.

  • out_idx – An optional tf.DType from: tf.int32, tf.int64. Defaults to tf.int32. Specifies the type of count output.

Returns

2-D tf.Tensor of same dtype as bitstrings, containing the unique

0-axis entries of bitstrings.

idx: The index of each value of the input in the unique output y. count: 1-D tf.Tensor of dtype out_idx such that count[i] is the

number of occurences of y[i] in bitstrings.

Return type

y

qhbmlib.utils.weighted_average(counts: tensorflow.python.framework.ops.Tensor, values: tensorflow.python.framework.ops.Tensor)[source]

Returns the weighted average of input values.

Subtensor i of values is multiplied by counts[i] resulting in a weighted version of values; the mean is then taken across the first dimension.

Parameters
  • counts – Non-negative integers of shape [batch_size].

  • values – Floats of shape [batch_size, …].

Returns

Tensor of shape […] which is the weighted average.