def test_fast_substitute(self): f = generate_variables(2, name="f") substitutions = {} substitutions[Dagger(f[0]) * f[0]] = -f[0] * Dagger(f[0]) monomial = Dagger(f[0]) * f[0] lhs = Dagger(f[0]) * f[0] rhs = -f[0] * Dagger(f[0]) self.assertTrue(fast_substitute(monomial, lhs, rhs) == monomial.subs(lhs, rhs)) monomial = Dagger(f[0]) * f[0] ** 2 self.assertTrue(fast_substitute(monomial, lhs, rhs) == monomial.subs(lhs, rhs)) monomial = Dagger(f[0]) ** 2 * f[0] self.assertTrue(fast_substitute(monomial, lhs, rhs) == monomial.subs(lhs, rhs)) monomial = Dagger(f[0]) ** 2 * f[0] lhs = Dagger(f[0]) ** 2 rhs = -f[0] * Dagger(f[0]) self.assertTrue(fast_substitute(monomial, lhs, rhs) == monomial.subs(lhs, rhs)) g = generate_variables(2, name="g") monomial = 2 * g[0] ** 3 * g[1] * Dagger(f[0]) ** 2 * f[0] self.assertTrue(fast_substitute(monomial, lhs, rhs) == monomial.subs(lhs, rhs)) monomial = S.One self.assertTrue(fast_substitute(monomial, lhs, rhs) == monomial.subs(lhs, rhs)) monomial = 5 self.assertTrue(fast_substitute(monomial, lhs, rhs) == monomial) monomial = 2 * g[0] ** 3 * g[1] * Dagger(f[0]) ** 2 * f[0] + f[1] self.assertTrue(fast_substitute(monomial, lhs, rhs) == monomial.subs(lhs, rhs)) monomial = f[1] * Dagger(f[0]) ** 2 * f[0] lhs = f[1] rhs = 1.0 + f[0] self.assertTrue(fast_substitute(monomial, lhs, rhs) == expand(monomial.subs(lhs, rhs))) monomial = f[1] ** 2 * Dagger(f[0]) ** 2 * f[0] result = fast_substitute(fast_substitute(monomial, lhs, rhs), lhs, rhs) self.assertTrue(result == expand(monomial.subs(lhs, rhs)))
def test_apply_substitutions(self): def apply_correct_substitutions(monomial, substitutions): if isinstance(monomial, int) or isinstance(monomial, float): return monomial original_monomial = monomial changed = True while changed: for lhs, rhs in substitutions.items(): monomial = monomial.subs(lhs, rhs) if original_monomial == monomial: changed = False original_monomial = monomial return monomial length, h, U, t = 2, 3.8, -6, 1 fu = generate_variables(length, name="fu") fd = generate_variables(length, name="fd") _b = flatten([fu, fd]) hamiltonian = 0 for j in range(length): hamiltonian += U * (Dagger(fu[j]) * Dagger(fd[j]) * fd[j] * fu[j]) hamiltonian += -h / 2 * (Dagger(fu[j]) * fu[j] - Dagger(fd[j]) * fd[j]) for k in get_neighbors(j, len(fu), width=1): hamiltonian += -t * Dagger(fu[j]) * fu[k] - t * Dagger(fu[k]) * fu[j] hamiltonian += -t * Dagger(fd[j]) * fd[k] - t * Dagger(fd[k]) * fd[j] substitutions = fermionic_constraints(_b) monomials = expand(hamiltonian).as_coeff_mul()[1][0].as_coeff_add()[1] substituted_hamiltonian = sum([apply_substitutions(monomial, substitutions) for monomial in monomials]) correct_hamiltonian = sum([apply_correct_substitutions(monomial, substitutions) for monomial in monomials]) self.assertTrue(substituted_hamiltonian == expand(correct_hamiltonian))
def test_ground_state(self): length, n, h, U, t = 2, 0.8, 3.8, -6, 1 fu = generate_variables(length, name="fu") fd = generate_variables(length, name="fd") _b = flatten([fu, fd]) monomials = [[ci for ci in _b]] monomials[-1].extend([Dagger(ci) for ci in _b]) monomials.append([cj * ci for ci in _b for cj in _b]) monomials.append([Dagger(cj) * ci for ci in _b for cj in _b]) monomials[-1].extend([cj * Dagger(ci) for ci in _b for cj in _b]) monomials.append([Dagger(cj) * Dagger(ci) for ci in _b for cj in _b]) hamiltonian = 0 for j in range(length): hamiltonian += U * (Dagger(fu[j]) * Dagger(fd[j]) * fd[j] * fu[j]) hamiltonian += -h / 2 * (Dagger(fu[j]) * fu[j] - Dagger(fd[j]) * fd[j]) for k in get_neighbors(j, len(fu), width=1): hamiltonian += -t * Dagger(fu[j]) * fu[k] - t * Dagger(fu[k]) * fu[j] hamiltonian += -t * Dagger(fd[j]) * fd[k] - t * Dagger(fd[k]) * fd[j] momentequalities = [n - sum(Dagger(br) * br for br in _b)] sdpRelaxation = SdpRelaxation(_b, verbose=0) sdpRelaxation.get_relaxation( -1, objective=hamiltonian, momentequalities=momentequalities, substitutions=fermionic_constraints(_b), extramonomials=monomials, ) sdpRelaxation.solve() s = 0.5 * (sum((Dagger(u) * u) for u in fu) - sum((Dagger(d) * d) for d in fd)) magnetization = get_xmat_value(s, sdpRelaxation) self.assertTrue(abs(magnetization - 0.021325317328560453) < 10e-5)
def __init__(self, lattice_length, lattice_width, solver, outputDir, periodic=0, window_length=0, removeequalities=False, parallel=True): SecondQuantizedModel.__init__(self, lattice_length, lattice_width, solver, outputDir, periodic, window_length, removeequalities, parallel=parallel) self._fu = generate_variables( 'fu', lattice_length * lattice_width, commutative=False) self._fd = generate_variables( 'fd', lattice_length * lattice_width, commutative=False) self._b = flatten([self._fu, self._fd]) self.mu, self.t, self.h, self.U = 0, 0, 0, 0
def test_solving(self): x = generate_variables(2, commutative=True) g0 = 4 * x[0] ** 2 + x[0] * x[1] - 4 * x[1] ** 2 - 2.1 * x[0] ** 4 + 4 * x[1] ** 4 + x[0] ** 6 / 3 sdpRelaxation = SdpRelaxation(x) sdpRelaxation.get_relaxation(3, objective=g0) sdpRelaxation.solve() self.assertTrue(abs(sdpRelaxation.primal + 1.0316282672706911) < 10e-5)
def test_solving_with_sdpa(self): x = generate_variables('x', 2, commutative=True) sdpRelaxation = SdpRelaxation(x) sdpRelaxation.get_relaxation(2, objective=x[0]*x[1] + x[1]*x[0], inequalities=[-x[1]**2 + x[1] + 0.5], substitutions={x[0]**2: x[0]}) sdpRelaxation.solve(solver="sdpa") self.assertTrue(abs(sdpRelaxation.primal + 0.7320505301965234) < 10e-5)
def test_solving(self): x = generate_variables('x', 2, commutative=True) g0 = 4 * x[0] ** 2 + x[0] * x[1] - 4 * x[1] ** 2 - \ 2.1 * x[0] ** 4 + 4 * x[1] ** 4 + x[0] ** 6 / 3 sdpRelaxation = SdpRelaxation(x) sdpRelaxation.get_relaxation(3, objective=g0) sdpRelaxation.solve() self.assertTrue(abs(sdpRelaxation.primal + 1.0316282672706911) < 10e-5)
def test_ground_state_energy(self): N = 3 a = generate_variables(N, name="a") substitutions = bosonic_constraints(a) hamiltonian = sum(Dagger(a[i]) * a[i] for i in range(N)) sdpRelaxation = SdpRelaxation(a, verbose=0) sdpRelaxation.get_relaxation(1, objective=hamiltonian, substitutions=substitutions) sdpRelaxation.solve() self.assertTrue(abs(sdpRelaxation.primal) < 10e-5)
def setUp(self): X = generate_variables(2, hermitian=True) self.sdpRelaxation = SdpRelaxation(X) self.sdpRelaxation.get_relaxation( 2, objective=X[0] * X[1] + X[1] * X[0], inequalities=[-X[1] ** 2 + X[1] + 0.5], substitutions={X[0] ** 2: X[0]}, )
def test_chordal_extension(self): X = generate_variables(3, commutative=True) inequalities = [1 - X[0] ** 2 - X[1] ** 2, 1 - X[1] ** 2 - X[2] ** 2] sdpRelaxation = SdpRelaxation(X) sdpRelaxation.get_relaxation( 2, objective=X[1] - 2 * X[0] * X[1] + X[1] * X[2], inequalities=inequalities, chordal_extension=True ) sdpRelaxation.solve() self.assertTrue(abs(sdpRelaxation.primal + 2.2443690631722637) < 10e-5)
def test_chordal_extension(self): X = generate_variables('x', 3, commutative=True) inequalities = [1-X[0]**2-X[1]**2, 1-X[1]**2-X[2]**2] sdpRelaxation = SdpRelaxation(X) sdpRelaxation.get_relaxation(2, objective=X[1] - 2*X[0]*X[1] + X[1]*X[2], inequalities=inequalities, chordal_extension=True) sdpRelaxation.solve() self.assertTrue(abs(sdpRelaxation.primal + 2.2443690631722637) < 10e-5)
def test_max_cut(self): W = np.diag(np.ones(8), 1) + np.diag(np.ones(7), 2) + np.diag([1, 1], 7) + np.diag([1], 8) W = W + W.T Q = (np.diag(np.dot(np.ones(len(W)).T, W)) - W) / 4 x = generate_variables(len(W), commutative=True) equalities = [xi ** 2 - 1 for xi in x] objective = -np.dot(x, np.dot(Q, np.transpose(x))) sdpRelaxation = SdpRelaxation(x) sdpRelaxation.get_relaxation(1, objective=objective, equalities=equalities, removeequalities=True) sdpRelaxation.solve() self.assertTrue(abs(sdpRelaxation.primal + 4.5) < 10e-5)
def test_max_cut(self): W = np.diag(np.ones(8), 1) + np.diag(np.ones(7), 2) + \ np.diag([1, 1], 7) + np.diag([1], 8) W = W + W.T Q = (np.diag(np.dot(np.ones(len(W)).T, W)) - W) / 4 x = generate_variables('x', len(W), commutative=True) equalities = [xi ** 2 - 1 for xi in x] objective = -np.dot(x, np.dot(Q, np.transpose(x))) sdpRelaxation = SdpRelaxation(x) sdpRelaxation.get_relaxation(1, objective=objective, equalities=equalities, removeequalities=True) sdpRelaxation.solve() self.assertTrue(abs(sdpRelaxation.primal + 13.5) < 10e-5)
def __init__(self, lattice_length, lattice_width, solver, outputDir, periodic, window_length, removeequalities, parallel=True): LatticeModel.__init__(self, lattice_length, lattice_width, solver, outputDir, removeequalities) self._b = generate_variables('b', lattice_length * lattice_width, commutative=False) self._level = -1 self._periodic = periodic self.nmax = None self.localNmax = None self.n = None self.nmin = None if window_length == 0: self.window_length = lattice_length * lattice_width else: if self._lattice_width != 1: raise NotImplementedError( "Windowed models in more than 1D not implemented!") self.window_length = window_length self._parallel = parallel self._debug_mode = False
def test_maximum_violation(self): def expectation_values(measurement, outcomes): exp_values = [] for k in range(len(measurement)): exp_value = 0 for j in range(len(measurement[k])): exp_value += outcomes[k][j] * measurement[k][j] exp_values.append(exp_value) return exp_values E = generate_variables(8, name="E", hermitian=True) M, outcomes = [], [] for i in range(4): M.append([E[2 * i], E[2 * i + 1]]) outcomes.append([1, -1]) A = [M[0], M[1]] B = [M[2], M[3]] substitutions = projective_measurement_constraints(A, B) C = expectation_values(M, outcomes) chsh = -(C[0] * C[2] + C[0] * C[3] + C[1] * C[2] - C[1] * C[3]) sdpRelaxation = SdpRelaxation(E, verbose=0) sdpRelaxation.get_relaxation(1, objective=chsh, substitutions=substitutions) sdpRelaxation.solve() self.assertTrue(abs(sdpRelaxation.primal + 2 * np.sqrt(2)) < 10e-5)
on Optimization, SIAM, 2010, 20, 2157-2180. Created on Fri May 10 09:45:11 2013 @author: Peter Wittek """ from ncpol2sdpa import generate_variables, SdpRelaxation, write_to_sdpa # Number of variables n_vars = 2 # Level of relaxation level = 2 # Get commutative variables X = generate_variables(n_vars, commutative=True) # Define the objective function obj = X[0] * X[1] + X[1] * X[0] # Inequality constraints inequalities = [-X[1] ** 2 + X[1] + 0.5] # Simple monomial substitutions monomial_substitution = {} monomial_substitution[X[0] ** 2] = X[0] # Obtain SDP relaxation sdpRelaxation = SdpRelaxation(X) sdpRelaxation.get_relaxation(level, objective=obj, inequalities=inequalities, substitutions=monomial_substitution)
on Optimization, SIAM, 2010, 20, 2157-2180. Created on Fri May 10 09:45:11 2013 @author: Peter Wittek """ from ncpol2sdpa import generate_variables, SdpRelaxation, write_to_sdpa # Number of variables n_vars = 2 # Level of relaxation level = 2 # Get commutative variables X = generate_variables(n_vars, commutative=True) # Define the objective function obj = X[0] * X[1] + X[1] * X[0] # Inequality constraints inequalities = [-X[1]**2 + X[1] + 0.5] # Simple monomial substitutions monomial_substitution = {} monomial_substitution[X[0]**2] = X[0] # Obtain SDP relaxation sdpRelaxation = SdpRelaxation(X) sdpRelaxation.get_relaxation(level, objective=obj,
def expectation_values(measurement, outcomes): exp_values = [] for k in range(len(measurement)): exp_value = 0 for j in range(len(measurement[k])): exp_value += outcomes[k][j] * measurement[k][j] exp_values.append(exp_value) return exp_values # Number of Hermitian variables n_vars = 8 # Level of relaxation level = 1 # Get Hermitian variables E = generate_variables(n_vars, name='E', hermitian=True) # Define measurements and outcomes M, outcomes = [], [] for i in range(int(n_vars / 2)): M.append([E[2 * i], E[2 * i + 1]]) outcomes.append([1, -1]) # Define which measurements Alice and Bob have A = [M[0], M[1]] B = [M[2], M[3]] substitutions = projective_measurement_constraints(A, B) C = expectation_values(M, outcomes)
on Optimization, SIAM, 2010, 20, 2157-2180. Created on Fri May 10 09:45:11 2013 @author: Peter Wittek """ from ncpol2sdpa import generate_variables, SdpRelaxation, convert_to_picos # Number of Hermitian variables n_vars = 2 # Level of relaxation level = 2 # Get Hermitian variables X = generate_variables(n_vars, hermitian=True) # Define the objective function obj = X[0] * X[1] + X[1] * X[0] # Inequality constraints inequalities = [-X[1]**2 + X[1] + 0.5] # Equality constraints equalities = [] equalities.append(X[0]**2 - X[0]) # Obtain SDP relaxation sdpRelaxation = SdpRelaxation(X) sdpRelaxation.get_relaxation(level, objective=obj,
Section 5.12 of the following paper: Henrion, D.; Lasserre, J. & Löfberg, J. GloptiPoly 3: moments, optimization and semidefinite programming. Optimization Methods & Software, 2009, 24, 761-779 Created on Thu May 15 12:12:40 2014 @author: wittek """ import numpy as np from ncpol2sdpa import SdpRelaxation, write_to_sdpa, generate_variables W = np.diag(np.ones(8), 1) + np.diag(np.ones(7), 2) + np.diag([1, 1], 7) + \ np.diag([1], 8) W = W + W.T n = len(W) e = np.ones(n) Q = (np.diag(np.dot(e.T, W)) - W) / 4 x = generate_variables(n, commutative=True) equalities = [xi ** 2 - 1 for xi in x] objective = -np.dot(x, np.dot(Q, np.transpose(x))) level = 1 sdpRelaxation = SdpRelaxation(x) sdpRelaxation.get_relaxation(level, objective=objective, equalities=equalities, removeequalities=True) write_to_sdpa(sdpRelaxation, 'max_cut.dat-s')
on Optimization, SIAM, 2010, 20, 2157-2180. Created on Fri May 10 09:45:11 2013 @author: Peter Wittek """ from ncpol2sdpa import generate_variables, SdpRelaxation, convert_to_picos # Number of Hermitian variables n_vars = 2 # Level of relaxation level = 2 # Get Hermitian variables X = generate_variables(n_vars, hermitian=True) # Define the objective function obj = X[0] * X[1] + X[1] * X[0] # Inequality constraints inequalities = [-X[1] ** 2 + X[1] + 0.5] # Equality constraints equalities = [] equalities.append(X[0] ** 2 - X[0]) # Obtain SDP relaxation sdpRelaxation = SdpRelaxation(X) sdpRelaxation.get_relaxation(level, objective=obj, inequalities=inequalities,
import time from sympy.physics.quantum.dagger import Dagger from ncpol2sdpa import generate_variables, bosonic_constraints, SdpRelaxation,\ write_to_sdpa # Level of relaxation level = 1 # Number of variables N = 3 # Parameters for the Hamiltonian hbar, omega = 1, 1 # Define ladder operators a = generate_variables(N, name='a') hamiltonian = 0 for i in range(N): hamiltonian += hbar * omega * (Dagger(a[i]) * a[i] + 0.5) substitutions, equalities = bosonic_constraints(a) inequalities = [] time0 = time.time() # Obtain SDP relaxation print("Obtaining SDP relaxation...") sdpRelaxation = SdpRelaxation(a, verbose=1) sdpRelaxation.get_relaxation(level, objective=hamiltonian, equalities=equalities, substitutions=substitutions,
def get_factorization_constraints(parties, moments, substitutions, level, all_parties=False, return_column_names=False): '''Creates all the constraints in moments related to n-locality, namely the factorizations <P_i P_j...> = <P_i><P_j>..., where P_i, P_j, ... are collections of operators of spacelike-separated parties i, j... :param parties: list of measurements for each of the parties spacelike separated. The structure is [party1, party2...], where party_i are the measurements of party i, arranged in the structure [meas1, meas2...], where meas_i is a list containing the symbols of the operators of measurement i. :type parties: list of lists of lists of sympy.core.Symbol :param moments: known moments obtained with get_moment_constraints. :type moments: dict :param substitutions: Measurement constraints (commuting, projective...) for the operators involved. Required by get_all_monomials. :type substitutions: dict :param level: level of the moment matrix :type level: int :param all_parties: Optional flag for specifying whether the columns for all parties should be created instead of a minimal set. :type all_parties: bool :param return_column_names: Optional flag to return the moments to which the extra columns correspond :type return_column_names: bool :returns momentsbilocal: dict with <P_i P_j...> = <P_i><P_j>... constraints. :returns extracolumns: list of sympy.core.Symbol that correspond to the extra monomials created. :returns columnsnames: list of original monomials corresponding to the names of the extra monomials created. ''' # Factorizations will at most be of size 1|2*level-1 parties_moments = [ get_all_monomials(flatten(party), None, substitutions, 2 * level - 1)[1:] for party in parties ] # Strictly speaking, we need to build extra columns of all except one party # to sucessfully implement all factorization constraints. if not all_parties: parties_moments = parties_moments[:-1] # Generate commuting symbols for all the additional columns parties_columns = [ generate_variables( str(party_moments[0])[0].split('_')[0].lower() + '_', len(party_moments)) for party_moments in parties_moments ] # Substitute symbols whose values are known parties_columns = [[ moments.get(parties_moments[i][parties_columns[i].index(element)], element) for element in party ] for i, party in enumerate(parties_columns)] # Obtain actual additional columns extracolumns = [ extra for extra in flatten(parties_columns) if isinstance(extra, Symbol) ] columnsnames = [ symbol for i, symbol in enumerate(flatten(parties_moments)) if flatten(parties_columns)[i] in extracolumns ] # Add identities for later computations partiesplus1 = [ party_moments + [S.One] for party_moments in parties_moments ] extramomentsplus1 = [extracols + [1] for extracols in parties_columns] momentsbilocal = {} for monomial in get_all_monomials(flatten(parties), None, substitutions, 2 * level)[1:]: monomial = monomial.as_ordered_factors() party_monomials = [[ element for element in monomial if element in flatten(party) ] for party in parties] factors = [prod(party) for party in party_monomials] if len(monomial) <= level: for z in flatten([extracolumns, 1]): key = prod([factor for factor in [z] + factors if factor != 1]) if all_parties: item = prod([z] + [ extramomentsplus1[i][partiesplus1[i].index(factors[i])] for i in range(len(factors)) ]) else: item = prod([z] + [ extramomentsplus1[i][partiesplus1[i].index(factors[i])] for i in range(len(factors) - 1) ] + [moments.get(factors[-1], factors[-1])]) if key != item: momentsbilocal[key] = item else: if prod([ len(party_monomial) < 2 * level for party_monomial in party_monomials ]): key = prod([factor for factor in factors if factor != 1]) if all_parties: item = prod([ extramomentsplus1[i][partiesplus1[i].index(factors[i])] for i in range(len(factors)) ]) else: item = prod([ extramomentsplus1[i][partiesplus1[i].index(factors[i])] for i in range(len(factors) - 1) ] + [moments.get(factors[-1], factors[-1])]) if key != item: momentsbilocal[key] = item if return_column_names: return momentsbilocal, extracolumns, columnsnames return momentsbilocal, extracolumns
""" import time from sympy.physics.quantum.dagger import Dagger from ncpol2sdpa import generate_variables, SdpRelaxation,\ bosonic_constraints # Level of relaxation level = 1 # Number of variables N = 3 # Parameters for the Hamiltonian hbar, omega = 1, 1 # Define ladder operators a = generate_variables(N, name='a') substitutions = bosonic_constraints(a) hamiltonian = sum(hbar * omega * (Dagger(a[i]) * a[i]) for i in range(N)) time0 = time.time() # Obtain SDP relaxation sdpRelaxation = SdpRelaxation(a, verbose=1) sdpRelaxation.get_relaxation(level, objective=hamiltonian, substitutions=substitutions) # Export relaxation to SDPA format sdpRelaxation.write_to_file("harmonic_oscillator.dat-s") print('%0.2f s' % ((time.time() - time0)))