コード例 #1
0
def compile_unitary(U):
    """
    Takes a unitary and returns a circuit - i.e. a list of CNOTs and single qubit gates.
    """

    # perform two level decomposition
    two_level_unitaries = two_level_decomp(U)

    assert(np.allclose(mat_mul(two_level_unitaries), U))

    controlled_ops = []

    # decompose each two-level unitary into fully controlled operations
    for t in two_level_unitaries:
        controlled_ops += two_level_to_fully_controlled(t)

    assert(np.allclose(mat_mul(controlled_ops),U))

    gates = []

    # decompose each fully controlled operations into single qubit and CNOT gates
    for c in controlled_ops:
        gates += fully_controlled_to_single_cnot(c)

    circ = Circuit(n)

    circ.add_gates(gates)

    prod = circ.evaluate()

    assert(np.allclose(prod, U))

    print('number of two-level: ' + str(len(two_level_unitaries)))
    print('number of fully controlled ops: ' + str(len(controlled_ops)))
    print('number of CNOT and single qubit gates: ' + str(len(gates)))
    s = [g for g in gates if type(g) is SingleQubitGate]
    c = [g for g in gates if type(g) is CNOTGate]

    print('Single gates: ' + str(len(s)))
    print('CNOT gates: ' + str(len(c)))

    print('approximation error: ' + str(np.linalg.norm(prod-U)))

    for g in gates:
        if np.allclose(g.total_matrix(), np.eye(2**g.num_qubits)):
            print('redundant gate')

    return circ