コード例 #1
0
 def test_valid_input_complex(self, adj):
     """Test if function returns ``False`` for a complex symmetric matrix"""
     assert utils.is_undirected(1j * adj)
コード例 #2
0
 def test_invalid_type(self, adj):
     """Test if function raises a ``TypeError`` when the input is not a NumPy array"""
     with pytest.raises(TypeError,
                        match="Input matrix must be a NumPy array"):
         utils.is_undirected(adj.tolist())
コード例 #3
0
 def test_valid_input(self, adj):
     """Test if function returns ``True`` for a symmetric matrix"""
     assert utils.is_undirected(adj)
コード例 #4
0
 def test_invalid_rank(self, adj):
     """Test if function returns ``False`` for an input array with dimension not equal to 2"""
     assert not utils.is_undirected(np.expand_dims(adj, axis=0))
コード例 #5
0
 def test_invalid_dimension(self, adj, dim):
     """Test if function returns ``False`` for a (1, 1)-dimensional NumPy array"""
     if dim == 2:
         assert not utils.is_undirected(adj[0:1, 0:1])
コード例 #6
0
 def test_invalid_sizes(self, adj, dim):
     """Test if function returns ``False`` for an input non-square matrix"""
     assert not utils.is_undirected(adj[:dim - 1])
コード例 #7
0
    def test_invalid_nonsymmetric(self, adj):
        """Test if function returns ``False`` for a non-symmetric matrix"""
        adj[1, 0] = 0

        assert not utils.is_undirected(adj)
コード例 #8
0
ファイル: sample.py プロジェクト: lneuhaus/strawberryfields-1
def quantum_sampler(A: np.ndarray,
                    n_mean: float,
                    samples: int = 1,
                    backend_options: Optional[dict] = None) -> list:
    r"""Generate samples from GBS

    Perform quantum sampling of adjacency matrix :math:`A` using the Gaussian boson sampling
    algorithm.

    Sampling can be controlled with the optional ``backend_options`` argument, which should be a
    dict containing any of the following:

    .. glossary::

        key: ``"remote"``, value: *bool*
            Performs sampling on a remote server if ``True``. Remote sampling is
            required for sampling on hardware. If not specified, sampling will be performed locally.

        key: ``"backend"``, value: *str*
            Requested backend for sampling. Available backends are listed in
            ``QUANTUM_BACKENDS``, these are:

            - ``"gaussian"``: for simulating the output of a GBS device using the
              :mod:`strawberryfields.backends.gaussianbackend`

        key: ``"threshold"``, value: *bool*
            Performs sampling using threshold (on/off click) detectors if ``True``
            or using photon number resolving detectors if ``False``. Defaults to ``True`` for
            threshold sampling.

        key: ``"postselect"``, value: *int*
            Causes samples with a photon number or click number less than the
            specified value to be filtered out. Defaults to ``0`` if unspecified, resulting in no
            postselection. Note that the number of samples returned in :func:`quantum_sampler` is
            still equal to the ``samples`` parameter.

    Args:
        A (array): the (real or complex) :math:`N \times N` adjacency matrix to sample from
        n_mean (float): mean photon number
        samples (int): number of samples; defaults to 1
        backend_options (dict[str, Any]): dictionary specifying options used by backends during
            sampling; defaults to :const:`BACKEND_DEFAULTS`

    Returns:
        list[list[int]]: a list of length ``samples`` whose elements are length :math:`N` lists of
        integers indicating events (e.g., photon numbers or clicks) in each of the :math:`N`
        modes of the detector
    """
    backend_options = {**BACKEND_DEFAULTS, **(backend_options or {})}

    if not utils.is_undirected(A):
        raise ValueError(
            "Input must be a NumPy array corresponding to a symmetric matrix")

    if samples < 1:
        raise ValueError("Number of samples must be at least one")

    nodes = len(A)
    p = sf.Program(nodes)

    mean_photon_per_mode = n_mean / float(nodes)

    # pylint: disable=expression-not-assigned,pointless-statement
    with p.context as q:
        sf.ops.GraphEmbed(A, mean_photon_per_mode=mean_photon_per_mode) | q
        sf.ops.Measure | q

    p = p.compile("gbs")

    postselect = backend_options["postselect"]
    threshold = backend_options["threshold"]

    if postselect == 0:
        s = _sample_sf(p, shots=samples, backend_options=backend_options)

        if threshold:
            s[s >= 1] = 1

        s = s.tolist()

    elif postselect > 0:
        s = []

        while len(s) < samples:
            samp = np.array(
                _sample_sf(p, shots=1, backend_options=backend_options))

            if threshold:
                samp[samp >= 1] = 1

            counts = np.sum(samp)

            if counts >= postselect:
                s.append(samp.tolist())

    else:
        raise ValueError("Can only postselect on nonnegative values")

    return s