Esempio n. 1
0
 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)
Esempio n. 2
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},
         )
Esempio n. 3
0
    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)
Esempio n. 4
0
    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)
Esempio n. 5
0
    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)
Esempio n. 6
0
def test_random_seed(dim, adj):
    """Test for the function ``glassonion.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)
Esempio n. 7
0
    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)
Esempio n. 8
0
    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()
Esempio n. 9
0
    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()
Esempio n. 10
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 ``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)
Esempio n. 11
0
 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)