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)
Exemple #4
0
 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)
Exemple #7
0
 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_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_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)
Exemple #15
0
 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)
Exemple #18
0
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,
Exemple #19
0
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)
Exemple #20
0
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,
Exemple #21
0
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,
Exemple #24
0
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)))