def init_comp(self): """ Convenient to have extra attributes calculated once, this is best place to put them """ dyn = self.parent #and now the new code self.full_dim = np.product(self.sub_dims) self.dimensional_norm = self.full_dim self.oper_dims = [self.sub_dims, self.sub_dims] #Simply the local targets with the relevent number of identities tensored # before and after it. # We only ever need the .dag() of this, so only storing that. self.large_local_targs_dag = [] for sub_sys in range(self.num_sub_sys): large_local_targ = [] for k in range(sub_sys): large_local_targ.append(identity(self.sub_dims[k])) large_local_targ.append(self.U_local_targs[sub_sys]) for k in range(sub_sys + 1, self.num_sub_sys): large_local_targ.append(identity(self.sub_dims[k])) large_local_targ = reduce(tensor, large_local_targ) if dyn.oper_dtype == Qobj: self.large_local_targs_dag.append(large_local_targ.dag()) else: self.large_local_targs_dag.append( large_local_targ.dag().full()) # Calculate the permutation matrices for the partial trace self.ptrace_perms = {} for sub_sys in range(self.num_sub_sys): self.ptrace_perms[sub_sys] = calc_perm(self.oper_dims, sub_sys)
def _ptrace(self, sys, sel): if isinstance(sel, int): perm = self.ptrace_perms[sel] elif len(sel) == 1: perm = self.ptrace_perms[sel[0]] else: perm = self.ptrace_perms.get(str(sel), None) if perm is None: perm = calc_perm(self.oper_dims, sel) self.ptrace_perms[str(sel)] = perm return partial_trace(sys, self.oper_dims, sel, perm=perm)[0]