def test_bit_flip_mixer_errors(self): """Tests that the bit-flip mixer throws the correct errors""" graph = [(0, 1), (1, 2)] with pytest.raises(ValueError, match=r"Input graph must be a nx.Graph object"): qaoa.bit_flip_mixer(graph, 0) n = 2 with pytest.raises(ValueError, match=r"'b' must be either 0 or 1"): qaoa.bit_flip_mixer(Graph(graph), n)
def max_clique(graph, constrained=True): r"""Returns the QAOA cost Hamiltonian and the recommended mixer corresponding to the Maximum Clique problem, for a given graph. The goal of Maximum Clique is to find the largest `clique <https://en.wikipedia.org/wiki/Clique_(graph_theory)>`__ of a graph --- the largest subgraph such that all vertices are connected by an edge. Args: graph (nx.Graph): a graph whose edges define the pairs of vertices on which each term of the Hamiltonian acts constrained (bool): specifies the variant of QAOA that is performed (constrained or unconstrained) Returns: (.Hamiltonian, .Hamiltonian): The cost and mixer Hamiltonians .. UsageDetails:: There are two variations of QAOA for this problem, constrained and unconstrained: **Constrained** .. note:: This method of constrained QAOA was introduced by Hadfield, Wang, Gorman, Rieffel, Venturelli, and Biswas in arXiv:1709.03489. The Maximum Clique cost Hamiltonian for constrained QAOA is defined as: .. math:: H_C \ = \ \displaystyle\sum_{v \in V(G)} Z_{v}, where :math:`V(G)` is the set of vertices of the input graph, and :math:`Z_i` is the Pauli-Z operator applied to the :math:`i`-th vertex. The returned mixer Hamiltonian is :func:`~qaoa.bit_flip_mixer` applied to :math:`\bar{G}`, the complement of the graph. .. note:: **Recommended initialization circuit:** Each wire in the :math:`|0\rangle` state. **Unconstrained** The Maximum Clique cost Hamiltonian for unconstrained QAOA is defined as: .. math:: H_C \ = \ 3 \sum_{(i, j) \in E(\bar{G})} (Z_i Z_j \ - \ Z_i \ - \ Z_j) \ + \ \displaystyle\sum_{i \in V(G)} Z_i where :math:`V(G)` is the set of vertices of the input graph :math:`G`, :math:`E(\bar{G})` is the set of edges of the complement of :math:`G`, and :math:`Z_i` is the Pauli-Z operator applied to the :math:`i`-th vertex. The returned mixer Hamiltonian is :func:`~qaoa.x_mixer` applied to all wires. .. note:: **Recommended initialization circuit:** Even superposition over all basis states. """ if not isinstance(graph, nx.Graph): raise ValueError("Input graph must be a nx.Graph, got {}".format( type(graph).__name__)) if constrained: cost_h = bit_driver(graph.nodes, 1) cost_h.grouping_indices = [list(range(len(cost_h.ops)))] return (cost_h, qaoa.bit_flip_mixer(nx.complement(graph), 0)) cost_h = 3 * edge_driver(nx.complement(graph), ["10", "01", "00"]) + bit_driver(graph.nodes, 1) mixer_h = qaoa.x_mixer(graph.nodes) # store the valuable information that all observables are in one commuting group cost_h.grouping_indices = [list(range(len(cost_h.ops)))] return (cost_h, mixer_h)
def test_bit_flip_mixer_output(self, graph, n, target_hamiltonian): """Tests that the output of the bit-flip mixer is correct""" mixer_hamiltonian = qaoa.bit_flip_mixer(graph, n) assert decompose_hamiltonian(mixer_hamiltonian) == decompose_hamiltonian(target_hamiltonian)
def min_vertex_cover(graph, constrained=True): r"""Returns the QAOA cost Hamiltonian and the recommended mixer corresponding to the Minimum Vertex Cover problem, for a given graph. To solve the Minimum Vertex Cover problem, we attempt to find the smallest `vertex cover <https://en.wikipedia.org/wiki/Vertex_cover>`__ of a graph --- a collection of vertices such that every edge in the graph has one of the vertices as an endpoint. Args: graph (nx.Graph): a graph whose edges define the pairs of vertices on which each term of the Hamiltonian acts constrained (bool): specifies the variant of QAOA that is performed (constrained or unconstrained) Returns: (.Hamiltonian, .Hamiltonian): The cost and mixer Hamiltonians .. UsageDetails:: There are two variations of QAOA for this problem, constrained and unconstrained: **Constrained** .. note:: This method of constrained QAOA was introduced by Hadfield, Wang, Gorman, Rieffel, Venturelli, and Biswas in arXiv:1709.03489. The Minimum Vertex Cover cost Hamiltonian for constrained QAOA is defined as: .. math:: H_C \ = \ - \displaystyle\sum_{v \in V(G)} Z_{v}, where :math:`V(G)` is the set of vertices of the input graph, and :math:`Z_i` is the Pauli-Z operator applied to the :math:`i`-th vertex. The returned mixer Hamiltonian is :func:`~qaoa.bit_flip_mixer` applied to :math:`G`. .. note:: **Recommended initialization circuit:** Each wire in the :math:`|1\rangle` state. **Unconstrained** The Minimum Vertex Cover cost Hamiltonian for unconstrained QAOA is defined as: .. math:: H_C \ = \ 3 \sum_{(i, j) \in E(G)} (Z_i Z_j \ + \ Z_i \ + \ Z_j) \ - \ \displaystyle\sum_{i \in V(G)} Z_i where :math:`E(G)` is the set of edges of :math:`G`, :math:`V(G)` is the set of vertices, and :math:`Z_i` is the Pauli-Z operator acting on the :math:`i`-th vertex. The returned mixer Hamiltonian is :func:`~qaoa.x_mixer` applied to all wires. .. note:: **Recommended initialization circuit:** Even superposition over all basis states. """ if not isinstance(graph, nx.Graph): raise ValueError("Input graph must be a nx.Graph, got {}".format( type(graph).__name__)) if constrained: return (bit_driver(graph.nodes, 0), qaoa.bit_flip_mixer(graph, 1)) cost_h = 3 * edge_driver(graph, ["11", "10", "01"]) + bit_driver( graph.nodes, 0) mixer_h = qaoa.x_mixer(graph.nodes) return (cost_h, mixer_h)
def max_independent_set(graph, constrained=True): r"""For a given graph, returns the QAOA cost Hamiltonian and the recommended mixer corresponding to the Maximum Independent Set problem. Given some graph :math:`G`, an independent set is a set of vertices such that no pair of vertices in the set share a common edge. The Maximum Independent Set problem, is the problem of finding the largest such set. Args: graph (nx.Graph): a graph whose edges define the pairs of vertices on which each term of the Hamiltonian acts constrained (bool): specifies the variant of QAOA that is performed (constrained or unconstrained) Returns: (.Hamiltonian, .Hamiltonian): The cost and mixer Hamiltonians .. UsageDetails:: There are two variations of QAOA for this problem, constrained and unconstrained: **Constrained** .. note:: This method of constrained QAOA was introduced by Hadfield, Wang, Gorman, Rieffel, Venturelli, and Biswas in arXiv:1709.03489. The Maximum Independent Set cost Hamiltonian for constrained QAOA is defined as: .. math:: H_C \ = \ \displaystyle\sum_{v \in V(G)} Z_{v}, where :math:`V(G)` is the set of vertices of the input graph, and :math:`Z_i` is the Pauli-Z operator applied to the :math:`i`-th vertex. The returned mixer Hamiltonian is :func:`~qaoa.bit_flip_mixer` applied to :math:`G`. .. note:: **Recommended initialization circuit:** Each wire in the :math:`|0\rangle` state. **Unconstrained** The Maximum Independent Set cost Hamiltonian for unconstrained QAOA is defined as: .. math:: H_C \ = \ 3 \sum_{(i, j) \in E(G)} (Z_i Z_j \ - \ Z_i \ - \ Z_j) \ + \ \displaystyle\sum_{i \in V(G)} Z_i where :math:`E(G)` is the set of edges of :math:`G`, :math:`V(G)` is the set of vertices, and :math:`Z_i` is the Pauli-Z operator acting on the :math:`i`-th vertex. The returned mixer Hamiltonian is :func:`~qaoa.x_mixer` applied to all wires. .. note:: **Recommended initialization circuit:** Even superposition over all basis states. """ if not isinstance(graph, nx.Graph): raise ValueError("Input graph must be a nx.Graph, got {}".format( type(graph).__name__)) if constrained: return (bit_driver(graph.nodes, 1), qaoa.bit_flip_mixer(graph, 0)) cost_h = 3 * edge_driver(graph, ["10", "01", "00"]) + bit_driver( graph.nodes, 1) mixer_h = qaoa.x_mixer(graph.nodes) return (cost_h, mixer_h)