The purpose of this notebook is to construct a "symmetrized-N-up-state" state vector and its corresponding density matrix, and then to calculate the "entanglement profile" of that state.
In Entaglish, density matrices are stored in the class DenMat. That class contains attributes: num_rows, row_shape and arr. arr is a numpy array of shape=(num_rows, num_rows). row_shape is a tuple such that the product of its components is num_rows. For example, a state with row_shape=(2,3,4) consists of 3 qudits with d=2,3,4 and num_rows=24.
See Entanglish-Original-Ref for an explicit definition of "symmetrized-N-up-states". As their name implies, such states consist of NT qubits, with N qubits up (i.e, in state 1) and NT-N qubits down (i.e., in state 0). A full symmetrization operator is applied to the state so that it completely forgets which of the NT qubits are up and which are down.
In Entanglish-Original-Ref, we derive an analytical formula for the entanglement of any symmetrized n-up state.
Given a state with num_row_axes qudits, one can define a (bipartite) entanglement for each possible bi-partitions of range( num_row_axes). By a bi-partition we mean two nonempty disjoint subsets whose union is range(num_row_axes). An entanglement profile is a dictionary mapping bi-partition half-size to a dictionary that maps each bi-partition of that half-size to its entanglement.
Entanglish-Original-Ref
Squashed Entanglement and a Python Implementation Thereof", by R.R.Tucci
First change your working directory to the entanglish directory in your computer, and add its path to the path environment variable.
import os
import sys
print(os.getcwd())
os.chdir('../../')
print(os.getcwd())
sys.path.insert(0,os.getcwd())
from entanglish.DenMat import *
from entanglish.SymNupState import *
from entanglish.PureStEnt import *
Create a SymNupState object st with 5 qubits, 3 of which are up. Its entanglement depends only on the number of axes in $\rvx$, and the number of axes in $\rvy$, not in their particular identities. st.get_known_entang() calculates entanglement using the known analytical formula.
num_up = 3
num_qbits = 5
st = SymNupState(num_up, num_qbits)
st_vec = st.get_st_vec()
print('st_vec=\n', st_vec)
for num_x_axes in range(0, num_qbits+1):
print('known entang for ' + str(num_x_axes) + ' x axes=',
st.get_known_entang(num_x_axes))
st_vec= [0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0.31622777+0.j 0. +0.j 0. +0.j 0. +0.j 0.31622777+0.j 0. +0.j 0.31622777+0.j 0.31622777+0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0.31622777+0.j 0. +0.j 0.31622777+0.j 0.31622777+0.j 0. +0.j 0. +0.j 0.31622777+0.j 0.31622777+0.j 0. +0.j 0.31622777+0.j 0. +0.j 0. +0.j 0. +0.j] known entang for 0 x axes= 0.0 known entang for 1 x axes= 0.6730116670092565 known entang for 2 x axes= 0.8979457248567798 known entang for 3 x axes= 0.8979457248567797 known entang for 4 x axes= 0.6730116670092565 known entang for 5 x axes= 0.0
Create a DenMat object called dm, and set dm.arr equal to st_vec times its Hermitian, where st_vec is the state vector for the symmetrized n-up state.
Class PureStEnt is a child of class EntangCase.
All objects with EntangCase as a parent calculate entanglement numerically, from an algorithm, not from a known analytical formula. For a pure state, that algo is the von Neumann entropy of a partial trace of dm.
All objects with EntangCase as a parent inherit methods for calculating and printing entanglement profiles.
num_rows = 1 << num_qbits
row_shape = tuple([2]*num_qbits)
dm = DenMat(num_rows, row_shape)
dm.set_arr_from_st_vec(st_vec)
ecase = PureStEnt(dm, 'eigen')
pf = ecase.get_entang_profile()
ecase.print_entang_profiles([pf], dm.row_shape)
bi-partition half-size=1 (0 | 1, 2, 3, 4) : 0.67301, max-entang= 0.69315 (1 | 0, 2, 3, 4) : 0.67301, max-entang= 0.69315 (2 | 0, 1, 3, 4) : 0.67301, max-entang= 0.69315 (3 | 0, 1, 2, 4) : 0.67301, max-entang= 0.69315 (4 | 0, 1, 2, 3) : 0.67301, max-entang= 0.69315 bi-partition half-size=2 (0, 1 | 2, 3, 4) : 0.89795, max-entang= 1.38629 (0, 2 | 1, 3, 4) : 0.89795, max-entang= 1.38629 (0, 3 | 1, 2, 4) : 0.89795, max-entang= 1.38629 (0, 4 | 1, 2, 3) : 0.89795, max-entang= 1.38629 (1, 2 | 0, 3, 4) : 0.89795, max-entang= 1.38629 (1, 3 | 0, 2, 4) : 0.89795, max-entang= 1.38629 (1, 4 | 0, 2, 3) : 0.89795, max-entang= 1.38629 (2, 3 | 0, 1, 4) : 0.89795, max-entang= 1.38629 (2, 4 | 0, 1, 3) : 0.89795, max-entang= 1.38629 (3, 4 | 0, 1, 2) : 0.89795, max-entang= 1.38629