def test_valid_input_complex(self, adj): """Test if function returns ``False`` for a complex symmetric matrix""" assert utils.is_undirected(1j * adj)
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())
def test_valid_input(self, adj): """Test if function returns ``True`` for a symmetric matrix""" assert utils.is_undirected(adj)
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))
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])
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])
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)
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