コード例 #1
0
ファイル: grover.py プロジェクト: zyzhang1992/Rigetti-Grove
    def find_bitstring(self, qc: QuantumComputer,
                       bitstring_map: Dict[str, int]) -> str:
        """
        Runs Grover's Algorithm to find the bitstring that is designated by ``bistring_map``.

        In particular, this will prepare an initial state in the uniform superposition over all bit-
        strings, an then use Grover's Algorithm to pick out the desired bitstring.

        :param qc: the connection to the Rigetti cloud to run pyQuil programs.
        :param bitstring_map: a mapping from bitstrings to the phases that the oracle should impart
            on them. If the oracle should "look" for a bitstring, it should have a ``-1``, otherwise
            it should have a ``1``.
        :return: Returns the bitstring resulting from measurement after Grover's Algorithm.
        """

        self._init_attr(bitstring_map)

        ro = self.grover_circuit.declare('ro', 'BIT', len(self.qubits))
        self.grover_circuit += [
            MEASURE(qubit, ro[idx]) for idx, qubit in enumerate(self.qubits)
        ]
        executable = qc.compile(self.grover_circuit)
        sampled_bitstring = qc.run(executable)

        return "".join([str(bit) for bit in sampled_bitstring[0]])
コード例 #2
0
def test_qc_joint_expectation(forest):
    device = NxDevice(nx.complete_graph(2))
    qc = QuantumComputer(
        name="testy!", qam=QVM(connection=forest), device=device, compiler=DummyCompiler()
    )

    # |01> state program
    p = Program()
    p += RESET()
    p += X(0)
    p.wrap_in_numshots_loop(10)

    # ZZ experiment
    sz = ExperimentSetting(
        in_state=sZ(0) * sZ(1), out_operator=sZ(0) * sZ(1), additional_expectations=[[0], [1]]
    )
    e = Experiment(settings=[sz], program=p)

    results = qc.experiment(e)

    # ZZ expectation value for state |01> is -1
    assert np.isclose(results[0].expectation, -1)
    assert np.isclose(results[0].std_err, 0)
    assert results[0].total_counts == 40
    # Z0 expectation value for state |01> is -1
    assert np.isclose(results[0].additional_results[0].expectation, -1)
    assert results[0].additional_results[1].total_counts == 40
    # Z1 expectation value for state |01> is 1
    assert np.isclose(results[0].additional_results[1].expectation, 1)
    assert results[0].additional_results[1].total_counts == 40
コード例 #3
0
def test_readout_symmetrization(forest):
    device = NxDevice(nx.complete_graph(3))
    noise_model = decoherence_noise_with_asymmetric_ro(gates=gates_in_isa(device.get_isa()))
    qc = QuantumComputer(
        name='testy!',
        qam=QVM(connection=forest, noise_model=noise_model),
        device=device,
        compiler=DummyCompiler()
    )

    prog = Program(I(0), X(1),
                   MEASURE(0, 0),
                   MEASURE(1, 1))
    prog.wrap_in_numshots_loop(1000)

    bs1 = qc.run(prog)
    avg0_us = np.mean(bs1[:, 0])
    avg1_us = 1 - np.mean(bs1[:, 1])
    diff_us = avg1_us - avg0_us
    assert diff_us > 0.03

    bs2 = qc.run_symmetrized_readout(prog, 1000)
    avg0_s = np.mean(bs2[:, 0])
    avg1_s = 1 - np.mean(bs2[:, 1])
    diff_s = avg1_s - avg0_s
    assert diff_s < 0.05
コード例 #4
0
def test_qpu_run():
    config = PyquilConfig()
    if config.qpu_url and config.qpu_compiler_url:
        g = nx.Graph()
        g.add_node(0)
        device = NxDevice(g)

        qc = QuantumComputer(
            name="pyQuil test QC",
            qam=QPU(endpoint=config.qpu_url, user="******"),
            device=device,
            compiler=QPUCompiler(
                quilc_endpoint=config.quilc_url,
                qpu_compiler_endpoint=config.qpu_compiler_url,
                device=device,
            ),
        )
        bitstrings = qc.run_and_measure(program=Program(X(0)), trials=1000)
        assert bitstrings[0].shape == (1000, )
        assert np.mean(bitstrings[0]) > 0.8
        bitstrings = qc.run(qc.compile(Program(X(0))))
        assert bitstrings.shape == (0, 0)
    else:
        pytest.skip(
            "QPU or compiler-server not available; skipping QPU run test.")
コード例 #5
0
def test_measure_bitstrings(forest):
    device = NxDevice(nx.complete_graph(2))
    qc_pyqvm = QuantumComputer(name='testy!',
                               qam=PyQVM(n_qubits=2),
                               device=device,
                               compiler=DummyCompiler())
    qc_forest = QuantumComputer(name='testy!',
                                qam=QVM(connection=forest,
                                        gate_noise=[0.00] * 3),
                                device=device,
                                compiler=DummyCompiler())
    prog = Program(I(0), I(1))
    meas_qubits = [0, 1]
    sym_progs, flip_array = _symmetrization(prog, meas_qubits, symm_type=-1)
    results = _measure_bitstrings(qc_pyqvm,
                                  sym_progs,
                                  meas_qubits,
                                  num_shots=1)
    # test with pyQVM
    answer = [
        np.array([[0, 0]]),
        np.array([[0, 1]]),
        np.array([[1, 0]]),
        np.array([[1, 1]])
    ]
    assert all([np.allclose(x, y) for x, y in zip(results, answer)])
    # test with regular QVM
    results = _measure_bitstrings(qc_forest,
                                  sym_progs,
                                  meas_qubits,
                                  num_shots=1)
    assert all([np.allclose(x, y) for x, y in zip(results, answer)])
コード例 #6
0
def test_qc():
    from pyquil.api import ForestConnection, QuantumComputer
    from pyquil.api._compiler import _extract_attribute_dictionary_from_program
    from pyquil.api._qac import AbstractCompiler
    from pyquil.device import NxDevice
    from pyquil.gates import I

    class BasicQVMCompiler(AbstractCompiler):
        def quil_to_native_quil(self, program: Program):
            return basic_compile(program)

        def native_quil_to_executable(self, nq_program: Program):
            return PyQuilExecutableResponse(
                program=nq_program.out(),
                attributes=_extract_attribute_dictionary_from_program(nq_program))
    try:
        qc = QuantumComputer(
            name='testing-qc',
            qam=QVM(connection=ForestConnection(), random_seed=52),
            device=NxDevice(nx.complete_graph(2)),
            compiler=BasicQVMCompiler(),
        )
        qc.run_and_measure(Program(I(0)), trials=1)
        return qc
    except (RequestException, TimeoutError) as e:
        return pytest.skip("This test requires a running local QVM: {}".format(e))
コード例 #7
0
def get_qubit_registers_for_adder(qc: QuantumComputer, num_length: int,
                                  qubits: Optional[Sequence[int]] = None)\
        -> Tuple[Sequence[int], Sequence[int], int, int]:
    """
    Searches for a layout among the given qubits for the two n-bit registers and two additional
    ancilla that matches the simple layout given in figure 4 of [CDKM96]_.

    This method ignores any considerations of physical characteristics of the qc aside from the
    qubit layout. An error is thrown if the appropriate layout is not found.

    :param qc: the quantum resource on which an adder program will be executed.
    :param num_length: the length of the bitstring representation of one summand
    :param qubits: the available qubits on which to run the adder program.
    :return: the necessary registers and ancilla labels for implementing an adder
        program to add the numbers a and b. The output can be passed directly to :func:`adder`
    """
    if qubits is None:
        unavailable = []  # assume this means all qubits in qc are available
    else:
        unavailable = [qubit for qubit in qc.qubits() if qubit not in qubits]

    graph = qc.qubit_topology().copy()
    for qubit in unavailable:
        graph.remove_node(qubit)

    # network x only provides subgraph isomorphism, but we want a subgraph monomorphism, i.e. we
    # specifically want to match the edges desired_layout with some subgraph of graph. To
    # accomplish this, we swap the nodes and edges of graph by making a line graph.
    line_graph = nx.line_graph(graph)

    # We want a path of n nodes, which has n-1 edges. Since we are matching edges of graph with
    # nodes of layout we make a layout of n-1 nodes.
    num_desired_nodes = 2 * num_length + 2
    desired_layout = nx.path_graph(num_desired_nodes - 1)

    g_matcher = nx.algorithms.isomorphism.GraphMatcher(line_graph,
                                                       desired_layout)

    try:
        # pick out a subgraph isomorphic to the desired_layout if one exists
        # this is an isomorphic mapping from edges in graph (equivalently nodes of line_graph) to
        # nodes in desired_layout (equivalently edges of a path graph with one more node)
        edge_iso = next(g_matcher.subgraph_isomorphisms_iter())
    except IndexError:
        raise Exception(
            "An appropriate layout for the qubits could not be found among the "
            "provided qubits.")

    # pick out the edges of the isomorphism from the original graph
    subgraph = nx.Graph(graph.edge_subgraph(edge_iso.keys()))

    # pick out an endpoint of our path to start the assignment
    start_node = -1
    for node in subgraph.nodes:
        if subgraph.degree(node) == 1:  # found an endpoint
            start_node = node
            break

    return assign_registers_to_line_or_cycle(start_node, subgraph, num_length)
コード例 #8
0
def test_device_stuff():
    topo = nx.from_edgelist([(0, 4), (0, 99)])
    qc = QuantumComputer(
        name='testy!',
        qam=None,  # not necessary for this test
        device=NxDevice(topo),
        compiler=DummyCompiler())
    assert nx.is_isomorphic(qc.qubit_topology(), topo)

    isa = qc.get_isa(twoq_type='CPHASE')
    assert sorted(isa.edges)[0].type == 'CPHASE'
    assert sorted(isa.edges)[0].targets == [0, 4]
コード例 #9
0
def test_run(forest):
    device = NxDevice(nx.complete_graph(3))
    qc = QuantumComputer(name='testy!',
                         qam=QVM(connection=forest, gate_noise=[0.01] * 3),
                         device=device,
                         compiler=DummyCompiler())
    bitstrings = qc.run(
        Program(H(0), CNOT(0, 1), CNOT(1, 2), MEASURE(0, 0), MEASURE(1, 1),
                MEASURE(2, 2)).wrap_in_numshots_loop(1000))

    assert bitstrings.shape == (1000, 3)
    parity = np.sum(bitstrings, axis=1) % 3
    assert 0 < np.mean(parity) < 0.15
コード例 #10
0
def test_run_pyqvm_noiseless():
    device = NxDevice(nx.complete_graph(3))
    qc = QuantumComputer(name='testy!',
                         qam=PyQVM(n_qubits=3),
                         device=device,
                         compiler=DummyCompiler())
    bitstrings = qc.run(
        Program(H(0), CNOT(0, 1), CNOT(1, 2), MEASURE(0, 0), MEASURE(1, 1),
                MEASURE(2, 2)).wrap_in_numshots_loop(1000))

    assert bitstrings.shape == (1000, 3)
    parity = np.sum(bitstrings, axis=1) % 3
    assert np.mean(parity) == 0
コード例 #11
0
def process_characterisation(qc: QuantumComputer) -> dict:
    """Convert a :py:class:`pyquil.api.QuantumComputer` to a dictionary containing
    Rigetti device Characteristics

    :param qc: A quantum computer to be converted
    :type qc: QuantumComputer
    :return: A dictionary containing Rigetti device characteristics
    """
    specs = qc.device.get_specs()

    coupling_map = [[n, ni]
                    for n, neigh_dict in qc.qubit_topology().adjacency()
                    for ni, _ in neigh_dict.items()]

    node_ers_dict = {}
    link_ers_dict = {}
    t1_times_dict = {}
    t2_times_dict = {}

    device_node_fidelities = specs.f1QRBs()  # type: ignore
    device_link_fidelities = specs.fCZs()  # type: ignore
    device_fROs = specs.fROs()  # type: ignore
    device_t1s = specs.T1s()  # type: ignore
    device_t2s = specs.T2s()  # type: ignore

    for index in qc.qubits():
        error_cont = QubitErrorContainer({OpType.Rx, OpType.Rz})
        error_cont.add_readout(1 - device_fROs[index])  # type: ignore
        t1_times_dict[index] = device_t1s[index]
        t2_times_dict[index] = device_t2s[index]
        error_cont.add_error(
            (OpType.Rx, 1 - device_node_fidelities[index]))  # type: ignore
        # Rigetti use frame changes for Rz, so they effectively have no error.
        node_ers_dict[Node(index)] = error_cont

    for (a, b), fid in device_link_fidelities.items():
        error_cont = QubitErrorContainer({OpType.CZ})
        error_cont.add_error((OpType.CZ, 1 - fid))  # type: ignore
        link_ers_dict[(Node(a), Node(b))] = error_cont
        link_ers_dict[(Node(b), Node(a))] = error_cont

    arc = Architecture(coupling_map)

    characterisation = dict()
    characterisation["NodeErrors"] = node_ers_dict
    characterisation["EdgeErrors"] = link_ers_dict
    characterisation["Architecture"] = arc
    characterisation["t1times"] = t1_times_dict
    characterisation["t2times"] = t2_times_dict

    return characterisation
コード例 #12
0
def metadata_save(qc: QuantumComputer,
                  repo_path: str = None,
                  filename: str = None) -> pd.DataFrame:
    '''
    This helper function saves metadata related to your run on a Quantum computer.

    Basic data saved includes the date and time. Additionally information related to the quantum
    computer is saved: device name, topology, qubit labels, edges that have two qubit gates,
    device specs

    If a path is passed to this function information related to the Git Repository is saved,
    specifically the repository: name, branch and commit.

    :param qc: The QuantumComputer to run the experiment on.
    :param repo_path: path to repository e.g. '../'
    :param filename: The name of the file to write JSON-serialized results to.
    :return: pandas DataFrame
    '''

    # Git related things
    if repo_path is not None:
        repo = Repo(repo_path)
        branch = repo.active_branch
        sha = repo.head.object.hexsha
        short_sha = repo.git.rev_parse(sha, short=7)
        the_repo = repo.git_dir
        the_branch = branch.name
        the_commit = short_sha
    else:
        the_repo = None
        the_branch = None
        the_commit = None

    metadata = {
        # Time and date
        'Date': str(date.today()),
        'Time': str(datetime.now().time()),
        # Git stuff
        'Repository': the_repo,
        'Branch': the_branch,
        'Git_commit': the_commit,
        # QPU data
        'Device_name': qc.name,
        'Topology': qc.qubit_topology(),
        'Qubits': list(qc.qubit_topology().nodes),
        'Two_Qubit_Gates': list(qc.qubit_topology().edges),
        'Device_Specs': qc.device.get_specs(),
    }
    if filename:
        pd.DataFrame(metadata).to_json(filename)
    return pd.DataFrame(metadata)
コード例 #13
0
def test_run_pyqvm_noiseless():
    device = NxDevice(nx.complete_graph(3))
    qc = QuantumComputer(
        name="testy!", qam=PyQVM(n_qubits=3), device=device, compiler=DummyCompiler()
    )
    prog = Program(H(0), CNOT(0, 1), CNOT(1, 2))
    ro = prog.declare("ro", "BIT", 3)
    for q in range(3):
        prog += MEASURE(q, ro[q])
    bitstrings = qc.run(prog.wrap_in_numshots_loop(1000))

    assert bitstrings.shape == (1000, 3)
    parity = np.sum(bitstrings, axis=1) % 3
    assert np.mean(parity) == 0
コード例 #14
0
def test_run_with_parameters(forest):
    device = NxDevice(nx.complete_graph(3))
    qc = QuantumComputer(name='testy!',
                         qam=QVM(connection=forest),
                         device=device,
                         compiler=DummyCompiler())
    bitstrings = qc.run(executable=Program(
        Declare(name='theta', memory_type='REAL'),
        Declare(name='ro', memory_type='BIT'), RX(MemoryReference('theta'), 0),
        MEASURE(0, MemoryReference('ro'))).wrap_in_numshots_loop(1000),
                        memory_map={'theta': [np.pi]})

    assert bitstrings.shape == (1000, 1)
    assert all([bit == 1 for bit in bitstrings])
コード例 #15
0
def test_run_pyqvm_noisy():
    device = NxDevice(nx.complete_graph(3))
    qc = QuantumComputer(
        name='testy!',
        qam=PyQVM(n_qubits=3,
                  post_gate_noise_probabilities={'relaxation': 0.01}),
        device=device,
        compiler=DummyCompiler())
    bitstrings = qc.run(
        Program(H(0), CNOT(0, 1), CNOT(1, 2), MEASURE(0, 0), MEASURE(1, 1),
                MEASURE(2, 2)).wrap_in_numshots_loop(1000))

    assert bitstrings.shape == (1000, 3)
    parity = np.sum(bitstrings, axis=1) % 3
    assert 0 < np.mean(parity) < 0.15
コード例 #16
0
    def run(self, qc: QuantumComputer,
            bitstring_map: Dict[str, str]) -> 'BernsteinVazirani':
        """
        Runs the Bernstein-Vazirani algorithm.

        Given a connection to a QVM or QPU, find the :math:`\\mathbf{a}` and :math:`b` corresponding
        to the function represented by the oracle function that will be constructed from the
        bitstring map.

        :param qc: connection to the QPU or QVM
        :param bitstring_map: a truth table describing the boolean function, whose dot-product
            vector and bias is to be found
        """
        # initialize all attributes
        self.input_bitmap = bitstring_map
        self.n_qubits = len(list(bitstring_map.keys())[0])
        self.computational_qubits = list(range(self.n_qubits))
        self.ancilla = self.n_qubits  # is the highest index now.

        # construct BV circuit
        self.bv_circuit = self._create_bv_circuit(bitstring_map)

        # find vector by running the full bv circuit
        full_circuit = Program()
        full_ro = full_circuit.declare('ro', 'BIT',
                                       len(self.computational_qubits) + 1)
        full_circuit += self.bv_circuit
        full_circuit += [
            MEASURE(qubit, ro)
            for qubit, ro in zip(self.computational_qubits, full_ro)
        ]
        full_executable = qc.compile(full_circuit)
        full_results = qc.run(full_executable)
        bv_vector = full_results[0][::-1]

        # To get the bias term we skip the Walsh-Hadamard transform
        ancilla_circuit = Program()
        ancilla_ro = ancilla_circuit.declare(
            'ro', 'BIT',
            len(self.computational_qubits) + 1)
        ancilla_circuit += self.bv_circuit
        ancilla_circuit += [MEASURE(self.ancilla, ancilla_ro[self.ancilla])]
        ancilla_executable = qc.compile(ancilla_circuit)
        ancilla_results = qc.run(ancilla_executable)
        bv_bias = ancilla_results[0][0]

        self.solution = ''.join([str(b) for b in bv_vector]), str(bv_bias)
        return self
コード例 #17
0
    def __init__(self, data, label, shuffle=False, qpu=False):
        weights = np.load(data)
        n_graphs = len(weights)

        # read labels from file, or as single label
        if os.path.exists(label):
            labels = np.load(label)
        else:
            labels = [label for _ in range(n_graphs)]

        if shuffle:
            self._shuffled_order = np.random.permutation(n_graphs)
            weights = weights[self._shuffled_order]
            labels = labels[self._shuffled_order]

        self.pset = AllProblems(weights, labels)
        self.num_qubits = self.pset.num_variables()

        qubits = list(range(self.num_qubits))
        angles = np.linspace(0, 2 * np.pi, NUM_ANGLES, endpoint=False)
        self.instrs = [
            CNOT(q0, q1) for q0, q1 in product(qubits, qubits) if q0 != q1
        ]
        self.instrs += [
            op(theta, q)
            for q, op, theta in product(qubits, [RX, RY, RZ], angles)
        ]
        self.action_space = gym.spaces.Discrete(len(self.instrs))

        obs_len = NUM_SHOTS * self.num_qubits + len(self.pset.problem(0))
        self.observation_space = gym.spaces.Box(np.full(obs_len, -1.0),
                                                np.full(obs_len, 1.0),
                                                dtype=np.float32)

        self.reward_threshold = 0.8

        self.qpu = qpu
        if qpu:
            self._qc = get_qc(QPU_NAME)
        else:
            self._qc = QuantumComputer(
                name="qvm",
                qam=PyQVM(n_qubits=self.num_qubits),
                device=NxDevice(nx.complete_graph(self.num_qubits)),
                compiler=MinimalPyQVMCompiler(),
            )

        self.reset()
コード例 #18
0
def apply_noise(qc: QuantumComputer, gate_time=50e-9):
    """
    Get new QuantumComputer with noise model applied
    :param qc: QuantumComputer instance to patch
    :param gate_time: gate time for using in noise model
    :return: patched QuantumComputer instance
    """
    if not isinstance(qc, QuantumComputer):
        raise ValueError(
            f"Invalid parameter {qc} for apply_em(). You should provide a QuantumComputer instance."
        )

    if hasattr(qc.qam, "noise_model") and qc.qam.noise_model is not None:
        raise ValueError(
            f"QuantumComputer {qc} instance should not have noise model.")

    original_run = qc.run

    def new_run(self, executable, *args, **kwargs):
        original_exec = executable.copy()
        new_exec = get_noisy_executable(qc,
                                        get_native_program(qc, original_exec),
                                        noise_param=gate_time)
        original_exec.program = new_exec.program

        return original_run(executable=original_exec, *args, **kwargs)

    qc.run = types.MethodType(new_run, qc)

    return qc
コード例 #19
0
def compile_rigetti(num_qubits, topology, program):
    if topology.lower() == 'ring':
        edge_list = []
        for i in range(0, num_qubits):
            edge_list.append((i, (i + 1) % num_qubits))

        topology = nx.from_edgelist(edge_list)
        device = NxDevice(topology)

        compiler = LocalQVMCompiler("http://localhost:6000", device)
        my_qc = QuantumComputer(name='my_qc',
                                qam=QVM(connection=ForestConnection()),
                                device=device,
                                compiler=compiler)
        executable = compiler.quil_to_native_quil(
            program)  #create QC compatible specification
        depth = compute_depth_rigetti(executable)
        volume = len(executable) - 3  #subtract extra directives
        print(executable)
        q2_count = two_qubit_count(executable)
        out_str = str(executable)
        out_str = out_str + ("#DEPTH: %s |VOL.: %s |2Q GATE COUNT: %s\n" %
                             (depth, volume, q2_count))
        print("DEPTH: %s |VOL.: %s |2Q GATE COUNT: %s" %
              (depth, volume, q2_count))
        print()
        print()
        return out_str
コード例 #20
0
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"
コード例 #21
0
def run_t1(qc: QuantumComputer,
           qubits: Union[int, List[int]],
           stop_time: float,
           n_shots: int = 1000,
           num_points: int = 15,
           filename: str = None) -> pd.DataFrame:
    """
    Execute experiments to measure the t1 decay time of 1 or more qubits.

    :param qc: The QuantumComputer to run the experiment on.
    :param qubits: Which qubits to measure.
    :param stop_time: The maximum decay time to measure at.
    :param n_shots: The number of shots to average over for each data point.
    :param num_points: The number of points for each t1 curve.
    :param filename: The name of the file to write JSON-serialized results to.
    """
    results = []
    for t, program in generate_t1_experiments(qubits, stop_time, n_shots,
                                              num_points):
        executable = qc.compiler.native_quil_to_executable(program)
        bitstrings = qc.run(executable)

        for i in range(len(qubits)):
            avg = np.mean(bitstrings[:, i])
            results.append({
                'qubit': qubits[i],
                'time': t,
                'n_bitstrings': len(bitstrings),
                'avg': float(avg),
            })

    df = pd.DataFrame(results)
    if filename is not None:
        df.to_json(filename)
    return df
コード例 #22
0
def run_rabi(qc: QuantumComputer,
             qubits: Union[int, List[int]],
             n_shots: int = 1000,
             num_points: int = 15,
             filename: str = None) -> pd.DataFrame:
    """
    Execute experiments to measure Rabi flop one or more qubits.

    :param qc: The QuantumComputer to run the experiment on.
    :param qubits: Which qubits to measure.
    :param n_shots: The number of shots to average over for each data point.
    :param num_points: The number of points for each Rabi curve.
    :param filename: The name of the file to write JSON-serialized results to.
    :return: DataFrame with Rabi results.
    """
    results = []
    for theta, program in generate_rabi_experiments(qubits, n_shots,
                                                    num_points):
        executable = qc.compiler.native_quil_to_executable(program)
        bitstrings = qc.run(executable)

        for i in range(len(qubits)):
            avg = np.mean(bitstrings[:, i])
            results.append({
                'qubit': qubits[i],
                'angle': theta,
                'n_bitstrings': len(bitstrings),
                'avg': float(avg),
            })

    if filename:
        pd.DataFrame(results).to_json(filename)
    return pd.DataFrame(results)
コード例 #23
0
def acquire_data_t2(
    qc: QuantumComputer,
    t2_experiment: pd.DataFrame,
) -> pd.DataFrame:
    """
    Execute experiments to measure the T2 star or T2 echo decay time of 1 or more qubits.

    :param qc: The QuantumComputer to run the experiment on
    :param t2_experiment: A pandas DataFrame containing: time, T2 program
    :param detuning: The additional detuning frequency about the z axis.
    :return: pandas DataFrame containing T2 results, and detuning used in creating experiments for
    those results.
    """
    results = []

    for index, row in t2_experiment.iterrows():
        t = row['Time']
        program = row['Program']
        detuning = row['Detuning']
        executable = qc.compiler.native_quil_to_executable(program)
        bitstrings = qc.run(executable)

        qubits = list(program.get_qubits())
        for i in range(len(qubits)):
            avg = np.mean(bitstrings[:, i])
            results.append({
                'Qubit': qubits[i],
                'Time': t,
                'Num_bitstrings': len(bitstrings),
                'Average': float(avg),
                'Detuning': float(detuning),
            })

    return pd.DataFrame(results)
コード例 #24
0
def get_parametric_program(qc: QuantumComputer,
                           q0: int,
                           q1: int,
                           n_shots: int = 1000):
    """
    Run one (beta, gamma) point for the simplest Maxcut QAOA.

    :param qc: The QuantumComputer to use
    :param beta: The beta angle (p = 1)
    :param gamma: The gamma angle (p = 1)
    :param q0: The index of the first qubit
    :param q1: The index of the second qubit
    :param n_shots: The number of shots to take for this (beta, gamma) point.
    """
    ising = generate_maxcut_ising(nx.from_edgelist([(0, 1)]))
    driver = sX(q0) + sX(q1)
    reward = sZ(q0) * sZ(q1) + 0  # add 0 to turn to PauliSum

    program = Program()
    beta = program.declare('beta', memory_type='REAL')
    gamma = program.declare('gamma', memory_type='REAL')
    program += get_qaoa_program(qubits=[q0, q1],
                                driver=driver,
                                reward=reward,
                                betas=[beta],
                                gammas=[gamma])
    ro = program.declare('ro', memory_size=2)
    program += MEASURE(q0, ro[0])
    program += MEASURE(q1, ro[1])
    program = program.wrap_in_numshots_loop(shots=n_shots)

    executable = qc.compile(program)
    return executable, ising
コード例 #25
0
def acquire_data_t1(
    qc: QuantumComputer,
    t1_experiment: pd.DataFrame,
) -> pd.DataFrame:
    """
    Execute experiments to measure the T1 decay time of 1 or more qubits.

    :param qc: The QuantumComputer to run the experiment on
    :param t1_experiment: A pandas DataFrame with columns: time, t1 program
    :return: pandas DataFrame
    """
    results = []

    for index, row in t1_experiment.iterrows():
        t = row['Time']
        program = row['Program']

        executable = qc.compiler.native_quil_to_executable(program)
        bitstrings = qc.run(executable)

        qubits = list(program.get_qubits())
        for i in range(len(qubits)):
            avg = np.mean(bitstrings[:, i])
            results.append({
                'Qubit': qubits[i],
                'Time': t,
                'Num_bitstrings': len(bitstrings),
                'Average': float(avg),
                'Program': program,
            })

    df = pd.DataFrame(results)
    return df
コード例 #26
0
def acquire_data_rabi(qc: QuantumComputer,
                      rabi_experiment: pd.DataFrame,
                      filename: str = None) -> pd.DataFrame:
    """
    Execute experiments to measure Rabi flop one or more qubits.

    :param qc: The QuantumComputer to run the experiment on
    :param rabi_experiment: pandas DataFrame: (theta, Rabi program)
    :return: DataFrame with Rabi results
    """
    results = []
    for index, row in rabi_experiment.iterrows():
        theta = row['Angle']
        program = row['Program']
        executable = qc.compiler.native_quil_to_executable(program)
        bitstrings = qc.run(executable)

        qubits = list(program.get_qubits())
        for i in range(len(qubits)):
            avg = np.mean(bitstrings[:, i])
            results.append({
                'Qubit': qubits[i],
                'Angle': theta,
                'Num_bitstrings': len(bitstrings),
                'Average': float(avg),
            })

    if filename:
        pd.DataFrame(results).to_json(filename)
    return pd.DataFrame(results)
コード例 #27
0
def test_run_with_parameters(forest):
    device = NxDevice(nx.complete_graph(3))
    qc = QuantumComputer(
        name="testy!", qam=QVM(connection=forest), device=device, compiler=DummyCompiler()
    )
    bitstrings = qc.run(
        executable=Program(
            Declare(name="theta", memory_type="REAL"),
            Declare(name="ro", memory_type="BIT"),
            RX(MemoryReference("theta"), 0),
            MEASURE(0, MemoryReference("ro")),
        ).wrap_in_numshots_loop(1000),
        memory_map={"theta": [np.pi]},
    )

    assert bitstrings.shape == (1000, 1)
    assert all([bit == 1 for bit in bitstrings])
コード例 #28
0
def expectation_from_sampling(pyquil_program: Program,
                              marked_qubits: List[int], qc: QuantumComputer,
                              samples: int,
                              stacked_params: np.ndarray) -> float:
    """
    Calculation of Z_{i} at marked_qubits

    Given a wavefunctions, this calculates the expectation value of the Zi
    operator where i ranges over all the qubits given in marked_qubits.

    :param pyquil_program: pyQuil program generating some state
    :param marked_qubits: The qubits within the support of the Z pauli
                          operator whose expectation value is being calculated
    :param qc: A QuantumComputer object.
    :param samples: Number of bitstrings collected to calculate expectation
                    from sampling.
    :returns: The expectation value as a float.
    """
    program = Program()
    ro = program.declare('ro', 'BIT', max(marked_qubits) + 1)
    program += pyquil_program
    program += [
        MEASURE(qubit, r)
        for qubit, r in zip(list(range(max(marked_qubits) + 1)), ro)
    ]
    program.wrap_in_numshots_loop(samples)
    try:
        executable = qc.compile(program)
    except:
        import pdb
        pdb.set_trace()

    bitstring_samples = qc.run(executable)
    bitstring_tuples = list(map(tuple, bitstring_samples))

    freq = Counter(bitstring_tuples)

    # perform weighted average
    expectation = 0
    for bitstring, count in freq.items():
        bitstring_int = int("".join([str(x) for x in bitstring[::-1]]), 2)
        if parity_even_p(bitstring_int, marked_qubits):
            expectation += float(count) / samples
        else:
            expectation -= float(count) / samples
    return expectation
コード例 #29
0
def sample_rand_circuits_for_heavy_out(
        qc: QuantumComputer,
        qubits: Sequence[int],
        depth: int,
        program_generator: Callable[
            [QuantumComputer, Sequence[int], Sequence[np.ndarray], np.ndarray],
            Program],
        num_circuits: int = 100,
        num_shots: int = 1000,
        show_progress_bar: bool = False) -> int:
    """
    This method performs the bulk of the work in the quantum volume measurement.

    For the given depth, num_circuits many random model circuits are generated, the heavy outputs
    are determined from the ideal output distribution of each circuit, and a native quil
    implementation of the model circuit output by the program generator is run on the qc. The total
    number of sampled heavy outputs is returned.

    :param qc: the quantum resource that will implement the PyQuil program for each model circuit
    :param qubits: the qubits available in the qc for the program_generator to use.
    :param depth: the depth (and width in num of qubits) of the model circuits
    :param program_generator: a method which takes an abstract description of a model circuit and
        returns a native quil program that implements that circuit. See measure_quantum_volume
        docstring for specifics.
    :param num_circuits: the number of random model circuits to sample at this depth; should be >100
    :param num_shots: the number of shots to sample from each model circuit
    :param show_progress_bar: displays a progress bar via tqdm if true.
    :return: the number of heavy outputs sampled among all circuits generated for this depth
    """
    wfn_sim = NumpyWavefunctionSimulator(depth)

    num_heavy = 0
    # display progress bar using tqdm
    for _ in tqdm(range(num_circuits), disable=not show_progress_bar):

        permutations, gates = generate_abstract_qv_circuit(depth)

        # generate a PyQuil program in native quil that implements the model circuit
        # The program should measure the output qubits in the order that is consistent with the
        # comparison of the bitstring results to the heavy outputs given by collect_heavy_outputs
        program = program_generator(qc, qubits, permutations, gates)

        # run the program num_shots many times
        program.wrap_in_numshots_loop(num_shots)
        executable = qc.compiler.native_quil_to_executable(program)
        results = qc.run(executable)

        # classically simulate model circuit represented by the perms and gates for heavy outputs
        heavy_outputs = collect_heavy_outputs(wfn_sim, permutations, gates)

        # determine if each result bitstring is a heavy output, as determined from simulation
        for result in results:
            # convert result to int for comparison with heavy outputs.
            output = bit_array_to_int(result)
            if output in heavy_outputs:
                num_heavy += 1

    return num_heavy
コード例 #30
0
def apply_em(
        qc: QuantumComputer,
        base_gate_time: float = 50e-9,
        order: int = 3,
        noise_param_multiply_coefficients: np.ndarray = None
) -> QuantumComputer:
    """
    Get new QuantumComputer which will run programs with EM technique applied.
    :param qc: QuantumComputer instance to patch
    :param base_gate_time: base noise parameter
    :param order: order of the Richardson extrapolation
    :param noise_param_multiply_coefficients: coefficients to be used for stretching base noise parameter
    :return: the new patched QuantumComputer instance
    """

    if not isinstance(qc, QuantumComputer):
        raise ValueError(
            f"Invalid parameter {qc} for apply_em(). You should provide a QuantumComputer instance."
        )

    if hasattr(qc.qam, "noise_model") and qc.qam.noise_model is not None:
        raise ValueError(
            f"QuantumComputer {qc} instance should not have noise model.")

    original_run = qc.run

    if noise_param_multiply_coefficients is None:
        noise_param_multiply_coefficients = np.arange(1, order + 2)

    def new_run(self, executable, *args, **kwargs):
        noise_params = noise_param_multiply_coefficients * base_gate_time
        original_exec = executable.copy()
        native_program = get_native_program(qc, original_exec)

        original_results = []
        trials, qubits = None, None

        for noise_param in noise_params:
            new_exec = get_noisy_executable(qc, native_program, noise_param)
            original_exec.program = new_exec.program

            bitstring = original_run(executable=original_exec, *args, **kwargs)
            trials, qubits = bitstring.shape
            original_results.append(get_expectations(bitstring))

        original_results = np.array(original_results)

        mitigated_result = get_extrapolated_with_richardson(
            noise_param_multiply_coefficients, original_results)
        result_bitstring = get_bitstrings_from_expectations(
            mitigated_result, (qubits, trials))

        return result_bitstring

    qc.run = types.MethodType(new_run, qc)

    return qc