def _get_unrestricted_qvm(connection: ForestConnection, noisy: bool, n_qubits: int = 34) -> QuantumComputer: """ A qvm with a fully-connected topology. This is obviously the least realistic QVM, but who am I to tell users what they want. Users interested in building their own QuantumComputer from parts may wish to look to this function for inspiration, but should not use this private function directly. :param connection: The connection to use to talk to external services :param noisy: Whether to construct a noisy quantum computer :param n_qubits: 34 qubits ought to be enough for anybody. :return: A pre-configured QuantumComputer """ fully_connected_device = NxDevice(topology=nx.complete_graph(n_qubits)) if noisy: # note to developers: the noise model specifies noise for each possible gate. In a fully # connected topology, there are a lot. noise_model = decoherence_noise_with_asymmetric_ro( gates=gates_in_isa(fully_connected_device.get_isa())) else: noise_model = None name = f'{n_qubits}q-noisy-qvm' if noisy else f'{n_qubits}q-qvm' return QuantumComputer(name=name, qam=QVM(connection=connection, noise_model=noise_model), device=fully_connected_device, compiler=_get_qvm_compiler_based_on_endpoint( device=fully_connected_device, endpoint=connection.compiler_endpoint))
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
def _get_9q_square_qvm(connection: ForestConnection, noisy: bool) -> QuantumComputer: """ A nine-qubit 3x3 square lattice. This uses a "generic" lattice not tied to any specific device. 9 qubits is large enough to do vaguely interesting algorithms and small enough to simulate quickly. Users interested in building their own QuantumComputer from parts may wish to look to this function for inspiration, but should not use this private function directly. :param connection: The connection to use to talk to external services :param noisy: Whether to construct a noisy quantum computer :return: A pre-configured QuantumComputer """ nineq_square = nx.convert_node_labels_to_integers(nx.grid_2d_graph(3, 3)) nineq_device = NxDevice(topology=nineq_square) if noisy: noise_model = decoherence_noise_with_asymmetric_ro( gates=gates_in_isa(nineq_device.get_isa())) else: noise_model = None name = '9q-square-noisy-qvm' if noisy else '9q-square-qvm' return QuantumComputer(name=name, qam=QVM(connection=connection, noise_model=noise_model), device=nineq_device, compiler=_get_qvm_compiler_based_on_endpoint( device=nineq_device, endpoint=connection.compiler_endpoint))
def _get_qvm_with_topology(name: str, topology: nx.Graph, noisy: bool = False, requires_executable: bool = True, connection: ForestConnection = None, qvm_type: str = 'qvm') -> QuantumComputer: """Construct a QVM with the provided topology. :param name: A name for your quantum computer. This field does not affect behavior of the constructed QuantumComputer. :param topology: A graph representing the desired qubit connectivity. :param noisy: Whether to include a generic noise model. If you want more control over the noise model, please construct your own :py:class:`NoiseModel` and use :py:func:`_get_qvm_qc` instead of this function. :param requires_executable: Whether this QVM will refuse to run a :py:class:`Program` and only accept the result of :py:func:`compiler.native_quil_to_executable`. Setting this to True better emulates the behavior of a QPU. :param connection: An optional :py:class:`ForestConnection` object. If not specified, the default values for URL endpoints will be used. :param qvm_type: The type of QVM. Either 'qvm' or 'pyqvm'. :return: A pre-configured QuantumComputer """ # Note to developers: consider making this function public and advertising it. device = NxDevice(topology=topology) if noisy: noise_model = decoherence_noise_with_asymmetric_ro( gates=gates_in_isa(device.get_isa())) else: noise_model = None return _get_qvm_qc(name=name, qvm_type=qvm_type, connection=connection, device=device, noise_model=noise_model, requires_executable=requires_executable)
def decoherance_noise_with_asymmetric_ro(isa: ISA, p00=0.975, p11=0.911): """Similar to :py:func`_decoherance_noise_model`, but with asymmetric readout. For simplicity, we use the default values for T1, T2, gate times, et al. and only allow the specification of readout fidelities. """ gates = gates_in_isa(isa) noise_model = _decoherence_noise_model(gates) aprobs = np.array([[p00, 1 - p00], [1 - p11, p11]]) aprobs = {q: aprobs for q in noise_model.assignment_probs.keys()} return NoiseModel(noise_model.gates, aprobs)
def test_gates_in_isa(isa_dict): isa = ISA.from_dict(isa_dict) gates = gates_in_isa(isa) for q in [0, 1, 2]: for g in [I, RX(np.pi / 2), RX(-np.pi / 2), RZ(THETA)]: assert g(q) in gates assert CZ(0, 1) in gates assert CZ(1, 0) in gates assert ISWAP(1, 2) in gates assert ISWAP(2, 1) in gates assert CPHASE(THETA)(2, 0) in gates assert CPHASE(THETA)(0, 2) in gates
def test_reset_confusion_consistency(qvm): noise_model = decoherence_noise_with_asymmetric_ro( gates=gates_in_isa(qvm.device.get_isa())) qvm.qam.noise_model = noise_model qvm.qam.random_seed = 1 num_trials = 10 qubits = (0, 1) passive_reset = estimate_joint_reset_confusion( qvm, qubits, num_trials, len(qubits), use_active_reset=False)[qubits] atol = .1 np.testing.assert_allclose(passive_reset[:, 0], np.ones(4).T, atol=atol)
def decoherance_noise_with_asymettric_ro(isa: ISA): """Reimplementation of `add_decoherance_noise` with asymmetric readout. For simplicity, we use the default values for T1, T2, gate times, et al. and hard-code readout fidelities here. """ gates = gates_in_isa(isa) noise_model = _decoherence_noise_model(gates) p00 = 0.975 p11 = 0.911 aprobs = np.array([[p00, 1 - p00], [1 - p11, p11]]) aprobs = {q: aprobs for q in noise_model.assignment_probs.keys()} return NoiseModel(noise_model.gates, aprobs)
def test_readout_confusion_matrix_consistency(qvm): noise_model = decoherence_noise_with_asymmetric_ro( gates=gates_in_isa(qvm.device.get_isa())) qvm.qam.noise_model = noise_model qvm.qam.random_seed = 1 num_shots = 500 qubits = (0, 1, 2) qubit = (0, ) # parameterized confusion matrices cm_3q_param = estimate_joint_confusion_in_set( qvm, qubits, num_shots=num_shots, joint_group_size=len(qubits))[qubits] cm_1q_param = estimate_joint_confusion_in_set(qvm, qubit, num_shots=num_shots, joint_group_size=1)[qubit] # non-parameterized confusion matrices cm_3q = estimate_joint_confusion_in_set(qvm, qubits, num_shots=num_shots, joint_group_size=len(qubits), use_param_program=False)[qubits] cm_1q = estimate_joint_confusion_in_set(qvm, qubit, num_shots=num_shots, joint_group_size=1, use_param_program=False, use_active_reset=True)[qubit] # single qubit cm single_q = estimate_confusion_matrix(qvm, qubit[0], num_shots) # marginals from 3q above marginal_1q_param = marginalize_confusion_matrix(cm_3q_param, qubits, qubit) marginal_1q = marginalize_confusion_matrix(cm_3q, qubits, qubit) atol = .03 np.testing.assert_allclose(cm_3q_param, cm_3q, atol=atol) np.testing.assert_allclose(cm_1q_param, single_q, atol=atol) np.testing.assert_allclose(cm_1q, single_q, atol=atol) np.testing.assert_allclose(cm_1q_param, marginal_1q_param, atol=atol) np.testing.assert_allclose(cm_1q, marginal_1q, atol=atol) np.testing.assert_allclose(marginal_1q_param, single_q, atol=atol)
def noise_model(self, dev: device.Device) -> noise.NoiseModel: return noise._decoherence_noise_model(gates=device.gates_in_isa( dev.get_isa()), T1=300e-6, T2=300e-6, ro_fidelity=0.99)