def reproducible_pickle_repr(expr): """ :param expr: sympy matrix (containig the relevant expression(s)) :return: byte-array (result of pickle.dumps) """ assert len(replaced_attributes) == 0 assert isinstance(expr, (sp.Basic, sp.MatrixBase)) if isinstance(expr, sp.MatrixBase): expr = sp.ImmutableDenseMatrix(expr) symbols = expr.atoms(sp.Symbol) # _enable_reproducible_pickle_repr_for_expr(expr) for s in symbols: _enable_reproducible_pickle_repr_for_expr(s) pickle_dump = pickle.dumps(expr) _rewind_all_dict_replacements() return pickle_dump
def _new(cls, *args, **kwargs): if args: try: # Constructor if input is (rows, cols, lambda) newobj = super(AbstractTensor, cls)._new(*args) except ValueError: # Constructor if input is list of list as (row, cols, list_of_list) # doesn't work as it expects a flattened. newobj = super(AbstractTensor, cls)._new(args[2]) # Filter grid and dimensions grid, dimensions = newobj._infer_dims() if grid is None and dimensions is None: return sympy.ImmutableDenseMatrix(*args) # Initialized with constructed object newobj.__init_finalize__(newobj.rows, newobj.cols, newobj.flat(), grid=grid, dimensions=dimensions) else: # Initialize components and create new Matrix from standard # Devito inputs comps = cls.__subfunc_setup__(*args, **kwargs) newobj = super(AbstractTensor, cls)._new(comps) newobj.__init_finalize__(*args, **kwargs) return newobj
def cp_state(n_qubits: int, symbols: List[str]): rs = sp.symbols(symbols[0] + ':2' * n_qubits, real=True, nonnegative=True) phis = sp.symbols(symbols[1] + ':2' * n_qubits, real=True) return sp.ImmutableDenseMatrix([[rs[0]], *[[rs[i] * sp.exp(sp.I * phis[i])] for i in range(1, len(rs))] ]), rs, phis[1:]
def diffusion_coefficients(surface_tensions): r"""Computes diffusion coefficients labeled ̅α in the paper""" assert surface_tensions.rows == surface_tensions.cols num_phases = surface_tensions.rows assert all(surface_tensions[k, k] == 0 for k in range( num_phases)), "Diagonal of surface tension matrix has to be 0" alpha_symbolic = sp.Matrix( num_phases, num_phases, lambda i, j: sp.symbols(f"α_{i}{j}" if i < j else f"α_{j}{i}")) for i in range(num_phases): alpha_symbolic[i, i] = -sum(alpha_symbolic[i, j] for j in range(num_phases) if i != j) gamma_vector = sp.Matrix(sp.symbols(f"γ_:{num_phases}")) unit_vector = sp.Matrix(num_phases, 1, lambda a, b: 1) unit_matrix = sp.Matrix(num_phases, num_phases, lambda a, b: 1 if a == b else 0) lemma_2_1 = alpha_symbolic * surface_tensions - unit_matrix - gamma_vector * unit_vector.T eq_sys = [ lemma_2_1[i, j] for i in range(num_phases) for j in range(num_phases) ] unknowns = list(alpha_symbolic.atoms(sp.Symbol)) + list( gamma_vector.atoms(sp.Symbol)) solution = sp.solve(eq_sys, unknowns) assert solution, "Equation system for diffusion coefficients could not be solved" return sp.ImmutableDenseMatrix( alpha_symbolic.subs(solution)), gamma_vector.subs(solution)
def symbolic_surface_tensions(num_phases): def creation_func(i, j): if i == j: return 0 if j < i: i, j = j, i return sp.Symbol("sigma_{}{}".format(i, j)) return sp.ImmutableDenseMatrix(num_phases, num_phases, creation_func)
def chemical_potential_n_phase_boyer(order_parameters, interface_width, surface_tensions, correction_factor, zero_threshold=0, assume_nonnegative=False): n = len(order_parameters) c = order_parameters if hasattr(surface_tensions, '__call__'): sigma = sp.ImmutableDenseMatrix( n, n, lambda i, j: surface_tensions(i, j) if i != j else 0) else: sigma = sp.ImmutableDenseMatrix( n, n, lambda i, j: surface_tensions[i, j] if i != j else 0) alpha, _ = diffusion_coefficients(sigma) capital_f = capital_f0(c, sigma) + correction_g( c, sigma) + correction_factor * stabilization_term(c, alpha) def f(c): return c**2 * (1 - c)**2 a, b = compute_ab(f) fe_bulk = free_energy_bulk(capital_f, b, interface_width) fe_if = free_energy_interfacial(c, sigma, a, interface_width) mu_bulk = chemical_potentials_from_free_energy(fe_bulk, order_parameters) mu_bulk = sp.Matrix([simplify_zero_conditions(e.doit()) for e in mu_bulk]) if zero_threshold != 0: substitutions = { sp.Eq(c_i, 0): sp.StrictLessThan(sp.Abs(c_i), zero_threshold) for c_i in c } mu_bulk = mu_bulk.subs(substitutions) if assume_nonnegative: substitutions = {c_i: sp.Dummy(nonnegative=True) for c_i in c} mu_bulk = mu_bulk.subs(substitutions).subs( {v: k for k, v in substitutions.items()}) mu_if = chemical_potentials_from_free_energy(fe_if, order_parameters) return fe_bulk, fe_if, mu_bulk, mu_if
def test_reading_different_matrix_types(): test = [ (sympy.MutableMatrix([kx**2]) , ['x']), (sympy.ImmutableMatrix([kx**2]) , ['x']), (sympy.MutableDenseMatrix([kx**2]) , ['x']), (sympy.ImmutableDenseMatrix([kx**2]) , ['x']), ] for inp, out in test: ham, got = discretize_symbolic(inp) assert got == out,\ "Should be: _split_factors({})=={}. Not {}".format(inp, out, got)
def test_subz(self): x1, x2, x3 = xx = sp.Matrix(sp.symbols("x1, x2, x3")) y1, y2, y3 = yy = sp.symbols("y1, y2, y3") a = x1 + 7 * x2 * x3 M1 = sp.Matrix([x2, x1 * x2, x3**2]) M2 = sp.ImmutableDenseMatrix(M1) self.assertEqual(x1.subs(lzip(xx, yy)), x1.subz(xx, yy)) self.assertEqual(a.subs(lzip(xx, yy)), a.subz(xx, yy)) self.assertEqual(M1.subs(lzip(xx, yy)), M1.subz(xx, yy)) self.assertEqual(M2.subs(lzip(xx, yy)), M2.subz(xx, yy))
def test_count_ops(self): a, b, t = sp.symbols("a, b, t") x1 = a + b x2 = a + b - 3 + sp.pi M1 = sp.Matrix([x2, t, a**2]) M2 = sp.ImmutableDenseMatrix(M1) self.assertEqual(st.count_ops(a), a.co) self.assertEqual(st.count_ops(x1), x1.co) self.assertEqual(st.count_ops(x2), x2.co) self.assertEqual(st.count_ops(M1), M1.co) self.assertEqual(st.count_ops(M2), M2.co)
def test_symbol_atoms(self): a, b, t = sp.symbols("a, b, t") x1 = a + b x2 = a + b - 3 + sp.pi M1 = sp.Matrix([x2, t, a**2]) M2 = sp.ImmutableDenseMatrix(M1) self.assertEqual(set([a]), a.s) self.assertEqual(x1.atoms(), x1.s) self.assertEqual(x2.atoms(sp.Symbol), x2.s) self.assertEqual(set([a, b, t]), M1.s) self.assertEqual(set([a, b, t]), M2.s)
def test_count_ops2(self): a, b, t = sp.symbols("a, b, t") x1 = a + b x2 = a + b - 3 + sp.pi M1 = sp.Matrix([x2, t, a**2, 0, 1]) M2 = sp.ImmutableDenseMatrix(M1) self.assertEqual(st.count_ops(0), 0) self.assertEqual(st.count_ops(a), 1) self.assertEqual(st.count_ops(1.3), 1) self.assertEqual(st.count_ops(x1), 2) self.assertEqual(st.count_ops(x2), 4) self.assertEqual(st.count_ops(M1), sp.Matrix([4, 1, 2, 0, 1])) self.assertEqual(st.count_ops(M2), sp.Matrix([4, 1, 2, 0, 1]))
def test_subz0(self): x1, x2, x3 = xx = st.symb_vector("x1, x2, x3") y1, y2, y3 = yy = st.symb_vector("y1, y2, y3") XX = (x1, x2) a = x1 + 7 * x2 * x3 M1 = sp.Matrix([x2, x1 * x2, x3**2]) M2 = sp.ImmutableDenseMatrix(M1) self.assertEqual(x1.subs(st.zip0(XX)), x1.subz0(XX)) self.assertEqual(a.subs(st.zip0(XX)), a.subz0(XX)) self.assertEqual(M1.subs(st.zip0(XX)), M1.subz0(XX)) self.assertEqual(M2.subs(st.zip0(XX)), M2.subz0(XX)) konst = sp.Matrix([1, 2, 3]) zz = konst + xx + 5 * yy self.assertEqual(zz.subz0(xx, yy), konst)
def test_is_scalar2(self): x1, x2, x3 = xx = st.symb_vector('x1:4') a1, a2, a3 = aa = st.symb_vector('a1:4') M1 = sp.Matrix([[0, 0], [a1, a2], [0, a3]]) M2 = sp.ImmutableDenseMatrix(M1) iss = st.is_scalar self.assertTrue(iss(x1)) self.assertTrue(iss(x1**2 + sp.sin(x2))) self.assertTrue(iss(0)) self.assertTrue(iss(0.1)) self.assertTrue(iss(7.5 - 23j)) self.assertTrue(iss(np.float64(0.1))) self.assertFalse(iss(M1)) self.assertFalse(iss(M2)) self.assertFalse(iss(M1[:1, :1])) self.assertFalse(iss(np.arange(5)))
def _new(cls, *args, **kwargs): if args: try: # Constructor if input is (rows, cols, lambda) newobj = super(AbstractTensor, cls)._new(*args) except ValueError: # Constructor if input is list of list as (row, cols, list_of_list) # doesn't work as it expects a flattened. newobj = super(AbstractTensor, cls)._new(args[2]) # Filter grid and dimensions grids = {getattr(c, 'grid', None) for c in newobj._mat} - {None} dimensions = { d for c in newobj._mat for d in getattr(c, 'dimensions', ()) } - {None} # If none of the components are devito objects, returns a sympy Matrix if len(grids) == 0 and len(dimensions) == 0: return sympy.ImmutableDenseMatrix(*args) elif len(grids) > 0: dimensions = None assert len(grids) == 1 grid = grids.pop() else: grid = None dimensions = tuple(dimensions) # Initialized with constructed object newobj.__init_finalize__(newobj.rows, newobj.cols, newobj._mat, grid=grid, dimensions=dimensions) else: # Initialize components and create new Matrix from standard # Devito inputs comps = cls.__subfunc_setup__(*args, **kwargs) newobj = super(AbstractTensor, cls)._new(comps) newobj.__init_finalize__(*args, **kwargs) return newobj
def test_nc_multiplication(self): a, b = sp.symbols("a, b", commutative=False) E = sp.eye(2) Mb = b * E Mab = a * b * E res = nct.nc_mul(a, Mb) - Mab self.assertEqual(res, 0 * E) res2 = nct.nc_mul(a * E, b * E) self.assertEqual(res2, Mab) res3 = nct.nc_mul(Mb, Mab) self.assertEqual(res3, b * a * b * E) # this was a bug 2019-02-08 10:18:36 Mb2 = sp.ImmutableDenseMatrix(Mb) self.assertEqual(nct.nc_mul(a, Mb2), Mb * a) self.assertEqual(nct.nc_mul(Mb2, a), a * Mb) self.assertFalse(Mb * a == a * Mb)
def iSWAP_N_3pi_2(N, targets): return sp.ImmutableDenseMatrix(qt.iswap(N, targets)).subs(1.0, 1)
state = sp.ImmutableDenseMatrix([*xs]) return state, xs def cp_state(n_qubits: int, symbols: List[str]): rs = sp.symbols(symbols[0] + ':2' * n_qubits, real=True, nonnegative=True) phis = sp.symbols(symbols[1] + ':2' * n_qubits, real=True) return sp.ImmutableDenseMatrix([[rs[0]], *[[rs[i] * sp.exp(sp.I * phis[i])] for i in range(1, len(rs))] ]), rs, phis[1:] U3 = lambda theta, phi, lamb: sp.ImmutableDenseMatrix( [[sp.cos(theta / 2), -sp.exp(I * lamb) * sp.sin(theta / 2)], [ sp.exp(I * phi) * sp.sin(theta / 2), sp.exp(I * (lamb + phi)) * sp.cos(theta / 2) ]]) # https://www.researchgate.net/figure/Example-universal-set-of-quantum-gates-consisting-of-three-single-qubit-rotation-gates_fig3_327671865 # NIelsen and Chuang p. 174 def RX(angle): return sp.ImmutableDenseMatrix([ [sp.cos(angle / 2), -1j * sp.sin(angle / 2)], [-1j * sp.sin(angle / 2), sp.cos(angle / 2)], ]) def RY(angle): return sp.ImmutableDenseMatrix([
def RY(angle): return sp.ImmutableDenseMatrix([ [sp.cos(angle / 2), -sp.sin(angle / 2)], [sp.sin(angle / 2), sp.cos(angle / 2)], ])
def state(n_qubits: int, symbol: str): x0 = sp.symbols(symbol + ':1' * n_qubits, real=True) xrest = sp.symbols(symbol + ':2' * n_qubits, complex=True) xs = [*x0, *xrest[1:]] state = sp.ImmutableDenseMatrix([*xs]) return state, xs
# xb (T1) – yb (C2) # # So that's 2 of the qubits as an input and 2 as output π = sp.pi t = sp.symbols('t', real=True, nonnegative=True) # Ut = U(t).subs(t, π/4).subs(sp.exp(1j*π/4), (1+1j)/sp.sqrt(2)) Ut = U(t).subs(sp.exp(1j * t), sp.cos(t) + 1j * sp.sin(t)) xs = sp.symbols('x:2:2', real=True, nonnegative=True) phis = sp.symbols('phi:2:2', real=True) x1, x2, x3, x4 = xs _, phi2, phi3, phi4 = phis state = sp.ImmutableDenseMatrix([[x1], [x2 * sp.exp(1j * phi2)], [x3 * sp.exp(1j * phi3)], [x4 * sp.exp(1j * phi4)]]) ws = sp.symbols('w:2:2', real=True, nonnegative=True) omegas = sp.symbols('omega:2:2', real=True) ws_conj = (sp.conjugate(w) for w in ws) w1, w2, w3, w4 = ws _, omega2, omega3, omega4 = omegas init_w_state = sp.ImmutableDenseMatrix([[w1], [w2 * sp.exp(1j * omega2)], [w3 * sp.exp(1j * omega3)], [w4 * sp.exp(1j * omega4)]]) xs2_sum = sum([1.0 * xs[i]**2 for i in range(4)]) ws2_sum = sum([1.0 * ws[i]**2 for i in range(4)]) state = sp.kronecker_product(state, init_w_state) state = swap(4, [1, 2]) @ state
if basis is None: state = sp.Matrix([*[[xi] for xi in x]]) else: state = sum([xi * b for xi, b in zip(x, basis)]) return normalize_state(state) # def product_encoding π = sp.pi I = sp.I I1 = sp.eye(2) print('--- 1-qubit state creation ---') s0 = sp.ImmutableDenseMatrix([[1], [0]]) state = s0 a = sp.symbols('a:20') o1 = U3(a[0], a[1], a[2]) state = o1 @ state pprint(state) print('--- Two 1-qubit tensor state creation ---') s0 = sp.ImmutableDenseMatrix([[1], [0]]) state = sp.kronecker_product(s0, s0) a = sp.symbols('a:20') o1 = sp.kronecker_product(U3(a[0], a[1], a[2]), U3(a[3], a[4], a[5])) state = o1 @ state pprint(state) print('--- 2-qubit state preparation ---')
def convert_to_c(args, expr, basename="expr", cfilepath="sp2clib.c", pathprefix=None, use_exisiting_so=True, additional_metadata=None): """ :param args: :param expr: :param basename: :param cfilepath: :param pathprefix: :param use_exisiting_so: either True (fastest), False (most secure) or "smart" (compromise). Optionally omit the generation of new c-code if an .so-file with appropriate name (value `True`) or expr-hash (option `"smart"`) already exists (True). :param additional_metadata: None or dict. Content will be stored inside the base64-coded metadata :return: python-callable wrapping the respective c-functions """ if pathprefix is None: pathprefix = path_of_caller() assert isinstance(pathprefix, basestring) cfilepath = os.path.join(pathprefix, cfilepath) sopath = _get_so_path(cfilepath) if sopath in loaded_so_files: # ensure to use actual information unload_lib(sopath) _loadlib(sopath) if isinstance(expr, sp.MatrixBase): shape = expr.shape # ensure immutable type expr_matrix = sp.ImmutableDenseMatrix(expr) scalar_flag = False else: scalar_flag = True shape = (1, 1) expr_matrix = sp.ImmutableDenseMatrix([expr]) # convert expr to pickle-string and calculate the hash # this is faster converting expr to str and then taking the hash fingerprint = reproducible_fast_hash(expr_matrix) if use_exisiting_so == "smart": md = get_meta_data(cfilepath) if md["fingerprint"] == fingerprint: use_exisiting_so = True else: print("Fingerprints of expression do not match.\n" "Regeneration of shared object.") use_exisiting_so = False if use_exisiting_so: if not os.path.isfile(sopath): print("Could not find {}. Create and compile new c-code.".format( sopath)) else: res = load_func(sopath) res.reused_c_code = True return res # use OrderedDict for reproducibility metadata = OrderedDict( fingerprint=fingerprint, timestamp=datetime.datetime.now().strftime(r"%Y-%m-%d-%H-%M-%S.%f"), nargs=len(args), args=args, # expr=expr_matrix, scalar_flag=scalar_flag, shape=expr_matrix.shape) if additional_metadata is None: additional_metadata = {} assert not set(metadata.keys()).intersection(additional_metadata.keys()) metadata.update(_dict_to_ordered_dict(additional_metadata)) metadata_s = b64encode(pickle.dumps(metadata)) _generate_ccode(args, expr_matrix, basename, cfilepath, shape, md=metadata_s) sopath = compile_ccode(cfilepath) sopath = ensure_valid_libpath(sopath) if sopath in loaded_so_files: # again ensure to use actual information unload_lib(sopath) _loadlib(sopath) res = load_func(sopath) res.reused_c_code = False res.metadata = metadata return res
def __init__(self): # We start out with all zeros |0000> self._dm = sp.ImmutableDenseMatrix([[1] + [0] * (2**4 - 1), *([[0] * (2**4)] * (2**4 - 1))]) self._swap_matrix = swap(4, [1, 2])
def RZ(angle): return sp.ImmutableDenseMatrix([ [sp.exp(-1j * angle / 2), 0], [0, sp.exp(1j * angle / 2)], ])