raqet_py.factor

Factor module of Raqet Python interface

Module for representing FactorMethod.

Classes

FactorMethod()

FactorMethod

class raqet_py.factor.FactorMethod

FactorMethod

FactorMethod is a catch-all class for factorization.

There is a known bug that all function signatures will display as empty. Please review all docstrings to see all the relevant information about inputs and outputs.

Examples

This will be expanded, but for now we'll assume that you know how to generate a PauliHamiltonian and a PauliLindbladNoiseOperator using struqture_py.

``` python import numpy as np from struqture_py.spins import (PauliProduct, DecoherenceProduct,

PauliHamiltonian, PauliLindbladNoiseOperator)

import raqet_py

## Part where user generates Hamiltonian and Noise terms, ## calling them myhamiltonian and mynoise.

nspins = 6

## Then using whichever metric you like, decide what elements ## are connected and add them to a set, something like: myconnectivity = set() for ii in range(nspins):

for jj in range(ii + 1, nspins):
if np.abs(jj - ii) <= 3:

myconnectivity.add((ii, jj))

## Initiate the FactorMethod: myfactor = raqet_py.factor.FactorMethod()

## Set the Hamiltonian: myfactor.set_hamiltonian(myhamiltonian)

## Set the noise: myfactor.set_noise(mynoise)

## Set the connectivity information myfactor.set_connectivity(myconnectivity)

## Set the maximum operator size (optional). If you are ## learning how to use raqet, 3 is a good choice for speed. myfactor.set_maximum_operator_size(3)

## Then we compute the equations of motion (EOMs), ## this is where the factoring happens. myfactor.compute_EOMs()

## You can then look at your equations of motion using:

linear_EOM = myfactor.linear_EOM() nonlinear_EOM = myfactor.nonlinear_EOM()

## For the linear and nonlinear parts of the EOMs respectively. ```

compute_EOMs()

This routine computes the equations of motion in FactorMethod

Given some initial set of observables to compute, compute_EOMs computes the equations of motion of every observable listed. Once completed, it takes note of all new operators it observed and runs again. It will keep doing this in a greedy fashion until it returns an output with no new operators. This ensures that only the operators that are strictly needed are computed. If no initial operators are provided, it will compute the EOMs of the 3N observables corresponding to the ⟨X⟩, ⟨Y⟩ and ⟨Z⟩ observables of the N spins.

# Raises:

  • ValueError: If the connectivity information is

    not found or an unknown error occurs.

estimate_operator_count()

Estimates the number of operators given the connectivity and maximum operator size

# Returns:

  • int: The estimated number of operators.

generate_two_time_correlation_density_matrices(operator, density_matrix=None)

Two-time correlation helper function

To compute the correlator of ⟨A(t)B(0)⟩, we use the quantum regression trick, where instead of time propagating the density matrix ρ, we propagate B ρ which is not a valid density in general. If your solver is purely linear, one can time-evolve this without issue. However, for the factoring method, we require to have physical density matrices else the method can diverge. Therefore we have written this function to help. This function takes in an operator and initial density matrix as input and returns two density matrices and a scalar such that the total time- evolution is given by:

⟨A(t)B(0)⟩ = k ( ⟨A(t)⟩₁ + i ⟨A(t)⟩₂ ),

where k is the scalar and ⟨A(t)⟩₁ and ⟨A(t)⟩₂ denote the time- dependent expectation values of A after evolving the first and second density matrices respectively.

Here we assume that the steady state solution is the fully-mixed density matrix. Providing solutions for other steady states may be available in the future but will require more investigative work.

Note, due to normalization requirements, neither the operator nor the density matrix provided are allowed to have symbolic values as we cannot determine their magnitudes normalization.

Furthermore, the operator values themselves may be quite small, this is because computation of the eigenvalues requires forming the full matrix, instead we make an over-eager estimate of the largest possible eigenvalue and normalize using that.

# Arguments

PauliOperatorWrapper - The operator to be correlated. PauliOperatorWrapper - The density matrix to be correlated.

# Returns

(PauliOperatorWrapper, PauliOperatorWrapper, f64) - The two operators to

be evaluated and their scalar prefix.

get_initial_observables_from_array()

Helper function to set the initial configuration for time evolution.

For a completely general factorization, the solver requires at least the 3N values corresponding to the ⟨X⟩, ⟨Y⟩ and ⟨Z⟩ expectation values of the N spins used in the simulation, represented as a list of lists (N × 3). Each element must be between -1 and 1 and the sum of the squares of the ⟨X⟩, ⟨Y⟩, ⟨Z⟩ components must be less than or equal to unity (with unity being a so-called pure state).

This will generate the initial expectation values for all higher order operators assuming that the initial state is factored, i.e. operators of the form ⟨1X2Y⟩ will be formed from the values of ⟨1X⟩ and ⟨2Y⟩ by ⟨1X2Y⟩ = ⟨1X⟩⟨2Y⟩.

# Arguments:

  • observables (List[List[float]]):

    List containing observables. Should be N×3.

# Returns:

  • List[float]: A list of all observables in the same

    order as operator_index_mapping

# Raises:

  • ValueError: When the columns, rows, observables

    or sum of squares of observables violates the conditions given in the docstring (need to work on translating the more informative rust errors to Python).

linear_EOM()

This routine returns the linear parts of the equations of motion computed during evaluation

neighbours()

Returns dictionary of the neighbours of each site in the system

# Returns:

  • Dict[int, List[int]]: The dictionary containing

    the neighbour lists of each of the sites.

nonlinear_EOM()

This routine returns the factored equations of motion

# Returns:

  • Dict[str, ExpectOperator]: A dictionary containing

    the key-value pairs of operators and their factorizations. Strings must follow struqture convention.

operator_index_mapping()

Returns the mapping between the operator and the indices.

# Returns:

  • mapping (Dict[str, int]): Dictionary which contains

    the mapping between the operators (str) and their positions in the ordered vectors for time evolution. Strings must follow struqture convention.

# Raises:

  • Error: If the Python interpreter fails to properly

    interface with rust (should be never).

return_all_cliques()

Returns all cliques corresponding to the connectivity and maximum operator size

# Returns:

  • List[List[int]]: A list containing all of the cliques.

return_all_operators()

Returns all operators that correspond to the cliques in return_all_cliques.

# Returns:

  • List[String]: A list containing all of the operators.

return_coo_indices(calc_dict=None)

Returns the COO representation of the linear parts of the equations of motion.

This function will output the linear part of the equations of motion in sparse COO form. This allows generation of a sparse matrix in Python which results in rapid speed-up for the linear terms. If using truncate mode this method is highly recommended. If using Ursell mode, or any other nonlinear mode, one should combine the outputs of this function with the return values from return_nonlinear_derivative to obtain optimal speed-up.

# Arguments:

  • calculator (Optional[Dict[str, float]]):

    A optional dictionary containing the values for the symbolic strings used as variables. If no symbolic variables are used, this is not needed.

# Returns:

  • derivatives (List[float]): The list of derivatives

    in order provided by

    operator_index_mapping

return_derivative(values, calc_dict=None)

Computes (total) derivatives from list of expectation values

# Arguments:

  • observables (List[float]): List of observables in

    the order provided by

    operator_index_mapping

  • calculator (Optional[Dict[str, float]]):

    A optional dictionary containing the values for the symbolic strings used as variables. If no symbolic variables are used, this is not needed.

# Returns:

  • derivatives (List[float]): The list of derivatives

    in order provided by

    operator_index_mapping

return_nonlinear_derivative(values, calc_dict=None)

Computes nonlinear parts of derivatives from list of expectation values

# Arguments:

  • observables (List[float]): List of observables in

    the order provided by

    operator_index_mapping

  • calculator (Optional[Dict[str, float]]):

    A optional dictionary containing the values for the symbolic strings used as variables. If no symbolic variables are used, this is not needed.

# Returns:

  • derivatives (List[float]): The list of derivatives

    in order provided by

    operator_index_mapping

set_clusters()

Set connectivity information using clusters instead of pairs.

Instead of providing pair-wise information, the user can provide desired clusters manually. This may be useful when you don't know exactly how to formulate the connections to gain the right cliques but you know that sections are good or you definitely want a given clique.

# Examples:

``` python ## Initialize factoring method myfactor = raqet_py.factor.FactorMethod()

## Insert Hamiltonian, Noise etc.

## Create new cluster set: clusters = [[0, 1, 4], [1, 2, 3], [3, 4]]

myfactor.set_clusters(cluster) ```

# Arguments:

  • clusters: A list of lists comprising all the desired clusters.

set_connectivity()

Sets the connectivity information.

Instead of providing spatial information, the user can provide the pair-wise connectivity information manually. This may be useful when a metric other than spatial proximity is used for closeness such as chemical bonding or resistance distance. Pairs must be given as a set of ordered tuples (i, j), where j > i. A list of neighbours of each site will also be generated to aid in the factoring routine and need not be provided explicitly.

# Examples:

``` python ## Initialize factoring method myfactor = raqet_py.factor.FactorMethod()

## Insert Hamiltonian, Noise etc. nspin = 5

## Create new connectivity set: connectivity = set()

## Fill it: for ii in range(nspin):

for jj in range(ii + 1, nspin):
if (jj - ii) <= 3:

connectivity.add((ii, jj)) # Add as a tuple

myfactor.set_connectivity(connectivity) ```

# Arguments:

  • pairs: The set of unique pairs (i, j), j > i.

set_factor_type()

Sets the factorization type.

Two modes, Ursell, the standard factorizing mode and Truncate which discards operators if they do not fit.

# Examples:

` python ## TODO `

# Arguments:

  • factor_type: The string containing the

    mode, either "Ursell" or "Truncate".

set_hamiltonian()

Set the Hamiltonian

This sets the Hamiltonian to be used in the following factorization.

# Arguments:

  • hamiltonian (PauliHamiltonian):

    Hamiltonian to be included in factorization.

set_maximum_operator_size()

Sets the maximum cluster to be used in the factorization

# Arguments:

  • maximum_operator_size (int):

    The maximum operator (size) to be allowed.

set_noise()

Set the noise

This function sets the Lindblad terms to be used in the factorization.

We do not use a combined SpinLindbladOpenSystem definition due to present limitations in struqture.

# Arguments:

  • noise (PauliLindbladNoiseOperator):

    Lindblad terms to be included in factorization.

set_operator_heap()

Sets the operator heap.

Raqet takes in a list of operators for which time- tracking is desired, then solves their equations of motion. After which it appends all new operators found and repeats the process in a greedy fashion until no more new operators are found. By solving them in this way, we track the minimum nunber of operators are required for the desired operators.

# Examples:

` python ## TODO `

# Arguments:

  • operator_heap: The set of operators to be

    tracked written in struqture string form e.g. "1X3Y34Z".

set_spatial_info()

Sets the positions and the radius to be used in the factoring method

The positions and the radius can be used to automatically deduce connectivity. Note that these are not required fields, but can be useful for the aforementioned behaviour. If they are not provided, the connectivity information must be provided elsewhere. The positions will be checked to make sure they have commensurate dimensions.

# Arguments:

  • positions (List[List[float]]): Spatial positions

  • radius (float): radius to determine connectedness

# Raises:

  • ValueError: The dimensions are incommensurate,

    the radius is unphysical or an unknown error occurred.