Skip to content

Tfim simulation using 2 CNOT rather than 3 CNOT#94

Open
shangtai wants to merge 13 commits intomainfrom
tfim_2cnot
Open

Tfim simulation using 2 CNOT rather than 3 CNOT#94
shangtai wants to merge 13 commits intomainfrom
tfim_2cnot

Conversation

@shangtai
Copy link
Contributor

This pull request is to address issue 70 where we consider the special TFIM model:

$$H^{(a)}=X_{a}X_{a+1}+B_{a}Z_{a}$$

where we can express the time evolution as

$$e^{-itH^{(a)}}=CNOT(a,a+1)e^{-it(X_a+B_aZ_a)}CNOT(a,a+1).$$

@shangtai shangtai linked an issue Oct 24, 2024 that may be closed by this pull request
@shangtai shangtai marked this pull request as draft October 24, 2024 17:06
@shangtai shangtai marked this pull request as ready for review October 29, 2024 19:40
steps: int = None
B_a: float = None

def circuit(self, a, t_duration, B_a, steps=None, order=None):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def circuit(self, a, t_duration, B_a, steps=None, order=None):
def circuit(self, t_duration, steps=None, order=None):

This class must implement eo.circuit(0.1) without requiring other parameters.

What is a?

Copy link
Contributor Author

@shangtai shangtai Nov 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use the notation in the paper where a is an index and B_a is another parameter.

$$H^{(a)}=X_{a}X_{a+1}+B_{a}Z_{a}$$


for _ in range(steps):
# Apply time evolution for X(a) + B_a * Z(a)
circuit += self._time_evolution_step(a, dt, B_a)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is commuting so it's equivalent to
circuit += self._time_evolution_step(a, t_duration, B_a)

Once you have for a in range(self.nqubits): (TFIM evolution oracle should be implemented for nqubits) then you need to do the CNOTs before every dt step here

Copy link
Contributor

@marekgluza marekgluza left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please provide test code demonstrating the functioning of this CNOT decomposition:

  • as the number of steps increase the comparison with H_TFIM_symbolic.exp(t) should be improving
  • in XXZ we used 2nd order, here we should do that too


# Time evolution under the transverse field Ising model Hamiltonian
# exp(-i t (X(a) + B_a * Z(a)))
dt = t_duration / steps # Divide the time duration for Trotterization if needed
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
dt = t_duration / steps # Divide the time duration for Trotterization if needed
dt = t_duration / steps # Divide the time duration for Trotterization if needed
for a in range(nqubits:
circuit.add(gates.CNOT(a, a + 1))
circuit += self._time_evolution_step(a, dt, B_a)
circuit.add(gates.CNOT(a, a + 1))

and then loop this over _ in range(steps)

Copy link
Contributor Author

@shangtai shangtai Nov 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

n_qubits = 3
h_coeff = 1
hamiltonian = SymbolicHamiltonian(nqubits=n_qubits)

oracle = TFIM_EvolutionOracle(h=hamiltonian, evolution_oracle_type="trotter", steps=1, B_a=0, order=2)

circuit = oracle.circuit(t_duration=1.0)

unitary = circuit.unitary()


from qibo import hamiltonians
from numpy.linalg import norm

def our_TFIM(nqubits, h: float = 0.0, dense: bool = True, backend=None):
        def multikron(matrix_list):
        """Calculates Kronecker product of a list of matrices."""
        return reduce(np.kron, matrix_list)

    from qibo.backends import matrices

    matrix = (
        - multikron([matrices.X, matrices.X]) - h * multikron([matrices.Z, matrices.I])
    )
    terms = [hamiltonians.terms.HamiltonianTerm(matrix, i, i + 1) for i in range(nqubits - 1)]
    terms.append(hamiltonians.terms.HamiltonianTerm(matrix, nqubits - 1, 0))
    ham = SymbolicHamiltonian(backend=backend)
    ham.terms = terms
    return ham

ham = our_TFIM(nqubits=n_qubits, h=h_coeff, dense=False)
truth = ham.exp(1)
verification_norm = []
for step in range(1, 21):
    oracle = TFIM_EvolutionOracle(h=hamiltonian, evolution_oracle_type="trotter", steps=step, B_a=h_coeff, order=2)
    circuit = oracle.circuit(t_duration=1.0)
    unitary = circuit.unitary()
    #print(norm(truth-unitary))
    verification_norm.append(norm(truth-unitary))

import matplotlib.pyplot as plt
x = np.array([i for i in range(1, 21)])
plt.plot(x, verification_norm, 'o')
plt.title("verification of TFIM 2 CNOT implementation")
plt.xlabel("steps")
plt.ylabel("norm of difference")

plt.show()

produces the following graph:

Screenshot 2024-11-20 at 3 19 27 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TFIM 2 CNOT not 3 CNOT compiling

2 participants