Decision Rules in If/Then format

### Describe the workflow you want to enable

Although Decision tree has the following to print rules,

```
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
from sklearn.tree import export_text

iris = load_iris()
X = iris['data']
y = iris['target']
decision_tree = DecisionTreeClassifier(random_state=0, max_depth=2)
decision_tree = decision_tree.fit(X, y)
r = export_text(decision_tree, feature_names=iris['feature_names'])
print(r)
```
Current Output: 
```
 |--- petal width (cm) <= 0.80
 |   |--- class: 0
 |--- petal width (cm) >  0.80
 |   |--- petal width (cm) <= 1.75
 |   |   |--- class: 1
 |   |--- petal width (cm) >  1.75
 |   |   |--- class: 2
```
Expected Output:
It would be more better if we have human readable rules , something like this:
```
'if (petal width (cm) > 0.8) and (petal width (cm) <= 1.75) then class: versicolor (proba: 90.74%) | based on 54 samples',
'if (petal width (cm) <= 0.8) then class: setosa (proba: 100.0%) | based on 50 samples',
'if (petal width (cm) > 0.8) and (petal width (cm) > 1.75) then class: virginica (proba: 97.83%) | based on 46 samples'
```
### Describe your proposed solution

I want to include this function to get human readable rules as i mentioned:

```
def get_rules(tree, feature_names, class_names):
    tree_ = tree.tree_
    feature_name = [ feature_names[i] if i != _tree.TREE_UNDEFINED else "undefined!" for i in tree_.feature ]
    paths = []
    path = []
    
    def recurse(node, path, paths):
        if tree_.feature[node] != _tree.TREE_UNDEFINED:
            name = feature_name[node]
            threshold = tree_.threshold[node]
            p1, p2 = list(path), list(path)
            p1 += [f"({name} <= {np.round(threshold, 3)})"]
            recurse(tree_.children_left[node], p1, paths)
            p2 += [f"({name} > {np.round(threshold, 3)})"]
            recurse(tree_.children_right[node], p2, paths)
        else:
            path += [(tree_.value[node], tree_.n_node_samples[node])]
            paths += [path]
            
    recurse(0, path, paths)

    # sort by samples count
    samples_count = [p[-1][1] for p in paths]
    ii = list(np.argsort(samples_count))
    paths = [paths[i] for i in reversed(ii)]
    
    rules = []
    for path in paths:
        rule = "if "
        
        for p in path[:-1]:
            if rule != "if ":
                rule += " and "
            rule += str(p)
        rule += " then "
        if class_names is None:
            rule += "response: "+str(np.round(path[-1][0][0][0],3))
        else:
            classes = path[-1][0][0]
            l = np.argmax(classes)
            rule += f"class: {class_names[l]} (proba: {np.round(100.0*classes[l]/np.sum(classes),2)}%)"
        rule += f" | based on {path[-1][1]:,} samples"
        rules += [rule]
        
    return rules
```
### Describe alternatives you've considered, if relevant

_No response_

### Additional context

_No response_

COMMENT:
Hey @hakunamatata1997 and maintainers,

Just stumbled upon this issue and thought, "Hey, this is pretty cool!" I've been messing around with decision trees for a while and reckon I could lend a hand with this.

If no one's on it yet, mind if I take a swing at it? And hey, if there's any inside scoop or things I should know before diving in, just holler.

Catch you later and hope we can make this work!

Cheers,
Sarthak Puri
@Sarthakpurii

Labels: New Feature, Needs Triage