1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
"""Test rules for classification and regression trees."""
import unittest
from Orange.widgets.visualize.utils.tree.rules import (
ContinuousRule,
IntervalRule,
)
class TestRules(unittest.TestCase):
"""Rules for classification and regression trees.
See Also
--------
Orange.widgets.visualize.widgetutils.tree.rules
"""
# CONTINUOUS RULES
def test_merging_two_gt_continuous_rules(self):
"""Merging `x > 1` and `x > 2` should produce `x > 2`."""
rule1 = ContinuousRule('Rule', True, 1)
rule2 = ContinuousRule('Rule', True, 2)
new_rule = rule1.merge_with(rule2)
self.assertEqual(new_rule.value, 2)
def test_merging_gt_with_gte_continuous_rule(self):
"""Merging `x > 1` and `x ≥ 1` should produce `x > 1`."""
rule1 = ContinuousRule('Rule', True, 1, inclusive=True)
rule2 = ContinuousRule('Rule', True, 1, inclusive=False)
new_rule = rule1.merge_with(rule2)
self.assertEqual(new_rule.inclusive, False)
def test_merging_two_lt_continuous_rules(self):
"""Merging `x < 1` and `x < 2` should produce `x < 1`."""
rule1 = ContinuousRule('Rule', False, 1)
rule2 = ContinuousRule('Rule', False, 2)
new_rule = rule1.merge_with(rule2)
self.assertEqual(new_rule.value, 1)
def test_merging_lt_with_lte_rule(self):
"""Merging `x < 1` and `x ≤ 1` should produce `x < 1`."""
rule1 = ContinuousRule('Rule', False, 1, inclusive=True)
rule2 = ContinuousRule('Rule', False, 1, inclusive=False)
new_rule = rule1.merge_with(rule2)
self.assertEqual(new_rule.inclusive, False)
def test_merging_lt_with_gt_continuous_rules(self):
"""Merging `x > 1` and `x < 2` should produce `1 < x < 2`."""
rule1 = ContinuousRule('Rule', True, 1)
rule2 = ContinuousRule('Rule', False, 2)
new_rule = rule1.merge_with(rule2)
self.assertIsInstance(new_rule, IntervalRule)
self.assertEqual(new_rule.left_rule, rule1)
self.assertEqual(new_rule.right_rule, rule2)
# INTERVAL RULES
def test_merging_interval_rule_with_smaller_continuous_rule(self):
"""Merging `1 < x < 2` and `x < 3` should produce `1 < x < 2`."""
rule1 = IntervalRule('Rule',
ContinuousRule('Rule', True, 1),
ContinuousRule('Rule', False, 2))
rule2 = ContinuousRule('Rule', False, 2)
new_rule = rule1.merge_with(rule2)
self.assertIsInstance(new_rule, IntervalRule)
self.assertEqual(new_rule.right_rule.value, 2)
def test_merging_interval_rule_with_larger_continuous_rule(self):
"""Merging `1 < x < 2` and `x < 3` should produce `1 < x < 2`."""
rule1 = IntervalRule('Rule',
ContinuousRule('Rule', True, 1),
ContinuousRule('Rule', False, 2))
rule2 = ContinuousRule('Rule', False, 3)
new_rule = rule1.merge_with(rule2)
self.assertIsInstance(new_rule, IntervalRule)
self.assertEqual(new_rule.left_rule.value, 1)
def test_merging_interval_rule_with_larger_lt_continuous_rule(self):
"""Merging `0 < x < 3` and `x > 1` should produce `1 < x < 3`."""
rule1 = IntervalRule('Rule',
ContinuousRule('Rule', True, 0),
ContinuousRule('Rule', False, 3))
rule2 = ContinuousRule('Rule', True, 1)
new_rule = rule1.merge_with(rule2)
self.assertIsInstance(new_rule, IntervalRule)
self.assertEqual(new_rule.left_rule.value, 1)
def test_merging_interval_rule_with_smaller_gt_continuous_rule(self):
"""Merging `0 < x < 3` and `x < 2` should produce `0 < x < 2`."""
rule1 = IntervalRule('Rule',
ContinuousRule('Rule', True, 0),
ContinuousRule('Rule', False, 3))
rule2 = ContinuousRule('Rule', False, 2)
new_rule = rule1.merge_with(rule2)
self.assertIsInstance(new_rule, IntervalRule)
self.assertEqual(new_rule.right_rule.value, 2)
def test_merging_interval_rules_with_smaller_lt_component(self):
"""Merging `1 < x < 2` and `0 < x < 2` should produce `1 < x < 2`."""
rule1 = IntervalRule('Rule',
ContinuousRule('Rule', True, 1),
ContinuousRule('Rule', False, 2))
rule2 = IntervalRule('Rule',
ContinuousRule('Rule', True, 0),
ContinuousRule('Rule', False, 2))
new_rule = rule1.merge_with(rule2)
self.assertEqual(new_rule.left_rule.value, 1)
self.assertEqual(new_rule.right_rule.value, 2)
def test_merging_interval_rules_with_larger_lt_component(self):
"""Merging `0 < x < 4` and `1 < x < 4` should produce `1 < x < 4`."""
rule1 = IntervalRule('Rule',
ContinuousRule('Rule', True, 0),
ContinuousRule('Rule', False, 4))
rule2 = IntervalRule('Rule',
ContinuousRule('Rule', True, 1),
ContinuousRule('Rule', False, 4))
new_rule = rule1.merge_with(rule2)
self.assertEqual(new_rule.left_rule.value, 1)
self.assertEqual(new_rule.right_rule.value, 4)
def test_merging_interval_rules_generally(self):
"""Merging `0 < x < 4` and `2 < x < 6` should produce `2 < x < 4`."""
rule1 = IntervalRule('Rule',
ContinuousRule('Rule', True, 0),
ContinuousRule('Rule', False, 4))
rule2 = IntervalRule('Rule',
ContinuousRule('Rule', True, 2),
ContinuousRule('Rule', False, 6))
new_rule = rule1.merge_with(rule2)
self.assertEqual(new_rule.left_rule.value, 2)
self.assertEqual(new_rule.right_rule.value, 4)
# ALL RULES
def test_merge_commutativity_on_continuous_rules(self):
"""Continuous rule merging should be commutative."""
rule1 = ContinuousRule('Rule1', True, 1)
rule2 = ContinuousRule('Rule1', True, 2)
new_rule1 = rule1.merge_with(rule2)
new_rule2 = rule2.merge_with(rule1)
self.assertEqual(new_rule1.value, new_rule2.value)
def test_merge_commutativity_on_interval_rules(self):
"""Interval rule merging should be commutative."""
rule1 = IntervalRule('Rule',
ContinuousRule('Rule', True, 0),
ContinuousRule('Rule', False, 4))
rule2 = IntervalRule('Rule',
ContinuousRule('Rule', True, 2),
ContinuousRule('Rule', False, 6))
new_rule1 = rule1.merge_with(rule2)
new_rule2 = rule2.merge_with(rule1)
self.assertEqual(new_rule1.left_rule.value,
new_rule2.left_rule.value)
self.assertEqual(new_rule1.right_rule.value,
new_rule2.right_rule.value)
def test_merge_keeps_gt_on_continuous_rules(self):
"""Merging ccontinuous rules should keep GT property."""
rule1 = ContinuousRule('Rule1', True, 1)
rule2 = ContinuousRule('Rule1', True, 2)
new_rule = rule1.merge_with(rule2)
self.assertEqual(new_rule.greater, True)
def test_merge_keeps_attr_name_on_continuous_rules(self):
"""Merging continuous rules should keep the name of the rule."""
rule1 = ContinuousRule('Rule1', True, 1)
rule2 = ContinuousRule('Rule1', True, 2)
new_rule = rule1.merge_with(rule2)
self.assertEqual(new_rule.attr_name, 'Rule1')
|