예제 #1
0
 def TeorThermDensity(self):
     '''
     Build theoretical thermal density
     '''
     # Exponentiate with eigenvectors
     d = np.exp(-self.beta * self.HamMatEnergies)
     return np.matmul(
         np.matmul(self.HamMatEstates, d),
         self.HamMatEstates.conj().T
     )
def natural_gradient(params):
    """Calculate the natural gradient of the qnode() cost function.

    The code you write for this challenge should be completely contained within this function
    between the # QHACK # comment markers.

    You should evaluate the metric tensor and the gradient of the QNode, and then combine these
    together using the natural gradient definition. The natural gradient should be returned as a
    NumPy array.

    The metric tensor should be evaluated using the equation provided in the problem text. Hint:
    you will need to define a new QNode that returns the quantum state before measurement.

    Args:
        params (np.ndarray): Input parameters, of dimension 6

    Returns:
        np.ndarray: The natural gradient evaluated at the input parameters, of dimension 6
    """

    natural_grad = np.zeros(6)
    # QHACK #
    gradient = np.zeros([6], dtype=np.float64)

    for i in range(6):
        params[i] += 0.1
        forward = qnode(params)
        params[i] -= 0.2
        backward = qnode(params)
        params[i] += 0.1
        gradient[i] = (forward - backward) / (2 * np.sin(0.1))

    @qml.qnode(dev)
    def fubini_qnode(params):
        variational_circuit(params)
        return qml.state()

    fubini = np.zeros([6, 6], dtype=np.float64)

    base = np.conj(fubini_qnode(params))

    def fubini_calculate():
        for i in range(6):
            for j in range(6):
                params[i] += np.pi / 2
                params[j] += np.pi / 2
                plusplus = np.abs(np.dot(base, fubini_qnode(params)))**2
                params[j] -= np.pi
                plusminus = np.abs(np.dot(base, fubini_qnode(params)))**2
                params[i] -= np.pi
                minusminus = np.abs(np.dot(base, fubini_qnode(params)))**2
                params[j] += np.pi
                minusplus = np.abs(np.dot(base, fubini_qnode(params)))**2
                fubini[i, j] = (-plusplus - minusminus + plusminus +
                                minusplus) / 8
                params[i] += np.pi / 2
                params[j] -= np.pi / 2

    fubini_calculate()

    natural_grad = np.matmul(np.linalg.inv(fubini), gradient)
    # QHACK #

    return natural_grad
def natural_gradient(params):
    """Calculate the natural gradient of the qnode() cost function.

    The code you write for this challenge should be completely contained within this function
    between the # QHACK # comment markers.

    You should evaluate the metric tensor and the gradient of the QNode, and then combine these
    together using the natural gradient definition. The natural gradient should be returned as a
    NumPy array.

    The metric tensor should be evaluated using the equation provided in the problem text. Hint:
    you will need to define a new QNode that returns the quantum state before measurement.

    Args:
        params (np.ndarray): Input parameters, of dimension 6

    Returns:
        np.ndarray: The natural gradient evaluated at the input parameters, of dimension 6
    """

    natural_grad = np.zeros(6)

    # QHACK #
    @qml.qnode(dev)
    def probabs(params, i):
        variational_circuit(params)
        return qml.probs(int(i))

    def state(params):
        qstate = np.zeros([
            8,
        ])

        prob0 = probabs(params, 0)
        prob1 = probabs(params, 1)
        prob2 = probabs(params, 2)

        index = 0
        for i in range(2):
            for j in range(2):
                for k in range(2):
                    qstate[index] = np.abs(
                        np.sqrt((prob0[i] * prob1[j] * prob2[k])))
                    index += 1
        normalise = np.vdot(qstate, qstate)
        normalise = 1 / np.abs((np.sqrt(normalise)))
        qstate = normalise * qstate

        return qstate

    def getTensorValue(params, i, j, qstate):

        params1 = params.copy()
        params1[i], params1[j] = params[i] + np.pi / 2, params[j] + np.pi / 2

        params2 = params.copy()
        params2[i], params2[j] = params[i] + np.pi / 2, params[j] - np.pi / 2

        params3 = params.copy()
        params3[i], params3[j] = params[i] - np.pi / 2, params[j] + np.pi / 2

        params4 = params.copy()
        params4[i], params4[j] = params[i] - np.pi / 2, params[j] - np.pi / 2

        answer = ((-(np.abs(np.vdot(qstate, state(params1))))**2 +
                   (np.abs(np.vdot(qstate, state(params2))))**2 +
                   (np.abs(np.vdot(qstate, state(params3))))**2 -
                   (np.abs(np.vdot(qstate, state(params4))))**2) / 8)

        return answer

    def PST(w, i):
        shifted_g = w.copy()
        shifted_g[i] += np.pi / 2
        pst_g_plus = qnode(shifted_g)

        shifted_g[i] -= np.pi
        pst_g_minus = qnode(shifted_g)

        return (pst_g_plus - pst_g_minus) / (2 * np.sin(np.pi / 2))

    qstate = state(params)
    tensor = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0],
              [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]

    for i in range(6):
        for j in range(6):
            tensor[i][j] = getTensorValue(params, i, j, qstate)

    gradient = [0, 0, 0, 0, 0, 0]
    for i in range(6):
        gradient[i] = PST(params, i)

    tensor_inv = np.linalg.inv(tensor)

    natural_grad = np.matmul(tensor_inv, gradient)
    # QHACK #

    return natural_grad
예제 #4
0
def U5f():
    return np.matmul(U_T32, U_T21)
예제 #5
0
def U6f():
    return np.matmul(U_T12, U_T21)
예제 #6
0
def U3f():
    return np.matmul(U_T32, U_T31)
예제 #7
0
def U4f():
    return np.matmul(U_T12, U_T31)
예제 #8
0
def U2f():
    return np.matmul(U_T12, U_T41)
예제 #9
0
def U1f():
    return np.matmul(U_T32, U_T41)
예제 #10
0
def U8f():
    return np.matmul(U_T12, U_T11)
예제 #11
0
def U7f():
    return np.matmul(U_T32, U_T11)
예제 #12
0
def natural_gradient(params):
    """Calculate the natural gradient of the qnode() cost function.

    The code you write for this challenge should be completely contained within this function
    between the # QHACK # comment markers.

    You should evaluate the metric tensor and the gradient of the QNode, and then combine these
    together using the natural gradient definition. The natural gradient should be returned as a
    NumPy array.

    The metric tensor should be evaluated using the equation provided in the problem text. Hint:
    you will need to define a new QNode that returns the quantum state before measurement.

    Args:
        params (np.ndarray): Input parameters, of dimension 6

    Returns:
        np.ndarray: The natural gradient evaluated at the input parameters, of dimension 6
    """

    natural_grad = np.zeros(6)

    # QHACK #
    s = 0.1
    gradient = np.zeros([6], dtype=np.float64)

    for i in range(6):
        params[i] += s
        plus_s = qnode(params)
        params[i] -= 2 * s
        minus_s = qnode(params)
        gradient[i] = (plus_s - minus_s) / (2 * np.sin(s))
        params[i] += s

    @qml.qnode(dev)
    def my_qnode(params):
        variational_circuit(params)
        return qml.state()

    s = np.pi / 2

    ket_state = my_qnode(params)
    bra_state = np.conj(ket_state)

    F = np.zeros([6, 6], dtype=np.float64)

    def get_F(qnode, params):
        for i in range(6):
            for j in range(6):
                params[i] += s
                params[j] += s
                pp_state = qnode(params)
                pp = np.abs(np.dot(bra_state, pp_state))**2
                params[j] -= 2 * s
                pm_state = qnode(params)
                pm = np.abs(np.dot(bra_state, pm_state))**2
                params[i] -= 2 * s
                params[j] += 2 * s
                mp_state = qnode(params)
                mp = np.abs(np.dot(bra_state, mp_state))**2
                params[j] -= 2 * s
                mm_state = qnode(params)
                mm = np.abs(np.dot(bra_state, mm_state))**2
                F[i, j] = (-pp + pm + mp - mm) / 8
                params[i] += s
                params[j] += s

    get_F(my_qnode, params)

    natural_grad = np.matmul(np.linalg.inv(F), gradient)
    # QHACK #

    return natural_grad