class_docstr: A space representing graph information as a series of `nodes` connected with `edges` according to an adjacency matrix represented as a series of `edge_links`.
  
  Example usage::
  
      self.observation_space = spaces.Graph(node_space=space.Box(low=-100, high=100, shape=(3,)), edge_space=spaces.Discrete(3))
class_docstr_tok: ["A","space","representing","graph","information","as","a","series","of","`","nodes","`","connected","with","`","edges","`","according","to","an","adjacency","matrix","represented","as","a","series","of","`","edge_links","`",".","Example","usage",":",":","self.observation_space","=","spaces.Graph","(","node_space=space.Box","(","low=-100",",","high=100",",","shape=","(","3",",",")",")",",","edge_space=spaces.Discrete","(","3",")",")"]
docstr: Generates a single sample graph with num_nodes between 1 and 10 sampled from the Graph.
  
  Args:
      mask: An optional tuple of optional node and edge mask that is only possible with Discrete spaces
          (Box spaces don't support sample masks).
          If no `num_edges` is provided then the `edge_mask` is multiplied by the number of edges
      num_nodes: The number of nodes that will be sampled, the default is 10 nodes
      num_edges: An optional number of edges, otherwise, a random number between 0 and `num_nodes`^2
  
  Returns:
      A NamedTuple representing a graph with attributes .nodes, .edges, and .edge_links.
docstr_tok: ["Generates","a","single","sample","graph","with","num_nodes","between","1","and","10","sampled","from","the","Graph",".","Args",":","mask",":","An","optional","tuple","of","optional","node","and","edge","mask","that","is","only","possible","with","Discrete","spaces","(","Box","spaces","do","n't","support","sample","masks",")",".","If","no","`","num_edges","`","is","provided","then","the","`","edge_mask","`","is","multiplied","by","the","number","of","edges","num_nodes",":","The","number","of","nodes","that","will","be","sampled",",","the","default","is","10","nodes","num_edges",":","An","optional","number","of","edges",",","otherwise",",","a","random","number","between","0","and","`","num_nodes","`","^2","Returns",":","A","NamedTuple","representing","a","graph","with","attributes",".nodes",",",".edges",",","and",".edge_links","."]
code: def sample(
      self,
      mask: Optional[
          Tuple[
              Optional[Union[np.ndarray, tuple]],
              Optional[Union[np.ndarray, tuple]],
          ]
      ] = None,
      num_nodes: int = 10,
      num_edges: Optional[int] = None,
  ) -> GraphInstance:
      """Generates a single sample graph with num_nodes between 1 and 10 sampled from the Graph.
  
      Args:
          mask: An optional tuple of optional node and edge mask that is only possible with Discrete spaces
              (Box spaces don't support sample masks).
              If no `num_edges` is provided then the `edge_mask` is multiplied by the number of edges
          num_nodes: The number of nodes that will be sampled, the default is 10 nodes
          num_edges: An optional number of edges, otherwise, a random number between 0 and `num_nodes`^2
  
      Returns:
          A NamedTuple representing a graph with attributes .nodes, .edges, and .edge_links.
      """
      assert (
          num_nodes > 0
      ), f"The number of nodes is expected to be greater than 0, actual value: {num_nodes}"
  
      if mask is not None:
          node_space_mask, edge_space_mask = mask
      else:
          node_space_mask, edge_space_mask = None, None
  
      # we only have edges when we have at least 2 nodes
      if num_edges is None:
          if num_nodes > 1:
              # maximal number of edges is `n*(n-1)` allowing self connections and two-way is allowed
              num_edges = self.np_random.integers(
                  num_nodes * (num_nodes - 1)
              )
          else:
              num_edges = 0
  
          if edge_space_mask is not None:
              edge_space_mask = tuple(
                  edge_space_mask for _ in range(num_edges)
              )
      else:
          if self.edge_space is None:
              warn(
                  f"The number of edges is set ({num_edges}) but the edge space is None."
              )
          assert (
              num_edges >= 0
          ), f"Expects the number of edges to be greater than 0, actual value: {num_edges}"
      assert num_edges is not None
  
      sampled_node_space = self._generate_sample_space(
          self.node_space, num_nodes
      )
      sampled_edge_space = self._generate_sample_space(
          self.edge_space, num_edges
      )
  
      assert sampled_node_space is not None
      sampled_nodes = sampled_node_space.sample(node_space_mask)
      sampled_edges = (
          sampled_edge_space.sample(edge_space_mask)
          if sampled_edge_space is not None
          else None
      )
  
      sampled_edge_links = None
      if sampled_edges is not None and num_edges > 0:
          sampled_edge_links = self.np_random.integers(
              low=0, high=num_nodes, size=(num_edges, 2)
          )
  
      return GraphInstance(
          sampled_nodes, sampled_edges, sampled_edge_links
      )
  
file_path: gym/gym/spaces/graph.py
imports: from typing import NamedTuple, Optional, Sequence, Tuple, Union
  import numpy
  from gym.logger import warn
  from gym.spaces.box import Box
  from gym.spaces.discrete import Discrete
  from gym.spaces.multi_discrete import MultiDiscrete
  from gym.spaces.space import Space
label_desc: Use image node_id 4 for calling the Graph obj's underlying member method code with example usage: obj.sample(mask, num_nodes, num_edges) and returns: GraphInstance