quimb.tensor.circuit_gen ======================== .. py:module:: quimb.tensor.circuit_gen .. autoapi-nested-parse:: Functions for generating specific, e.g. ansatz, circuits. Functions --------- .. autoapisummary:: quimb.tensor.circuit_gen.inject_u3s quimb.tensor.circuit_gen.gates_to_param_circuit quimb.tensor.circuit_gen.gates_1D_zigzag quimb.tensor.circuit_gen.circ_ansatz_1D_zigzag quimb.tensor.circuit_gen.gates_1D_brickwork quimb.tensor.circuit_gen.circ_ansatz_1D_brickwork quimb.tensor.circuit_gen.gates_1D_rand quimb.tensor.circuit_gen.circ_ansatz_1D_rand quimb.tensor.circuit_gen.gates_a2a_rand quimb.tensor.circuit_gen.circ_a2a_rand quimb.tensor.circuit_gen.gates_qaoa quimb.tensor.circuit_gen.circ_qaoa Module Contents --------------- .. py:function:: inject_u3s(ent_gates, gate2='cz', avoid_doubling=False, seed=None) Take a sequence of pairs denoting qubits to entangle and interleave one single qubit gate inbetween every leg. For example: ent_gates = [(0, 1), (2, 3), (1, 2)] Would go get made into a circuit like:: | | | | | | | | | | | | | u u | | | | | | | | | | o++o | u o++o u | | | | | | | | | | | | --> | u u | | | | | | | | | o++o o++o o++o o++o | | | | | | | | | | | | u u u u | | | | | | | | Technically, this generates a bipartite graph between single qubit and two qubit tensors, and should be the most expressive circuit possible for that 'budget' of entangling gates. :param ent_gates: A 'stack' of entangling gate pairs to apply. :type ent_gates: sequence[tuple[int]] :param gate2: The gate to use for the entanling pairs. :type gate2: {'cx', 'cy', 'cz', 'iswap', ..., str}, optional :param avoid_doubling: Whether to avoid placing an entangling gate directly above the same entangling gate (there will still be single qubit gates interleaved). :type avoid_doubling: bool, optional :rtype: Circuit .. py:function:: gates_to_param_circuit(gates, n, parametrize='U3', **circuit_opts) Turn the sequence ``gates`` into a ``Circuit`` of ``n`` qubits, with any gates that appear in ``parametrize`` being... parametrized. :param gates: The gates describing the circuit. :type gates: sequence[tuple[str, float, int]] :param n: The number of qubits to make the circuit act one. :type n: int :param parametrize: Which gates to parametrize. :type parametrize: str or sequence[str], optional :param circuit_opts: Supplied to :class:`~quimb.tensor.circuit.Circuit`. :rtype: Circuit .. py:function:: gates_1D_zigzag(n, depth, gate2='cz', seed=None) .. py:function:: circ_ansatz_1D_zigzag(n, depth, gate2='cz', seed=None, **circuit_opts) A 1D circuit ansatz with forward and backward layers of entangling gates interleaved with U3 single qubit unitaries:: | | | | u u | | o++o u | | | | u | o++o | | | u | | | o++o u u u u | | o++o | | u | | o++o | | u | u o++o u | u u | | | | | | :param n: The number of qubits. :type n: int :param depth: The number of entangling gates per pair. :type depth: int :param gate2: The gate to use for the entanling pairs. :type gate2: {'cx', 'cy', 'cz', 'iswap', ..., str}, optional :param seed: Random seed for parameters. :type seed: int, optional :param opts: Supplied to :func:`~quimb.tensor.circuit_gen.gates_to_param_circuit`. :rtype: Circuit .. seealso:: :py:obj:`circ_ansatz_1D_rand`, :py:obj:`circ_ansatz_1D_brickwork` .. py:function:: gates_1D_brickwork(n, depth, cyclic=False, gate2='cz', seed=None) .. py:function:: circ_ansatz_1D_brickwork(n, depth, cyclic=False, gate2='cz', seed=None, **circuit_opts) A 1D circuit ansatz with odd and even layers of entangling gates interleaved with U3 single qubit unitaries:: | | | | | | u u u u u o++o o++o | u u u | o++o o++o u | u u u | u o++o o++o | u u u | o++o o++o u | u u u u u o++o o++o | u u u | o++o o++o u u u u u | | | | | | :param n: The number of qubits. :type n: int :param depth: The number of entangling gates per pair. :type depth: int :param cyclic: Whether to add entangling gates between qubits 0 and n - 1. :type cyclic: bool, optional :param gate2: The gate to use for the entanling pairs. :type gate2: {'cx', 'cy', 'cz', 'iswap', ..., str}, optional :param seed: Random seed for parameters. :type seed: int, optional :param opts: Supplied to :func:`~quimb.tensor.circuit_gen.gates_to_param_circuit`. :rtype: Circuit .. seealso:: :py:obj:`circ_ansatz_1D_zigzag`, :py:obj:`circ_ansatz_1D_rand` .. py:function:: gates_1D_rand(n, depth, seed=None, cyclic=False, gate2='cz', avoid_doubling=True) .. py:function:: circ_ansatz_1D_rand(n, depth, seed=None, cyclic=False, gate2='cz', avoid_doubling=True, **circuit_opts) A 1D circuit ansatz with randomly place entangling gates interleaved with U3 single qubit unitaries. :param n: The number of qubits. :type n: int :param depth: The number of entangling gates per pair. :type depth: int :param seed: Random seed. :type seed: int, optional :param cyclic: Whether to add entangling gates between qubits 0 and n - 1. :type cyclic: bool, optional :param gate2: The gate to use for the entanling pairs. :type gate2: {'cx', 'cy', 'cz', 'iswap', ..., str}, optional :param avoid_doubling: Whether to avoid placing an entangling gate directly above the same entangling gate (there will still be single qubit gates interleaved). :type avoid_doubling: bool, optional :param opts: Supplied to :func:`~quimb.tensor.circuit_gen.gates_to_param_circuit`. :rtype: Circuit .. seealso:: :py:obj:`circ_ansatz_1D_zigzag`, :py:obj:`circ_ansatz_1D_brickwork` .. py:function:: gates_a2a_rand(n, depth, seed=None, gate2='cz') .. py:function:: circ_a2a_rand(n, depth, seed=None, gate2='cz', **circuit_opts) Generate a random all-to-all quantum circuit. :param n: The number of qubits. :type n: int :param depth: The circuit depth. Each layer consists of `n // 2` entangling gates applied between a random permutation of qubit pairs. :type depth: int :param seed: Random seed. :type seed: int, optional :param gate2: The gate to use for the entanling pairs. :type gate2: {'cx', 'cy', 'cz', 'iswap', ..., str}, optional :rtype: Circuit .. py:function:: gates_qaoa(terms, depth, gammas, betas) .. py:function:: circ_qaoa(terms, depth, gammas, betas, **circuit_opts) Generate the QAOA circuit for weighted graph described by ``terms``. .. math:: |{\bar{\gamma}, \bar{\beta}}\rangle = U_B (\beta _p) U_C (\gamma _p) \cdots U_B (\beta _1) U_C (\gamma _1) |{+}\rangle with .. math:: U_C (\gamma) = e^{-i \gamma \mathcal{C}} = \prod \limits_{i, j \in E(G)} e^{-i \gamma w_{i j} Z_i Z_j} and .. math:: U_B (\beta) = \prod \limits_{i \in G} e^{-i \beta X_i} :param terms: The mapping of integer pair keys ``(i, j)`` to the edge weight values, ``wij``. The integers should be a contiguous range enumerated from zero, with the total number of qubits being inferred from this. :type terms: dict[tuple[int], float] :param depth: The number of layers of gates to apply, ``p`` above. :type depth: int :param gammas: The interaction angles for each layer. :type gammas: iterable of float :param betas: The rotation angles for each layer. :type betas: iterable of float :param circuit_opts: Supplied to :class:`~quimb.tensor.circuit.Circuit`. Note ``gate_opts={'contract': False}`` is set by default (it can be overridden) since the RZZ gate, even though it has a rank-2 decomposition, is also diagonal.