pypsqueak package

pypsqueak.api module

Front end of pypSQUEAK. Contains definitions of qReg, qOp, and qOracle classes which provide abstract representations of quantum hardware.

class pypsqueak.api.qOp(matrix_rep=[[1, 0], [0, 1]], kraus_ops=None)

Bases: object

A qOp is a high-level primitive which provides users with a representation of a quantum gate. In this implementation, the hardware of the gate is simulated with a pypsqueak.squeakcore.Gate object. Like the underlying Gate, a qOp is a unitary operation. When instantiated with no arguments, the resulting qOp is the identity. Other operations can be represented by using a matrix representation of the operator as a creation argument. Additionally, noise can be modeled by providing a set of Kraus operators that characterizes said noise in the form of a pypsqueak.noise.NoiseModel object.

Examples

Here we demonstrate how to define the Pauli spin operators:

>>> from pypsqueak.api import qOp
>>> p_x = qOp([[0, 1], [1, 0]])
>>> p_y = qOp([[0, -1j], [1j, 0]])
>>> p_z = qOp([[1, 0], [0, -1]])

The multiplication operator is overloaded to implement matrix multiplication:

>>> p_x * p_x
[[1 0]
 [0 1]]
>>> p_y * p_y
[[1 0]
 [0 1]]
>>> iden = p_z * p_z
>>> iden
[[1 0]
 [0 1]]
>>> p_x * p_y * p_z
[[0.-1.j 0.+0.j]
 [0.+0.j 0.-1.j]]

qOp instances are applied to qReg objects via the qOp.on() method:

>>> from pypsqueak.api import qReg
>>> q = qReg()
>>> q.peek()
'(1.00e+00)|0>'
>>> p_x.on(q)
>>> q.peek()
'(1.00e+00)|1>'

We can define a function with return type qOp to implement parameterized gates:

>>> import numpy as np
>>> def rot_x(theta):
...     m_rep = [[np.cos(theta/2), -1j * np.sin(theta/2)],
...              [-1j * np.sin(theta/2), np.cos(theta/2)]]
...     return qOp(m_rep)
...
>>> q = qReg()
>>> rot_x(np.pi).on(q)
>>> q.peek()
'(6.12e-17+0.00e+00j)|0> + (0.00e+00-1.00e+00j)|1>'
dagger()

Returns the Hermitian conjugate of the qOp. This is equivalent to the transpose conjugate of the matrix representation.

Returns:The Hermitian conjugate of the operator.
Return type:pypsqueak.api.qOp
kron(another_op, *more_ops)

Returns the tensor product (implemented as a matrix Kronecker product) of self (x) another_op. Optionally continues to tensor-in additional ops in more_ops. Ignores noise model set on any of the factors.

Parameters:
Returns:

Kronecker product.

Return type:

pypsqueak.api.qOp

Examples

Here we build the identity operator acting on three qubits:

>>> from pypsqueak.api import qOp
>>> iden_3 = qOp().kron(qOp(), qOp())
>>> iden_3
[[1 0 0 0 0 0 0 0]
 [0 1 0 0 0 0 0 0]
 [0 0 1 0 0 0 0 0]
 [0 0 0 1 0 0 0 0]
 [0 0 0 0 1 0 0 0]
 [0 0 0 0 0 1 0 0]
 [0 0 0 0 0 0 1 0]
 [0 0 0 0 0 0 0 1]]

Less trivially, let’s make the operator applying an X gate to the first qubit and the identity operator to the zeroeth qubit:

>>> from pypsqueak.gates import X
>>> X.kron(qOp())
[[0 0 1 0]
 [0 0 0 1]
 [1 0 0 0]
 [0 1 0 0]]
on(q_reg, *targets)

Applies a qOp to a qReg. If the size of the qOp agrees with the size of the qReg, no target qubits are required. If the qOp is smaller than the qReg, the qOp is lifted to the higher-dimensional Hilbert space of the qReg. In that case, n target qubits must be, specified, where n is the size of the qOp before lifting. If the size of the qOp is larger than the size of the qReg, an exception is raised.

When the size of the qOp is smaller than the size of the qReg, the targets specify how to order the qubits in the qReg before application of the lifted operator (that is, the tensor product I^n (x) qOp, where n is the length of the qReg minus the size of the qOp). From left to right, the qubits named in the targets are swapped with the qubits at addresses zero, one, two, etc. All remaining qubits get bumped up to the next highest available register addresses which were NOT involved in the swap. After operation with the lifted qOp, the qReg is permuted back to its original ordering.

As an example, if a qReg is in the state |abcdef> and and qOp.on() is called with with targets = [3, 0, 4, 1], then the qReg is permuted to |adebfc> before application of the qOp.

If the size of the qOp and qReg match, then calling qOp.on() with no targets skips permutation of the register before applying the operator.

Parameters:
  • q_reg (pypsqueak.api.qReg) – The register to apply the operation to.
  • *targets (int) – A list of locations in the register. The corresponding qubits are permuted to the lowest positions in the register before application of the operator. Must be nonnegative.
Returns:

This method only has the side effect of applying the qOp to a qReg.

Return type:

None

Examples

Here we apply a controlled NOT gate to the state |01> both with and without specifying targets:

>>> from pypsqueak.api import qReg, qOp
>>> from pypsqueak.gates import X, CNOT
>>> q = qReg()
>>> X.on(q)
>>> q += 1
>>> q.peek()
'(1.00e+00)|01>'
>>> CNOT.on(q)
>>> q.peek()
'(1.00e+00)|01>'
>>> CNOT.on(q, 0, 1)
'(1.00e+00)|01>'
>>> CNOT.on(q, 1, 0)
>>> q.peek()
'(1.00e+00)|11>'

Since the controlled NOT is a two-qubit gate, an exception is raised when we call it with only one target:

>>> CNOT.on(q, 1)
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "pypsqueak/api.py", line 763, in on
pypsqueak.errors.WrongShapeError: Number of registers must match number
of qubits gate operates on.
set_noise_model(kraus_ops)

Changes the NoiseModel on the qOp to that specified by kraus_ops, Each of the elements of the NoiseModel has the same dimensions (matching the qOp) and they are collectively trace-preserving.

By defualt kraus_ops = None. The qOp is then noiselessly emulated. That this method would be absent/do nothing for a hardware implementation of the backend.

Parameters:kraus_ops (NoiseModel or None) – A NoiseModel instance. Each element of the NoiseModel is an operation element in a generalized quantum operation. If None, no noise is emulated.

Examples

If we want to model a noisy single-qubit channel, we can instantiate an identity operator with the corresponding noise. Let’s make a channel exhibiting a bit flip noise with probability 0.5 of a flip, and then send a qubit in the |0> state through it 1000 times:

>>> from pypsqueak.api import qReg, qOp
>>> from pypsqueak.noise import b_flip_map
>>> noisy_channel = qOp(kraus_ops=b_flip_map(0.5))
>>> noisy_channel
[[1 0]
 [0 1]]
>>> send_results = []
>>> for i in range(1000):
...      q = qReg()
...      noisy_channel.on(q)
...      send_results.append(q.measure(0))
...
>>> n_zeros = 0
>>> n_ones = 0
>>> for result in send_results:
...     if result == 0:
...             n_zeros += 1
...     else:
...             n_ones += 1
...
>>> n_zeros/1000
0.512
>>> n_ones/1000
0.488

To turn off noisy modeling, just call qOp.set_noise_model(None).

shape()

Returns the dimensions of the matrix representation of the qOp.

Returns:The shape of the matrix representation of the qOp.
Return type:tuple
size()

Returns the number of qubits that the qOp acts on. This is log base two of the dimensions of the corresponding matrix representation.

Returns:The size of the qOp.
Return type:int
class pypsqueak.api.qOracle(func, n, m=1, kraus_ops=None)

Bases: pypsqueak.api.q_op.qOp

Subclass of qOp. Useful for representing quantum black-boxes, such as that appearing in the Deutsch-Jozsa algorithm.

qOracle implements a unitary transformation U_f|x>|y> = |x>|y XOR f(x)> where the classical function f maps nonnegative integers to nonnegative integers. The XOR is performed bitwise on the computational basis label y and f(x). This reduces to mod 2 addition when y and f(x) are both one bit long. n specifies the number of qubits in the left side portion of the quantum register, while m specifies the number of qubits in the right side portion.

classical_func(x_val)

Returns the classical value of the function implemented by the qOracle. Raises an exception if the argument isn’t nonnegative or if larger than the n portion of the intended register.

Parameters:x_val (int) – Argument of function.
Returns:Value of the function.
Return type:int

Examples

>>> from pypsqueak.api import qOracle
>>> black_box = qOracle(lambda x: 0, 2)
>>> black_box.classical_func(1)
0
>> black_box.classical_func(3)
0
>> black_box.classical_func(3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "pypsqueak/api.py", line 1065, in classical_func
    raise ValueError("Classical function input out of bounds.")
ValueError: Classical function input out of bounds.
class pypsqueak.api.qReg(n_qubits=1)

Bases: object

A qReg is a high-level primitive which provides users with a representation of a quantum register. In this implementation, the quantum device on which the register exists is simulated via a pypsqueak.squeakcore.Qubit object. Like the underlying Qubit, a qReg is initialized in the |0> state.

Per the no-cloning theorem, any attempt to copy a qReg object will throw an exception. Additionally, operations which would otherwise leave duplicates of a specific instance of a qReg lying around ‘dereference’ the register. Once a qReg is dereferenced, any attempt to interact with the qReg will throw an exception.

Since this implementation uses simulated quantum hardware, methods for examining the quantum state as a Dirac ket and returning the state as a numpy array are provided. They are qReg.peek() and qReg.dump_state(), respectively.

Examples

Here we demonstrate three ways to initialize a qReg with 3 qubits.

>>> from pypsqueak.api import qReg, qOp
>>> a = qReg(3)
>>> b = qReg()
>>> b += 2
>>> c = qReg()
>>> identity_op = qOp()
>>> identity_op.on(c, 2)
>>> a == b
False
>>> a.dump_state() == b.dump_state()
array([ True,  True,  True,  True,  True,  True,  True,  True])
>>> a.dump_state() == c.dump_state()
array([ True,  True,  True,  True,  True,  True,  True,  True])
>>> a.peek()
'(1.00e+00)|000>'

Note that different instances of a qReg are considered unequal even if the underlying state is the same. Additionally, when qOp.on() is applied to a target in a qReg that is outside the range of the register, new filler qubits are automatically initialzed in the zero state.

Now we demonstrate which operators are overloaded for qReg objects as well as their behavior. We can append any number of qubits to a qReg like so:

>>> from pypsqueak.gates import X
>>> a = qReg(1)
>>> X.on(a, 1)
>>> a += 3
>>> a.peek()
'(1.00e+00)|00010>'

Two registers can be joined into one via the tensor product. This can be done in place:

>>> a *= qReg(2)
>>> a.peek()
'(1.00e+00)|0001000>'

A new qReg can be created similarly:

>>> a = qReg()
>>> X.on(a, 0)
>>> b = qReg()
>>> c = a * b
>>> c
qReg(2)
>>> c.peek()
'(1.00e+00)|10>'
>>> a
Dereferenced qReg
>>> a.peek()
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "pypsqueak/api.py", line 199, in peek

pypsqueak.errors.IllegalRegisterReference: Dereferenced register encountered.

Notice that taking the product of qReg objects dereferences any operands.

dump_state()

Returns a copy of the state of a qReg as a numpy array. Would have no effect on a hardware implementation of the backend. If the register has been dereferenced, raises an exception.

Returns:The state of qReg as a vector in the computational basis. Has no side effects.
Return type:numpy.ndarray

Examples

Here we get a vector corresponding to the Hadamard state:

>>> from pypsqueak.api import qReg
>>> from pypsqueak.gates import H
>>> a = qReg(3)
>>> H.on(a, 0)
>>> a.dump_state()
array([0.70710678, 0.70710678, 0.        , 0.        , 0.        ,
       0.        , 0.        , 0.        ])

Now we dereference the qReg and run into an exception when we try to dump its state again:

>>> a * qReg()
qReg(4)
>>> a.dump_state()
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "pypsqueak/api.py", line 342, in dump_state
    exception.
pypsqueak.errors.IllegalRegisterReference: Dereferenced register
encountered.
measure(target)

Performs a projective measurement on the qubit at the address target. In this simulated implementation, there are three steps:

  1. Compute probability of each measurement using the amplitudes of each basis vector in the computational basis decomposition.
  2. Use these probabilities to randomly pick a measurement result.
  3. Project the qReg state onto the result’s corresponding eigenspace.
Parameters:target (int) – The index of the qubit in the qReg to measure. An exception gets thrown if the value is negative or out of range.
Returns:Either a one or a zero, depending on the result of the measurement. The state of the qReg is projected onto the corresponding subspace.
Return type:int

Examples

Here we prepare the Bell state and then measure qubit one in the qReg.

>>> from pypsqueak.api import qReg
>>> from pypsqueak.gates import CNOT, H
>>> a = qReg()
>>> H.on(a, 0)
>>> CNOT.on(a, 1, 0)
>>> a.peek()
'(7.07e-01)|00> + (7.07e-01)|11>'
>>> a.measure(1)
1
>>> a.peek()
'(1.00e+00)|11>'
measure_observable(observable)

Performs a projective measurement of the observable corresponding to a qOp.

Parameters:observable (pypsqueak.api.qOp) – The qOp corresponding to some observable to measure. An exception gets thrown if its size larger than the size of the qReg.
Returns:One of the eigenvalues of observable. The state of the qReg is projected onto the corresponding subspace.
Return type:int

Examples

When the size of the operator is smaller than the qReg, the the operator is prepended with identity operators.

>>> from pypsqueak.api import qReg, qOp
>>> from pypsqueak.gates import X
>>> a = qReg(3)
>>> X.on(a, 0)
>>> a.peek()
'(1.00e+00)|001>'
>>> print(a.measure_observable(X))
-1.0
>>> a.peek()
'(-7.07e-01)|000> + (7.07e-01)|001>'
peek()

Returns a ket description of the state of a qReg. Would have no effect on hardware implementations of the backend. If the register has been dereferenced, raises an exception.

Returns:Description of qReg state. Has no side effects.
Return type:str

Examples

Here we peek at a register in the Hadamard state:

>>> from pypsqueak.api import qReg
>>> from pypsqueak.gates import H
>>> a = qReg(3)
>>> H.on(a, 0)
>>> a.peek()
'(7.07e-01)|000> + (7.07e-01)|001>'

After dereferencing the register via a multiplication, calling peek() raises an exception:

>>> a * qReg()
qReg(4)
>>> a.peek()
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "pypsqueak/api.py", line 309, in peek
        raise IllegalRegisterReference('Dereferenced register '
                                             'encountered.')
pypsqueak.errors.IllegalRegisterReference: Dereferenced register
encountered.

pypsqueak.errors module

exception pypsqueak.errors.IllegalCopyAttempt

Bases: NotImplementedError

Raised when a qReg is copied.

exception pypsqueak.errors.IllegalRegisterReference

Bases: NameError

Raised when any kind of operation is attempted on a killed qReg.

exception pypsqueak.errors.NonUnitaryInputError

Bases: ValueError

Raised wherever a non-unitary matrix is encountered and a unitary matrix is expected.

exception pypsqueak.errors.NormalizationError

Bases: ValueError

Raised when the normalization of a Qubit is broken.

exception pypsqueak.errors.NullVectorError

Bases: ValueError

Raised when trying to initialize a Qubit with the null vector.

exception pypsqueak.errors.WrongShapeError

Bases: ValueError

Generally raised when trying to initialize a Qubit or Gate with an improper shape.

pypsqueak.gates module

Static gates

Pre-defined qOp objects are provided implementing the common static gates X, Y, Z, I, H, S (phase), and T (pi/8).

Parametric gates

Common parametric gates (such as rotation operators) are implemented here as functions returning a qOp object.

pypsqueak.gates.PHASE(theta=0)
pypsqueak.gates.ROT_X(theta=0)
pypsqueak.gates.ROT_Y(theta=0)
pypsqueak.gates.ROT_Z(theta=0)

pypsqueak.noise module

Implements functions returning sets of trace-one Kraus operators. Each function corresponds to a specific kind of one-qubit noise. For an example of usage, see set_noise_model().

class pypsqueak.noise.NoiseModel(kraus_ops=None)

Bases: object

A map characterizing a kind of noise to be simulated in a qOp. Takes a list of numpy ndarrays as creation argument, or argument to NoiseModel.setKrausOperators(). The elemnts of the list must all have the same dimension, and collectively be trace-preserving.

getKrausOperators()
setKrausOperators(listOfKrausOperators)
shape()
pypsqueak.noise.b_flip_map(prob=0.1)

Bit flip.

Parameters:prob (numeric, between 0 and 1) – Probability characterizing the likelihood of the outcomes represented by the various Kraus operators.
Returns:Container of ndarray matrix representations of the Kraus operators in the corresponding quantum operation.
Return type:NoiseModel
pypsqueak.noise.bp_flip_map(prob=0.1)

Bit-phase flip.

Parameters:prob (numeric, between 0 and 1) – Probability characterizing the likelihood of the outcomes represented by the various Kraus operators.
Returns:Container of ndarray matrix representations of the Kraus operators in the corresponding quantum operation.
Return type:NoiseModel
pypsqueak.noise.damping_map(prob=0.1)

Amplitude damping.

Parameters:prob (numeric, between 0 and 1) – Probability characterizing the likelihood of the outcomes represented by the various Kraus operators.
Returns:Container of ndarray matrix representations of the Kraus operators in the corresponding quantum operation.
Return type:NoiseModel
pypsqueak.noise.depolarization_map(prob=0.1)

Depolarizing channel.

Parameters:prob (numeric, between 0 and 1) – Probability characterizing the likelihood of the outcomes represented by the various Kraus operators.
Returns:Container of ndarray matrix representations of the Kraus operators in the corresponding quantum operation.
Return type:NoiseModel
pypsqueak.noise.p_flip_map(prob=0.1)

Phase flip.

Parameters:prob (numeric, between 0 and 1) – Probability characterizing the likelihood of the outcomes represented by the various Kraus operators.
Returns:Container of ndarray matrix representations of the Kraus operators in the corresponding quantum operation.
Return type:NoiseModel
pypsqueak.noise.phase_map(prob=0.1)

Phase damping.

Parameters:prob (numeric, between 0 and 1) – Probability characterizing the likelihood of the outcomes represented by the various Kraus operators.
Returns:Container of ndarray matrix representations of the Kraus operators in the corresponding quantum operation.
Return type:NoiseModel

pypsqueak.squeakcore module

Provides core Qubit and Gate objects that function as the simulated backend of pypSQUEAK.

class pypsqueak.squeakcore.Gate(some_matrix=[(1, 0), (0, 1)], name=None)

Bases: object

A Gate is a variable-sized (shape is a tuple of powers of two), unitary matrix. Its state (returned by state()) is a two-dimensional numpy array consisting of the computational basis representation of the quantum gate. By default it is initialized to the one qubit identity gate, but this can be overridden if the Gate is instantiated with some other numeric matrix as argument. If the matrix argument is not unitary, the Gate will fail to initialize. Additionally, the gate can be given a name via the corresponding kwarg. If not provided, defaults to None.

Note that len(some_gate) returns the number of qubits that some_gate acts on (log2(some_gate.shape()[0]))

Examples

>>> from pypsqueak.squeakcore import Gate
>>> g1 = Gate()
>>> g1
[[1 0]
 [0 1]]
>>> g1.state()
array([[1, 0],
       [0, 1]])
>>> g2 = Gate([(0, 1), (1, 0)])
>>> g2
[[0 1]
 [1 0]]
>>> g3 = Gate(np.eye(4))
>>> g3
[[1. 0. 0. 0.]
 [0. 1. 0. 0.]
 [0. 0. 1. 0.]
 [0. 0. 0. 1.]]
>>> (len(g2), len(g3))
(1, 2)
>>> not_unitary = Gate([(0, 0), (1, 1)])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
pypsqueak.errors.NonUnitaryInputError: Gate must be unitary.
gate_product(*gates)

Method for returning the Kronecker product of a gate with one or more other gates. When multiple arguments are specified, the product is computed sequentially from left to right.

Note that this method does NOT have side-effects; it simply returns the product as a new Gate object.

Returns the Kronecker product of a Gate with one or more other Gate instances.

When multiple arguments are specified, the product is computed sequentially from the leftmost argument to the rightmost.

Parameters:*gates (pypsqueak.squeakcore.Gate) – One or more Gate objects. Raises an exception if called with no arguments.
Returns:The left to right Kronecker product.
Return type:pypsqueak.squeakcore.Gate

Examples

>>> from pypsqueak.squeakcore import Gate
>>> g1 = Gate()
>>> g2 = Gate([[0, 1], [1, 0]])
>>> g1_g2 = g1.gate_product(g2)
>>> g1_g2
[[0 1 0 0]
 [1 0 0 0]
 [0 0 0 1]
 [0 0 1 0]]
>>> g2_g1 = g2.gate_product(g1)
>>> g2_g1
[[0 0 1 0]
 [0 0 0 1]
 [1 0 0 0]
 [0 1 0 0]]
name()
Returns:The name of the Gate.
Return type:arbitrary
shape()

Tuple of the Gate’s shape. Equivalent to (2**len(some_gate),) * 2.

Returns:A copy of the Gate’s shape.
Return type:tuple
state()

The state of the Gate as an ndarray.

Returns:A copy of the Gate’s state.
Return type:numpy.ndarray
class pypsqueak.squeakcore.Qubit(init_state=[1, 0])

Bases: object

A Qubit is a variable-sized (length can be powers of two), normalized, complex vector. Its state (returned by state()) is a one-dimensional numpy array consisting of the computational basis representation of the quantum state. By default it is initialized in the |0> state, but this can be overridden if a Qubit is instantiated with some other numeric vector as argument (the resulting Qubit will use the normalized version of that vector).

The state a Qubit can be changed with a call to Qubit.change_state(). Additionally, a dictionary with computational basis state labels as keys and corresponding components as values gets returned by Qubit.computational_decomp().

Note that the length of a Qubit is the number of qubits that the state vector corresponds to (log2(len(state_vector))).

Examples

Here we initialize a Qubit in the |0> state, and then change it to the |11> state.

>>> from pypsqueak.squeakcore import Qubit
>>> q = Qubit()
>>> p = Qubit([0, 1, 0, 0])
>>> q
[1. 0.]
>>> print(q)
(1.00e+00)|0> + (0.00e+00)|0>
>>> print(p)
(0.00e+00)|00> + (1.00e+00)|01> + (0.00e+00)|10> +(0.00e+00)|11>
>>> q.change_state([0, 0, 0, 1])
>>> print(q)
(0.00e+00)|00> + (0.00e+00)|01> + (0.00e+00)|10> + (1.00e+00)|11>
change_state(new_state)

Changes the state of the Qubit to the normalized vector corresponding to the argument.

Parameters:new_state (list-like) – The vector representation of the new state in the computational basis. Must have a length which is a power of two.
Returns:The Qubit instance on which change_state() is called is altered.
Return type:None
computational_decomp()

A representation of the Qubit’s state via a dict. Computational basis labels are the keys and the components of the Qubit are the values. Note that the basis state labels (i.e. the keys) are big-endian.

Returns:A computational basis representation of the Qubit.
Return type:dict
qubit_product(*arg)

Returns the Kronecker product of a Qubit with one or more other Qubit objects.

When multiple arguments are specified, the product is computed sequentially from the leftmost argument to the rightmost.

Parameters:*arg (pypsqueak.squeakcore.Qubit) – One or more Qubit objects. Raises an exception if called with no arguments.
Returns:The left to right Kronecker product.
Return type:pypsqueak.squeakcore.Qubit

Examples

>>> from pypsqueak.squeakcore import Qubit
>>> q1 = Qubit()
>>> q2 = Qubit([0, 1])
>>> q3 = Qubit([1, 0, 0, 0])
>>> q1_q2 = q1.qubit_product(q2)
>>> q1_q2
[1. 0.]
>>> q1_q2.state()
array([0., 1., 0., 0.])
>>> q2_q1 = q2.qubit_product(q1)
>>> q2_q1
[0. 0. 1. 0.]
>>> q1_q2_q3 = q1.qubit_product(q2, q3)
>>> q1_q2_q3
[0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
state()

The state of the Qubit as an ndarray.

Returns:A copy of the Qubit’s state.
Return type:numpy.ndarray