|
| 1 | +import fuzzylite as fl |
| 2 | +import unittest |
| 3 | +import numpy as np |
| 4 | + |
| 5 | + |
| 6 | +class TestIssue91(unittest.TestCase): |
| 7 | + """ |
| 8 | + Test case for https://github.com/fuzzylite/pyfuzzylite/issues/91 |
| 9 | + """ |
| 10 | + |
| 11 | + def engine(self) -> fl.Engine: |
| 12 | + fll = """ |
| 13 | +Engine: tipper |
| 14 | +description: (service and food) -> (tip) |
| 15 | +InputVariable: service |
| 16 | + description: quality of service |
| 17 | + enabled: true |
| 18 | + range: 0.000 10.000 |
| 19 | + lock-range: true |
| 20 | + term: poor Discrete 0.000 1.000 2.500 1.000 5.000 0.000 10.000 0.000 |
| 21 | + term: good Discrete 0.000 0.000 2.500 0.000 5.000 1.000 7.500 0.000 10.000 0.000 |
| 22 | + term: excellent Discrete 0.000 0.000 5.000 0.000 7.500 1.000 10.000 1.000 |
| 23 | +InputVariable: food |
| 24 | + description: quality of food |
| 25 | + enabled: true |
| 26 | + range: 0.000 10.000 |
| 27 | + lock-range: true |
| 28 | + term: rancid Discrete 0.000 1.000 2.500 1.000 7.500 0.000 10.000 0.000 |
| 29 | + term: delicious Discrete 0.000 0.000 2.500 0.000 7.500 1.000 10.000 1.000 |
| 30 | +OutputVariable: mTip |
| 31 | + description: tip based on Mamdani inference |
| 32 | + enabled: true |
| 33 | + range: 0.000 30.000 |
| 34 | + lock-range: false |
| 35 | + aggregation: Maximum |
| 36 | + defuzzifier: Centroid 100 |
| 37 | + default: 0.0 |
| 38 | + lock-previous: false |
| 39 | + term: cheap Discrete 0.000 0.000 5.000 1.000 10.000 0.000 30.000 0.000 |
| 40 | + term: average Discrete 0.000 0.000 10.000 0.000 15.000 1.000 20.000 0.000 30.000 0.000 |
| 41 | + term: generous Discrete 0.000 0.000 20.000 0.000 25.000 1.000 30.000 0.000 |
| 42 | +OutputVariable: tsTip |
| 43 | + description: tip based on Takagi-Sugeno inference |
| 44 | + enabled: true |
| 45 | + range: 0.000 30.000 |
| 46 | + lock-range: false |
| 47 | + aggregation: none |
| 48 | + defuzzifier: WeightedAverage TakagiSugeno |
| 49 | + default: 0.0 |
| 50 | + lock-previous: false |
| 51 | + term: cheap Constant 5.000 |
| 52 | + term: average Constant 15.000 |
| 53 | + term: generous Constant 25.000 |
| 54 | +RuleBlock: mamdani |
| 55 | + description: Mamdani inference |
| 56 | + enabled: true |
| 57 | + conjunction: AlgebraicProduct |
| 58 | + disjunction: AlgebraicSum |
| 59 | + implication: Minimum |
| 60 | + activation: General |
| 61 | + rule: if service is poor or food is rancid then mTip is cheap |
| 62 | + rule: if service is good then mTip is average |
| 63 | + rule: if service is excellent or food is delicious then mTip is generous with 0.5 |
| 64 | + rule: if service is excellent and food is delicious then mTip is generous with 1.0 |
| 65 | +RuleBlock: takagiSugeno |
| 66 | + description: Takagi-Sugeno inference |
| 67 | + enabled: true |
| 68 | + conjunction: AlgebraicProduct |
| 69 | + disjunction: AlgebraicSum |
| 70 | + implication: none |
| 71 | + activation: General |
| 72 | + rule: if service is poor or food is rancid then tsTip is cheap |
| 73 | + rule: if service is good then tsTip is average |
| 74 | + rule: if service is excellent or food is delicious then tsTip is generous with 0.5 |
| 75 | + rule: if service is excellent and food is delicious then tsTip is generous with 1.0 |
| 76 | + """ |
| 77 | + return fl.FllImporter().from_string(fll) |
| 78 | + |
| 79 | + def test_issue_91(self) -> None: |
| 80 | + # "'numpy.float64' object does not support item assignment" |
| 81 | + engine = self.engine() |
| 82 | + engine.variable("food").value = 10 |
| 83 | + engine.variable("service").value = 10 |
| 84 | + engine.process() |
| 85 | + np.testing.assert_almost_equal(engine.variable("mTip").value, 25.00104979) |
| 86 | + np.testing.assert_almost_equal(engine.variable("tsTip").value, 25) |
0 commit comments