#!/usr/bin/env python3 # FILE CONTENTS: (symbolic) methods for performing qubit operations import sympy as sym from itertools import product as cartesian_product from itertools import combinations, permutations from sympy.physics.quantum import TensorProduct as tensor # single-atom pseudospin states dn = sym.Matrix([1, 0]) up = sym.Matrix([0, 1]) # two-atom pseudospin states uu = tensor(up, up) ud = tensor(up, dn) du = tensor(dn, up) dd = tensor(dn, dn) # all states of n qubits def qubit_states(n): return cartesian_product([-1, 1], repeat=n) # single-qubit matrix entry: | final >< initial | def qubit_matrix_entry(initial, final): state_in = (up if initial == 1 else dn) state_out = (up if final == 1 else dn) return tensor(state_out, state_in.H)
def qubit_matrix_entry(initial, final): state_in = (up if initial == 1 else dn) state_out = (up if final == 1 else dn) return tensor(state_out, state_in.H)
def elem(self, atom_number=None, debug=False): assert (len(self.vec) % 2 == 0) if atom_number == None: atom_number = len(self.vec) // 2 vec = deepcopy(self.vec) sign = 1 current_spin = [0 for n in range(atom_number)] current_band = [0 for n in range(atom_number)] zero_matrix = sym.zeros(2**atom_number) while len(vec) > 0: if vec[0].create: return zero_matrix if vec[0].band != current_band[vec[0].nuclear_spin]: return zero_matrix if (current_spin[vec[0].nuclear_spin] != 0 and vec[0].spin != current_spin[vec[0].nuclear_spin]): return zero_matrix found = False # have we found a matching fermionic operator? for ii in range(1, len(vec)): match = vec[0].nuclear_spin == vec[ii].nuclear_spin if match: if not vec[ii].create: return zero_matrix found = True if debug: print() print(vec[0]) print(vec[ii]) print(vec[::-1]) current_spin[vec[0].nuclear_spin] = vec[ii].spin current_band[vec[0].nuclear_spin] = vec[ii].band vec.pop(ii) vec.pop(0) break else: sign *= -1 if not found: return zero_matrix if (0 in current_spin or current_band != [0 for n in range(atom_number)]): return zero_matrix if debug: print() print(self) # individual effective spin operators spin_ops = [sym.eye(2) for n in range(atom_number)] for nuclear_spin in set( [operator.nuclear_spin for operator in self.vec]): # loop over annihilation operators for operator in self.vec: if operator.nuclear_spin == nuclear_spin: s_in = operator.spin break # loop over creation operators for operator in self.vec[::-1]: if operator.nuclear_spin == nuclear_spin: s_out = operator.spin break if debug: print() print(nuclear_spin) print(s_in, "-->", s_out) spin_ops[nuclear_spin] = qubit_matrix_entry(s_in, s_out) if debug: print() print("sign:", sign) pprint(spin_ops) return sign * tensor(*spin_ops)
def convert_to_sympy_matrix(expr, full_space=None): """Convert a QAlgebra expression to an explicit ``n x n`` instance of `sympy.Matrix`, where ``n`` is the dimension of `full_space`. The entries of the matrix may contain symbols. Parameters: expr: a QAlgebra expression full_space (HilbertSpace): The Hilbert space in which `expr` is defined. If not given, ``expr.space`` is used. The Hilbert space must have a well-defined basis. Raises: BasisNotSetError: if `full_space` does not have a defined basis ValueError: if `expr` is not in `full_space`, or if `expr` cannot be converted. """ if full_space is None: full_space = expr.space if not expr.space.is_tensor_factor_of(full_space): raise ValueError("expr must be in full_space") if expr is IdentityOperator: return sympy.eye(full_space.dimension) elif expr is ZeroOperator: return 0 elif isinstance(expr, LocalOperator): n = full_space.dimension if full_space != expr.space: all_spaces = full_space.local_factors own_space_index = all_spaces.index(expr.space) factors = [ sympy.eye(s.dimension) for s in all_spaces[:own_space_index] ] factors.append(convert_to_sympy_matrix(expr, expr.space)) factors.extend( [ sympy.eye(s.dimension) for s in all_spaces[own_space_index + 1 :] ] ) return tensor(*factors) if isinstance(expr, (Create, Jz, Jplus)): return SympyCreate(n) elif isinstance(expr, (Destroy, Jminus)): return SympyCreate(n).H elif isinstance(expr, Phase): phi = expr.phase result = sympy.zeros(n) for i in range(n): result[i, i] = sympy.exp(sympy.I * i * phi) return result elif isinstance(expr, Displace): alpha = expr.operands[1] a = SympyCreate(n) return (alpha * a - alpha.conjugate() * a.H).exp() elif isinstance(expr, Squeeze): eta = expr.operands[1] a = SympyCreate(n) return ( (eta / 2) * a ** 2 - (eta.conjugate() / 2) * (a.H) ** 2 ).exp() elif isinstance(expr, LocalSigma): ket = basis_state(expr.index_j, n) bra = basis_state(expr.index_k, n).H return ket * bra else: raise ValueError( "Cannot convert '%s' of type %s" % (str(expr), type(expr)) ) elif isinstance(expr, Operator) and isinstance(expr, Operation): if isinstance(expr, OperatorPlus): s = convert_to_sympy_matrix(expr.operands[0], full_space) for op in expr.operands[1:]: s += convert_to_sympy_matrix(op, full_space) return s elif isinstance(expr, OperatorTimes): # if any factor acts non-locally, we need to expand distributively. if any(len(op.space) > 1 for op in expr.operands): se = expr.expand() if se == expr: raise ValueError( "Cannot represent as sympy matrix: %s" % expr ) return convert_to_sympy_matrix(se, full_space) all_spaces = full_space.local_factors by_space = [] ck = 0 for ls in all_spaces: # group factors by associated local space ls_ops = [ convert_to_sympy_matrix(o, o.space) for o in expr.operands if o.space == ls ] if len(ls_ops): # compute factor associated with local space by_space.append(ls_ops[0]) for ls_op in ls_ops[1:]: by_space[-1] *= ls_op ck += len(ls_ops) else: # if trivial action, take identity matrix by_space.append(sympy.eye(ls.dimension)) assert ck == len(expr.operands) # combine local factors in tensor product if len(by_space) == 1: return by_space[0] else: return tensor(*by_space) elif isinstance(expr, Adjoint): return convert_to_sympy_matrix(expr.operand, full_space).H elif isinstance(expr, PseudoInverse): raise NotImplementedError( 'Cannot convert PseudoInverse to sympy matrix' ) elif isinstance(expr, NullSpaceProjector): raise NotImplementedError( 'Cannot convert NullSpaceProjector to sympy' ) elif isinstance(expr, ScalarTimesOperator): return expr.coeff * convert_to_sympy_matrix(expr.term, full_space) else: raise ValueError( "Cannot convert '%s' of type %s" % (str(expr), type(expr)) ) else: raise ValueError( "Cannot convert '%s' of type %s" % (str(expr), type(expr)) )
import sys import time I = np.array([[1., 0.], [0., 1.]]) zero = np.array([[1., 0.], [0., 0.]]) one = np.array([[0., 0.], [0., 1.]]) X = np.array([[0., 1.], [1., 0.]]) I_2 = np.eye(4) I_3 = np.eye(8) I_4 = np.eye(16) I_5 = np.eye(32) I_6 = np.eye(64) # T1 conditional on 1,1 - acts on qubits 1,2 and flips 8 U_T11 = tensor(zero, tensor(zero, I_6)) + tensor(zero, tensor( one, I_6)) + tensor(one, tensor(zero, I_6)) + tensor( one, tensor(one, tensor(I_5, X))) # T2 conditional on 1,0 - acts on qubits 1,2 and flips 8 U_T21 = tensor(zero, tensor(zero, I_6)) + tensor(zero, tensor( one, I_6)) + tensor(one, tensor(zero, tensor(I_5, X))) + tensor( one, tensor(one, I_6)) # T3 conditional on 0,1 - acts on qubits 1,2 and flips 8 U_T31 = tensor(zero, tensor( zero, I_6)) + tensor(zero, tensor(one, tensor(I_5, X))) + tensor( one, tensor(zero, I_6)) + tensor(one, tensor(one, tensor(I_5, X))) # T4 conditional on 0,0 - acts on qubits 1,2 and flips 8 U_T41 = tensor(zero, tensor(zero, tensor(I_5, X))) + tensor( zero, tensor(one, I_6)) + tensor(one, tensor(zero, I_6)) + tensor( one, tensor(one, I_6))
-1j * cos / (1 - sin), sin / (1 - cos), -sin / (1 - cos) ] # z[3], z[4], z[5], = z[5], z[3], z[4] c = 1 if np.sum(i) == 0: for a1 in range(12): for b1 in range(a1 + 1, 12): c = c * (z[a1] - z[b1])**(i[a1] * i[b1] / 2) return c else: return 0 Gs4 = Qobj(np.zeros((16, 1)), [Lis(2, 4), Lis(1, 4)]) for i1, i2, i3, i4 in itr.product([-1, 1], [-1, 1], [-1, 1], [-1, 1]): Gs42 = Gs4 + Semion4([i1, i2, i3, i4]) * tensor(v(i1), v(i2), v(i3), v(i4)) Gs4 = Gs42 NGs4 = Gs4 / np.linalg.norm(Gs4) Gs6 = Qobj(np.zeros((64, 1)), [Lis(2, 6), Lis(1, 6)]) for i1, i2, i3, i4, i5, i6 in itr.product([-1, 1], [-1, 1], [-1, 1], [-1, 1], [-1, 1], [-1, 1]): Gs62 = Gs6 + Semion6([i1, i2, i3, i4, i5, i6]) * tensor( v(i1), v(i2), v(i3), v(i4), v(i5), v(i6)) Gs6 = Gs62 NGs6 = Gs6 / np.linalg.norm(Gs6) Gs8 = Qobj(np.zeros((2**8, 1)), [Lis(2, 8), Lis(1, 8)]) for i1, i2, i3, i4, i5, i6, i7, i8 in itr.product([-1, 1], [-1, 1], [-1, 1], [-1, 1], [-1, 1], [-1, 1], [-1, 1], [-1, 1]):
def convert_to_sympy_matrix(expr, full_space=None): """Convert a QNET expression to an explicit ``n x n`` instance of `sympy.Matrix`, where ``n`` is the dimension of `full_space`. The entries of the matrix may contain symbols. Parameters: expr: a QNET expression full_space (qnet.algebra.hilbert_space_algebra.HilbertSpace): The Hilbert space in which `expr` is defined. If not given, ``expr.space`` is used. The Hilbert space must have a well-defined basis. Raises: qnet.algebra.hilbert_space_algebra.BasisNotSetError: if `full_space` does not have a defined basis ValueError: if `expr` is not in `full_space`, or if `expr` cannot be converted. """ if full_space is None: full_space = expr.space if not expr.space.is_tensor_factor_of(full_space): raise ValueError("expr must be in full_space") if expr is IdentityOperator: return sympy.eye(full_space.dimension) elif expr is ZeroOperator: return 0 elif isinstance(expr, LocalOperator): n = full_space.dimension if full_space != expr.space: all_spaces = full_space.local_factors() own_space_index = all_spaces.index(expr.space) return tensor(*( [sympy.eye(s.dimension) for s in all_spaces[:own_space_index]] + convert_to_sympy_matrix(expr, expr.space) + [sympy.eye(s.dimension) for s in all_spaces[own_space_index + 1:]] )) if isinstance(expr, (Create, Jz, Jplus)): return SympyCreate(n) elif isinstance(expr, (Destroy, Jminus)): return SympyCreate(n).H elif isinstance(expr, Phase): phi = expr.operands[1] result = sympy.zeros(n) for i in range(n): result[i,i] = sympy.exp(sympy.I * i * phi) return result elif isinstance(expr, Displace): alpha = expr.operands[1] a = SympyCreate(n) return (alpha * a - alpha.conjugate() * a.H).exp() elif isinstance(expr, Squeeze): eta = expr.operands[1] a = SympyCreate(n) return ((eta/2) * a**2 - (eta.conjugate()/2) * (a.H)**2).exp() elif isinstance(expr, LocalSigma): k, j = expr.operands[1:] ket = basis_state(k, n) bra = basis_state(j, n).H return ket * bra else: raise ValueError("Cannot convert '%s' of type %s" % (str(expr), type(expr))) elif isinstance(expr, OperatorOperation): if isinstance(expr, OperatorPlus): s = convert_to_sympy_matrix(expr.operands[0], full_space) for op in expr.operands[1:]: s += convert_to_sympy_matrix(op, full_space) return s elif isinstance(expr, OperatorTimes): # if any factor acts non-locally, we need to expand distributively. if any(len(op.space) > 1 for op in expr.operands): se = expr.expand() if se == expr: raise ValueError("Cannot represent as sympy matrix: %s" % expr) return convert_to_sympy_matrix(se, full_space) all_spaces = full_space.local_factors() by_space = [] ck = 0 for ls in all_spaces: # group factors by associated local space ls_ops = [convert_to_sympy_matrix(o, o.space) for o in expr.operands if o.space == ls] if len(ls_ops): # compute factor associated with local space by_space.append(ls_ops[0]) for ls_op in ls_ops[1:]: by_space[-1] *= ls_op ck += len(ls_ops) else: # if trivial action, take identity matrix by_space.append(sympy.eye(ls.dimension)) assert ck == len(expr.operands) # combine local factors in tensor product if len(by_space) == 1: return by_space[0] else: return tensor(*by_space) elif isinstance(expr, Adjoint): return convert_to_sympy_matrix(expr.operand, full_space).H elif isinstance(expr, PseudoInverse): raise NotImplementedError('Cannot convert PseudoInverse to sympy ' 'matrix') elif isinstance(expr, NullSpaceProjector): raise NotImplementedError('Cannot convert NullSpaceProjector to ' 'sympy') else: raise ValueError("Cannot convert '%s' of type %s" % (str(expr), type(expr))) elif isinstance(expr, ScalarTimesOperator): return expr.coeff * convert_to_sympy_matrix(expr.term, full_space) elif isinstance(expr, ScalarTimesOperator): raise NotImplementedError('Cannot convert OperatorTrace to ' 'sympy') # actually, this is perfectly doable in principle, but requires a bit # of work else: raise ValueError("Cannot convert '%s' of type %s" % (str(expr), type(expr)))