def test_cost_graph_error(self): """Tests that the cost Hamiltonians throw the correct error""" graph = [(0, 1), (1, 2)] with pytest.raises(ValueError, match=r"Input graph must be a nx\.Graph"): qaoa.maxcut(graph) with pytest.raises(ValueError, match=r"Input graph must be a nx\.Graph"): qaoa.max_independent_set(graph) with pytest.raises(ValueError, match=r"Input graph must be a nx\.Graph"): qaoa.min_vertex_cover(graph) with pytest.raises(ValueError, match=r"Input graph must be a nx\.Graph"): qaoa.max_clique(graph)
def test_max_clique_output(self, graph, constrained, cost_hamiltonian, mixer_hamiltonian): """Tests that the output of the Maximum Clique method is correct""" cost_h, mixer_h = qaoa.max_clique(graph, constrained=constrained) assert decompose_hamiltonian(cost_hamiltonian) == decompose_hamiltonian(cost_h) assert decompose_hamiltonian(mixer_hamiltonian) == decompose_hamiltonian(mixer_h)
def max_clique_falqon(graph, n, beta_1, delta_t, dev): comm_h = build_hamiltonian(graph) # Builds the commutator cost_h, driver_h = qaoa.max_clique(graph, constrained=False) # Builds H_c and H_d ansatz = build_maxclique_ansatz(cost_h, driver_h, delta_t) # Builds the FALQON ansatz beta = [beta_1] # Records each value of beta_k energies = [] # Records the value of the cost function at each step for i in range(n): # Creates a function that can evaluate the expectation value of the commutator cost_fn = qml.ExpvalCost(ansatz, comm_h, dev) # Creates a function that returns the expectation value of the cost Hamiltonian cost_fn_energy = qml.ExpvalCost(ansatz, cost_h, dev) # Adds a value of beta to the list and evaluates the cost function beta.append(-1 * cost_fn(beta)) energy = cost_fn_energy(beta) energies.append(energy) return beta, energies
# where each qubit is a node in the graph, and the states :math:`|0\rangle` and :math:`|1\rangle` # represent whether the vertex has been marked as part of the clique, as is the case for `most standard QAOA encoding # schemes <https://arxiv.org/abs/1709.03489>`__. # Note that :math:`\bar{G}` is the complement of :math:`G`: the graph formed by connecting all nodes that **do not** share # an edge in :math:`G`. # # In addition to defining :math:`H_c`, we also require a driver Hamiltonian :math:`H_d` which does not commute # with :math:`H_c`. The driver Hamiltonian's role is similar to that of the mixer Hamiltonian in QAOA. # To keep things simple, we choose a sum over Pauli :math:`X` operations on each qubit: # # .. math:: H_d = \displaystyle\sum_{i \in V(G)} X_i. # # These Hamiltonians come nicely bundled together in the PennyLane QAOA module: # cost_h, driver_h = qaoa.max_clique(graph, constrained=False) print("Cost Hamiltonian") print(cost_h) print("Driver Hamiltonian") print(driver_h) ###################################################################### # One of the main ingredients in the FALQON algorithm is the operator :math:`i [H_d, H_c]`. In # the case of MaxClique, we can write down the commutator :math:`[H_d, H_c]` explicitly: # # .. math:: [H_d, H_c] = 3 \displaystyle\sum_{k \in V(G)} \displaystyle\sum_{(i, j) \in E(\bar{G})} \big( [X_k, Z_i Z_j] - [X_k, Z_i] # - [X_k, Z_j] \big) + 3 \displaystyle\sum_{i \in V(G)} \displaystyle\sum_{j \in V(G)} [X_i, Z_j]. # # There are two distinct commutators that we must calculate, :math:`[X_k, Z_j]` and :math:`[X_k, Z_i Z_j]`. # This is straightforward as we know exactly what the