-
Notifications
You must be signed in to change notification settings - Fork 3
Low Level Data Structures
The most basic data structures available in QSimov are QRegistry and QSystem. They are only available for simulators following Doki's API. Both of them inherit from the QStructure abstract class, and they provide access to almost the same functionality.
The main difference between QRegistry and QSystem is that the first considers all qubits to be potentially entangled (exponential memory cost), while the latter considers them unentangled until after using multiple-qubit gates that can potentially entangle them (from linear up to exponential memory cost).
A list of the available constructor and methods when using a QStructure is written here:
- QStructure(Integer num_qubits, Module doki=None, Boolean verbose=False)
- num_qubits: Number of qubits available in this structure. Can't be changed
- doki (optional): Python module following Doki's API to use. None -> import doki. Defaults to None
- verbose (optional): Whether to enable Doki's debug messages or not. Defaults to False
You cannot directly instantiate a QStructure!
Usage samples:
- QRegistry(3) # This creates a QRegistry with 3 available qubits
- QSystem(1000) # This creates a QSystem with 1000 available qubits
- Integer get_num_qubits()
- return -> Number of qubits available in the quantum system
- QStructure apply_gate(QuantumGate gate, List<Integer> targets=None, Set<Integer> controls=None, Set<Integer> anticontrols=None, Integer num_threads=-1)
- gate: can be a String, a SimpleGate or a QGate. The gate to be applied to the specified qubit
- targets (optional): The id or a list of ids of the qubits the gate will be applied to (on multiple qubit gates the order in which they appear may alter the results). Defaults to None -> Uses the less significant qubits available
- controls (optional): The id or a set of ids of the qubits that will be used as controls when applying the gate. Classically speaking, the gate will be applied to the targets iff all the control bits have a value of 1. Defaults to None -> No control qubits
- anticontrols (optional): The id or a set of ids of the qubits that will be used as anti-controls when applying the gate. Classically speaking, the gate will be applied to the targets iff all the anti-control bits have a value of 0. Defaults to None -> No anti-control qubits
- num_threads: Number of threads to use (>= 1) or -1 (let OpenMP decide). Defaults to -1
- return -> QStructure resultant of applying the gate to the previous QStructure
- List<Boolean> measure(Set<Integer> ids, Producer<Real> random_generator=numpy.random.rand)
- ids: The set of ids of the qubits to be measured
- random_generator (optional): Function that receives no arguments and returns a float number in [0, 1). Defaults to numpy.random.rand
- return -> Tuple with two elements:
- QStructure resultant of measuring the specified qubits in the previous QStructure
- List of the same size as the number of qubits in the original QStructure. The result of measuring the ith qubit is stored in the ith position of the list if said qubit has been measured. Otherwise None would be found in that position
- Real prob(Integer id)
- id: The id of a qubit in the QStructure
- return -> The chance of getting 1 when measuring the specified qubit
- NumpyArray<Complex> get_state(key=None, canonical=False) # DO NOT USE FOR ANYTHING OTHER THAN DEBUG PURPOSES
- key: an Integer or a Python Slice
- canonical: whether to extract the hidden phase from the state vector or not before returning its values. Defaults to False
- return -> Numpy Array containing the specified (key) probability amplitudes of the system's state vector
- Integer get_state_size()
- return -> Number of probability amplitudes stored in the QStructure. For a QRegistry it will always be 2^num_qubits. For a QSystem it might vary depending on the number of qubits potentially entangled, from 2 x num_qubits to 2^num_qubits
- Boolean get_classic(Integer id)
- id: The id of a qubit in the QStructure
- return -> Value of a qubit that has previously been measured (only for QRegistry). If the qubit is in a coherent state, this returns None
- QStructure clone(Integer num_threads=-1 xor Boolean deep=False)
- num_threads (only for QRegistry): Number of threads to use (>= 1) or -1 (let OpenMP decide). Defaults to -1
- deep (only for QSystem): Whether to make a deep copy or not. A deep copy has had all its internal data copied. Defaults to False
- return -> A copy of the current QStructure
- void free() # UNSTABLE FOR QSYSTEMS. FREEING A QSYSTEM CAN MAKE ITS (NOT DEEP) CLONES AND CHILDREN ERROR
- Frees the allocated memory
- Real[2] or List<Real[2]> get_bloch_coords(key=None)
- key: an Integer or a Python Slice. Default to None -> The ids of all the independent qubits in a coherent state
- return -> A pair or a list of pairs of real values, containing the coordinates in the Bloch sphere of the specified qubit ids
- Figure or List<Figure> bloch(key=None)
- key: an Integer or a Python Slice. Default to None -> The ids of all the independent qubits in a coherent state
- return -> A matplotlib.pyplot.figure or a list of matplotlib.pyplot.figure, containing a drawing of the Bloch sphere of the specified qubit ids
The state vector of a QRegistry can also be accessed by using the list access notation [ ].
- FunctionalMatrix density_matrix(canonical=False) # DO NOT USE FOR OTHER THAN DEBUG PURPOSES
- canonical: whether to extract the hidden phase from the state vector or not before returning its values. Defaults to False
- return -> The density matrix of the current state. Freeing the QStructure can cause problems with the values in the matrix
- Real get_entropy(Real base=2) # DO NOT USE FOR OTHER THAN DEBUG PURPOSES
- base (optional): The base to use when calculating logarithms. The string "e" is a valid value. Defaults to 2
- return -> A real number with the Von Neumann entropy of the system
- NumpyArray<Complex> bra() # DO NOT USE FOR OTHER THAN DEBUG PURPOSES
- return -> A vector with the Bra of the state vector
- NumpyArray<Complex> ket() # DO NOT USE FOR OTHER THAN DEBUG PURPOSES
- return -> A column vector with the Ket of the state vector
- QRegistry as_qregistry(num_threads=-1, canonical=False)
- num_threads: Number of threads to use (>= 1) or -1 (let OpenMP decide). Defaults to -1
- canonical: whether to extract the hidden phase from the state vector or not before returning its values. Defaults to False
- return -> A QRegistry representing the same quantum state as the QSystem
- Tuple<Integer> get_split_num_qubits()
- return -> Python tuple that contains the number of qubits in each group of qubits potentially entangled
- Tuple<Integer> get_sizes()
- return -> Python tuple that contains the number of probability amplitudes representing each group of qubits potentially entangled