class_docstr: Tree structure to model a search space.
  
  Fairly elaborate unit test.
  
  >>> space = {'a': {'b0': {'c0': {'d0': {'e0': [0, 10], 'e1': [-2, -1]},
  ...                              'd1': {'e2': [-3, -1]},
  ...                              'd2': None
  ...                              },
  ...                       'c1': [0.0, 1.0],
  ...                      },
  ...                'b1': {'c2': [-2.0, -1.0]},
  ...                'b2': None
  ...               }
  ...          }
  >>> tree = SearchTree(space)
  >>> b = tree.to_box()
  >>> print(b['a'] == [0.0, 3.0] and
  ...       b['a|b0|c0'] == [0.0, 3.0] and
  ...       b['a|b0|c1'] == [0.0, 1.0] and
  ...       b['a|b1|c2'] == [-2.0, -1.0] and
  ...       b['a|b0|c0|d0|e0'] == [0, 10] and
  ...       b['a|b0|c0|d0|e1'] == [-2, -1] and
  ...       b['a|b0|c0|d1|e2'] == [-3, -1])
  True
  
  >>> d = tree.decode({'a': 2.5})
  >>> d['a'] == 'b2'
  True
  
  >>> d = tree.decode({'a': 1.5, 'a|b1|c2': -1.5})
  >>> print(d['a'] == 'b1' and
  ...       d['c2'] == -1.5)
  True
  
  >>> d = tree.decode({'a': 0.5, 'a|b0|c0': 1.7, 'a|b0|c0|d1|e2': -1.2})
  >>> print(d['a'] == 'b0' and
  ...       d['c0'] == 'd1' and
  ...       d['e2'] == -1.2)
  True
  
  >>> d = tree.decode({'a': 0.5, 'a|b0|c0': 2.7})
  >>> print(d['a'] == 'b0' and
  ...       d['c0'] == 'd2')
  True
  
  >>> d = tree.decode({'a': 0.5, 'a|b0|c0': 0.7, 'a|b0|c0|d0|e0': 2.3, 'a|b0|c0|d0|e1': -1.5})
  >>> print(d['a'] == 'b0' and
  ...       d['c0'] == 'd0' and
  ...       d['e0'] == 2.3 and
  ...       d['e1'] == -1.5)
  True
class_docstr_tok: ["Tree","structure","to","model","a","search","space",".","Fairly","elaborate","unit","test",".",">",">",">","space","=","{","'","a","'",":","{","'b0","'",":","{","'c0","'",":","{","'d0","'",":","{","'e0","'",":","[","0",",","10","]",",","'e1","'",":","[","-2",",","-1","]","}",",","...","'d1","'",":","{","'e2","'",":","[","-3",",","-1","]","}",",","...","'d2","'",":","None","...","}",",","...","'c1","'",":","[","0.0",",","1.0","]",",","...","}",",","...","'b1","'",":","{","'c2","'",":","[","-2.0",",","-1.0","]","}",",","...","'b2","'",":","None","...","}","...","}",">",">",">","tree","=","SearchTree","(","space",")",">",">",">","b","=","tree.to_box","(",")",">",">",">","print","(","b","[","'","a","'","]","==","[","0.0",",","3.0","]","and","...","b","[","'","a|b0|c0","'","]","==","[","0.0",",","3.0","]","and","...","b","[","'","a|b0|c1","'","]","==","[","0.0",",","1.0","]","and","...","b","[","'","a|b1|c2","'","]","==","[","-2.0",",","-1.0","]","and","...","b","[","'","a|b0|c0|d0|e0","'","]","==","[","0",",","10","]","and","...","b","[","'","a|b0|c0|d0|e1","'","]","==","[","-2",",","-1","]","and","...","b","[","'","a|b0|c0|d1|e2","'","]","==","[","-3",",","-1","]",")","True",">",">",">","d","=","tree.decode","(","{","'","a","'",":","2.5","}",")",">",">",">","d","[","'","a","'","]","==","'b2'","True",">",">",">","d","=","tree.decode","(","{","'","a","'",":","1.5",",","'","a|b1|c2","'",":","-1.5","}",")",">",">",">","print","(","d","[","'","a","'","]","==","'b1","'","and","...","d","[","'c2","'","]","==","-1.5",")","True",">",">",">","d","=","tree.decode","(","{","'","a","'",":","0.5",",","'","a|b0|c0","'",":","1.7",",","'","a|b0|c0|d1|e2","'",":","-1.2","}",")",">",">",">","print","(","d","[","'","a","'","]","==","'b0","'","and","...","d","[","'c0","'","]","==","'d1","'","and","...","d","[","'e2","'","]","==","-1.2",")","True",">",">",">","d","=","tree.decode","(","{","'","a","'",":","0.5",",","'","a|b0|c0","'",":","2.7","}",")",">",">",">","print","(","d","[","'","a","'","]","==","'b0","'","and","...","d","[","'c0","'","]","==","'d2","'",")","True",">",">",">","d","=","tree.decode","(","{","'","a","'",":","0.5",",","'","a|b0|c0","'",":","0.7",",","'","a|b0|c0|d0|e0","'",":","2.3",",","'","a|b0|c0|d0|e1","'",":","-1.5","}",")",">",">",">","print","(","d","[","'","a","'","]","==","'b0","'","and","...","d","[","'c0","'","]","==","'d0","'","and","...","d","[","'e0","'","]","==","2.3","and","...","d","[","'e1","'","]","==","-1.5",")","True"]
docstr: Decodes a vector representation (as a dictionary) into a result dictionary.
  
  :param vd: vector representation
  :type vd: dict
  :returns: dict containing the decoded representation.
  
  * Choices are given as key:value pairs.
  * Active hyperparameters have numeric values.
  * Inactive hyperparameters have value None.
docstr_tok: ["Decodes","a","vector","representation","(","as","a","dictionary",")","into","a","result","dictionary",".",":","param","vd",":","vector","representation",":","type","vd",":","dict",":","returns",":","dict","containing","the","decoded","representation",".","*","Choices","are","given","as","key",":","value","pairs",".","*","Active","hyperparameters","have","numeric","values",".","*","Inactive","hyperparameters","have","value","None","."]
code: def decode(self, vd):
      """
      Decodes a vector representation (as a dictionary) into a result dictionary.
  
      :param vd: vector representation
      :type vd: dict
      :returns: dict containing the decoded representation.
  
      * Choices are given as key:value pairs.
      * Active hyperparameters have numeric values.
      * Inactive hyperparameters have value None.
  
      """
      result = {}
      currently_decoding_nested = []
      items = sorted(vd.items())
      idx = 0
  
      while idx < len(items):
          k, v = items[idx]
          keylist = k.split(DELIM)
  
          if currently_decoding_nested and len(keylist) >= len(
              currently_decoding_nested
          ):
              if not all(
                  map(
                      lambda t: t[0] == t[1],
                      zip(currently_decoding_nested, keylist),
                  )
              ):
                  # keylist doesnt match what we are currently decoding
                  # and it is longer than what we are decoding
                  # so this must be the wrong key, skip it
                  idx += 1
  
                  # add a None value for this particular function argument
                  # this is required to keep call logs functional
                  key = keylist[-1]
                  if not key in result:
                      result[key] = None
                  continue
  
          elif currently_decoding_nested:
              # keylist is shorter than decoding list -> move up one nesting level
              currently_decoding_nested = currently_decoding_nested[:-2]
              continue
  
          content = self.vectorcontent[k]
          if type(content) is Options:
              # determine which option to use
              # this is done by checking in which partition the current value
              # of the choice parameter (v) falls
  
              option_idx = int(math.floor(v))
              option = content[option_idx]
              result[
                  DELIM.join(keylist[len(currently_decoding_nested) :])
              ] = option
              currently_decoding_nested.extend([keylist[-1], option])
  
              idx += 1
  
          else:
              result[keylist[-1]] = v
              idx += 1
  
      return result
  
imports: import functools
  import itertools
  import collections
  import math
label_desc: Use image node_id 7 for calling the SearchTree obj's underlying member method code with example usage: obj.decode(vd) and returns: result