# Buggy code
def get_parameters_for_tree_trav_common(
    lefts, rights, features, thresholds, values, extra_config={}
):
    """
    Common functions used by all tree algorithms to generate the parameters according to the tree_trav strategies.

    Args:
        left: The left nodes
        right: The right nodes
        features: The features used in the decision nodes
        thresholds: The thresholds used in the decision nodes
        values: The values stored in the leaf nodes

    Returns:
        An array containing the extracted parameters
    """
    if len(lefts) == 1:
        # Model creating tree with just a single leaf node. We transform it
        # to a model with one internal node.
        lefts = [1, -1, -1]
        rights = [2, -1, -1]
        features = [0, 0, 0]
        thresholds = [0, 0, 0]
        n_classes = values.shape[1] if type(values) is np.ndarray else 1
        values = np.array([np.array([0.0]), values[0], values[0]])
        values.reshape(3, n_classes)

    ids = [i for i in range(len(lefts))]
    nodes = list(zip(ids, lefts, rights, features, thresholds, values))

    # Refactor the tree parameters in the proper format.
    nodes_map = {0: Node(0)}
    current_node = 0
    for i, node in enumerate(nodes):
        id, left, right, feature, threshold, value = node

        if left != -1:
            l_node = Node(left)
            nodes_map[left] = l_node
        else:
            lefts[i] = id
            l_node = -1
            feature = -1

        if right != -1:
            r_node = Node(right)
            nodes_map[right] = r_node
        else:
            rights[i] = id
            r_node = -1
            feature = -1

        nodes_map[current_node].left = l_node
        nodes_map[current_node].right = r_node
        nodes_map[current_node].feature = feature
        nodes_map[current_node].threshold = threshold
        nodes_map[current_node].value = value

        current_node += 1

    lefts = np.array(lefts)
    rights = np.array(rights)
    features = np.array(features)
    thresholds = np.array(thresholds)
    values = np.array(values)

    return [nodes_map, ids, lefts, rights, features, thresholds, values]


# Traceback (ValueError)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
~/anaconda3/envs/p37/lib/python3.7/site-packages/hummingbird/ml/_topology.py in convert(topology, backend, test_input, device, extra_config)
162
--> 163             operator_map[operator.full_name] = converter(operator, device, extra_config)
164         except ValueError:

~/anaconda3/envs/p37/lib/python3.7/site-packages/hummingbird/ml/operator_converters/sklearn/decision_tree.py in convert_sklearn_random_forest_classifier(operator, device, extra_config)
45     return convert_decision_ensemble_tree_common(
---> 46         tree_infos, get_parameters_for_sklearn_common, get_parameters_for_tree_trav_sklearn, n_features, classes, extra_config
47     )

~/anaconda3/envs/p37/lib/python3.7/site-packages/hummingbird/ml/operator_converters/_tree_commons.py in convert_decision_ensemble_tree_common(tree_infos, get_parameters, get_parameters_for_tree_trav, n_features, classes, extra_config)
407         )
--> 408         for tree_param in tree_parameters
409     ]

~/anaconda3/envs/p37/lib/python3.7/site-packages/hummingbird/ml/operator_converters/_tree_commons.py in <listcomp>(.0)
407         )
--> 408         for tree_param in tree_parameters
409     ]

~/anaconda3/envs/p37/lib/python3.7/site-packages/hummingbird/ml/operator_converters/_tree_commons.py in get_parameters_for_tree_trav_sklearn(lefts, rights, features, thresholds, values, extra_config)
276
--> 277     return get_parameters_for_tree_trav_common(lefts, rights, features, thresholds, values)
278

~/anaconda3/envs/p37/lib/python3.7/site-packages/hummingbird/ml/operator_converters/_tree_commons.py in get_parameters_for_tree_trav_common(lefts, rights, features, thresholds, values, extra_config)
208         values = np.array([np.array([0.0]), values[0], values[0]])
--> 209         values.reshape(3, n_classes)
210

ValueError: cannot reshape array of size 3 into shape (3,2)

During handling of the above exception, another exception occurred:

MissingConverter                          Traceback (most recent call last)
<ipython-input-2-70faf2a01f51> in <module>
10 clf = RandomForestClassifier(random_state=seed)
11 clf.fit(X, y)
---> 12 model = hummingbird.ml.convert(clf, "torch")

~/anaconda3/envs/p37/lib/python3.7/site-packages/hummingbird/ml/convert.py in convert(model, backend, test_input, device, extra_config)
429     """
430     assert constants.REMAINDER_SIZE not in extra_config
--> 431     return _convert_common(model, backend, test_input, device, extra_config)
432
433

~/anaconda3/envs/p37/lib/python3.7/site-packages/hummingbird/ml/convert.py in _convert_common(model, backend, test_input, device, extra_config)
390         return _convert_sparkml(model, backend, test_input, device, extra_config)
391
--> 392     return _convert_sklearn(model, backend, test_input, device, extra_config)
393
394

~/anaconda3/envs/p37/lib/python3.7/site-packages/hummingbird/ml/convert.py in _convert_sklearn(model, backend, test_input, device, extra_config)
98
99     # Convert the Topology object into a PyTorch model.
--> 100     hb_model = topology_converter(topology, backend, test_input, device, extra_config=extra_config)
101     return hb_model
102

~/anaconda3/envs/p37/lib/python3.7/site-packages/hummingbird/ml/_topology.py in convert(topology, backend, test_input, device, extra_config)
165             raise MissingConverter(
166                 "Unable to find converter for {} type {} with extra config: {}.".format(
--> 167                     operator.type, type(getattr(operator, "raw_model", None)), extra_config
168                 )
169             )

MissingConverter: Unable to find converter for SklearnRandomForestClassifier type <class 'NoneType'> with extra config: {'container': True, 'n_threads': 10, 'n_trees': 100}.
It usually means the pipeline being converted contains a
transformer or a predictor with no corresponding converter implemented.
Please fill an issue at https://github.com/microsoft/hummingbird.

# Fixed code
def get_parameters_for_tree_trav_common(
    lefts, rights, features, thresholds, values, extra_config={}
):
    """
    Common functions used by all tree algorithms to generate the parameters according to the tree_trav strategies.

    Args:
        left: The left nodes
        right: The right nodes
        features: The features used in the decision nodes
        thresholds: The thresholds used in the decision nodes
        values: The values stored in the leaf nodes

    Returns:
        An array containing the extracted parameters
    """
    if len(lefts) == 1:
        # Model creating tree with just a single leaf node. We transform it
        # to a model with one internal node.
        lefts = [1, -1, -1]
        rights = [2, -1, -1]
        features = [0, 0, 0]
        thresholds = [0, 0, 0]
        n_classes = values.shape[1] if type(values) is np.ndarray else 1
        values = np.array([np.zeros(n_classes), values[0], values[0]])
        values.reshape(3, n_classes)

    ids = [i for i in range(len(lefts))]
    nodes = list(zip(ids, lefts, rights, features, thresholds, values))

    # Refactor the tree parameters in the proper format.
    nodes_map = {0: Node(0)}
    current_node = 0
    for i, node in enumerate(nodes):
        id, left, right, feature, threshold, value = node

        if left != -1:
            l_node = Node(left)
            nodes_map[left] = l_node
        else:
            lefts[i] = id
            l_node = -1
            feature = -1

        if right != -1:
            r_node = Node(right)
            nodes_map[right] = r_node
        else:
            rights[i] = id
            r_node = -1
            feature = -1

        nodes_map[current_node].left = l_node
        nodes_map[current_node].right = r_node
        nodes_map[current_node].feature = feature
        nodes_map[current_node].threshold = threshold
        nodes_map[current_node].value = value

        current_node += 1

    lefts = np.array(lefts)
    rights = np.array(rights)
    features = np.array(features)
    thresholds = np.array(thresholds)
    values = np.array(values)

    return [nodes_map, ids, lefts, rights, features, thresholds, values]