def phase_estimation_circuit(gate: Gate, outputs: Qubits) -> Circuit:
    """Returns a circuit for quantum phase estimation.

    The gate has an eigenvector with eigenvalue e^(i 2 pi phase). To
    run the circuit, the eigenvector should be set on the gate qubits,
    and the output qubits should be in the zero state. After evolution and
    measurement, the output qubits will be (approximately) a binary fraction
    representation of the phase.

    The output registers can be converted with the aid of the
    quantumflow.utils.bitlist_to_int() method.

    >>> import numpy as np
    >>> import quantumflow as qf
    >>> N = 8
    >>> phase = 1/4
    >>> gate = qf.RZ(-4*np.pi*phase, N)
    >>> circ = qf.phase_estimation_circuit(gate, range(N))
    >>> res = circ.run().measure()[0:N]
    >>> est_phase = int(''.join([str(d) for d in res]), 2) / 2**N # To float
    >>> print(phase, est_phase)
    0.25 0.25

    """
    circ = Circuit()
    circ += map_gate(H(), list(zip(outputs)))  # Hadamard on all output qubits

    for cq in reversed(outputs):
        cgate = control_gate(cq, gate)
        circ += cgate
        gate = gate @ gate

    circ += qft_circuit(outputs).H

    return circ
Returns a circuit for quantum phase estimation.

    The gate has an eigenvector with eigenvalue e^(i 2 pi phase). To
    run the circuit, the eigenvector should be set on the gate qubits,
    and the output qubits should be in the zero state. After evolution and
    measurement, the output qubits will be (approximately) a binary fraction
    representation of the phase.

    The output registers can be converted with the aid of the
    quantumflow.utils.bitlist_to_int() method.

    >>> import numpy as np
    >>> import quantumflow as qf
    >>> N = 8
    >>> phase = 1/4
    >>> gate = qf.RZ(-4*np.pi*phase, N)
    >>> circ = qf.phase_estimation_circuit(gate, range(N))
    >>> res = circ.run().measure()[0:N]
    >>> est_phase = int(''.join([str(d) for d in res]), 2) / 2**N # To float
    >>> print(phase, est_phase)
    0.25 0.25