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
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
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
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