def test_invalid_adjacency(self, adj, monkeypatch): """Test if function raises a ``ValueError`` for a matrix that fails :func:`graph.utils.is_undirected` """ with monkeypatch.context() as m: m.setattr(utils, "is_undirected", lambda _: False) with pytest.raises(ValueError, match="Input must be a NumPy array"): sample.quantum_sampler(A=adj, n_mean=1.0)
def test_badpostselect(self, adj): """Tests if function raises a ``ValueError`` when a negative value is set for ``postselect`` """ with pytest.raises(ValueError, match="Can only postselect on nonnegative values"): sample.quantum_sampler(A=adj, n_mean=1.0, samples=sample_number, backend_options={"postselect": -1})
def test_threshold_postselect(self, adj, monkeypatch, valid_backends): """Test if function returns samples when threshold detection is used and postselection. With threshold detection, all non-zero elements of a sample are set to 1. Postselection only returns samples with a total click number (number of 1's) not less than the parameter specified. """ def dummy_sample_sf(*args, **kwargs): """Dummy ``_sample_sf`` function""" return sample_pnr_postselect with monkeypatch.context() as m: m.setattr(sample, "_sample_sf", dummy_sample_sf) samples = np.array( sample.quantum_sampler( A=adj, n_mean=1.0, samples=sample_number, backend_options={ "backend": valid_backends, "threshold": True, "postselect": 1 }, )) samples_target = np.array( [sample_pnr_postselect[0] for _ in range(sample_number)]) samples_target[samples_target >= 1] = 1 assert np.allclose(samples, samples_target)
def test_pnr_postselect(self, adj, monkeypatch, valid_backends): """Test if function returns samples when photon-number resolving detection is used and postselection. Postselection only returns samples with a total photon number not less than the parameter specified. """ def dummy_sample_sf(*args, **kwargs): """Dummy ``_sample_sf`` function""" return sample_pnr_postselect with monkeypatch.context() as m: m.setattr(sample, "_sample_sf", dummy_sample_sf) samples = np.array( sample.quantum_sampler( A=adj, n_mean=1.0, samples=sample_number, backend_options={ "backend": valid_backends, "threshold": False, "postselect": 1, }, )) samples_target = np.array( [sample_pnr_postselect[0] for _ in range(sample_number)]) assert np.allclose(samples, samples_target)
def test_threshold_nopostselect(self, adj, monkeypatch, valid_backends): """Test if function returns correct samples when threshold detection is used and no postselection on samples. With threshold detection, all non-zero elements of a sample are set to 1. """ samples_threshold_nopostselect = samples_pnr_nopostselect.copy() samples_threshold_nopostselect[samples_threshold_nopostselect >= 1] = 1 def dummy_sample_sf(*args, **kwargs): """Dummy ``_sample_sf`` function""" return samples_pnr_nopostselect with monkeypatch.context() as m: m.setattr(sample, "_sample_sf", dummy_sample_sf) samples = np.array( sample.quantum_sampler( A=adj, n_mean=1.0, samples=sample_number, backend_options={ "backend": valid_backends, "threshold": True, "postselect": 0 }, )) assert set(tuple(samples.flatten())) == {0, 1} assert np.allclose(samples, samples_threshold_nopostselect)
def test_random_seed(dim, adj): """Test for the function ``strawberryfields.gbs.sample.random_seed``. Checks that samples are identical after repeated initialization of ``random_seed``.""" sample.random_seed(1968) q_s_1 = sample.quantum_sampler(A=adj, n_mean=2, samples=10, backend_options={"threshold": False}) u_s_1 = sample.uniform_sampler(modes=dim, sampled_modes=2, samples=10) sample.random_seed(1968) q_s_2 = sample.quantum_sampler(A=adj, n_mean=2, samples=10, backend_options={"threshold": False}) u_s_2 = sample.uniform_sampler(modes=dim, sampled_modes=2, samples=10) assert np.array_equal(q_s_1, q_s_2) assert np.array_equal(u_s_1, u_s_2)
def test_pnr_nopostselect(self, adj, monkeypatch, valid_backends): """Test if function returns correct samples with no additional manipulation, i.e., no postselection or threshold detection """ def dummy_sample_sf(*args, **kwargs): """Dummy ``_sample_sf`` function""" return samples_pnr_nopostselect with monkeypatch.context() as m: m.setattr(sample, "_sample_sf", dummy_sample_sf) samples = sample.quantum_sampler( A=adj, n_mean=1.0, samples=sample_number, backend_options={ "backend": valid_backends, "threshold": False, "postselect": 0 }, ) assert np.allclose(samples_pnr_nopostselect, samples)
def test_pnr_nopostselect_integration(self, adj): """Integration test to check if function returns samples of correct form, i.e., correct number of samples, correct number of modes, all non-negative integers """ samples = np.array( sample.quantum_sampler( A=adj, n_mean=1.0, samples=integration_sample_number, backend_options={ "threshold": False, "postselect": 0 }, )) dims = samples.shape assert len(dims) == 2 assert dims[0] == integration_sample_number assert dims[1] == len(adj) assert samples.dtype == "int" assert (samples >= 0).all()
def test_threshold_postselect_integration(self, adj): """Integration test to check if function returns samples of correct form, i.e., correct number of samples, correct number of modes, all integers of zeros and ones with total click number not less than 1 """ samples = np.array( sample.quantum_sampler( A=adj, n_mean=1.0, samples=integration_sample_number, backend_options={ "threshold": True, "postselect": 1 }, )) dims = samples.shape assert len(dims) == 2 assert dims[0] == integration_sample_number assert dims[1] == len(adj) assert samples.dtype == "int" assert (samples >= 0).all() assert (samples <= 1).all() assert (np.sum(samples, axis=1) >= 1).all()
def test_invalid_samples(self, adj, monkeypatch): """Test if function raises a ``ValueError`` when a number of samples less than one is requested """ with pytest.raises(ValueError, match="Number of samples must be at least one"): sample.quantum_sampler(A=adj, n_mean=1.0, samples=0)
def sample_subgraphs( graph: nx.Graph, nodes: int, samples: int = 1, sample_options: Optional[dict] = None, backend_options: Optional[dict] = None, ) -> list: """Functionality for sampling subgraphs. The optional ``sample_options`` argument can be used to specify the type of sampling. It should be a dict that contains any of the following: .. glossary:: key: ``"distribution"``, value: *str* Subgraphs can be sampled according to the following distributions: - ``"gbs"``: for generating subgraphs according to the Gaussian boson sampling distribution. In this distribution, subgraphs are sampled with a variable size ( default). - ``"uniform"``: for generating subgraphs uniformly at random. When using this distribution, subgraphs are of a fixed size. Note that ``backend_options`` are not used and that remote sampling is unavailable due to the simplicity of the distribution. key: ``"postselect_ratio"``, value: *float* Ratio of ``nodes`` used to determine the minimum size of subgraph sampled; defaults to 0.75. Args: graph (nx.Graph): the input graph nodes (int): the mean size of subgraph samples samples (int): number of samples; defaults to 1 sample_options (dict[str, Any]): dictionary specifying options used by :func:`sample_subgraphs`; defaults to :const:`SAMPLE_DEFAULTS` backend_options (dict[str, Any]): dictionary specifying options used by backends during sampling; defaults to ``None`` Returns: list[list[int]]: a list of length ``samples`` whose elements are subgraphs given by a list of nodes """ sample_options = {**SAMPLE_DEFAULTS, **(sample_options or {})} distribution = sample_options["distribution"] if distribution == "uniform": s = sample.uniform_sampler(modes=graph.order(), sampled_modes=nodes, samples=samples) elif distribution == "gbs": postselect = int(sample_options["postselect_ratio"] * nodes) backend_options = {**(backend_options or {}), "postselect": postselect} s = sample.quantum_sampler( A=nx.to_numpy_array(graph), n_mean=nodes, samples=samples, backend_options=backend_options, ) else: raise ValueError("Invalid distribution selected") return to_subgraphs(graph, s)