示例#1
0
def _generate_experiment_programs(
    tomo_experiment: TomographyExperiment, active_reset: bool = False
) -> Tuple[List[Program], List[List[int]]]:
    """
    Generate the programs necessary to estimate the observables in a TomographyExperiment.
    Grouping of settings to be run in parallel, e.g. by a call to group_experiments, should be
    done before this function is called.

    .. CAUTION::
        One must be careful with compilation of the output programs before the appropriate MEASURE
        instructions are added, because compilation may re-index the qubits so that
        the output list of `measure_qubits` no longer accurately indexes the qubits that
        should be measured.

    :param tomo_experiment: a single TomographyExperiment to be translated to a series of programs
        that, when run serially, can be used to estimate each of its observables.
    :param active_reset: whether or not to begin the program by actively resetting. If true,
        execution of each of the returned programs in a loop on the QPU will generally be faster.
    :return: a list of programs along with a corresponding list of the groups of qubits that are
        measured by that program. The returned programs may be run on a qc after measurement
        instructions are added for the corresponding group of qubits in meas_qubits, or by a call
        to `qc.run_symmetrized_readout` -- see :func:`raw_estimate_observables` for possible usage.
    """
    # Outer loop over a collection of grouped settings for which we can simultaneously estimate.
    programs = []
    meas_qubits = []
    for settings in tomo_experiment:

        # Prepare a state according to the amalgam of all setting.in_state
        total_prog = Program()
        if active_reset:
            total_prog += RESET()
        max_weight_in_state = _max_weight_state(setting.in_state for setting in settings)
        if max_weight_in_state is None:
            raise ValueError(
                "Input states are not compatible. Re-group the experiment settings "
                "so that groups of parallel settings have compatible input states."
            )
        for oneq_state in max_weight_in_state.states:
            total_prog += _one_q_state_prep(oneq_state)

        # Add in the program
        total_prog += tomo_experiment.program

        # Prepare for measurement state according to setting.out_operator
        max_weight_out_op = _max_weight_operator(setting.out_operator for setting in settings)
        if max_weight_out_op is None:
            raise ValueError(
                "Observables not compatible. Re-group the experiment settings "
                "so that groups of parallel settings have compatible observables."
            )
        for qubit, op_str in max_weight_out_op:
            total_prog += _local_pauli_eig_meas(op_str, qubit)

        programs.append(total_prog)

        meas_qubits.append(max_weight_out_op.get_qubits())
    return programs, meas_qubits
示例#2
0
 def _expt_settings_diagonal_in_tpb(es1: ExperimentSetting,
                                    es2: ExperimentSetting):
     """
     Extends the concept of being diagonal in the same tpb to ExperimentSettings, by
     determining if the pairs of in_states and out_operators are separately diagonal in the same
     tpb
     """
     max_weight_in = _max_weight_state([es1.in_state, es2.in_state])
     max_weight_out = _max_weight_operator(
         [es1.out_operator, es2.out_operator])
     return max_weight_in is not None and max_weight_out is not None
示例#3
0
def test_expt_settings_share_ntpb():
    expts = [
        [
            ExperimentSetting(zeros_state([0, 1]),
                              sX(0) * sI(1)),
            ExperimentSetting(zeros_state([0, 1]),
                              sI(0) * sX(1)),
        ],
        [
            ExperimentSetting(zeros_state([0, 1]),
                              sZ(0) * sI(1)),
            ExperimentSetting(zeros_state([0, 1]),
                              sI(0) * sZ(1)),
        ],
    ]
    for group in expts:
        for e1, e2 in itertools.combinations(group, 2):
            assert _max_weight_state([e1.in_state, e2.in_state]) is not None
            assert _max_weight_operator([e1.out_operator,
                                         e2.out_operator]) is not None
示例#4
0
def test_max_weight_operator_4():
    # this last example illustrates that a pair of commuting operators
    # need not be diagonal in the same tpb
    assert _max_weight_operator([sX(1) * sZ(0), sZ(1) * sX(0)]) is None
示例#5
0
def test_max_weight_operator_misc():
    assert _max_weight_operator([sZ(0), sZ(0) * sZ(1)]) is not None
    assert _max_weight_operator([sX(5), sZ(4)]) is not None
    assert _max_weight_operator([sX(0), sY(0) * sZ(2)]) is None

    x_term = sX(0) * sX(1)
    z1_term = sZ(1)
    z0_term = sZ(0)
    z0z1_term = sZ(0) * sZ(1)
    assert _max_weight_operator([x_term, z1_term]) is None
    assert _max_weight_operator([z0z1_term, x_term]) is None

    assert _max_weight_operator([z1_term, z0_term]) is not None
    assert _max_weight_operator([z0z1_term, z0_term]) is not None
    assert _max_weight_operator([z0z1_term, z1_term]) is not None
    assert _max_weight_operator([z0z1_term, sI(1)]) is not None
    assert _max_weight_operator([z0z1_term, sI(2)]) is not None
    assert _max_weight_operator([z0z1_term, sX(5) * sZ(7)]) is not None

    xxxx_terms = (sX(1) * sX(2) + sX(2) + sX(3) * sX(4) + sX(4) +
                  sX(1) * sX(3) * sX(4) + sX(1) * sX(4) +
                  sX(1) * sX(2) * sX(3))
    true_term = sX(1) * sX(2) * sX(3) * sX(4)
    assert _max_weight_operator(xxxx_terms.terms) == true_term

    zzzz_terms = sZ(1) * sZ(2) + sZ(3) * sZ(4) + sZ(1) * sZ(3) + sZ(1) * sZ(
        3) * sZ(4)
    assert _max_weight_operator(
        zzzz_terms.terms) == sZ(1) * sZ(2) * sZ(3) * sZ(4)

    pauli_terms = [sZ(0), sX(1) * sZ(0), sY(2) * sX(1), sZ(5) * sI(3)]
    assert _max_weight_operator(pauli_terms) == sZ(5) * sY(2) * sX(1) * sZ(0)
示例#6
0
def test_max_weight_operator_3():
    pauli_terms = [sZ(0) * sX(5), sX(1) * sZ(0), sY(2) * sX(1), sZ(5) * sI(3)]
    assert _max_weight_operator(pauli_terms) is None
示例#7
0
def test_max_weight_operator_1():
    pauli_terms = [sZ(0), sX(1) * sZ(0), sY(2) * sX(1)]
    assert _max_weight_operator(pauli_terms) == sY(2) * sX(1) * sZ(0)