Пример #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