Beispiel #1
0
def test_build_experiment_setting_memory_map():
    p = Program()
    s = ExperimentSetting(in_state=sX(0), out_operator=sZ(0) * sY(1))
    e = TomographyExperiment(settings=[s], program=p)
    memory_map = e.build_setting_memory_map(s)
    assert memory_map == {
        'preparation_alpha': [0.0],
        'preparation_beta': [np.pi / 2],
        'preparation_gamma': [0.0],
        'measurement_alpha': [0.0, np.pi / 2],
        'measurement_beta': [0.0, np.pi / 2],
        'measurement_gamma': [0.0, -np.pi / 2]
    }
Beispiel #2
0
def test_build_symmetrization_memory_maps():
    p = Program()
    s = ExperimentSetting(in_state=sZ(0) * sZ(1), out_operator=sZ(0) * sZ(1))
    e = TomographyExperiment(settings=[s], program=p)
    memory_maps = [{
        'symmetrization': [0.0, 0.0]
    }, {
        'symmetrization': [0.0, np.pi]
    }, {
        'symmetrization': [np.pi, 0.0]
    }, {
        'symmetrization': [np.pi, np.pi]
    }]
    assert e.build_symmetrization_memory_maps([0, 1]) == memory_maps
def test_for_negative_probabilities():
    # trivial program to do state tomography on
    prog = Program(I(0))

    # make TomographyExperiment
    expt_settings = [ExperimentSetting(zeros_state([0]), pt) for pt in [sI(0), sX(0), sY(0), sZ(0)]]
    experiment_1q = TomographyExperiment(settings=expt_settings, program=prog)

    # make a quantum computer object
    device = NxDevice(nx.complete_graph(1))
    qc_density = QuantumComputer(
        name="testy!",
        qam=PyQVM(n_qubits=1, quantum_simulator_type=ReferenceDensitySimulator),
        device=device,
        compiler=DummyCompiler(),
    )

    # initialize with a pure state
    initial_density = np.array([[1.0, 0.0], [0.0, 0.0]])
    qc_density.qam.wf_simulator.density = initial_density

    try:
        list(measure_observables(qc=qc_density, tomo_experiment=experiment_1q, n_shots=3000))
    except ValueError as e:
        # the error is from np.random.choice by way of self.rs.choice in ReferenceDensitySimulator
        assert str(e) != "probabilities are not non-negative"

    # initialize with a mixed state
    initial_density = np.array([[0.9, 0.0], [0.0, 0.1]])
    qc_density.qam.wf_simulator.density = initial_density

    try:
        list(measure_observables(qc=qc_density, tomo_experiment=experiment_1q, n_shots=3000))
    except ValueError as e:
        assert str(e) != "probabilities are not non-negative"
Beispiel #4
0
def group_experiments_greedy(tomo_expt: TomographyExperiment):
    """
    Greedy method to group ExperimentSettings in a given TomographyExperiment

    :param tomo_expt: TomographyExperiment to group ExperimentSettings within
    :return: TomographyExperiment, with grouped ExperimentSettings according to whether
        it consists of PauliTerms diagonal in the same tensor product basis
    """
    diag_sets = _max_tpb_overlap(tomo_expt)
    grouped_expt_settings_list = list(diag_sets.values())
    grouped_tomo_expt = TomographyExperiment(grouped_expt_settings_list,
                                             program=tomo_expt.program)
    return grouped_tomo_expt
Beispiel #5
0
def test_tomo_experiment():
    expts = [
        ExperimentSetting(TensorProductState(),
                          sX(0) * sY(1)),
        ExperimentSetting(plusZ(0), sZ(0)),
    ]

    suite = TomographyExperiment(settings=expts, program=Program(X(0), Y(1)))
    assert len(suite) == 2
    for e1, e2 in zip(expts, suite):
        # experiment suite puts in groups of length 1
        assert len(e2) == 1
        e2 = e2[0]
        assert e1 == e2
    prog_str = str(suite).splitlines()[3:5]
    assert prog_str == EXPERIMENT_REPR.splitlines()[4:6]
Beispiel #6
0
def test_qc_expectation_larger_lattice(forest):
    device = NxDevice(nx.complete_graph(4))
    qc = QuantumComputer(name='testy!',
                         qam=QVM(connection=forest),
                         device=device,
                         compiler=DummyCompiler())

    q0 = 2
    q1 = 3

    # bell state program
    p = Program()
    p += RESET()
    p += H(q0)
    p += CNOT(q0, q1)
    p.wrap_in_numshots_loop(10)

    # XX, YY, ZZ experiment
    sx = ExperimentSetting(in_state=sZ(q0) * sZ(q1),
                           out_operator=sX(q0) * sX(q1))
    sy = ExperimentSetting(in_state=sZ(q0) * sZ(q1),
                           out_operator=sY(q0) * sY(q1))
    sz = ExperimentSetting(in_state=sZ(q0) * sZ(q1),
                           out_operator=sZ(q0) * sZ(q1))

    e = TomographyExperiment(settings=[sx, sy, sz], program=p)

    results = qc.experiment(e)

    # XX expectation value for bell state |00> + |11> is 1
    assert np.isclose(results[0].expectation, 1)
    assert np.isclose(results[0].std_err, 0)
    assert results[0].total_counts == 40

    # YY expectation value for bell state |00> + |11> is -1
    assert np.isclose(results[1].expectation, -1)
    assert np.isclose(results[1].std_err, 0)
    assert results[1].total_counts == 40

    # ZZ expectation value for bell state |00> + |11> is 1
    assert np.isclose(results[2].expectation, 1)
    assert np.isclose(results[2].std_err, 0)
    assert results[2].total_counts == 40
Beispiel #7
0
def test_experiment_deser(tmpdir):
    expts = [
        [
            ExperimentSetting(TensorProductState(),
                              sX(0) * sI(1)),
            ExperimentSetting(TensorProductState(),
                              sI(0) * sX(1))
        ],
        [
            ExperimentSetting(TensorProductState(),
                              sZ(0) * sI(1)),
            ExperimentSetting(TensorProductState(),
                              sI(0) * sZ(1))
        ],
    ]

    suite = TomographyExperiment(settings=expts, program=Program(X(0), Y(1)))
    to_json(f'{tmpdir}/suite.json', suite)
    suite2 = read_json(f'{tmpdir}/suite.json')
    assert suite == suite2
Beispiel #8
0
def group_experiments_clique_removal(
        experiments: TomographyExperiment) -> TomographyExperiment:
    """
    Group experiments that are diagonal in a shared tensor product basis (TPB) to minimize number
    of QPU runs, using a graph clique removal algorithm.

    :param experiments: a tomography experiment
    :return: a tomography experiment with all the same settings, just grouped according to shared
        TPBs.
    """
    g = construct_tpb_graph(experiments)
    _, cliqs = clique_removal(g)
    new_cliqs = []
    for cliq in cliqs:
        new_cliq = []
        for expt in cliq:
            # duplicate `count` times
            new_cliq += [expt] * g.nodes[expt]["count"]

        new_cliqs += [new_cliq]

    return TomographyExperiment(new_cliqs, program=experiments.program)
Beispiel #9
0
def test_tomo_experiment_pre_grouped():
    expts = [
        [
            ExperimentSetting(TensorProductState(),
                              sX(0) * sI(1)),
            ExperimentSetting(TensorProductState(),
                              sI(0) * sX(1))
        ],
        [
            ExperimentSetting(TensorProductState(),
                              sZ(0) * sI(1)),
            ExperimentSetting(TensorProductState(),
                              sI(0) * sZ(1))
        ],
    ]

    suite = TomographyExperiment(settings=expts, program=Program(X(0), Y(1)))
    assert len(suite) == 2  # number of groups
    for es1, es2 in zip(expts, suite):
        for e1, e2 in zip(es1, es2):
            assert e1 == e2
    prog_str = str(suite).splitlines()[3:5]
    assert prog_str == EXPERIMENT_REPR.splitlines()[4:6]
Beispiel #10
0
    def simulate(self, amplitudes):
        """Perform the simulation for the molecule.

        Args:
            amplitudes (list): The initial amplitudes (float64).
        Returns:
            float64: The total energy (energy).
        Raise:
            ValueError: If the dimension of the amplitude list is incorrect.
        """
        if len(amplitudes) != self.amplitude_dimension:
            raise ValueError("Incorrect dimension for amplitude list.")

        #Anti-hermitian operator and its qubit form
        generator = uccsd_singlet_generator(amplitudes, self.of_mole.n_qubits,
                                            self.of_mole.n_electrons)
        jw_generator = jordan_wigner(generator)
        pyquil_generator = qubitop_to_pyquilpauli(jw_generator)

        p = Program(Pragma('INITIAL_REWIRING', ['"GREEDY"']))
        # Set initial wavefunction (Hartree-Fock)
        for i in range(self.of_mole.n_electrons):
            p.inst(X(i))
        # Trotterization (unitary for UCCSD state preparation)
        for term in pyquil_generator.terms:
            term.coefficient = np.imag(term.coefficient)
            p += exponentiate(term)
        p.wrap_in_numshots_loop(self.backend_options["n_shots"])

        #  Do not simulate if no operator was passed
        if len(self.qubit_hamiltonian.terms) == 0:
            return 0.
        else:
            # Run computation using the right backend
            if isinstance(self.backend_options["backend"],
                          WavefunctionSimulator):
                energy = self.backend_options["backend"].expectation(
                    prep_prog=p, pauli_terms=self.forest_qubit_hamiltonian)
            else:
                # Set up experiment, each setting corresponds to a particular measurement basis
                settings = [
                    ExperimentSetting(in_state=TensorProductState(),
                                      out_operator=forest_term)
                    for forest_term in self.forest_qubit_hamiltonian.terms
                ]
                experiment = TomographyExperiment(settings=settings, program=p)
                print(experiment, "\n")
                results = self.backend_options["backend"].experiment(
                    experiment)

                energy = 0.
                coefficients = [
                    forest_term.coefficient
                    for forest_term in self.forest_qubit_hamiltonian.terms
                ]
                for i in range(len(results)):
                    energy += results[i].expectation * coefficients[i]

            energy = np.real(energy)

        # Save the amplitudes so we have the optimal ones for RDM calculation
        self.optimized_amplitudes = amplitudes

        return energy
Beispiel #11
0
def test_tomo_experiment_empty():
    suite = TomographyExperiment([], program=Program(X(0)))
    assert len(suite) == 0
    assert str(suite.program) == 'X 0\n'
Beispiel #12
0
def test_generate_experiment_program():
    # simplest example
    p = Program()
    s = ExperimentSetting(in_state=sZ(0), out_operator=sZ(0))
    e = TomographyExperiment(settings=[s], program=p, symmetrization=0)
    exp = e.generate_experiment_program()
    test_exp = Program()
    ro = test_exp.declare('ro', 'BIT')
    test_exp += MEASURE(0, ro[0])
    assert exp.out() == test_exp.out()
    assert exp.num_shots == 1

    # 2Q exhaustive symmetrization
    p = Program()
    s = ExperimentSetting(in_state=sZ(0) * sZ(1), out_operator=sZ(0) * sZ(1))
    e = TomographyExperiment(settings=[s], program=p)
    exp = e.generate_experiment_program()
    test_exp = Program()
    test_exp += parameterized_readout_symmetrization([0, 1])
    ro = test_exp.declare('ro', 'BIT', 2)
    test_exp += MEASURE(0, ro[0])
    test_exp += MEASURE(1, ro[1])
    assert exp.out() == test_exp.out()
    assert exp.num_shots == 1

    # add shots
    p = Program()
    p.wrap_in_numshots_loop(1000)
    s = ExperimentSetting(in_state=sZ(0), out_operator=sZ(0))
    e = TomographyExperiment(settings=[s], program=p, symmetrization=0)
    exp = e.generate_experiment_program()
    test_exp = Program()
    ro = test_exp.declare('ro', 'BIT')
    test_exp += MEASURE(0, ro[0])
    assert exp.out() == test_exp.out()
    assert exp.num_shots == 1000

    # active reset
    p = Program()
    p += RESET()
    s = ExperimentSetting(in_state=sZ(0), out_operator=sZ(0))
    e = TomographyExperiment(settings=[s], program=p, symmetrization=0)
    exp = e.generate_experiment_program()
    test_exp = Program()
    test_exp += RESET()
    ro = test_exp.declare('ro', 'BIT')
    test_exp += MEASURE(0, ro[0])
    assert exp.out() == test_exp.out()
    assert exp.num_shots == 1

    # state preparation and measurement
    p = Program()
    s = ExperimentSetting(in_state=sY(0), out_operator=sX(0))
    e = TomographyExperiment(settings=[s], program=p, symmetrization=0)
    exp = e.generate_experiment_program()
    test_exp = Program()
    test_exp += parameterized_single_qubit_state_preparation([0])
    test_exp += parameterized_single_qubit_measurement_basis([0])
    ro = test_exp.declare('ro', 'BIT')
    test_exp += MEASURE(0, ro[0])
    assert exp.out() == test_exp.out()
    assert exp.num_shots == 1

    # multi-qubit state preparation and measurement
    p = Program()
    s = ExperimentSetting(in_state=sZ(0) * sY(1), out_operator=sZ(0) * sX(1))
    e = TomographyExperiment(settings=[s], program=p, symmetrization=0)
    exp = e.generate_experiment_program()
    test_exp = Program()
    test_exp += parameterized_single_qubit_state_preparation([0, 1])
    test_exp += parameterized_single_qubit_measurement_basis([0, 1])
    ro = test_exp.declare('ro', 'BIT', 2)
    test_exp += MEASURE(0, ro[0])
    test_exp += MEASURE(1, ro[1])
    assert exp.out() == test_exp.out()
    assert exp.num_shots == 1