Acquaintance strategy for pairs of pairs.

    Implements UpCCGSD ansatz from arXiv:1810.02327.

def quartic_paired_acquaintance_strategy(
    qubit_pairs: Iterable[Tuple[ops.Qid, ops.Qid]]
    ) -> Tuple[circuits.Circuit, Sequence[ops.Qid]]:
    """Acquaintance strategy for pairs of pairs.

    Implements UpCCGSD ansatz from arXiv:1810.02327.
    """

    qubit_pairs = tuple(
            cast(Tuple[ops.Qid, ops.Qid], tuple(qubit_pair))
            for qubit_pair in qubit_pairs)
    qubits = qubit_pairs_to_qubit_order(qubit_pairs)
    n_qubits = len(qubits)
    swap_network = SwapNetworkGate((1,) * n_qubits, 2)(*qubits)
    strategy = circuits.Circuit.from_ops(swap_network,
            device=UnconstrainedAcquaintanceDevice)
    expose_acquaintance_gates(strategy)
    for i in reversed(range(0, n_qubits, 2)):
        moment = ops.Moment([acquaint(*qubits[j: j + 4])
                             for j in range(i % 4, n_qubits - 3, 4)])
        strategy.insert(2 * i, moment)
    return strategy, qubits