def energy_trace_batch(energy_states, dims, strt, end): """ For a givens portion of the states specified by the strt and num variables calculates trace distance and energy distance and returns values of cartesian prod NOTE: the ptrace turns the state directly into the density matrix without need for calling Ket2dm speeds up and stops issue of memory buffer overwrite etc """ energys = [] traces = [] dim = list(range(dims)) for pair1, pair2 in product(energy_states[strt:end], energy_states): if pair1 != pair2: energys.append(abs(pair1[0] - pair2[0])) substate1 = pair1[1].ptrace(dim) substate2 = pair2[1].ptrace(dim) trace_distance_val = tracedist(substate1, substate2) traces.append(trace_distance_val) return energys, traces
def get_max_trace_distance(t_list, H, dm_groundstate, dephased): ''' given a list of times, the unitary evolution hamiltonian and two density matrices, computes the maximum subsequent trace distance between the two states. ''' rhos_dephased = mesolve(H,dephased,t_list,[],[]).states trace_distances = [] for rho_dephased in rhos_dephased: trace_distances.append(tracedist(dm_groundstate.ptrace(0), rho_dephased.ptrace(0))) max_trace_distace = np.array(trace_distances).max() total_trace_distance = get_total_distance(dm_groundstate,dephased) return dm_groundstate, rhos_dephased, trace_distances, max_trace_distace, total_trace_distance
def get_max_trace_distnace(t_list, H, dm_groundstate, dephased): ''' given a list of times, the unitary evolution hamiltonian and two density matrices, computes the maximum subsequent trace distance between the two states. ''' rhos_ground = [] rhos_dephased = [] trace_distances = [] for t in t_list: time_evol = -H * 1.j * t rho_ground = time_evol.expm() * dm_groundstate * (time_evol.expm().dag()) rhos_ground.append(rho_ground) rho_dephased = time_evol.expm() * dephased * (time_evol.expm().dag()) rhos_dephased.append(rho_dephased) trace_distances.append(tracedist(rho_ground.ptrace(0), rho_dephased.ptrace(0))) max_trace_distace = np.array(trace_distances).max() return rhos_ground, rhos_dephased, trace_distances, max_trace_distace
def equilibration_analyser_p(energys, eigstates, init_state, stop, steps, trace=[0], _proc=4): coef = [init_state.overlap(state) for state in eigstates] n = len(init_state.dims[0]) subsys_trace = trace bath_trace = [dim for dim in range(n) if dim not in subsys_trace] equilibrated_dens_op = get_equilibrated_dens_op_P(eigstates, coef, n, proc=_proc) effective_dimension_sys = eff_dim(equilibrated_dens_op) effective_dimension_bath = eff_dim(equilibrated_dens_op.ptrace(bath_trace)) #now we have the actual effective dimension trace over as can't do it before or messes up equilibrated_dens_op = equilibrated_dens_op.ptrace(subsys_trace) bound_loose = 0.5 * sqrt( (2**len(subsys_trace))**2 / effective_dimension_sys) bound_tight = 0.5 * sqrt(2**len(subsys_trace) / effective_dimension_bath) trace_dist_compare = lambda state: tracedist(equilibrated_dens_op, state.ptrace(trace)) trace_distances = simulate(energys, eigstates, coef, 0, stop, steps, ret_func=trace_dist_compare, proc=_proc) times = linspace(0, stop, steps) print(f"Effective dimension of system: {effective_dimension_sys}") return times, trace_distances, bound_loose, bound_tight
def get_total_distance(dm_groundstate,dephased): return tracedist(dm_groundstate,dephased)