nodes: 0, module; 1, function_definition; 2, function_name:add_edge; 3, parameters; 4, block; 5, identifier:self; 6, identifier:start; 7, identifier:end; 8, dictionary_splat_pattern; 9, expression_statement; 10, try_statement; 11, if_statement; 12, expression_statement; 13, if_statement; 14, identifier:kwargs; 15, comment:"""
          Add an edge between two nodes.
  
          The nodes will be automatically added if they are not present in the network.
  
          Parameters
          ----------
          start: tuple
                 Both the start and end nodes should specify the time slice as
                 (node_name, time_slice). Here, node_name can be any hashable
                 python object while the time_slice is an integer value,
                 which denotes the time slice that the node belongs to.
  
          end: tuple
                 Both the start and end nodes should specify the time slice as
                 (node_name, time_slice). Here, node_name can be any hashable
                 python object while the time_slice is an integer value,
                 which denotes the time slice that the node belongs to.
  
          Examples
          --------
          >>> from pgmpy.models import DynamicBayesianNetwork as DBN
          >>> model = DBN()
          >>> model.add_nodes_from(['D', 'I'])
          >>> model.add_edge(('D',0), ('I',0))
          >>> sorted(model.edges())
          [(('D', 0), ('I', 0)), (('D', 1), ('I', 1))]
          """; 16, block; 17, except_clause; 18, comparison_operator:start == end; 19, block; 20, elif_clause; 21, call; 22, comparison_operator:start[1] == end[1]; 23, block; 24, else_clause; 25, if_statement; 26, identifier:TypeError; 27, block; 28, identifier:start; 29, identifier:end; 30, raise_statement; 31, boolean_operator; 32, block; 33, attribute; 34, argument_list; 35, subscript; 36, subscript; 37, expression_statement; 38, block; 39, boolean_operator; 40, block; 41, elif_clause; 42, elif_clause; 43, elif_clause; 44, elif_clause; 45, elif_clause; 46, raise_statement; 47, call; 48, boolean_operator; 49, line_continuation:\; 50, call; 51, raise_statement; 52, call; 53, identifier:add_edge; 54, identifier:start; 55, identifier:end; 56, dictionary_splat; 57, identifier:start; 58, integer:1; 59, identifier:end; 60, integer:1; 61, call; 62, expression_statement; 63, comparison_operator:len(start) != 2; 64, comparison_operator:len(end) != 2; 65, raise_statement; 66, boolean_operator; 67, block; 68, comparison_operator:start[1] == end[1]; 69, block; 70, comparison_operator:start[1] == end[1] - 1; 71, block; 72, comparison_operator:start[1] > end[1]; 73, block; 74, comparison_operator:start[1] != end[1]; 75, block; 76, call; 77, identifier:ValueError; 78, argument_list; 79, comparison_operator:start in super(DynamicBayesianNetwork, self).nodes(); 80, comparison_operator:end \
                  in super(DynamicBayesianNetwork, self).nodes(); 81, attribute; 82, argument_list; 83, call; 84, identifier:super; 85, argument_list; 86, identifier:kwargs; 87, attribute; 88, argument_list; 89, call; 90, call; 91, integer:2; 92, call; 93, integer:2; 94, call; 95, not_operator; 96, not_operator; 97, raise_statement; 98, subscript; 99, subscript; 100, expression_statement; 101, expression_statement; 102, subscript; 103, binary_operator:end[1] - 1; 104, expression_statement; 105, expression_statement; 106, subscript; 107, subscript; 108, raise_statement; 109, subscript; 110, subscript; 111, raise_statement; 112, identifier:ValueError; 113, argument_list; 114, string; 115, identifier:start; 116, call; 117, identifier:end; 118, line_continuation:\; 119, call; 120, identifier:nx; 121, identifier:has_path; 122, identifier:self; 123, identifier:end; 124, identifier:start; 125, identifier:ValueError; 126, argument_list; 127, identifier:DynamicBayesianNetwork; 128, identifier:self; 129, call; 130, identifier:add_edge; 131, tuple; 132, tuple; 133, attribute; 134, argument_list; 135, identifier:len; 136, argument_list; 137, identifier:len; 138, argument_list; 139, identifier:ValueError; 140, argument_list; 141, call; 142, call; 143, call; 144, identifier:start; 145, integer:1; 146, identifier:end; 147, integer:1; 148, assignment; 149, assignment; 150, identifier:start; 151, integer:1; 152, subscript; 153, integer:1; 154, assignment; 155, assignment; 156, identifier:start; 157, integer:1; 158, identifier:end; 159, integer:1; 160, call; 161, identifier:start; 162, integer:1; 163, identifier:end; 164, integer:1; 165, call; 166, string; 167, string_content:Self Loops are not allowed; 168, attribute; 169, argument_list; 170, attribute; 171, argument_list; 172, call; 173, identifier:super; 174, argument_list; 175, subscript; 176, binary_operator:1 - start[1]; 177, subscript; 178, binary_operator:1 - end[1]; 179, call; 180, identifier:add_node; 181, tuple; 182, identifier:start; 183, identifier:end; 184, string; 185, identifier:isinstance; 186, argument_list; 187, identifier:isinstance; 188, argument_list; 189, identifier:ValueError; 190, argument_list; 191, identifier:start; 192, tuple; 193, identifier:end; 194, tuple; 195, identifier:end; 196, integer:1; 197, identifier:start; 198, tuple; 199, identifier:end; 200, tuple; 201, identifier:NotImplementedError; 202, argument_list; 203, identifier:ValueError; 204, argument_list; 205, string_content:Nodes must be of type (node, time_slice).; 206, call; 207, identifier:nodes; 208, call; 209, identifier:nodes; 210, attribute; 211, argument_list; 212, identifier:DynamicBayesianNetwork; 213, identifier:self; 214, identifier:start; 215, integer:0; 216, integer:1; 217, subscript; 218, identifier:end; 219, integer:0; 220, integer:1; 221, subscript; 222, identifier:super; 223, argument_list; 224, subscript; 225, binary_operator:1 - end[1]; 226, string_content:Nodes must be of type (node, time_slice).; 227, subscript; 228, identifier:int; 229, subscript; 230, identifier:int; 231, string; 232, subscript; 233, integer:0; 234, subscript; 235, integer:0; 236, subscript; 237, integer:0; 238, subscript; 239, integer:1; 240, string; 241, string:"Edges over multiple time slices is not currently supported"; 242, identifier:super; 243, argument_list; 244, identifier:super; 245, argument_list; 246, string; 247, identifier:format; 248, keyword_argument; 249, keyword_argument; 250, identifier:start; 251, integer:1; 252, identifier:end; 253, integer:1; 254, identifier:DynamicBayesianNetwork; 255, identifier:self; 256, identifier:end; 257, integer:0; 258, integer:1; 259, subscript; 260, identifier:start; 261, integer:1; 262, identifier:end; 263, integer:1; 264, string_content:Nodes must be of type (node, time_slice).; 265, identifier:start; 266, integer:0; 267, identifier:end; 268, integer:0; 269, identifier:start; 270, integer:0; 271, identifier:end; 272, integer:0; 273, string_content:Edges in backward direction are not allowed.; 274, identifier:DynamicBayesianNetwork; 275, identifier:self; 276, identifier:DynamicBayesianNetwork; 277, identifier:self; 278, string_content:Loops are not allowed. Adding the edge from ({start} --> {end}) forms a loop.; 279, identifier:start; 280, call; 281, identifier:end; 282, call; 283, identifier:end; 284, integer:1; 285, identifier:str; 286, argument_list; 287, identifier:str; 288, argument_list; 289, identifier:start; 290, identifier:end
code: def add_edge(self, start, end, **kwargs):
          """
          Add an edge between two nodes.
  
          The nodes will be automatically added if they are not present in the network.
  
          Parameters
          ----------
          start: tuple
                 Both the start and end nodes should specify the time slice as
                 (node_name, time_slice). Here, node_name can be any hashable
                 python object while the time_slice is an integer value,
                 which denotes the time slice that the node belongs to.
  
          end: tuple
                 Both the start and end nodes should specify the time slice as
                 (node_name, time_slice). Here, node_name can be any hashable
                 python object while the time_slice is an integer value,
                 which denotes the time slice that the node belongs to.
  
          Examples
          --------
          >>> from pgmpy.models import DynamicBayesianNetwork as DBN
          >>> model = DBN()
          >>> model.add_nodes_from(['D', 'I'])
          >>> model.add_edge(('D',0), ('I',0))
          >>> sorted(model.edges())
          [(('D', 0), ('I', 0)), (('D', 1), ('I', 1))]
          """
          try:
              if len(start) != 2 or len(end) != 2:
                  raise ValueError('Nodes must be of type (node, time_slice).')
              elif not isinstance(start[1], int) or not isinstance(end[1], int):
                  raise ValueError('Nodes must be of type (node, time_slice).')
              elif start[1] == end[1]:
                  start = (start[0], 0)
                  end = (end[0], 0)
              elif start[1] == end[1] - 1:
                  start = (start[0], 0)
                  end = (end[0], 1)
              elif start[1] > end[1]:
                  raise NotImplementedError('Edges in backward direction are not allowed.')
              elif start[1] != end[1]:
                  raise ValueError("Edges over multiple time slices is not currently supported")
          except TypeError:
              raise ValueError('Nodes must be of type (node, time_slice).')
  
          if start == end:
              raise ValueError('Self Loops are not allowed')
          elif start in super(DynamicBayesianNetwork, self).nodes() and end \
                  in super(DynamicBayesianNetwork, self).nodes() and \
                  nx.has_path(self, end, start):
              raise ValueError('Loops are not allowed. Adding the edge from ({start} --> {end}) forms a loop.'.format(
                  start=str(start), end=str(end)))
  
          super(DynamicBayesianNetwork, self).add_edge(start, end, **kwargs)
  
          if start[1] == end[1]:
              super(DynamicBayesianNetwork, self).add_edge((start[0], 1 - start[1]), (end[0], 1 - end[1]))
          else:
              super(DynamicBayesianNetwork, self).add_node((end[0], 1 - end[1]))