class_docstr: A plain python object modeling a heterogeneous graph with various
  attributes (Node types in :class:`HeteroGraph` require string type).
  
  Args:
      G (:class:`networkx.classes.graph`): A NetworkX graph object which
          contains features and labels for each node type and edge type.
      **kwargs: Keyworded argument list with keys such
          as :obj:`"node_feature"`, :obj:`"node_label"` and
          corresponding attributes.
class_docstr_tok: ["A","plain","python","object","modeling","a","heterogeneous","graph","with","various","attributes","(","Node","types","in",":","class",":","`","HeteroGraph","`","require","string","type",")",".","Args",":","G","(",":","class",":","`","networkx.classes.graph","`",")",":","A","NetworkX","graph","object","which","contains","features","and","labels","for","each","node","type","and","edge","type",".","*","*","kwargs",":","Keyworded","argument","list","with","keys","such","as",":","obj",":","`","``","node_feature","''","`",",",":","obj",":","`","``","node_label","''","`","and","corresponding","attributes","."]
docstr: Create negative samples for link prediction,
  and changes the edge_label and edge_label_index accordingly
  (if already existed).
  
  Simplest link prediction has no label. It will be treated as
  binary classification.
  edge_label will be set to 1 for positives and 0 for negative examples.
  
  For link prediction that requires prediction of edge type, it will be
  a multi-class classification task.
  negative examples will be set for (original label + 1).
  Hence the number of prediction classes will be incremented by 1.
  In this case dataset.num_edge_labels should be called after split
  (which calls this function).
  
  Args:
      negative_sampling_ratio (float or int): ratio of negative sampling
          edges compared with the original edges.
      resample (boolean): whether should resample.
docstr_tok: ["Create","negative","samples","for","link","prediction",",","and","changes","the","edge_label","and","edge_label_index","accordingly","(","if","already","existed",")",".","Simplest","link","prediction","has","no","label",".","It","will","be","treated","as","binary","classification",".","edge_label","will","be","set","to","1","for","positives","and","0","for","negative","examples",".","For","link","prediction","that","requires","prediction","of","edge","type",",","it","will","be","a","multi-class","classification","task",".","negative","examples","will","be","set","for","(","original","label","+","1",")",".","Hence","the","number","of","prediction","classes","will","be","incremented","by","1",".","In","this","case","dataset.num_edge_labels","should","be","called","after","split","(","which","calls","this","function",")",".","Args",":","negative_sampling_ratio","(","float","or","int",")",":","ratio","of","negative","sampling","edges","compared","with","the","original","edges",".","resample","(","boolean",")",":","whether","should","resample","."]
code: def _create_neg_sampling(
      self,
      negative_sampling_ratio: float,
      split_types: List[str] = None,
      resample: bool = False,
  ):
      r"""
      Create negative samples for link prediction,
      and changes the edge_label and edge_label_index accordingly
      (if already existed).
  
      Simplest link prediction has no label. It will be treated as
      binary classification.
      edge_label will be set to 1 for positives and 0 for negative examples.
  
      For link prediction that requires prediction of edge type, it will be
      a multi-class classification task.
      negative examples will be set for (original label + 1).
      Hence the number of prediction classes will be incremented by 1.
      In this case dataset.num_edge_labels should be called after split
      (which calls this function).
  
      Args:
          negative_sampling_ratio (float or int): ratio of negative sampling
              edges compared with the original edges.
          resample (boolean): whether should resample.
      """
      if split_types is None:
          split_types = self.message_types
      if not isinstance(split_types, list):
          raise TypeError(
              "Split_types must be string or list of string."
          )
  
      # filter split_types
      split_types = [
          message_type
          for message_type in split_types
          if message_type in self.edge_label_index
      ]
  
      if resample and self._num_positive_examples is not None:
          for (
              message_type,
              edge_type_positive_num,
          ) in self._num_positive_examples.items():
              self.edge_label_index[
                  message_type
              ] = self.edge_label_index[message_type][
                  :, :edge_type_positive_num
              ]
  
      num_pos_edges = {
          message_type: edge_type_positive.shape[-1]
          for message_type, edge_type_positive in self.edge_label_index.items()
          if message_type in split_types
      }
      num_neg_edges = {
          message_type: int(edge_type_num * negative_sampling_ratio)
          for message_type, edge_type_num in num_pos_edges.items()
      }
  
      if (
          set(self.edge_index.keys())
          == set(self.edge_label_index.keys())
          and all(
              self.edge_index[message_type].size(1)
              == self.edge_label_index[message_type].size(1)
              for message_type in split_types
          )
          and all(
              torch.sum(
                  self.edge_index[message_type]
                  - self.edge_label_index[message_type]
              )
              == 0
              for message_type in split_types
          )
      ):
          edge_index_all = {
              message_type: edge_type_positive
              for message_type, edge_type_positive in self.edge_index.items()
              if message_type in split_types
          }
      else:
          edge_index_all = {}
          for message_type in split_types:
              edge_index_all[message_type] = torch.cat(
                  [
                      self.edge_index[message_type],
                      self.edge_label_index[message_type],
                  ],
                  -1,
              )
  
      # handle multigraph
      if hasattr(self, "_edge_index_all"):
          if not (
              set(self._edge_index_all.keys())
              == set(edge_index_all.keys())
          ) or not (
              all(
                  torch.equal(
                      edge_index_all[message_type],
                      self._edge_index_all[message_type],
                  )
                  for message_type in edge_index_all
              )
          ):
              edge_index_all_unique = {}
              for message_type in edge_index_all:
                  edge_index_all_unique[message_type] = torch.unique(
                      edge_index_all[message_type], dim=1
                  )
          else:
              edge_index_all_unique = self._edge_index_all_unique
      else:
          edge_index_all_unique = {}
          for message_type in edge_index_all:
              edge_index_all_unique[message_type] = torch.unique(
                  edge_index_all[message_type], dim=1
              )
          self._edge_index_all = edge_index_all
          self._edge_index_all_unique = edge_index_all_unique
  
      negative_edges = self.negative_sampling(
          edge_index_all_unique, self.num_nodes(), num_neg_edges
      )
  
      if not resample:
          if self.edge_label is None:
              positive_label = {
                  message_type: torch.ones(
                      edge_type_positive, dtype=torch.long
                  )
                  for message_type, edge_type_positive in num_pos_edges.items()
              }
  
              negative_label = {
                  message_type: torch.zeros(
                      edge_type_negative, dtype=torch.long
                  )
                  for message_type, edge_type_negative in num_neg_edges.items()
              }
          else:
              positive_label = {
                  message_type: edge_type_positive
                  for message_type, edge_type_positive in self.edge_label.items()
              }
  
              negative_label_val = self.negative_label_val
              negative_label = {
                  message_type: negative_label_val
                  * torch.ones(edge_type_negative, dtype=torch.long)
                  for message_type, edge_type_negative in num_neg_edges.items()
              }
  
          self.edge_label = {
              message_type: torch.cat(
                  [
                      positive_label[message_type],
                      negative_label[message_type],
                  ],
                  -1,
              ).type(torch.long)
              for message_type in split_types
          }
  
      for message_type in split_types:
          self.edge_label_index[message_type] = torch.cat(
              [
                  self.edge_label_index[message_type],
                  negative_edges[message_type],
              ],
              -1,
          )
  
      self._num_positive_examples = num_pos_edges
  
imports: import math
  import copy
  import random
  import torch
  import networkx
  import numpy
  from deepsnap.graph import Graph
  from typing import Dict, List, Union
  import warnings
label_desc: Use image node_id 38 for calling the HeteroGraph obj's underlying member method code with example usage: obj._create_neg_sampling(negative_sampling_ratio, split_types, resample) without return types