code: def vector_to_edge_index(
      idx: Tensor,
      size: Tuple[int, int],
      bipartite: bool,
      force_undirected: bool = False,
  ) -> Tensor:
      if bipartite:  # No need to account for self-loops.
          row = idx.div(size[1], rounding_mode="floor")
          col = idx % size[1]
          return torch.stack([row, col], dim=0)
  
      elif force_undirected:
          assert size[0] == size[1]
          num_nodes = size[0]
  
          offset = torch.arange(1, num_nodes, device=idx.device).cumsum(
              0
          )
          end = torch.arange(
              num_nodes,
              num_nodes * num_nodes,
              num_nodes,
              device=idx.device,
          )
          row = torch.bucketize(idx, end.sub_(offset), right=True)
          col = offset[row].add_(idx) % num_nodes
          return torch.stack(
              [torch.cat([row, col]), torch.cat([col, row])], 0
          )
  
      else:
          assert size[0] == size[1]
          num_nodes = size[0]
  
          row = idx.div(num_nodes - 1, rounding_mode="floor")
          col = idx % (num_nodes - 1)
          col[row <= col] += 1
          return torch.stack([row, col], dim=0)
  
file_path: pytorch_geometric/torch_geometric/utils/_negative_sampling.py
imports: import random
  from typing import Optional, Tuple, Union
  import numpy
  import torch
  from torch import Tensor
  from torch_geometric.utils import coalesce, cumsum, degree, remove_self_loops
  from torch_geometric.utils.num_nodes import maybe_num_nodes
label_desc: Use image node_id 7 for calling a global function with example usage: vector_to_edge_index(idx, size, bipartite, force_undirected) and returns: torch, torch, torch