Пример #1
0
def circuit_QAOA(theta, adjacency_matrix, N, P):
    """
    This function constructs the parameterized QAOA circuit which is composed of P layers of two blocks:
    one block is based on the problem Hamiltonian H which encodes the classical problem,
    and the other is constructed from the driving Hamiltonian describing the rotation around Pauli X
    acting on each qubit. It outputs the final state of the QAOA circuit.

    Args:
        theta: parameters to be optimized in the QAOA circuit
        adjacency_matrix:  the adjacency matrix of the graph encoding the classical problem
        N: number of qubits, or equivalently, the number of parameters in the original classical problem
        P: number of layers of two blocks in the QAOA circuit
    Returns:
        the QAOA circuit
    """

    cir = UAnsatz(N)

    # prepare the input state in the uniform superposition of 2^N bit-strings in the computational basis
    cir.superposition_layer()
    # This loop defines the QAOA circuit with P layers of two blocks
    for layer in range(P):
        # The second and third loops construct the first block which involves two-qubit operation
        #  e^{-i\gamma Z_iZ_j} acting on a pair of qubits or nodes i and j in the circuit in each layer.
        for row in range(N):
            for col in range(N):
                if adjacency_matrix[row, col] and row < col:
                    cir.cnot([row, col])
                    cir.rz(theta[layer][0], col)
                    cir.cnot([row, col])
        # This loop constructs the second block only involving the single-qubit operation e^{-i\beta X}.
        for i in range(N):
            cir.rx(theta[layer][1], i)

    return cir
Пример #2
0
def circuit_QAOA(E, V, n, p, gamma, beta):
    """
    This function constructs the parameterized QAOA circuit which is composed of P layers of two blocks:
    one block is based on the problem Hamiltonian H which encodes the classical problem,
    and the other is constructed from the driving Hamiltonian describing the rotation around Pauli X
    acting on each qubit. It outputs the final state of the QAOA circuit.
    Args:
        E: edges of the graph
        V: vertices of the graph
        n: number of qubits in th QAOA circuit
        p: number of layers of two blocks in the QAOA circuit
        gamma: parameter to be optimized in the QAOA circuit, parameter for the first block
        beta: parameter to be optimized in the QAOA circui, parameter for the second block
    Returns:
        the QAOA circuit
    """
    cir = UAnsatz(n)
    cir.superposition_layer()
    for layer in range(p):
        for (u, v) in E:
            cir.cnot([u, v])
            cir.rz(gamma[layer], v)
            cir.cnot([u, v])
        for v in V:
            cir.rx(beta[layer], v)
    return cir
Пример #3
0
def circuit_maxcut(E, V, p, gamma, beta):
    r"""构建用于最大割问题的 QAOA 参数化电路。

    Args:
        E: 图的边
        V: 图的顶点
        p: QAOA 电路的层数
        gamma: 与最大割问题哈密顿量相关的电路参数
        beta: 与混合哈密顿量相关的电路参数

    Returns:
        UAnsatz: 构建好的 QAOA 电路
    """
    # Number of qubits needed
    n = len(V)
    cir = UAnsatz(n)
    cir.superposition_layer()
    for layer in range(p):
        for (u, v) in E:
            cir.cnot([u, v])
            cir.rz(gamma[layer], v)
            cir.cnot([u, v])
        for i in V:
            cir.rx(beta[layer], i)

    return cir
Пример #4
0
def circuit_extend_QAOA(theta, input_state, adjacency_matrix, N, P):
    """
    This is an extended version of the QAOA circuit, and the main difference is U_theta[layer]([1]-[3]) constructed
    from the driving Hamiltonian describing the rotation around an arbitrary direction on each qubit.

    Args:
        theta: parameters to be optimized in the QAOA circuit
        input_state: input state of the QAOA circuit which usually is the uniform superposition of 2^N bit-strings
                     in the computational basis
        adjacency_matrix:  the adjacency matrix of the problem graph encoding the original problem
        N: number of qubits, or equivalently, the number of parameters in the original classical problem
        P: number of layers of two blocks in the QAOA circuit
    Returns:
        final state of the QAOA circuit: cir.state

    Note: If this U_extend_theta function is used to construct QAOA circuit, then we need to change the parameter layer
           in the Net function defined below from the Net(shape=[D, 2]) for U_theta function to Net(shape=[D, 4])
           because the number of parameters doubles in each layer in this QAOA circuit.
    """

    cir = UAnsatz(N, input_state=input_state)

    # The first loop defines the QAOA circuit with P layers of two blocks
    for layer in range(P):
        # The second and third loops aim to construct the first block U_theta[layer][0] which involves
        # two-qubit operation e^{-i\beta Z_iZ_j} acting on a pair of qubits or nodes i and j in the circuit.
        for row in range(N):
            for col in range(N):
                if abs(adjacency_matrix[row, col]) and row < col:
                    cir.cnot([row + 1, col + 1])
                    cir.rz(
                        theta=theta[layer][0] * adjacency_matrix[row, col],
                        which_qubit=col + 1,
                    )
                    cir.cnot([row + 1, col + 1])
        # This loops constructs the second block U_theta[layer][1]-[3] composed of three single-qubit operation
        #  e^{-i\beta[1] Z}e^{-i\beta[2] X}e^{-i\beta[3] X} sequentially acting on single qubits.
        for i in range(1, N + 1):
            cir.rz(theta=theta[layer][1], which_qubit=i)
            cir.rx(theta=theta[layer][2], which_qubit=i)
            cir.rz(theta=theta[layer][3], which_qubit=i)

    return cir.state
Пример #5
0
def circuit_QAOA(theta, input_state, adjacency_matrix, N, P):
    """
    This function constructs the parameterized QAOA circuit which is composed of P layers of two blocks:
    one block is U_theta[layer][0] based on the problem Hamiltonian H which encodes the classical problem,
    and the other is U_theta[layer][1] constructed from the driving Hamiltonian describing the rotation around Pauli X
    acting on each qubit. It finally outputs the final state of the QAOA circuit.

    Args:
         theta: parameters to be optimized in the QAOA circuit
         input_state: initial state of the QAOA circuit which usually is the uniform superposition of 2^N bit-strings
                    in the computational basis $|0\rangle, |1\rangle$
         adjacency_matrix:  the adjacency matrix of the graph encoding the classical problem
         N: number of qubits, or equivalently, the number of nodes in the given graph
         P: number of layers of two blocks in the QAOA circuit
    Returns:
        the final state of the QAOA circuit: cir.state

    """

    cir = UAnsatz(N, input_state=input_state)
    # The first loop defines the QAOA circuit with P layers of two blocks
    for layer in range(P):
        # The second and third loops aim to construct the first block U_theta[layer][0] which involves
        # two-qubit operation e^{-i\beta Z_iZ_j} acting on a pair of qubits or nodes i and j in the circuit.
        for row in range(N):
            for col in range(N):
                if abs(adjacency_matrix[row, col]) and row < col:
                    cir.cnot([row + 1, col + 1])
                    cir.rz(
                        theta=theta[layer][0] * adjacency_matrix[row, col],
                        which_qubit=col + 1,
                    )
                    cir.cnot([row + 1, col + 1])
        # This loops constructs the second block U_theta only involving the single-qubit operation e^{-i\beta X}.
        for i in range(1, N + 1):
            cir.rx(theta=theta[layer][1], which_qubit=i)

    return cir.state
Пример #6
0
def U_theta(theta, input_state, N, D):  # definition of U_theta
    """
    :param theta:
    :param input_state:
    :return:
    """

    cir = UAnsatz(N, input_state=input_state)
    for i in range(N):
        cir.rx(theta=theta[0][0][i], which_qubit=i + 1)
        cir.ry(theta=theta[0][1][i], which_qubit=i + 1)
        cir.rx(theta=theta[0][2][i], which_qubit=i + 1)

    for repeat in range(D):
        for i in range(1, N):
            cir.cnot(control=[i, i + 1])

        for i in range(N):
            cir.ry(theta=theta[repeat][0][i], which_qubit=i + 1)
            # cir.ry(theta=theta[repeat][1][i], which_qubit=i + 1)
            # cir.ry(theta=theta[repeat][2][i], which_qubit=i + 1)

    return cir.state