def test_1_qubit_control():
    prog = Program()
    qubit = Qubit(0)
    control_qubit = Qubit(1)
    prog += (ControlledProgramBuilder().with_controls(
        [control_qubit]).with_target(qubit).with_operation(
            SIGMA_Z).with_gate_name(SIGMA_Z_NAME).build())
    # This should be one "CZ" instruction, from control_qubit to qubit.
    assert len(prog) == 1
    instruction = prog.instructions[0]
    assert instruction.name == (ControlledProgramBuilder().format_gate_name(
        "C", SIGMA_Z_NAME))
    assert instruction.qubits == [control_qubit, qubit]
Пример #2
0
def double_control_test(instructions, target_qubit, control_qubit_one,
                        control_qubit_two):
    """A list of asserts testing the simple case of a double controlled Z gate. Used in the next
     two tests."""
    cpg = ControlledProgramBuilder()
    sqrt_z = cpg.format_gate_name("SQRT", SIGMA_Z_NAME)
    assert instructions[0][1].operator_name == (cpg.format_gate_name(
        "C", sqrt_z))
    assert instructions[0][1].arguments == [control_qubit_two, target_qubit]

    assert instructions[1][1].operator_name == cpg.format_gate_name("C", "NOT")
    assert instructions[1][1].arguments == [
        control_qubit_one, control_qubit_two
    ]

    assert instructions[2][1].operator_name == cpg.format_gate_name(
        "C", sqrt_z) + '-INV'
    assert instructions[2][1].arguments == [control_qubit_two, target_qubit]

    assert instructions[3][1].operator_name == cpg.format_gate_name("C", "NOT")
    assert instructions[3][1].arguments == [
        control_qubit_one, control_qubit_two
    ]

    assert instructions[4][1].operator_name == cpg.format_gate_name(
        "C", sqrt_z)
    assert instructions[4][1].arguments == [control_qubit_one, target_qubit]
Пример #3
0
def test_1_qubit_control():
    prog = Program()
    qubit = prog.alloc()
    control_qubit = prog.alloc()
    prog += (ControlledProgramBuilder().with_controls(
        [control_qubit]).with_target(qubit).with_operation(
            SIGMA_Z).with_gate_name(SIGMA_Z_NAME).build())
    # This should be one "CZ" instruction, from control_qubit to qubit.
    assert prog_len(prog) == 1
    prog.synthesize()
    instruction = non_action_insts(prog)[0]
    assert instruction[1].operator_name == (
        ControlledProgramBuilder().format_gate_name("C", SIGMA_Z_NAME))
    assert instruction[1].arguments == [control_qubit, qubit]
Пример #4
0
def decomposed_diffusion_program(qubits):
    """
    Constructs the diffusion operator used in Grover's Algorithm, acted on both sides by an
    a Hadamard gate on each qubit. Note that this means that the matrix representation of this
    operator is diag(1, -1, ..., -1). In particular, this decomposes the diffusion operator, which
    is a :math:`2**{len(qubits)}\times2**{len(qubits)}` sparse matrix, into
     :math:`\mathcal{O}(len(qubits)**2) single and two qubit gates.

    See C. Lavor, L.R.U. Manssur, and R. Portugal (2003) `Grover's Algorithm: Quantum Database
    Search`_ for more information.

    .. _`Grover's Algorithm: Quantum Database Search`: https://arxiv.org/abs/quant-ph/0301079

    :param qubits: A list of ints corresponding to the qubits to operate on.
                   The operator operates on bistrings of the form
                   ``|qubits[0], ..., qubits[-1]>``.
    """
    program = pq.Program()
    if len(qubits) == 1:
        program.inst(Z(qubits[0]))
    else:
        program.inst([X(q) for q in qubits])
        program.inst(H(qubits[-1]))
        program.inst(RZ(-np.pi, qubits[0]))
        program += (ControlledProgramBuilder().with_controls(
            qubits[:-1]).with_target(qubits[-1]).with_operation(
                X_GATE).with_gate_name(X_GATE_LABEL).build())
        program.inst(RZ(-np.pi, qubits[0]))
        program.inst(H(qubits[-1]))
        program.inst([X(q) for q in qubits])
    return program
Пример #5
0
def diffusion_program(qubits):
    """Constructs the diffusion operator used in Grover's Algorithm, acted on both sides by an
     a Hadamard gate on each qubit. Note that this means that the matrix representation of this
     operator is diag(1, -1, ..., -1).

    See C. Lavor, L.R.U. Manssur, and R. Portugal (2003) `Grover's Algorithm: Quantum Database
    Search`_ for more information.

    .. _`Grover's Algorithm: Quantum Database Search`: https://arxiv.org/abs/quant-ph/0301079

    :param qubits: A list of ints corresponding to the qubits to operate on.
                   The operator operates on bistrings of the form
                   |qubits[0], ..., qubits[-1]>.
    """
    diffusion_program = pq.Program()

    if len(qubits) == 1:
        diffusion_program.inst(Z(qubits[0]))
    else:
        diffusion_program.inst([X(q) for q in qubits])
        diffusion_program.inst(H(qubits[-1]))
        diffusion_program.inst(RZ(-np.pi)(qubits[0]))
        diffusion_program += (ControlledProgramBuilder()
                              .with_controls(qubits[:-1])
                              .with_target(qubits[-1])
                              .with_operation(X_GATE)
                              .with_gate_name("NOT").build())
        diffusion_program.inst(RZ(-np.pi)(qubits[0]))
        diffusion_program.inst(H(qubits[-1]))
        diffusion_program.inst([X(q) for q in qubits])
    return diffusion_program
def test_recursive_builder():
    """Here we test the _recursive_builder in ControlledProgramBuilder individually."""
    control_qubit_one = 1
    control_qubit_two = 2
    target_qubit = 3
    cpg = (ControlledProgramBuilder().with_controls(
        [control_qubit_one, control_qubit_two]).with_target(
            target_qubit).with_operation(SIGMA_Z).with_gate_name(SIGMA_Z_NAME))
    prog = cpg._recursive_builder(cpg.operation, cpg.gate_name,
                                  cpg.control_qubits, cpg.target_qubit)
    # Run tests
    double_control_test(prog.instructions, Qubit(target_qubit),
                        Qubit(control_qubit_one), Qubit(control_qubit_two))
Пример #7
0
def test_2_qubit_control():
    """Test that ControlledProgramBuilder builds the program correctly all the way through."""
    prog = Program()
    qubit = Qubit(0)
    control_qubit_one = Qubit(1)
    control_qubit_two = Qubit(2)
    prog += (ControlledProgramBuilder()
             .with_controls([control_qubit_one, control_qubit_two])
             .with_target(qubit)
             .with_operation(SIGMA_Z)
             .with_gate_name(SIGMA_Z_NAME).build())
    # This should be one "CZ" instruction, from control_qubit to qubit.
    assert len(prog) == 5
    # Run tests
    double_control_test(prog.instructions, qubit, control_qubit_one, control_qubit_two)
Пример #8
0
def test_2_qubit_control():
    """Test that ControlledProgramBuilder builds the program correctly all the way through."""
    prog = Program()
    qubit = prog.alloc()
    control_qubit_one = prog.alloc()
    control_qubit_two = prog.alloc()
    prog += (ControlledProgramBuilder().with_controls([
        control_qubit_one, control_qubit_two
    ]).with_target(qubit).with_operation(SIGMA_Z).with_gate_name("Z").build())
    # This should be one "CZ" instruction, from control_qubit to qubit.
    assert prog_len(prog) == 5
    prog.synthesize()
    instructions = non_action_insts(prog)
    # Run tests
    double_control_test(instructions, qubit, control_qubit_one,
                        control_qubit_two)
Пример #9
0
def basis_selector_oracle(qubits: List[int], bitstring: str) -> Program:
    """
    Defines an oracle that selects the ith element of the computational basis.

    Flips the sign of the state :math:`\\vert x\\rangle>`
    if and only if x==bitstring and does nothing otherwise.

    :param qubits: The qubits the oracle is called on. The qubits are assumed to be ordered from
     most significant qubit to least significant qubit.
    :param bitstring: The desired bitstring, given as a string of ones and zeros. e.g. "101"
    :return: A program representing this oracle.
    """
    if len(qubits) != len(bitstring):
        raise ValueError("The bitstring should be the same length as the number of qubits.")
    oracle_prog = Program()

    # In the case of one qubit, we just want to flip the phase of state relative to the other.
    if len(bitstring) == 1:
        oracle_prog.inst(Z(qubits[0]))
        return oracle_prog
    else:
        bitflip_prog = Program()
        for i, qubit in enumerate(qubits):
            if bitstring[i] == '0':
                bitflip_prog.inst(X(qubit))
        oracle_prog += bitflip_prog
        controls = qubits[:-1]
        target = qubits[-1]
        operation = np.array([[1, 0], [0, -1]])
        gate_name = 'Z'
        n_qubit_controlled_z = (ControlledProgramBuilder()
                                .with_controls(controls)
                                .with_target(target)
                                .with_operation(operation)
                                .with_gate_name(gate_name)
                                .build())
        oracle_prog += n_qubit_controlled_z
        oracle_prog += bitflip_prog
    return oracle_prog