#!/usr/bin/env python # coding: utf-8 # # Maximally Entangled States # $$ # \newcommand{\ul}[1]{\underline{#1}} # \newcommand{\rvx}[0]{{\ul{x}}} # \newcommand{\rvy}[0]{{\ul{y}}} # $$ # # The purpose of this notebook is to construct a maximally entangled 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 the maximally entangled states that we use. The basic requirement for a density matrix $\rho_{\rvx, \rvy}$ # to be maximally entangled is for its partial trace $\rho_{\rvx}={\rm tr}_\rvy \rho_{\rvx, \rvy}$ to be a diagonal matrix with all terms in the diagonal equal to the same constant. The sum of the diagonal elements must of course be one. For example, $\rho_{\rvx}={\rm diag}(0.25, 0.25, 0.25, 0.25)$. (If $\rvx$ and $\rvy$ have different numbers of possible values, this assumes that # $\rvx$ is the one with the smaller number of values.) # # 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** # * "A New Algorithm for Calculating # 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. # In[1]: import os import sys print(os.getcwd()) os.chdir('../../') print(os.getcwd()) sys.path.insert(0,os.getcwd()) # In[2]: from entanglish.DenMat import * from entanglish.MaxEntangState import * from entanglish.EntangCase import * from entanglish.PureStEnt import * # Create a DenMat object called dm_max with num_rows=24 and row_shape=(2, 2, 3 ,2).Then # set its arr to a maximally entangled state. # In[3]: dm_max = DenMat(24, (2, 2, 3, 2)) max_ent_st = MaxEntangState(dm_max.num_rows, dm_max.row_shape, [0, 1, 3], [2]) EntangCase.check_max_entang_st(max_ent_st) st_vec = max_ent_st.get_st_vec() entang = max_ent_st.get_known_entang() dm_max.set_arr_from_st_vec(st_vec) print('st_vec=\n', st_vec) print("entang=", entang) # 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 # In[4]: ecase = PureStEnt(dm_max, 'eigen') pf = ecase.get_entang_profile() ecase.print_entang_profiles([pf], dm_max.row_shape)