code: def is_undirected(  # noqa: F811
      edge_index: Tensor,
      edge_attr: Union[Optional[Tensor], List[Tensor]] = None,
      num_nodes: Optional[int] = None,
  ) -> bool:
      r"""Returns :obj:`True` if the graph given by :attr:`edge_index` is
      undirected.
  
      Args:
          edge_index (LongTensor): The edge indices.
          edge_attr (Tensor or List[Tensor], optional): Edge weights or multi-
              dimensional edge features.
              If given as a list, will check for equivalence in all its entries.
              (default: :obj:`None`)
          num_nodes (int, optional): The number of nodes, *i.e.*
              :obj:`max(edge_index) + 1`. (default: :obj:`None`)
  
      :rtype: bool
  
      Examples:
          >>> edge_index = torch.tensor([[0, 1, 0],
          ...                         [1, 0, 0]])
          >>> weight = torch.tensor([0, 0, 1])
          >>> is_undirected(edge_index, weight)
          True
  
          >>> weight = torch.tensor([0, 1, 1])
          >>> is_undirected(edge_index, weight)
          False
  
      """
      num_nodes = maybe_num_nodes(edge_index, num_nodes)
  
      edge_attrs: List[Tensor] = []
      if isinstance(edge_attr, Tensor):
          edge_attrs.append(edge_attr)
      elif isinstance(edge_attr, (list, tuple)):
          edge_attrs = edge_attr
  
      edge_index1, edge_attrs1 = sort_edge_index(
          edge_index,
          edge_attrs,
          num_nodes=num_nodes,
          sort_by_row=True,
      )
      edge_index2, edge_attrs2 = sort_edge_index(
          edge_index,
          edge_attrs,
          num_nodes=num_nodes,
          sort_by_row=False,
      )
  
      if not torch.equal(edge_index1[0], edge_index2[1]):
          return False
  
      if not torch.equal(edge_index1[1], edge_index2[0]):
          return False
  
      assert isinstance(edge_attrs1, list) and isinstance(
          edge_attrs2, list
      )
      for edge_attr1, edge_attr2 in zip(edge_attrs1, edge_attrs2):
          if not torch.equal(edge_attr1, edge_attr2):
              return False
  
      return True
  
file_path: pytorch_geometric/torch_geometric/utils/undirected.py
imports: import typing
  from typing import List, Optional, Tuple, Union
  import torch
  from torch import Tensor
  from torch_geometric.typing import OptTensor
  from torch_geometric.utils import coalesce, sort_edge_index
  from torch_geometric.utils.num_nodes import maybe_num_nodes
label_desc: Use image node_id 3 for calling a global function with example usage: is_undirected(edge_index, edge_attr, num_nodes) and returns: True, False, False, False