Download Notebook

State and state_typical

[1]:
import numpy as np
np.set_printoptions(linewidth=200)

State

Quantum state (density matrix) can be represented by a linear combination of basis. vec represents the coefficients of this linear combination in the form of a numpy array.

Example.
\(z_0 = \begin{bmatrix} 1 & 0 \\ 0 & 0 \\ \end{bmatrix}\) can be represented by a linear combination of basis \(1/\sqrt{2} \cdot I/\sqrt{2} + 0 \cdot X/\sqrt{2} + 0 \cdot Y/\sqrt{2} + 1/\sqrt{2} \cdot Z/\sqrt{2}\). In this case vec of \(z_0\) is \([ 1/\sqrt{2}, 0, 0, 1/\sqrt{2} ]\).

The methods for generating a State includes the following:

  • Generate from state_typical module

  • Generate State object directly

Generate from state_typical module by specifying CompositeSystem and state name (ex. “z0”).

[2]:
from quara.objects.composite_system_typical import generate_composite_system
from quara.objects.state_typical import generate_state_from_name

c_sys = generate_composite_system("qubit", 1)
state = generate_state_from_name(c_sys, "z0")
print(state)
Type:
State

Dim:
2

Vec:
[0.70710678 0.         0.         0.70710678]

Generate State object directly using CompositeSystem and a numpy array.

[3]:
from quara.objects.composite_system import CompositeSystem
from quara.objects.elemental_system import ElementalSystem
from quara.objects.matrix_basis import get_normalized_pauli_basis
from quara.objects.state import State

basis = get_normalized_pauli_basis(1)
e_sys = ElementalSystem(0, basis)
c_sys = CompositeSystem([e_sys])
vec = np.array([1, 0, 0, 1]) / np.sqrt(2)
state = State(c_sys, vec)
print(state)
Type:
State

Dim:
2

Vec:
[0.70710678 0.         0.         0.70710678]

specific properties

The property vec of State is a numpy array specified by the constructor argument vec.

[4]:
state = State(c_sys, vec)
print(f"vec: {state.vec}")
vec: [0.70710678 0.         0.         0.70710678]

The property dim of State is a square root of the size of element of vec.

[5]:
print(f"dim: {state.dim}")
print(f"square root of the size of element of vec: {int(np.sqrt(len(vec)))}")
dim: 2
square root of the size of element of vec: 2

functions to check constraints

The is_eq_constraint_satisfied() function returns True, if and only if \(\text{Tr}[\rho] = 1\), where \(\rho\) is a density matrix of State.

[6]:
print(f"is_eq_constraint_satisfied(): {state.is_eq_constraint_satisfied()}")
print(f"trace of density matrix: {np.trace(state.to_density_matrix())}")
is_eq_constraint_satisfied(): True
trace of density matrix: (0.9999999999999998+0j)

The is_ineq_constraint_satisfied() function returns True, if and only if \(\rho\) is positive semidifinite matrix, where \(\rho\) is a density matrix of State.

[7]:
print(f"is_eq_constraint_satisfied(): {state.is_eq_constraint_satisfied()}")
print(f"is_positive_semidefinite(): {state.is_positive_semidefinite()}")
is_eq_constraint_satisfied(): True
is_positive_semidefinite(): True

projection functions

calc_proj_eq_constraint() function calculates the projection of State on equal constraint.
This function replaces the first element of vec with \(1/\sqrt{d}\), where \(d\) is dim.
[8]:
vec = np.array([1.0, 2.0, 3.0, 4.0])
state = State(c_sys, vec, is_physicality_required=False)
proj_state = state.calc_proj_eq_constraint()
print(f"vec: {proj_state.vec}")
vec: [0.70710678 2.         3.         4.        ]

calc_proj_ineq_constraint() function calculates the projection of State on inequal constraint as follows:

  • Executes singular value decomposition on the density matrix \(\rho\) of state, \(\rho = U \Lambda U^{\dagger}\), where \(\Lambda = \text{diag}[\lambda_0, \dots , \lambda_{d-1}]\), and \(\lambda_{i} \in \mathbb{R}\).

  • \(\lambda^{\prime}_{i} := \begin{cases} \lambda_{i} & (\lambda_{i} \geq 0) \\ 0 & (\lambda_{i} < 0) \end{cases}\)

  • \(\Lambda^{\prime} = \text{diag}[\lambda^{\prime}_0, \dots , \lambda^{\prime}_{d-1}]\)

  • \(\rho^{\prime} = U \Lambda^{\prime} U^{\dagger}\)

  • The projection of State is \(|\rho^{\prime} \rangle\rangle\).

[9]:
vec = np.sqrt(2) * np.array([0, 0, 0, 1])
state = State(c_sys, vec, is_physicality_required=False)
print(f"density matrix before projection: \n{state.to_density_matrix()}")
proj_state = state.calc_proj_ineq_constraint()
print(f"density matrix after projection: \n{proj_state.to_density_matrix()}")
print(f"vec after projection: \n{proj_state.vec}")
density matrix before projection:
[[ 1.+0.j  0.+0.j]
 [ 0.+0.j -1.+0.j]]
density matrix after projection:
[[1.+0.j 0.+0.j]
 [0.+0.j 0.+0.j]]
vec after projection:
[0.70710678 0.         0.         0.70710678]

functions to transform parameters

to_stacked_vector() function returns a one-dimensional numpy array of all variables. This is equal to vec.

[10]:
print(f"to_stacked_vector(): {state.to_stacked_vector()}")
print(f"vec: {state.vec}")
to_stacked_vector(): [0.         0.         0.         1.41421356]
vec: [0.         0.         0.         1.41421356]
If on_para_eq_constraint is True, then the first element of vec is equal to \(1/\sqrt{d}\), where \(d\) is dim. Thus, State is characterized by the second and subsequent elements of vec.
Therefore, to_var() function returns the second and subsequent elements of vec, where on_para_eq_constraint is True.
[11]:
vec = np.array([1, 0, 0, 1]) / np.sqrt(2)
[12]:
# on_para_eq_constraint=True
state = State(c_sys, vec, on_para_eq_constraint=True)
print(f"to_var(): {state.to_var()}")
to_var(): [0.         0.         0.70710678]
[13]:
# on_para_eq_constraint=False
state = State(c_sys, vec, on_para_eq_constraint=False)
print(f"to_var(): {state.to_var()}")
to_var(): [0.70710678 0.         0.         0.70710678]

functions to generate special objects

[14]:
zero_state = state.generate_zero_obj()
print(f"zero: {zero_state.vec}")
origin_state = state.generate_origin_obj()
print(f"origin: {origin_state.vec}")
zero: [0. 0. 0. 0.]
origin: [0.70710678 0.         0.         0.        ]

supports arithmetic operations

[15]:
vec1 = np.array([1.0, 2.0, 3.0, 4.0])
state1 = State(c_sys, vec1, is_physicality_required=False)
vec2 = np.array([5.0, 6.0, 7.0, 8.0])
state2 = State(c_sys, vec2, is_physicality_required=False)

print(f"sum: {(state1 + state2).vec}")
print(f"subtraction: {(state1 - state2).vec}")
print(f"right multiplication: {(2 * state1).vec}")
print(f"left multiplication: {(state1 * 2).vec}")
print(f"division: {(state1 / 2).vec}")
sum: [ 6.  8. 10. 12.]
subtraction: [-4. -4. -4. -4.]
right multiplication: [2. 4. 6. 8.]
left multiplication: [2. 4. 6. 8.]
division: [0.5 1.  1.5 2. ]

calc_gradient functions

Calculates gradient of State with variable index.

[16]:
grad_state = state.calc_gradient(0)
print(f"vec: {grad_state.vec}")
vec: [1. 0. 0. 0.]

convert_basis function

Returns vec converted to the specified basis.

[17]:
from quara.objects.matrix_basis import get_comp_basis

state = generate_state_from_name(c_sys, "z0")
converted_vec = state.convert_basis(get_comp_basis())
print(f"vec: {converted_vec}")
vec: [1.+0.j 0.+0.j 0.+0.j 0.+0.j]

to_density_matrix function

Returns density matrix of State.

[18]:
state = generate_state_from_name(c_sys, "z0")
print(f"to_density_matrix(): \n{state.to_density_matrix()}")
print(f"to_density_matrix_with_sparsity(): \n{state.to_density_matrix_with_sparsity()}")
to_density_matrix():
[[1.+0.j 0.+0.j]
 [0.+0.j 0.+0.j]]
to_density_matrix_with_sparsity():
[[1.+0.j 0.+0.j]
 [0.+0.j 0.+0.j]]

some utility functions

[19]:
print(f"is_trace_one(): {state.is_trace_one()}")
print(f"is_hermitian(): {state.is_hermitian()}")
print(f"is_positive_semidefinite(): {state.is_positive_semidefinite()}")
print(f"calc_eigenvalues(): {state.calc_eigenvalues()}")
is_trace_one(): True
is_hermitian(): True
is_positive_semidefinite(): True
calc_eigenvalues(): [0.9999999999999998, 0.0]

state_typical

generate_state_object_from_state_name_object_name() function in state_typical module can easily generate objects related to State.
The generate_state_object_from_state_name_object_name() function has the following arguments:
  • The string that can be specified for state_name can be checked by executing the get_state_names() function. The tensor product of state_name “a”, “b” is written “a_b”.

  • object_name can be the following string:

  • “pure_state_vector” - vector of pure state.

  • “density_mat” - density matrix.

  • “density_matrix_vector” - vectorized density matrix.

  • “state” - State object.

  • c_sys - CompositeSystem of objects related to State. Specify when object_name is “density_matrix_vector” or “state”.

  • is_physicality_required - Whether the generated object is physicality required, by default True.

[20]:
from quara.objects.state_typical import (
    get_state_names,
    generate_state_object_from_state_name_object_name,
)

#get_state_names()

object_name = “pure_state_vector”

[21]:
vec = generate_state_object_from_state_name_object_name("z0", "pure_state_vector")
print(vec)
[1.+0.j 0.+0.j]

object_name = “density_mat”

[22]:
density_mat = generate_state_object_from_state_name_object_name("z0", "density_mat")
print(density_mat)
[[1.+0.j 0.+0.j]
 [0.+0.j 0.+0.j]]

object_name = “density_matrix_vector”

[23]:
c_sys = generate_composite_system("qubit", 1)
vec = generate_state_object_from_state_name_object_name("z0", "density_matrix_vector", c_sys=c_sys)
print(vec)
[0.70710678 0.         0.         0.70710678]

object_name = “state”

[24]:
c_sys = generate_composite_system("qubit", 1)
state = generate_state_object_from_state_name_object_name("z0", "state", c_sys=c_sys)
print(state)
Type:
State

Dim:
2

Vec:
[0.70710678 0.         0.         0.70710678]

Download Notebook