def generate_uf(f, n, name):
    """
    Parameters: f is an anonymous function and n is the number of bits in input: f:{0,1}^n -> {0,1}
    This function returns an oracle gate representing the function f
        for all x in {0,1}^n and y in {0,1}, the desired result is of the oracle is mapping the input
        |x,y> to |x, y + f(x)> where + is addition modulo 2. The function first finds the list of bitstring
        permutations of n bits, it then establishes a mapping which is representative of the decimal number of the
        bitstring represents. It then determines for each |x,y>, it calculates |x, f(x) + y>. Finally it constructs a
        permutation gate which treats each permutation as a different basis vector in the 2^(n+1) dimensional complex
        hilbert space that represents a system of n + 1 qubits. The permutation gate is returned.
    """
    # generate list of all bitstrings of size n
    bitstrings = list()
    get_bitstring_permutations(0, bitstrings, n + 1, [0] * (n + 1))
    # initialize mapping and permutation list
    perm_dict = dict()
    perm_list = list()
    # populate mapping
    for permutation, bitstring in enumerate(bitstrings):
        perm_dict["".join(str(bit) for bit in bitstring)] = permutation
    # Send each |xy> to |x, f(x) + y>
    for bitstring in bitstrings:
        params = bitstring[:n]
        params.append((f(params) + bitstring[-1]) % 2)
        perm_list.append(perm_dict["".join(str(bit) for bit in params)])
    # Create and return permutation gate
    return DefPermutationGate(name, perm_list)
Beispiel #2
0
def test_def_permutation_gate():
    perm_gate = DefPermutationGate("CCNOT", [0, 1, 2, 3, 4, 5, 7, 6])

    perm_gate_str = 'DEFGATE CCNOT AS PERMUTATION:\n    0, 1, 2, 3, 4, 5, 7, 6'.strip(
    )

    parse_equals(perm_gate_str, perm_gate)
Beispiel #3
0
 def exitDefGate(self, ctx: QuilParser.DefGateContext):
     gate_name = ctx.name().getText()
     gate_type = ctx.gatetype()
     if gate_type and gate_type.getText() == 'PERMUTATION':
         permutation = _permutation(ctx.matrix())
         self.result.append(DefPermutationGate(gate_name, permutation))
     else:
         matrix = _matrix(ctx.matrix())
         parameters = [_variable(v) for v in ctx.variable()]
         self.result.append(DefGate(gate_name, matrix, parameters))
Beispiel #4
0
def merge_programs(prog_list):
    """
    Merges a list of pyQuil programs into a single one by appending them in sequence.
    If multiple programs in the list contain the same gate and/or noisy gate definition
    with identical name, this definition will only be applied once. If different definitions
    with the same name appear multiple times in the program list, each will be applied once
    in the order of last occurrence.

    :param list prog_list: A list of pyquil programs
    :return: a single pyQuil program
    :rtype: Program
    """
    definitions = [
        gate for prog in prog_list for gate in Program(prog).defined_gates
    ]
    seen = {}
    # Collect definitions in reverse order and reapply definitions in reverse
    # collected order to ensure that the last occurrence of a definition is applied last.
    for definition in reversed(definitions):
        name = definition.name
        if name in seen.keys():
            # Do not add truly identical definitions with the same name
            # If two different definitions share a name, we include each definition so as to provide
            # a waring to the user when the contradictory defgate is called.
            if definition not in seen[name]:
                seen[name].append(definition)
        else:
            seen[name] = [definition]
    new_definitions = [
        gate for key in seen.keys() for gate in reversed(seen[key])
    ]

    # Combine programs without gate definitions; avoid call to _synthesize by using _instructions
    p = Program(*[prog._instructions for prog in prog_list])

    for definition in new_definitions:
        if isinstance(definition, DefPermutationGate):
            p.inst(
                DefPermutationGate(definition.name,
                                   list(definition.permutation)))
        else:
            p.defgate(definition.name, definition.matrix,
                      definition.parameters)

    return p
Beispiel #5
0
def _remove_reset_from_program(program: Program) -> Program:
    """
    Trim the RESET from a program because in measure_observables it is re-added.

    :param program: Program to remove RESET(s) from.
    :return: Trimmed Program.
    """
    definitions = [gate for gate in program.defined_gates]

    p = Program(*[inst for inst in program if not isinstance(inst, Reset)])

    for definition in definitions:
        if isinstance(definition, DefPermutationGate):
            p.inst(
                DefPermutationGate(definition.name,
                                   list(definition.permutation)))
        else:
            p.defgate(definition.name, definition.matrix,
                      definition.parameters)
    return p
Beispiel #6
0
 def def_gate_as_permutation(self, name, matrix):
     return DefPermutationGate(name, permutation=matrix)
Beispiel #7
0
def test_prog_merge():
    prog_0 = Program(X(0))
    prog_1 = Program(Y(0))
    assert merge_programs([prog_0, prog_1]).out() == (prog_0 + prog_1).out()
    test_def = DefGate("test", np.eye(2))
    TEST = test_def.get_constructor()
    prog_0.inst(test_def)
    prog_0.inst(TEST(0))
    prog_1.inst(test_def)
    prog_1.inst(TEST(0))
    assert (merge_programs([prog_0, prog_1]).out() == """DEFGATE test:
    1.0, 0
    0, 1.0

X 0
test 0
Y 0
test 0
""")
    perm_def = DefPermutationGate("PERM", [0, 1, 3, 2])
    PERM = perm_def.get_constructor()
    prog_0.inst(perm_def)
    prog_0.inst(PERM(0, 1))
    prog_1.inst(perm_def)
    prog_1.inst(PERM(1, 0))
    assert (merge_programs([prog_0,
                            prog_1]).out() == """DEFGATE PERM AS PERMUTATION:
    0, 1, 3, 2
DEFGATE test:
    1.0, 0
    0, 1.0

X 0
test 0
PERM 0 1
Y 0
test 0
PERM 1 0
""")
    assert (merge_programs([
        Program("DECLARE ro BIT[1]"),
        Program("H 0"),
        Program("MEASURE 0 ro[0]")
    ]).out() == """DECLARE ro BIT[1]
H 0
MEASURE 0 ro[0]
""")

    q0 = QubitPlaceholder()
    q0_str = "{" + str(q0) + "}"
    p0 = Program(X(q0))
    p1 = Program(Z(q0))
    merged = merge_programs([p0, p1])
    assert (str(merged) == f"""X {q0_str}
Z {q0_str}
""")
    assert (address_qubits(merged, {q0: 1}).out() == """X 1
Z 1
""")
    q1 = QubitPlaceholder()
    p2 = Program(Z(q1))
    assert (address_qubits(merge_programs([p0, p2]), {
        q0: 1,
        q1: 2
    }).out() == """X 1
Z 2
""")
    p0 = address_qubits(p0, {q0: 2})
    p1 = address_qubits(p1, {q0: 1})
    assert (merge_programs([p0, p1]).out() == """X 2
Z 1
""")