Core¶
The core module contains the most important code parts used in zyglrox
Circuit¶
The Circuit class contains all functionality for constructing quantum circuits and calculating observables. The circuit
is defined by passing a list of Gate objects to the constructor. The combination of \(M\) quantum gates is equal to a single unitary operation
Our quantum computer then calculates the state
If the gates \(\mathcal{U}_i\) are paramterized by some parameter \(\theta_i\), so \(\mathcal{U}_i\to\mathcal{U}_i(\theta_i)\), we have what is called a variational quantum circuit
These variational quantum circuits are essential for algorithms such as the Quantum Variational Eigensolver, the Quantum Boltzmann Machine or Quantum Approximate Adiabatic Optimization.
For more information on the available gates in zyglrox, see the section
about Gates.
Note
This class inherits from the tf.keras.models.Model class, and can thus be accessed in a similar fashion as other Keras
Models. This allows for easy integration of your variational quantum circuit with the deep learning tools available in TensorFlow and Keras.
-
class
zyglrox.core.circuit.QuantumCircuit(tf.keras.models.Model)¶ Bases:
objectQuantum Circuit TensorFlow Interface
This class is an interface to build quantum circuits using TensorFlow. On initialization, the graph for the circuit is constructed. The circuit is defined by passing a list of
Gateobjects.- Args:
- nqubits (int):
Number of qubits.
- gates (list):
List of
Gateobjects.- tensorboard (bool):
Boolean that indicates whether we store the store meta data for tensorboard. Default false.
- Keyword Arguments
- batch_size (int):
Number of parallel iterations for map_fn when using batches of parammeters.
- Returns (inplace):
None
-
initialize() → None¶ Initialize session, variables, and the Tensorboard writer.
Args:
- device (string):
Device of choice for running tensorflow.
- Returns (inplace):
None
-
execute() → tensorflow.python.framework.ops.Tensor¶ Exectute the circuit, starting from the initial zero state \(|0\rangle^{\otimes N}\) .
Returns (Tensor):
Circuit output, a wave function of shape (None, 2,…,2).
-
call(inputs, training=False) → tensorflow.python.framework.ops.Tensor¶ Call the circuit for a given wave function or batch of wave functions
- Args:
- inputs (Tensor):
Input tensor corresponding to the wave function of shape (None, 2,…,2). In the case of a single wave function we get a shape (1,2,…,2)
- training (Bool):
Indicates whether to run the circuit in training mode or inference mode.
Returns (Tensor):
Circuit output, a wave function of shape (None, 2,…,2).
-
set_parameters(theta)¶ Set the parameters of the quantum circuit by an external input. Also works for batches of parameters if the QuantumCircuit has been initialized with batch_params=True.
- Args:
- theta (tensor):
Parameters to be fed into the circuit, either of dimension (1, nparams, 1) or (None,nparams,1) where nparams is the total number of parameters in the circuit.
Returns:
-
print_layer_ordering()¶ Print the layer gates per layer.
- Returns (inplace):
None
-
draw()¶ Draw the circuit using matplotlib.
- Returns (inplace):
None
Gates¶
A quantum gate acting \(\mathcal{U}\) on a single qubit \(i\), acts on full the tensor subspace of the \(N\)-qubit state vector. To perform this calculation, we can calculate the tensor representation of this operation on the full state space as follows:
However, this provides a lot of overhead, since for every gate we need to calculate and store a \(2^N\times2^N\) matrix.
A more efficient method is to only let the quantum gate act on the relevant tensor subspace. Throughout zyglrox,
the wave function \(|\psi\rangle^{\otimes N}\) is stored as a tensor of shape \((2,2,\ldots,2)\). The gate operation can
then be performed as:
Which can be implemented in tensorflow in the following way:
phi_hat = tf.tensordot(self.op, phi,
axes=[list(range(self.nqubits, 2 * self.nqubits)), self.wires]
)
# tensordot sets the contracted axes first, so we need to reshuffle them
unused_idxs = [idx for idx in range(self.total_qubits) if idx not in self.wires]
perm = self.wires + unused_idxs
inv_perm = np.argsort(perm)
tf.transpose(phi, perm=inv_perm)
-
class
zyglrox.core.gates.Gate(nparams: int, wires: List[int], value: List[float] = None, name=None, **kwargs)¶ Abstract Quantum Gate class
The
Gateclass performs unitary quantum gates on the tensor subspace of a wave function- Args:
- nparams (int):
Number of parameters of gate.
- wires (list):
List of numbers on which the gate is acting.
- value (None of ndarray):
Intial value of parameterized gate in 1D numpy array. When combined with setting
trainable=False, this will create a static gate that cannot be altered during any optimization.- name (str):
Name of the gate.
- Keyword Arguments
- trainable (bool):
Boolean that indicates whether the paramaters of this gate are trainable.
- Returns (inplace):
None
-
set_external_input(external_input: tensorflow.python.framework.ops.Tensor)¶ Connect an external tensor to the gate parameters. Tensor must have shape (nparams, 1). This function enables the construction of hybrid architectures by having the parameters of the circuit be fed from some external model.
- Args:
- external_input (Tensor):
Tensor of shape (nparams, 1) with gate parameters.
- Returns (inplace):
None
-
build(input_shape)¶ Called once from __call__, when we know the shapes of inputs and dtype. Should initialize the trainable variables, and call the super’s build().
- Args:
- input_shape (list):
Input shapes of the incoming tensor.
-
call(inputs: tensorflow.python.framework.ops.Tensor, **kwargs) → tensorflow.python.framework.ops.Tensor¶ Gate Logic goes here.
Gate Templates¶
Below is a table of the most commonly used quantum gates that are already implemented in zyglrox.
|
Gate that implements the CNOT unitary operation. |
|
Gate that implements the Hadamard unitary operation. |
|
Gate that implements the Pauli X unitary operation. |
|
Gate that implements the Pauli Y unitary operation. |
|
Gate that implements the Pauli Z unitary operation. |
|
Gate that implements a rotation around the spin x-axis. |
|
Gate that implements a rotation around the spin y-axis. |
|
Gate that implements a rotation around the spin z-axis. |
|
Gate that implements a rotation around an arbitrary spin axis. |
|
Gate that implements a conditional rotation around the spin x-axis. |
|
Gate that implements a conditional rotation around the spin y-axis. |
|
Gate that implements a conditional rotation around the spin z-axis. |
|
Gate that implements a conditional rotation around an arbitrary spin axis. |
|
Gate that implements the CZ unitary operation. |
|
Gate that implements a phase rotation |
|
Projector that projects the state onto an eigenvector of a Hermitian observable |
|
Projector that projects the state onto an eigenvector of a Hermitian observable |
|
Gate that implements a conditional rotation Ising XX spin interaction. |
|
Gate that implements a conditional rotation Ising YY spin interaction. |
|
Gate that implements a conditional rotation Ising ZZ spin interaction. |
|
Gate that implements the SWAP unitary operation. |
|
Gate that implements a controlled-controlled flip by applying the Toffoli gate. |
Observables¶
We can calculate observables \(\mathcal{O}\) in a similar fashion as quantum gates. By letting the observable of interest work on the required tensor subspace, we can efficiently obtain the corresponding expectation value.
where \(|\hat{\psi}\rangle\) is calculated as in the section about Gates
-
class
zyglrox.core.observables.Observable(op_name: str, wires: List[int], **kwargs)¶ Bases:
tensorflow.python.keras.engine.base_layer.LayerAbstract Observable class
The
Observableclass calculates Hermitian observables from the quantum circuit.- Args:
- op_name (str):
Name of an operation defined in the
observable_dict- wires (list):
List of numbers where the observable of interest is to be measured
- **kwargs:
Additional arguments.
- Returns (inplace):
None
-
build(input_shape, **kwargs)¶ Called once from __call__, when we know the shapes of inputs and dtype. Should initialize the trainable variables, and call the super’s build().
- Args:
- input_shape (list):
Input shapes of the incoming tensor.
-
get_evals_and_projectors(O)¶ Get the eigenvalues and projectors of a Hermitian observable
- Args:
- O (Tensor):
Tensorflow tensor representing a Hermitian observable.
- Returns (Tuple):
eigenvalues and the corresponding stacked projectors.
-
call(inputs, **kwargs)¶ Called in the Keras Model
__call__method after making surebuild()has been called once. Should actually perform the logic of applying the layer to the input tensors (which should be passed in as the first argument).- Args:
- inputs (Tensor):
Input tensor corresponding to the wave function
- **kwargs:
Additional arguments.
- Returns (Tensor):
Output tensor corresponding to wave function after the circuit has been applied
-
class
zyglrox.core.observables.ExpectationValue(observables)¶ Bases:
tensorflow.python.keras.engine.base_layer.LayerAbstract Observable class
The
ExpectationValueclass calculates batches of Hermitian observables from the quantum circuit.- Args:
- observables (str):
List of
Observableobjects
- Returns (inplace):
None
-
build(input_shape)¶ Called once from __call__, when we know the shapes of inputs and dtype. Should initialize the trainable variables, and call the super’s build().
- Args:
- input_shape (list):
Input shapes of the incoming tensor.
-
call(inputs, **kwargs)¶ Called in the Keras Model
__call__method after making surebuild()has been called once. Should actually perform the logic of applying the layer to the input tensors (which should be passed in as the first argument).- Args:
- inputs (Tensor):
Input tensor corresponding to the wave function
- **kwargs:
Additional arguments.
- Returns (Tensor):
Batch of expectation values of shape (None, n_observables,1,1)
-
class
zyglrox.core.observables.SampleExpectationValue(observables: List[zyglrox.core.observables.Observable], number_of_samples: int = 100)¶ Bases:
tensorflow.python.keras.engine.base_layer.LayerAbstract Observable class
The
ExpectationValueclass calculates batches of Hermitian observables from the quantum circuit.- Args:
- observables (str):
List of
Observableobjects- number_of_samples (int):
The number of samples used for determining the observation values.
- Returns (inplace):
None
-
build(input_shape)¶ Called once from __call__, when we know the shapes of inputs and dtype. Should initialize the trainable variables, and call the super’s build().
- Args:
- input_shape (list):
Input shapes of the incoming tensor.
-
call(inputs, **kwargs)¶ Called in the Keras Model
__call__method after making surebuild()has been called once. Should actually perform the logic of applying the layer to the input tensors (which should be passed in as the first argument).- Args:
- inputs (Tensor):
Input tensor corresponding to the wave function
- **kwargs:
Additional arguments.
- Returns (Tensor):
Batch of expectation values of shape (None, n_observables,1,1)
Hamiltonians¶
-
class
zyglrox.core.hamiltonians.Hamiltonian(topology: dict, interactions: dict, model_parameters: dict = {}, **kwargs)¶ Hamiltonian is the abstract class for defining Hamiltonians of physical systems. For our purposes, the Hamiltonian exists of three components:
1. A topology \(\Lambda\) defining the lattice that our model lives on. This can be as simple as a line or square lattice, or as complicated as a fully connected model where each site is physically connected to each other site.
2. An interaction graph \(\Lambda_a \subseteq \Lambda\) which is sub-graph of the full topology with a corresponding string \(\alpha\beta\ldots\) with \(\alpha,\beta,\ldots \in \{x,y,z\}\) that indicates which Pauli interaction we are considering.
3. Model parameters that correspond to the strength of the interactions. This can be either a single value, so that the interaction strength is the same everywhere, or this can be a set of nodes where each vertex has its own interaction strength.
With these three ingredients, a wide range of spin models can be described. When the this class is initialized, a subfolder
./hamiltoniansis automatically created relative to the root. Additionally, one can pass thefile_pathkwarg to specify a different location.- Args:
- topology (dict):
A dict with nodes as keys and a list of edges as values.
- interactions (dict):
A dict with strings of the type \(\alpha\beta\ldots\) as keys and topology dicts as values.
- model_parameters (dict):
A dict with strings of the type \(\alpha\beta\ldots\) as keys and floats as values. If the interaction strength varies per site this can be a dict of vertices with each its own interaction strength
- **kwargs:
Additional arguments.
- Returns (inplace):
None
-
get_hamiltonian_terms() → numpy.ndarray¶ Get all the interactions in the Hamiltonian and add them to a 1d array. When calculating expectation values, this array can be used to multiply with the observables to get the energies.
- Returns (np.ndarray):
Array with interaction strengths according to
self.interaction_order, a sorted list of the interactions provided.
-
get_observables() → List[zyglrox.core.observables.Observable]¶ Get a list of
Observableobjects corresponding to all the terms in the hamiltonian. The order of the observables is according toself.interaction_order, a sorted list of the interactions provided.- Returns (list):
A list of
Observableobjects.
-
get_hamiltonian()¶ Get a sparse matrix representation of the hamiltonian and calculate the eigenvalues and eigenvectors. When the system is degenerate, we store all \(N\) degenerate eigenstates and energies. The Hamiltonian is automatically saved in the
./hamiltonianspath or in the otherwise specifiedfile_pathkwarg- Returns (inplace):
None
-
draw_lattice(**kwargs)¶ Use Networkx to plot a Kamada-Kawai layout of the lattice. Takes the kwargs
poswhich is a dict of vertices and coordinates that indicates the location of the vertices in the plot.- Args:
- **kwargs:
Additional arguments.
- Returns (inplace):
None
-
draw_color_lattice(**kwargs)¶ Use Networkx to plot an edge coloring of the graph. Makes use of
applyHeuristicinzyglrox.core.edge_coloringto find a suitable edge coloring. Per default uses the Kamada-Kawai layout of the lattice. Takes the kwargsposwhich is a dict of vertices and coordinates that indicates the location of the vertices in the plot.- Args:
- **kwargs:
Additional arguments.
- Returns (inplace):
None
Hamiltonian Templates¶
Below is a table of the most commonly used quantum gates that are already implemented in zyglrox.
|
The transverse field Ising-model is given by the Hamiltonian |
|
The XXX Heisenberg model is given by the Hamiltonian |
|
The XXZ Heisenberg model is given by the Hamiltonian |
|
The XYZ Heisenberg model is given by the Hamiltonian |
|
The fully-connected random couplings is given by the Hamiltonian |
|
The \(J_1-J_2\) model is given by the Hamiltonian |
Circuit Templates¶
-
zyglrox.core.circuit_templates.verify_circuit_input(N, depth, initial_parameters, desired_shape)¶
-
zyglrox.core.circuit_templates.staircase_cnot(N: int, mod=True)¶ Circuit architecture where \(N\) CNOTs are applied to qubit \(i\) with target \((i+1)\text{mod} (N)\)
#TODO: insert figure of circuit
- Args:
- N (int):
Number of qubits
- Returns (list):
List of
Gateobjects.
-
zyglrox.core.circuit_templates.target_staircase_cnot(N: int, target: int)¶ Circuit architecture where \(N-1\) CNOTs are applied, all with the same target qubit.
#TODO: insert figure of circuit
- Args:
- N (int):
Number of qubits.
- target (int):
Target qubit in the staircase circuit.
- Returns (list):
List of
Gateobjects.
-
zyglrox.core.circuit_templates.circuit6(N: int)¶ The most expressive circuit at depth \(L=1\) according to Sim et al. (2019).
- Args:
- N (int):
Number of qubits.
- Returns (list):
List of
Gateobjects.
-
zyglrox.core.circuit_templates.custom_cnot(locs: List)¶ Make custom CNOT padding
- Args:
- locs (list):
List with tuples with (control, target).
- Returns (list):
List of
Gateobjects.
-
zyglrox.core.circuit_templates.tfi_1d_hva_circuit(N: int, depth: int, initial_parameters, boundary_condition: str)¶
-
zyglrox.core.circuit_templates.tfi_1d_projective_hva_circuit(N: int, depth: int, projectors, initial_parameters, boundary_condition: str, nmeas: int)¶
-
zyglrox.core.circuit_templates.xy_1d_hva_alt_circuit(N: int, depth: int, initial_parameters, boundary_condition)¶
-
zyglrox.core.circuit_templates.xy_1d_hva_circuit(N: int, depth: int, initial_parameters, boundary_condition)¶
-
zyglrox.core.circuit_templates.tfi_2d_hva_circuit(N: int, depth: int, edge_coloring: dict, initial_parameters, f_or_af: f)¶
-
zyglrox.core.circuit_templates.xxz_1d_hva_circuit(N: int, depth: int, initial_parameters, boundary_condition)¶
-
zyglrox.core.circuit_templates.xxz_1d_projective_hva_circuit(N: int, depth: int, projectors, initial_parameters, boundary_condition: str, nmeas: int)¶
-
zyglrox.core.circuit_templates.xxz_1d_projective_hva_circuit_multi_measure(N: int, depth: int, projectors, initial_parameters, boundary_condition: str, nmeas: int)¶
-
zyglrox.core.circuit_templates.xxz_1d_projective_hva_circuit_single_measure(N: int, depth: int, projectors, initial_parameters, boundary_condition: str, nmeas: int)¶
-
zyglrox.core.circuit_templates.xxz_1d_perm_hva_circuit(N: int, depth: int, initial_parameters, boundary_condition, permutation)¶
-
zyglrox.core.circuit_templates.xxz_2d_hva_circuit(depth: int, edge_coloring: dict, initial_parameters: numpy.ndarray)¶
-
zyglrox.core.circuit_templates.kitaev_honeycomb_circuit(depth: int, edge_coloring: dict, initial_parameters: numpy.ndarray)¶
-
zyglrox.core.circuit_templates.kitaev_ladder_circuit(depth: int, edge_coloring: dict, initial_parameters: numpy.ndarray)¶
Topologies¶
-
zyglrox.core.topologies.graph_kagome_12(boundary_condition='open')¶
-
zyglrox.core.topologies.graph_kagome_18b(boundary_condition='open')¶
-
zyglrox.core.topologies.graph_kagome_24(boundary_condition='open')¶
-
zyglrox.core.topologies.graph_honeycomb_8(link=None)¶
-
zyglrox.core.topologies.graph_honeycomb_16(link=None)¶
-
zyglrox.core.topologies.graph_ladder(L: int, link=None, boundary_condition='open')¶
-
zyglrox.core.topologies.graph_honeycomb_13()¶
-
zyglrox.core.topologies.graph_kagome_18b_torus()¶
-
zyglrox.core.topologies.graph_kagome_12_torus()¶
-
zyglrox.core.topologies.graph_kagome_24_torus()¶
-
zyglrox.core.topologies.graph_kagome_27()¶
Edge Coloring¶
-
zyglrox.core.edge_coloring.properlyColored(G, u, D)¶
-
zyglrox.core.edge_coloring.checkEdgeColoring(G, D)¶
-
zyglrox.core.edge_coloring.conflictLevel(G, u)¶
-
zyglrox.core.edge_coloring.createConflictDictionary(G, D)¶
-
zyglrox.core.edge_coloring.updateConflictDictionary(G, u, conflict_dictionary, old_conflict_level_u)¶
-
zyglrox.core.edge_coloring.maxConflictLevel(conflict_dictionary)¶
-
zyglrox.core.edge_coloring.totalNumberOfConflicts(conflict_dictionary)¶
-
zyglrox.core.edge_coloring.colorEdgeAndUpdate(G, u, v, color, conflict_dictionary)¶
-
zyglrox.core.edge_coloring.KempeNext(G, last, node, new_color, conflict_dictionary)¶
-
zyglrox.core.edge_coloring.KempeStep(G, last, node, new_color, conflict_dictionary)¶
-
zyglrox.core.edge_coloring.KempeProcess(G, last, node, new_color, conflict_dictionary)¶
-
zyglrox.core.edge_coloring.KempeStart(G, D, node, conflict_dictionary)¶
-
zyglrox.core.edge_coloring.preColoring(G, D)¶
-
zyglrox.core.edge_coloring.heuristic(G, D, repetition_limit)¶
-
zyglrox.core.edge_coloring.applyHeuristic(G, D, repetition_limit, iteration_limit)¶
Optimizers¶
-
zyglrox.core.optimizers.Newton(loss, vrs, optimizer=None)¶ Newton’s second order gradient method.
Args:
- loss (Tensor):
Loss function that uses the provided state.
- vrs (Variables):
Variables to be optimized.
- optimizer (Tensorflow Optimizer):
Tensorflow optimizer from the tf.train API
- Returns (Operation):
Train step operation.
-
zyglrox.core.optimizers.ImaginaryTimeEvolution(state, loss, vrs, optimizer=None, stability_shift=None, learning_rate=0.01)¶ Implementation of the imaginary time evolution gradient method
- Args:
- state (Tensor):
Output state of the circuit.
- loss (Tensor):
Loss function that uses the provided state.
- vrs (Variables):
Variables to be optimized.
- optimizer (Tensorflow Optimizer):
Tensorflow optimizer from the tf.train API
- Returns (Operation):
Train step operation.
-
zyglrox.core.optimizers.QuantumNaturalGradient(state, loss, vrs, optimizer=None, stability_shift=None, learning_rate: float = 0.01)¶ Implementation of the quantum natural gradient gradient method
- Args:
- state (Tensor):
Output state of the circuit.
- loss (Tensor):
Loss function that uses the provided state.
- vrs (Variables):
Variables to be optimized.
- optimizer (Tensorflow Optimizer):
Tensorflow optimizer from the tf.train API
- Returns (Operation):
Train step operation.
-
zyglrox.core.optimizers.prepGeometricTensor(state, vrs)¶
-
zyglrox.core.optimizers.prep_variables(vrs)¶
Utils¶
-
zyglrox.core.utils.integer_generator(start)¶ Generator for infinite integers. Always useful.
- Args:
- start (int):
starting integer for the generator.
- Returns (int):
Infinite integers.
-
zyglrox.core.utils.tf_kron(a: tensorflow.python.framework.ops.Tensor, b: tensorflow.python.framework.ops.Tensor) → tensorflow.python.framework.ops.Tensor¶ Implementation of Kronecker product for tensorflow Tensors.
- Args:
- a (Tensor):
Tensor of size \(N \times M\)
- b (Tensor):
Tensor of size \(P \times K\)
- Returns (Tensor):
Tensor of size \((N \cdot P) \times (M \cdot K)\)
-
zyglrox.core.utils.partial_trace_np(psi: numpy.ndarray, keep: list, dims: list) → numpy.ndarray¶ Calculate the partial trace of an outer product
\[\rho_a = \text{Tr}_b (| u \rangle \langle u |)\]- Args:
- psi (tensor):
Quantum state of shape (None ,2,2,…,2), where None is a batch dimension.
- keep (list):
An array of indices of the spaces to keep after being traced. For instance, if the space is A x B x C x D and we want to trace out B and D, keep = [0,2]
- dims (list):
- An array of the dimensions of each space. For instance, if the space is A x B x C x D,
dims = [None, dim_A, dim_B, dim_C, dim_D]. None is used as a batch dimension.
- Returns (Tensor):
Partially traced out matrix
-
zyglrox.core.utils.partial_trace(psi: tensorflow.python.framework.ops.Tensor, keep: list, dims: list) → tensorflow.python.framework.ops.Tensor¶ Calculate the partial trace of an outer product
\[\rho_a = \text{Tr}_b (| u \rangle \langle u |)\]- Args:
- psi (tensor):
Quantum state of shape (None ,2,2,…,2), where None is a batch dimension.
- keep (list):
An array of indices of the spaces to keep after being traced. For instance, if the space is A x B x C x D and we want to trace out B and D, keep = [0,2]
- dims (list):
- An array of the dimensions of each space. For instance, if the space is A x B x C x D,
dims = [None, dim_A, dim_B, dim_C, dim_D]. None is used as a batch dimension.
- Returns (Tensor):
Partially traced out matrix
-
zyglrox.core.utils.von_neumann_entropy(rho: Union[tensorflow.python.framework.ops.Tensor, numpy.ndarray]) → Union[tensorflow.python.framework.ops.Tensor, numpy.ndarray]¶ Calculate the Von Neumann entropy of a reduced density matrix.
\[S(\rho) = -\text{Tr} \rho \log \rho\]- Args:
- red_rho (tensor):
Density matrix.
- Returns (tensor):
Scalar containing the Von Neumann entropy.
-
zyglrox.core.utils.logarithmic_negativity(rho: Union[tensorflow.python.framework.ops.Tensor, numpy.ndarray]) → Union[tensorflow.python.framework.ops.Tensor, numpy.ndarray]¶ Calculate the Von Neumann entropy of a reduced density matrix.
\[S(\rho) = -\text{Tr} \rho \log \rho\]- Args:
- red_rho (tensor):
Density matrix.
- Returns (tensor):
Scalar containing the Von Neumann entropy.
-
zyglrox.core.utils.get_available_devices(device_type)¶
-
zyglrox.core.utils.renyi_entropy(rho: tensorflow.python.framework.ops.Tensor, alpha: float = 0.5) → tensorflow.python.framework.ops.Tensor¶ Calculate the Von Neumann entropy of a reduced density matrix.
\[S(\rho) = \frac{1}{1-\alpha}\log \text{Tr} \rho^\alpha\]- Args:
- red_rho (tensor):
Density matrix.
- Returns (tensor):
Scalar containing the Von Neumann entropy.
-
zyglrox.core.utils.flatten(x: tensorflow.python.framework.ops.Tensor) → tensorflow.python.framework.ops.Tensor¶ Flatten tensor to 1D array.
- Args:
- x (Tensor):
Input tensor with shape \((M_{i_1},M_{i_2},\ldots,M_{i_m})\).
- Returns (Tensor):
Flattened tensor with shape \((\prod_n^m M_{i_n}, )\).
-
zyglrox.core.utils.ops_print(observables)¶ Print the observables in a readable manner.
- Args:
- observables (list):
List of
Observableobjects.
- Returns (inplace):
None
-
zyglrox.core.utils.tensordot(a, b, axes, name: Optional[str] = None) → tensorflow.python.framework.ops.Tensor¶ Full credit for this part goes to the developers of the Google TensorNetworks library, thanks to Martin for mentioning this. Source: https://github.com/google/TensorNetwork/blob/master/tensornetwork/backends/tensorflow/tensordot2.py
Tensor contraction of a and b along specified axes. Tensordot (also known as tensor contraction) sums the product of elements from a and b over the indices specified by a_axes and b_axes. The lists a_axes and b_axes specify those pairs of axes along which to contract the tensors. The axis a_axes[i] of a must have the same dimension as axis b_axes[i] of b for all i in range(0, len(a_axes)). The lists a_axes and b_axes must have identical length and consist of unique integers that specify valid axes for each of the tensors. This operation corresponds to numpy.tensordot(a, b, axes).
Example 1: When a and b are matrices (order 2), the case axes = 1 is equivalent to matrix multiplication.
Example 2: When a and b are matrices (order 2), the case axes = [[1], [0]] is equivalent to matrix multiplication.
Example 3: Suppose that \(a_{ijk}\) and \(b_{lmn}\) represent two tensors of order 3. Then, contract(a, b, [[0], [2]]) is the order 4 tensor \(c_{jklm}\) whose entry corresponding to the indices \((j,k,l,m)\) is given by: \( c_{jklm} = sum_i a_{ijk} b_{lmi} \).
In general, order(c) = order(a) + order(b) - 2*len(axes[0]).
- Args:
- tf:
The TensorFlow module. This must be passed in instead of imported
since we don’t assume users have TensorFlow installed.
- a:
Tensor of type float32 or float64.
- b:
Tensor with the same type as a.
- axes:
Either a scalar N, or a list or an int32 Tensor of shape [2, k]. If axes is a scalar, sum over the last N axes of a and the first N axes of b in order. If axes is a list or Tensor the first and second row contain the set of unique integers specifying axes along which the contraction is computed, for a and b, respectively. The number of axes for a and b must be equal.
- name:
A name for the operation (optional).
- Returns:
A Tensor with the same type as a.
- Raises:
- ValueError:
If the shapes of a, b, and axes are incompatible.
- IndexError:
If the values in axes exceed the rank of the corresponding tensor.