Exemple #1
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
Exemple #2
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
Exemple #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
Exemple #4
0
def U_theta(theta, n, depth):  
    """
    :param theta: dim: [n, depth + 3]
    :param n: number of qubits
    :param depth: circuit depth
    :return: U_theta
    """
    # 初始化网络
    cir = UAnsatz(n)
    
    # 先搭建广义的旋转层
    for i in range(n):
        cir.rz(theta[i][0], i)
        cir.ry(theta[i][1], i)
        cir.rz(theta[i][2], i)

    # 默认深度为 depth = 1
    # 搭建纠缠层和 Ry旋转层
    for d in range(3, depth + 3):
        for i in range(n-1):
            cir.cnot([i, i + 1])
        cir.cnot([n-1, 0])
        for i in range(n):
            cir.ry(theta[i][d], i)

    return cir.U
def U_theta(theta, N):
    """
    U_theta
    """

    cir = UAnsatz(N)
    # ============== D1=2 ==============
    cir.ry(theta[0], 2)
    cir.rz(theta[1], 2)
    cir.cnot([2, 1])
    cir.ry(theta[2], 2)
    cir.rz(theta[3], 2)
    cir.cnot([2, 1])

    # ============== D2=2 ==============
    cir.ry(theta[4], 1)
    cir.ry(theta[5], 2)
    cir.rz(theta[6], 1)
    cir.rz(theta[7], 2)
    cir.cnot([1, 2])

    cir.ry(theta[8], 1)
    cir.ry(theta[9], 2)
    cir.rz(theta[10], 1)
    cir.rz(theta[11], 2)
    cir.cnot([1, 2])

    return cir.state
def Encoder(theta):

    # use UAnsatz to initialize the network
    cir = UAnsatz(N)

    for layer_num in range(cir_depth):

        for which_qubit in range(N):
            cir.ry(theta[block_len * layer_num * N + which_qubit], which_qubit)
            cir.rz(theta[(block_len * layer_num + 1) * N + which_qubit],
                   which_qubit)

        for which_qubit in range(N - 1):
            cir.cnot([which_qubit, which_qubit + 1])
        cir.cnot([N - 1, 0])

    return cir.U
def Encoder(theta):

    # 用 UAnsatz 初始化网络
    cir = UAnsatz(N)

    # 搭建层级结构:
    for layer_num in range(cir_depth):

        for which_qubit in range(N):
            cir.ry(theta[block_len * layer_num * N + which_qubit], which_qubit)
            cir.rz(theta[(block_len * layer_num + 1) * N + which_qubit],
                   which_qubit)

        for which_qubit in range(N - 1):
            cir.cnot([which_qubit, which_qubit + 1])
        cir.cnot([N - 1, 0])

    return cir.U
def U_theta(theta, n, depth):
    """
    :param theta: dim: [n, depth + 3]
    :param n: number of qubits
    :param depth: circuit depth
    :return: U_theta
    """
    cir = UAnsatz(n)

    for i in range(n):
        cir.rz(theta[i][0], i)
        cir.ry(theta[i][1], i)
        cir.rz(theta[i][2], i)

    for d in range(3, depth + 3):
        for i in range(n - 1):
            cir.cnot([i, i + 1])
        cir.cnot([n - 1, 0])
        for i in range(n):
            cir.ry(theta[i][d], i)

    return cir.U
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
Exemple #10
0
def circuit_extend_QAOA(theta, adjacency_matrix, N, P):
    """
    This is an extended version of the QAOA circuit, and the main difference is the block 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:
        the extended QAOA circuit

    Note:
        If this circuit_extend_QAOA 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 circuit_QAOA function to Net(shape=[D, 4])
        because the number of parameters doubles in each layer in this 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()
    for layer in range(P):
        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])

        for i in range(N):
            cir.u3(*theta[layer][1:], i)

    return cir
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
Exemple #12
0
def U_theta(theta, input_state, N, D):
    """
    Circuit
    """

    cir = UAnsatz(N, input_state=input_state)
    for i in range(N):
        cir.rz(theta=theta[0][0][i], which_qubit=i + 1)
        cir.ry(theta=theta[0][1][i], which_qubit=i + 1)
        cir.rz(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.rz(theta=theta[repeat][2][i], which_qubit=i + 1)

    return cir.state