Exemple #1
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()
    prog_0.defgate("test", np.eye(2))
    prog_0.inst(("test", 0))
    prog_1.defgate("test", np.eye(2))
    prog_1.inst(("test", 0))
    assert merge_programs([prog_0, prog_1]).out() == """DEFGATE test:
def merge_sequences(sequences: List[List[Program]]) -> List[Program]:
    """
    Takes a list of equal-length "sequences" (lists of Programs) and merges them element-wise,
    returning the merged outcome.
    :param sequences: List of equal-length Lists of Programs
    :return: A single List of Programs
    """
    depth = len(sequences[0])
    assert all([len(s) == depth for s in sequences])
    return [merge_programs([seq[idx] for seq in sequences]) for idx in range(depth)]
def rb_seq_to_program(rb_seq: List[Program], subgraph: List[Tuple]) -> Program:
    """
    Combines an RB sequence into a single program that includes appends measurements and returns
    this Program.

    :rtype: Program
    """
    qubits = list(chain.from_iterable(subgraph))
    program = merge_programs(rb_seq)
    ro = program.declare('ro', 'BIT', len(qubits))
    return program.measure_all(*zip(qubits,ro))
 def run(qc: QuantumComputer, seq: List[Program], subgraph: List[List[int]], num_trials: int) -> np.ndarray:
     prog = merge_programs(seq)
     # TODO: parallelize
     results = []
     for qubits in subgraph:
         state_prep = prog
         tomo_exp = generate_state_tomography_experiment(state_prep, qubits=qubits)
         _rs = list(measure_observables(qc, tomo_exp, num_trials))
         # Inelegant shim from state tomo refactor. To clean up!
         expectations=[r.expectation for r in _rs[1:]]
         variances=[r.std_err ** 2 for r in _rs[1:]]
         results.append((expectations, variances))
     return results
def group_sequences_into_parallel_experiments(parallel_expts_seqs: Sequence[List[List[Program]]],
                                              qubit_groups: Sequence[Sequence[int]],
                                              is_unitarity_expt: bool = False) \
        -> List[ObservablesExperiment]:
    """
    Consolidates randomized benchmarking sequences on separate groups of qubits into a flat list
    of ObservablesExperiments which merge parallel sets of distinct sequences.

    Each returned ObservablesExperiment constitutes a single 'parallel RB sequence' where all of
    the qubits are acted upon and measured. Running all of these ObservablesExperiments in series
    constitutes a 'parallel RB' experiment from which you can determine a decay constant for each
    group of qubits. Note that there is an important physical distinction (e.g. due to
    cross-talk) between running separate RB experiments on different groups of qubits and running
    a 'parallel RB' experiment on the collection of those groups. For this reason one should not
    expect in general that the rb decay for a particular group of qubits is comparable between
    the individual and parallel modes of rb experiment.

    :param parallel_expts_seqs: the outer Sequence is indexed by disjoint groups of qubits;
        Clifford sequences from each of these different groups (which should be of the same depth
        across qubit groups) will be merged together into a single program. The intended use-case
        is that each List[List[program]] of sequences of Cliffords is an output of
        generate_rb_experiment_sequences for disjoint groups of qubits but with identical
        depths input (see generate_rb_experiments for example). If sequences of different depth are
        merged into a Program then some qubits may be sitting idle while the sequences of greater
        depth continue running. Measurement occurs only when all sequences have terminated.
    :param qubit_groups: The partition of the qubits into groups for each of which you would like to
        estimate an rb decay. Typically this grouping of qubits should match the qubits that are
        acted on by each sequence in the corresponding List[List[Program]] of the input
        parallel_expts_seqs.
    :param is_unitarity_expt: True if the desired experiment is a unitarity experiment, in which
        case additional settings are required to estimate the purity of the sequence output.
    :return: a list of ObservablesExperiments constituting a parallel rb experiment.
    """
    expts = []
    for parallel_sequence_group in zip(*parallel_expts_seqs):
        program = merge_programs(merge_sequences(parallel_sequence_group))

        if is_unitarity_expt:
            settings = [sett for group in qubit_groups for sett in _state_tomo_settings(group)]
            expt = group_settings(ObservablesExperiment(settings, program))
        else:
            # measure observables of products of I and Z on qubits in the group, excluding all I
            settings = [ExperimentSetting(zeros_state(group), op)
                        for group in qubit_groups for op in all_traceless_pauli_z_terms(group)]
            expt = ObservablesExperiment([settings], program)
        expts.append(expt)
    return expts
Exemple #6
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
""")
Exemple #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()