class_docstr: Maintains bidirectional dict
  
  Example:
      bd = BiDict({'a': 1, 'b': 2})
      print(bd)                     # {'a': 1, 'b': 2}
      print(bd.inverse)             # {1: ['a'], 2: ['b']}
      bd['c'] = 1                   # Now two keys have the same value (= 1)
      print(bd)                     # {'a': 1, 'c': 1, 'b': 2}
      print(bd.inverse)             # {1: ['a', 'c'], 2: ['b']}
      del bd['c']
      print(bd)                     # {'a': 1, 'b': 2}
      print(bd.inverse)             # {1: ['a'], 2: ['b']}
      del bd['a']
      print(bd)                     # {'b': 2}
      print(bd.inverse)             # {2: ['b']}
      bd['b'] = 3
      print(bd)                     # {'b': 3}
      print(bd.inverse)             # {2: [], 3: ['b']}
code: def __setitem__(self, key, value):
      if key in self:
          self.inverse[self[key]].remove(key)
      super(BiDict, self).__setitem__(key, value)
      self.inverse.setdefault(value, []).append(key)
  
imports: import math
  import itertools
  from dataclasses import replace
  from typing import Mapping, Any, Sequence, Iterable, Iterator, Union, Tuple, Dict, Set
label_desc: Use image node_id 2 for calling the BiDict obj's underlying member method code with example usage: obj.__setitem__(key, value) without return types