QHack 2023 challenge: A Noisy Heisenberg Model

Use this topic to ask your questions about the QHack 2023 challenge: A Noisy Heisenberg Model

HI Pennylane Team, I’ve been a bit confused with the problem statement and the coding that I’ve been doing. Can you please guide me on it? Following is the code.
I’m unsure whether I understand the problem statement correctly or the implementation issue, so I need your suggestions.

t=0.1
    while t<=time:
        for d in range(depth): 
            for i in range(num_wires-1):
                qml.CNOT([i,i+1])
                qml.DepolarizingChannel(p, wires=i+1)
                qml.RX(couplings[0]*t, wires=i+1)
                qml.CNOT([i+1,i])
                qml.DepolarizingChannel(p, wires=i)
                
                qml.CNOT([i,i+1])
                qml.DepolarizingChannel(p, wires=i+1)
                qml.RY(couplings[1]*t, wires=i+1)
                qml.CNOT([i+1,i])
                qml.DepolarizingChannel(p, wires=i)
        
                qml.CNOT([i,i+1])
                qml.DepolarizingChannel(p, wires=i+1)
                qml.RZ(couplings[2]*t, wires=i+1)
                qml.CNOT([i+1,i])
                qml.DepolarizingChannel(p, wires=i)
        
            for i in range(num_wires):
                qml.RX(couplings[3]*t, wires=i)
        t+=0.01
    return qml.state()

Hi @roysuman088

Your implementation is indeed incorrect and I think it’s due to a combination of understanding the concepts and implementation details.

I’d say the main one is that you don’t need a while loop. When you use a gate to evolve a state up to time t, you’re evolving it from time 0 up to time t. So here what you’re actually doing is evolving many times from time 0 to different t times, which is not what the challenge asks.

You may also want to draw your circuit to see if it’s actually looking the way you expect. I hope this helps!

Hello,

Can someone help me understand why my implementation does not work ? I am very close from the expected answer but not close enough.

# Put your code here #
N = num_wires
J_x, J_y, J_z, h = couplings
for j in range(1, depth+1):
    for i in range(N):
        # implementing ising XX
        qml.RY(np.pi/2, i)
        qml.RY(np.pi/2, (i+1)%N)
        
        qml.CNOT([i, (i+1)%N])
        qml.DepolarizingChannel(p, (i+1)%N)
        qml.RZ(-2*J_x*time/depth, (i+1)%N)
        qml.CNOT([i, (i+1)%N])
        qml.DepolarizingChannel(p, (i+1)%N)
        
        qml.RY(-np.pi/2, i)
        qml.RY(-np.pi/2, (i+1)%N)

        # implementing ising YY
        qml.RX(np.pi/2, i)
        qml.RX(np.pi/2, (i+1)%N)
        
        qml.CNOT([i, (i+1)%N])
        qml.DepolarizingChannel(p, (i+1)%N)
        qml.RZ(-2*J_y*time/depth, (i+1)%N)
        qml.CNOT([i, (i+1)%N])
        qml.DepolarizingChannel(p, (i+1)%N)
        
        qml.RX(-np.pi/2, i)
        qml.RX(-np.pi/2, (i+1)%N)

        # implementing ising ZZ
        qml.CNOT([i, (i+1)%N])
        qml.DepolarizingChannel(p, (i+1)%N)
        qml.RZ(-2*J_z*time/depth, (i+1)%N)
        qml.CNOT([i, (i+1)%N])
        qml.DepolarizingChannel(p, (i+1)%N)

        # implementing X
        qml.RX(-2*h*time/depth, i)
        
return qml.state()

Thanks

Hi @yoshypdf ,

It looks like you’ve got some gates wrong and you’re overcomplicating yourself in some things. For example you don’t need to use modulo %. You’ve also got errors in the ranges you’re using for i and j. Why don’t you try running this locally or on Google Colab for a small circuit and trying to draw it or run it? That can help you debug it!

Hello all,

I am very close to getting the correct result, but I can’t figure out what I’m getting wrong, any help will be appreciated! My approach was to decompose the RZZ, RYY, and RXX gates and then just apply them to every pair of wires in the closed loop.

    # Put your code here #

    def RXX_decomposed(theta, wires, p):
        """Decomposes the RXX gate using RX, RY, RZ, and CNOT gates with noise after each CNOT.
    
        Args:
            theta (float): The rotation angle.
            wires (list): The two qubits the gate acts on.
            p (float): The depolarization probability after each CNOT gate.
        """
        qml.Hadamard(wires=wires[0])
        qml.Hadamard(wires=wires[1])
        qml.CNOT(wires=[wires[0], wires[1]])
        qml.DepolarizingChannel(p, wires=wires[1])
        qml.RZ(theta, wires=wires[1])
        qml.CNOT(wires=[wires[0], wires[1]])
        qml.DepolarizingChannel(p, wires=wires[1])
        qml.Hadamard(wires=wires[0])
        qml.Hadamard(wires=wires[1])

    def RYY_decomposed(theta, wires, p):
        """Decomposes the RYY gate using RX, RY, RZ, and CNOT gates with noise after each CNOT.
    
        Args:
            theta (float): The rotation angle.
            wires (list): The two qubits the gate acts on.
            p (float): The depolarization probability after each CNOT gate.
        """
        qml.RX(np.pi / 2, wires=wires[0])
        qml.RX(np.pi / 2, wires=wires[1])
        qml.CNOT(wires=[wires[0], wires[1]])
        qml.DepolarizingChannel(p, wires=wires[1])
        qml.RZ(theta, wires=wires[1])
        qml.CNOT(wires=[wires[0], wires[1]])
        qml.DepolarizingChannel(p, wires=wires[1])
        qml.RX(-np.pi / 2, wires=wires[0])
        qml.RX(-np.pi / 2, wires=wires[1])

    def RZZ_decomposed(theta, wires, p):
        """Decomposes the RZZ gate using RX, RY, RZ, and CNOT gates with noise after each CNOT.
    
        Args:
            theta (float): The rotation angle.
            wires (list): The two qubits the gate acts on.
            p (float): The depolarization probability after each CNOT gate.
        """
        qml.CNOT(wires=[wires[0], wires[1]])
        qml.DepolarizingChannel(p, wires=wires[1])
        qml.RZ(theta, wires=wires[1])
        qml.CNOT(wires=[wires[0], wires[1]])
        qml.DepolarizingChannel(p, wires=wires[1])

    # Unpack couplings
    Jx, Jy, Jz, h = couplings
    n_qubits = num_wires

    dt = time / depth  # Time step for Trotterization

    def heisenberg_step():

        # Apply local magnetic field in X direction
        for i in range(num_wires):
            qml.RX(-h * dt, wires=i)
            
        # ZZ coupling
        for i in range(num_wires):
            RZZ_decomposed(-Jz * dt, wires=[i, (i + 1) % num_wires], p=p)

        # YY coupling
        for i in range(num_wires):
            RYY_decomposed(-Jy * dt, wires=[i, (i + 1) % num_wires], p=p)

        # XX coupling
        for i in range(num_wires):
            RXX_decomposed(-Jx * dt, wires=[i, (i + 1) % num_wires], p=p)


    # Apply Trotter steps
    for _ in range(depth):
        heisenberg_step()
        
    return qml.state()