def test_constructor(self) -> None: VariableAssert(self, fl.Variable("name", "description")) \ .exports_fll( "\n".join([ "Variable: name", " description: description", " enabled: true", " range: -inf inf", " lock-range: false" ])) VariableAssert(self, fl.Variable(name="name", description="description", minimum=-1.0, maximum=1.0, terms=[ fl.Triangle('A', -1.0, 1.0), fl.Triangle('B', -10.0, 10.0) ])) \ .exports_fll( "\n".join([ "Variable: name", " description: description", " enabled: true", " range: -1.000 1.000", " lock-range: false", " term: A Triangle -1.000 0.000 1.000", " term: B Triangle -10.000 0.000 10.000", ]))
def test_constructor(self) -> None: OutputVariableAssert(self, fl.OutputVariable("name", "description")) \ .exports_fll("\n".join(["OutputVariable: name", " description: description", " enabled: true", " range: -inf inf", " lock-range: false", " aggregation: none", " defuzzifier: none", " default: nan", " lock-previous: false" ])) OutputVariableAssert(self, fl.OutputVariable(name="name", description="description", minimum=-1.0, maximum=1.0, terms=[ fl.Triangle('A', -1.0, 1.0), fl.Triangle('B', -10.0, 10.0) ])) \ .exports_fll("\n".join(["OutputVariable: name", " description: description", " enabled: true", " range: -1.000 1.000", " lock-range: false", " aggregation: none", " defuzzifier: none", " default: nan", " lock-previous: false", " term: A Triangle -1.000 0.000 1.000", " term: B Triangle -10.000 0.000 10.000", ]))
def test_input_variable(self) -> None: iv = fl.InputVariable(name="input_variable", description="an input variable", minimum=0, maximum=1, terms=[fl.Triangle("A")]) self.assertEqual(fl.PythonExporter().to_string(iv), fl.PythonExporter().input_variable(iv)) self.assertEqual( fl.PythonExporter().input_variable(iv), """\ fl.InputVariable( name="input_variable", description="an input variable", enabled=True, minimum=0, maximum=1, lock_range=False, terms=[fl.Triangle("A", nan, nan, nan)] )""") iv.terms.append(fl.Triangle("Z")) self.assertEqual( fl.PythonExporter().input_variable(iv), """\ fl.InputVariable( name="input_variable", description="an input variable", enabled=True, minimum=0, maximum=1, lock_range=False, terms=[ fl.Triangle("A", nan, nan, nan), fl.Triangle("Z", nan, nan, nan) ] )""")
def test_engine(self) -> None: engine = fl.Engine( name="engine", description="an engine", input_variables=[ fl.InputVariable(name="input_variable", description="an input variable", minimum=0, maximum=1, terms=[fl.Triangle("A")]) ], output_variables=[ fl.OutputVariable(name="output_variable", description="an output variable", minimum=0, maximum=1, terms=[fl.Triangle("A")]) ], rule_blocks=[ fl.RuleBlock(name="rb", description="a rule block", rules=[fl.Rule.create("if a then z")]) ]) self.assertEqual(fl.FllExporter().to_string(engine), fl.FllExporter().engine(engine)) self.assertEqual( fl.FllExporter().engine(engine), """\ Engine: engine description: an engine InputVariable: input_variable description: an input variable enabled: true range: 0 1 lock-range: false term: A Triangle nan nan nan OutputVariable: output_variable description: an output variable enabled: true range: 0 1 lock-range: false aggregation: none defuzzifier: none default: nan lock-previous: false term: A Triangle nan nan nan RuleBlock: rb description: a rule block enabled: true conjunction: none disjunction: none implication: none activation: none rule: if a then z """)
def test_describe(self) -> None: self.assertEqual( "OutputVariable[{" "'default_value': 'nan', 'defuzzifier': 'None', " "'fuzzy': 'term: x Aggregated []', " "'lock_previous': 'False', 'previous_value': 'nan'" "}]", fl.Op.describe( fl.OutputVariable("x", "an x", terms=[fl.Triangle("t")]))) self.assertEqual( "InputVariable[{}]", fl.Op.describe( fl.InputVariable("x", "an x", terms=[fl.Triangle("t")])))
def test_term(self) -> None: term: fl.Term = fl.Triangle("A", 0.0, 1.0, 2.0, 0.5) self.assertEqual(fl.PythonExporter().to_string(term), fl.PythonExporter().term(term)) self.assertEqual(fl.PythonExporter().term(term), "fl.Triangle(\"A\", 0.000, 1.000, 2.000, 0.500)") term = fl.Discrete("B", [0.0, 0.0, 0.5, 1.0, 1.0, 0.0]) self.assertEqual(fl.PythonExporter().to_string(term), fl.PythonExporter().term(term)) self.assertEqual( fl.PythonExporter().term(term), "fl.Discrete(\"B\", [0.000, 0.000, 0.500, 1.000, 1.000, 0.000])") term = fl.Function("C", "x + 1") self.assertEqual(fl.PythonExporter().to_string(term), fl.PythonExporter().term(term)) self.assertEqual(fl.PythonExporter().term(term), "fl.Function.create(\"C\", \"x + 1\", engine)") term = fl.Linear("D", [0.0, 1.0, 2.0, -fl.inf, fl.inf]) self.assertEqual(fl.PythonExporter().to_string(term), fl.PythonExporter().term(term)) self.assertEqual( fl.PythonExporter().term(term), "fl.Linear(\"D\", [0.000, 1.000, 2.000, -fl.inf, fl.inf], engine)")
def test_bisector(self) -> None: DefuzzifierAssert(self, fl.Bisector()) \ .exports_fll("Bisector 100") \ .has_parameters("100") \ .configured_as("200") \ .exports_fll("Bisector 200") DefuzzifierAssert(self, fl.Bisector()) \ .defuzzifies( { fl.Triangle("", -1, -1, 0): -0.5, fl.Triangle("", -1, 1, 2): 0.0, fl.Triangle("", 0, 0, 3): 0.5, fl.Aggregated("", 0, 1, fl.Maximum(), [ fl.Activated(fl.Triangle("Medium", 0.25, 0.5, 0.75), 0.2, fl.Minimum()), fl.Activated(fl.Triangle("High", 0.5, 0.75, 1.0), 0.8, fl.Minimum()) ]): 0.7200552486187846 }, -1, 0)
def test_centroid(self) -> None: DefuzzifierAssert(self, fl.Centroid()) \ .exports_fll("Centroid 100") \ .has_parameters("100") \ .configured_as("200") \ .exports_fll("Centroid 200") DefuzzifierAssert(self, fl.Centroid()) \ .defuzzifies( { fl.Triangle("", -1, 0): -0.5, fl.Triangle("", -1, 1): 0.0, fl.Triangle("", 0, 1): 0.5, fl.Aggregated("", 0, 1, fl.Maximum(), [ fl.Activated(fl.Triangle("Medium", 0.25, 0.5, 0.75), 0.2, fl.Minimum()), fl.Activated(fl.Triangle("High", 0.5, 0.75, 1.0), 0.8, fl.Minimum()) ]): 0.6900552486187845 }, -1, 1)
def test_fuzzy_value(self) -> None: low, medium, high = [ fl.Triangle('Low', -1.0, -1.0, 0.0), fl.Triangle('Medium', -0.5, 0.0, 0.5), fl.Triangle('High', 0.0, 1.0, 1.0) ] OutputVariableAssert(self, fl.OutputVariable(name="name", description="description", minimum=-1.0, maximum=1.0, terms=[low, medium, high])) \ .activated_values({tuple(): "0.000/Low + 0.000/Medium + 0.000/High", tuple([fl.Activated(low, 0.5)]): "0.500/Low + 0.000/Medium + 0.000/High", tuple([fl.Activated(low, -1.0), fl.Activated(medium, -0.5), fl.Activated(high, -0.1)]): "-1.000/Low - 0.500/Medium - 0.100/High"})
def test_weighted_sum(self) -> None: DefuzzifierAssert(self, fl.WeightedSum()).exports_fll("WeightedSum Automatic") DefuzzifierAssert(self, fl.WeightedSum()) \ .configured_as("TakagiSugeno") \ .exports_fll("WeightedSum TakagiSugeno") with self.assertRaises(KeyError): fl.WeightedSum().configure("SugenoTakagi") defuzzifier = fl.WeightedSum() defuzzifier.type = None # type: ignore with self.assertRaisesRegex(ValueError, "expected a type of defuzzifier, but found none"): defuzzifier.defuzzify(fl.Aggregated(terms=[fl.Activated(fl.Term())])) with self.assertRaisesRegex(ValueError, re.escape( "expected an Aggregated term, but found <class 'fuzzylite.term.Triangle'>")): defuzzifier.defuzzify(fl.Triangle()) DefuzzifierAssert(self, fl.WeightedSum()) \ .defuzzifies({fl.Aggregated(): fl.nan, fl.Aggregated(terms=[fl.Activated(fl.Constant("", 1.0), 1.0), fl.Activated(fl.Constant("", 2.0), 1.0), fl.Activated(fl.Constant("", 3.0), 1.0), ]): 6.0, fl.Aggregated(terms=[fl.Activated(fl.Constant("", 1.0), 1.0), fl.Activated(fl.Constant("", 2.0), 0.5), fl.Activated(fl.Constant("", 3.0), 1.0), ]): 5.0, fl.Aggregated(terms=[fl.Activated(fl.Constant("", -1.0), 1.0), fl.Activated(fl.Constant("", -2.0), 1.0), fl.Activated(fl.Constant("", 3.0), 1.0), ]): 0.0, fl.Aggregated(terms=[fl.Activated(fl.Constant("", 1.0), 1.0), fl.Activated(fl.Constant("", -2.0), 1.0), fl.Activated(fl.Constant("", -3.0), 0.5), ]): -2.5 }) DefuzzifierAssert(self, fl.WeightedSum()) \ .configured_as("Tsukamoto") \ .defuzzifies({fl.Aggregated(): fl.nan, fl.Aggregated(terms=[fl.Activated(fl.Constant("", 1.0), 1.0), fl.Activated(fl.Constant("", 2.0), 1.0), fl.Activated(fl.Constant("", 3.0), 1.0), ]): 6.0, fl.Aggregated(terms=[fl.Activated(fl.Constant("", 1.0), 1.0), fl.Activated(fl.Constant("", 2.0), 0.5), fl.Activated(fl.Constant("", 3.0), 1.0), ]): 5.0, fl.Aggregated(terms=[fl.Activated(fl.Constant("", -1.0), 1.0), fl.Activated(fl.Constant("", -2.0), 1.0), fl.Activated(fl.Constant("", 3.0), 1.0), ]): 0.0, fl.Aggregated(terms=[fl.Activated(fl.Constant("", 1.0), 1.0), fl.Activated(fl.Constant("", -2.0), 1.0), fl.Activated(fl.Constant("", -3.0), 0.5), ]): -2.5 })
def test_variable(self) -> None: variable = fl.Variable(name="variable", description="a variable", minimum=0, maximum=1, terms=[fl.Triangle("A")]) self.assertEqual(fl.FllExporter().to_string(variable), fl.FllExporter().variable(variable)) self.assertEqual(fl.FllExporter().variable(variable), """\ Variable: variable description: a variable enabled: true range: 0 1 lock-range: false term: A Triangle nan nan nan""")
def test_output_variable(self) -> None: ov = fl.OutputVariable(name="output_variable", description="an output variable", minimum=0.0, maximum=1.0, terms=[fl.Triangle("A")]) self.assertEqual(fl.PythonExporter().to_string(ov), fl.PythonExporter().output_variable(ov)) self.assertEqual( fl.PythonExporter().output_variable(ov), """\ fl.OutputVariable( name="output_variable", description="an output variable", enabled=True, minimum=0.000, maximum=1.000, lock_range=False, aggregation=None, defuzzifier=None, lock_previous=False, terms=[fl.Triangle("A", nan, nan, nan)] )""") ov.terms.append(fl.Triangle("Z")) self.assertEqual( fl.PythonExporter().output_variable(ov), """\ fl.OutputVariable( name="output_variable", description="an output variable", enabled=True, minimum=0.000, maximum=1.000, lock_range=False, aggregation=None, defuzzifier=None, lock_previous=False, terms=[ fl.Triangle("A", nan, nan, nan), fl.Triangle("Z", nan, nan, nan) ] )""")
def test_fuzzy_value(self) -> None: InputVariableAssert(self, fl.InputVariable(name="name", description="description", minimum=-1.0, maximum=1.0, terms=[ fl.Triangle('Low', -1.0, -1.0, 0.0), fl.Triangle('Medium', -0.5, 0.0, 0.5), fl.Triangle('High', 0.0, 1.0, 1.0) ])) \ .fuzzy_values({-1.00: "1.000/Low + 0.000/Medium + 0.000/High", -0.50: "0.500/Low + 0.000/Medium + 0.000/High", -0.25: "0.250/Low + 0.500/Medium + 0.000/High", 0.00: "0.000/Low + 1.000/Medium + 0.000/High", 0.25: "0.000/Low + 0.500/Medium + 0.250/High", 0.50: "0.000/Low + 0.000/Medium + 0.500/High", 0.75: "0.000/Low + 0.000/Medium + 0.750/High", 1.00: "0.000/Low + 0.000/Medium + 1.000/High", math.nan: "nan/Low + nan/Medium + nan/High", math.inf: "0.000/Low + 0.000/Medium + 0.000/High", -math.inf: "0.000/Low + 0.000/Medium + 0.000/High", })
def test_clear(self) -> None: low, medium, high = [ fl.Triangle('Low', -1.0, -1.0, 0.0), fl.Triangle('Medium', -0.5, 0.0, 0.5), fl.Triangle('High', 0.0, 1.0, 1.0) ] variable = fl.OutputVariable(name="name", description="description", minimum=-1.0, maximum=1.0, terms=[low, medium, high]) variable.value = 0.0 variable.previous_value = -1.0 variable.fuzzy.terms.extend( [fl.Activated(term, 0.5) for term in variable.terms]) OutputVariableAssert(self, variable) \ .exports_fll("\n".join(["OutputVariable: name", " description: description", " enabled: true", " range: -1.000 1.000", " lock-range: false", " aggregation: none", " defuzzifier: none", " default: nan", " lock-previous: false", " term: Low Triangle -1.000 -1.000 0.000", " term: Medium Triangle -0.500 0.000 0.500", " term: High Triangle 0.000 1.000 1.000", ])) self.assertEqual(variable.value, 0.0) self.assertEqual(variable.previous_value, -1.0) self.assertSequenceEqual( [term.parameters() for term in variable.fuzzy.terms], ["(0.500*Low)", "(0.500*Medium)", "(0.500*High)"]) variable.clear() self.assertEqual(math.isnan(variable.value), True) self.assertEqual(math.isnan(variable.previous_value), True) self.assertSequenceEqual(variable.fuzzy.terms, [])
def test_highest_membership(self) -> None: low, medium, high = (fl.Triangle('Low', -1.0, -.5, 0.0), fl.Triangle('Medium', -0.5, 0.0, 0.5), fl.Triangle('High', 0.0, .5, 1.0)) VariableAssert(self, fl.Variable(name="name", description="description", minimum=-1.0, maximum=1.0, terms=[low, medium, high])) \ .highest_memberships( {-1.00: (0.0, None), -0.75: (0.5, low), -0.50: (1.0, low), -0.25: (0.5, low), 0.00: (1.0, medium), 0.25: (0.5, medium), 0.50: (1.0, high), 0.75: (0.5, high), 1.00: (0.0, None), math.nan: (0.0, None), math.inf: (0.0, None), -math.inf: (0.0, None), })
def test_output_variable(self) -> None: variable = fl.OutputVariable(name="output_variable", description="an output variable", minimum=0, maximum=1, terms=[fl.Triangle("A")]) self.assertEqual(fl.FllExporter().to_string(variable), fl.FllExporter().output_variable(variable)) self.assertEqual(fl.FllExporter().output_variable(variable), """\ OutputVariable: output_variable description: an output variable enabled: true range: 0 1 lock-range: false aggregation: none defuzzifier: none default: nan lock-previous: false term: A Triangle nan nan nan""")
def test_weighted_defuzzifier(self) -> None: self.assertEqual(fl.WeightedDefuzzifier().type, fl.WeightedDefuzzifier.Type.Automatic) defuzzifier = fl.WeightedDefuzzifier() defuzzifier.configure("TakagiSugeno") self.assertEqual(defuzzifier.type, fl.WeightedDefuzzifier.Type.TakagiSugeno) defuzzifier.type = None # type: ignore defuzzifier.configure("") self.assertEqual(defuzzifier.type, None) with self.assertRaises(KeyError): defuzzifier.configure("ABC") with self.assertRaises(NotImplementedError): defuzzifier.defuzzify(fl.Term(), fl.nan, fl.nan) self.assertEqual(defuzzifier.infer_type(fl.Constant()), fl.WeightedDefuzzifier.Type.TakagiSugeno) self.assertEqual(defuzzifier.infer_type(fl.Triangle()), fl.WeightedDefuzzifier.Type.Tsukamoto)
engine = fl.Engine( name="tipper", description="(service and food) -> (tip)" ) engine.input_variables = [ fl.InputVariable( name="service", description="quality of service", enabled=True, minimum=0.000, maximum=10.000, lock_range=True, terms=[ fl.Trapezoid("poor", 0.000, 0.000, 2.500, 5.000), fl.Triangle("good", 2.500, 5.000, 7.500), fl.Trapezoid("excellent", 5.000, 7.500, 10.000, 10.000) ] ), fl.InputVariable( name="food", description="quality of food", enabled=True, minimum=0.000, maximum=10.000, lock_range=True, terms=[ fl.Trapezoid("rancid", 0.000, 0.000, 2.500, 7.500), fl.Trapezoid("delicious", 2.500, 7.500, 10.000, 10.000) ] )
engine = fl.Engine( name="tank2", description="" ) engine.input_variables = [ fl.InputVariable( name="level", description="", enabled=True, minimum=-1.000, maximum=1.000, lock_range=False, terms=[ fl.Trapezoid("high", -2.000, -1.000, -0.800, -0.001), fl.Triangle("good", -0.150, 0.000, 0.500), fl.Trapezoid("low", 0.001, 0.800, 1.000, 1.500) ] ), fl.InputVariable( name="change", description="", enabled=True, minimum=-0.100, maximum=0.100, lock_range=False, terms=[ fl.Trapezoid("falling", -0.140, -0.100, -0.060, 0.000), fl.Trapezoid("rising", -0.001, 0.060, 0.100, 0.140) ] )
name='collision_avoidance', description='' ) avoidance_engine.input_variables = [ fl.InputVariable( name='Left_Laser', description='', enabled=True, minimum=0.0, # The true range_min specified in sensor_msgs/LaserScan is ~0.1 maximum=5.0, lock_range=True, terms=[ # Ramp is defined so that start is the bottom of ramp and end is the top fl.Ramp('near', .75, 0), fl.Triangle('medium', .5, 2.5, 3.75), fl.Ramp('far', 2.5, 5) ] ), fl.InputVariable( name='Right_Laser', description='', enabled=True, minimum=0.0, maximum=5.0, lock_range=True, terms=[ fl.Ramp('near', .75, 0), fl.Triangle('medium', .5, 2.5, 3.75), fl.Ramp('far', 2.5, 5) ]
def test_engine(self) -> None: engine = fl.Engine( name="engine", description="an engine", input_variables=[ fl.InputVariable(name="input_variable", description="an input variable", minimum=0, maximum=1, terms=[fl.Triangle("A")]) ], output_variables=[ fl.OutputVariable(name="output_variable", description="an output variable", minimum=0, maximum=1, terms=[fl.Triangle("A")]) ], rule_blocks=[ fl.RuleBlock(name="rb", description="a rule block", rules=[fl.Rule.create("if a then z")]) ]) self.assertEqual(fl.PythonExporter().to_string(engine), fl.PythonExporter().engine(engine)) self.assertEqual(second=fl.PythonExporter().engine(engine), first="""\ import fuzzylite as fl engine = fl.Engine( name="engine", description="an engine" ) engine.input_variables = [ fl.InputVariable( name="input_variable", description="an input variable", enabled=True, minimum=0, maximum=1, lock_range=False, terms=[fl.Triangle("A", nan, nan, nan)] ) ] engine.output_variables = [ fl.OutputVariable( name="output_variable", description="an output variable", enabled=True, minimum=0, maximum=1, lock_range=False, aggregation=None, defuzzifier=None, lock_previous=False, terms=[fl.Triangle("A", nan, nan, nan)] ) ] engine.rule_blocks = [ fl.RuleBlock( name="rb", description="a rule block", enabled=True, conjunction=None, disjunction=None, implication=None, activation=None, rules=[fl.Rule.create("if a then z", engine)] ) ] """)
import fuzzylite as fl engine = fl.Engine(name="AllTerms", description="") engine.input_variables = [ fl.InputVariable(name="AllInputTerms", description="", enabled=True, minimum=0.000, maximum=6.500, lock_range=False, terms=[ fl.Sigmoid("A", 0.500, -20.000), fl.ZShape("B", 0.000, 1.000), fl.Ramp("C", 1.000, 0.000), fl.Triangle("D", 0.500, 1.000, 1.500), fl.Trapezoid("E", 1.000, 1.250, 1.750, 2.000), fl.Concave("F", 0.850, 0.250), fl.Rectangle("G", 1.750, 2.250), fl.Discrete("H", [ 2.000, 0.000, 2.250, 1.000, 2.500, 0.500, 2.750, 1.000, 3.000, 0.000 ]), fl.Gaussian("I", 3.000, 0.200), fl.Cosine("J", 3.250, 0.650), fl.GaussianProduct("K", 3.500, 0.100, 3.300, 0.300), fl.Spike("L", 3.640, 1.040), fl.Bell("M", 4.000, 0.250, 3.000), fl.PiShape("N", 4.000, 4.500, 4.500, 5.000), fl.Concave("O", 5.650, 6.250), fl.SigmoidDifference("P", 4.750, 10.000, 30.000, 5.250),
import fuzzylite as fl engine = fl.Engine( name="approximation", description="" ) engine.input_variables = [ fl.InputVariable( name="inputX", description="", enabled=True, minimum=0.000, maximum=10.000, lock_range=False, terms=[ fl.Triangle("NEAR_1", 0.000, 1.000, 2.000), fl.Triangle("NEAR_2", 1.000, 2.000, 3.000), fl.Triangle("NEAR_3", 2.000, 3.000, 4.000), fl.Triangle("NEAR_4", 3.000, 4.000, 5.000), fl.Triangle("NEAR_5", 4.000, 5.000, 6.000), fl.Triangle("NEAR_6", 5.000, 6.000, 7.000), fl.Triangle("NEAR_7", 6.000, 7.000, 8.000), fl.Triangle("NEAR_8", 7.000, 8.000, 9.000), fl.Triangle("NEAR_9", 8.000, 9.000, 10.000) ] ) ] engine.output_variables = [ fl.OutputVariable( name="outputFx", description="",
import fuzzylite as fl engine = fl.Engine(name="cubic_approximator", description="") engine.input_variables = [ fl.InputVariable(name="X", description="", enabled=True, minimum=-5.000, maximum=5.000, lock_range=False, terms=[ fl.Triangle("AboutNegFive", -6.000, -5.000, -4.000), fl.Triangle("AboutNegFour", -5.000, -4.000, -3.000), fl.Triangle("AboutNegThree", -4.000, -3.000, -2.000), fl.Triangle("AboutNegTwo", -3.000, -2.000, -1.000), fl.Triangle("AboutNegOne", -2.000, -1.000, 0.000), fl.Triangle("AboutZero", -1.000, 0.000, 1.000), fl.Triangle("AboutOne", 0.000, 1.000, 2.000), fl.Triangle("AboutTwo", 1.000, 2.000, 3.000), fl.Triangle("AboutThree", 2.000, 3.000, 4.000), fl.Triangle("AboutFour", 3.000, 4.000, 5.000), fl.Triangle("AboutFive", 4.000, 5.000, 6.000) ]) ] engine.output_variables = [ fl.OutputVariable(name="ApproxXCubed", description="", enabled=True, minimum=-5.000, maximum=5.000, lock_range=False,
def test_engine(self) -> None: engine = fl.Engine() engine.name = "tipper" engine.description = "(service and food) -> (tip)" service = fl.InputVariable() service.name = "service" service.description = "quality of service" service.enabled = True service.range = (0.000, 10.000) service.lock_range = True service.terms.append(fl.Trapezoid("poor", 0.000, 0.000, 2.500, 5.000)) service.terms.append(fl.Triangle("good", 2.500, 5.000, 7.500)) service.terms.append(fl.Trapezoid("excellent", 5.000, 7.500, 10.000, 10.000)) engine.input_variables.append(service) food = fl.InputVariable() food.name = "food" food.description = "quality of food" food.enabled = True food.range = (0.000, 10.000) food.lock_range = True food.terms.append(fl.Trapezoid("rancid", 0.000, 0.000, 2.500, 7.500)) food.terms.append(fl.Trapezoid("delicious", 2.500, 7.500, 10.000, 10.000)) engine.input_variables.append(food) mTip = fl.OutputVariable() # noqa N806 should be lowercase mTip.name = "mTip" mTip.description = "tip based on Mamdani inference" mTip.enabled = True mTip.range = (0.000, 30.000) mTip.lock_range = False mTip.aggregation = fl.Maximum() mTip.defuzzifier = fl.Centroid(100) mTip.default_value = fl.nan mTip.lock_previous = False mTip.terms.append(fl.Triangle("cheap", 0.000, 5.000, 10.000)) mTip.terms.append(fl.Triangle("average", 10.000, 15.000, 20.000)) mTip.terms.append(fl.Triangle("generous", 20.000, 25.000, 30.000)) engine.output_variables.append(mTip) tsTip = fl.OutputVariable() # noqa N806 should be lowercase tsTip.name = "tsTip" tsTip.description = "tip based on Takagi-Sugeno inference" tsTip.enabled = True tsTip.range = (0.000, 30.000) tsTip.lock_range = False tsTip.aggregation = None tsTip.defuzzifier = fl.WeightedAverage("TakagiSugeno") tsTip.default_value = fl.nan tsTip.lock_previous = False tsTip.terms.append(fl.Constant("cheap", 5.000)) tsTip.terms.append(fl.Constant("average", 15.000)) tsTip.terms.append(fl.Constant("generous", 25.000)) engine.output_variables.append(tsTip) mamdani = fl.RuleBlock() mamdani.name = "mamdani" mamdani.description = "Mamdani inference" mamdani.enabled = True mamdani.conjunction = fl.AlgebraicProduct() mamdani.disjunction = fl.AlgebraicSum() mamdani.implication = fl.Minimum() mamdani.activation = fl.General() mamdani.rules.append( fl.Rule.create("if service is poor or food is rancid then mTip is cheap", engine)) mamdani.rules.append(fl.Rule.create("if service is good then mTip is average", engine)) mamdani.rules.append(fl.Rule.create( "if service is excellent or food is delicious then mTip is generous with 0.5", engine)) mamdani.rules.append(fl.Rule.create( "if service is excellent and food is delicious then mTip is generous with 1.0", engine)) engine.rule_blocks.append(mamdani) takagiSugeno = fl.RuleBlock() # noqa N806 should be lowercase takagiSugeno.name = "takagiSugeno" takagiSugeno.description = "Takagi-Sugeno inference" takagiSugeno.enabled = True takagiSugeno.conjunction = fl.AlgebraicProduct() takagiSugeno.disjunction = fl.AlgebraicSum() takagiSugeno.implication = None takagiSugeno.activation = fl.General() takagiSugeno.rules.append(fl.Rule.create( "if service is poor or food is rancid then tsTip is cheap", engine)) takagiSugeno.rules.append(fl.Rule.create( "if service is good then tsTip is average", engine)) takagiSugeno.rules.append(fl.Rule.create( "if service is excellent or food is delicious then tsTip is generous with 0.5", engine)) takagiSugeno.rules.append(fl.Rule.create( "if service is excellent and food is delicious then tsTip is generous with 1.0", engine)) engine.rule_blocks.append(takagiSugeno) EngineAssert(self, engine) \ .has_name("tipper") \ .has_description("(service and food) -> (tip)") \ .has_n_inputs(2).has_inputs(["service", "food"]) \ .has_n_outputs(2).has_outputs(["mTip", "tsTip"]) \ .has_n_blocks(2).has_blocks(["mamdani", "takagiSugeno"]) \ .evaluate_fld( """\ #service food mTip tsTip 0.0000000000000000 0.0000000000000000 4.9989502099580099 5.0000000000000000 0.0000000000000000 3.3333333333333335 7.7561896551724301 6.5384615384615392 0.0000000000000000 6.6666666666666670 12.9489036144578247 10.8823529411764728 0.0000000000000000 10.0000000000000000 13.5707062050051448 11.6666666666666661 3.3333333333333335 0.0000000000000000 8.5688247396168276 7.5000000000000000 3.3333333333333335 3.3333333333333335 10.1101355034654858 8.6734693877551035 3.3333333333333335 6.6666666666666670 13.7695060342408198 12.9245283018867916 3.3333333333333335 10.0000000000000000 14.3676481312670976 13.8888888888888911 6.6666666666666670 0.0000000000000000 12.8954528230390419 11.0000000000000000 6.6666666666666670 3.3333333333333335 13.2040624705105234 12.7966101694915260 6.6666666666666670 6.6666666666666670 17.9862390284958273 20.6363636363636367 6.6666666666666670 10.0000000000000000 21.1557340720221632 22.7777777777777821 10.0000000000000000 0.0000000000000000 13.5707062050051448 11.6666666666666661 10.0000000000000000 3.3333333333333335 13.7092196934510024 13.8888888888888875 10.0000000000000000 6.6666666666666670 20.2157800031293959 22.7777777777777821 10.0000000000000000 10.0000000000000000 25.0010497900419928 25.0000000000000000 """, decimals=16)
import fuzzylite as fl engine = fl.Engine(name="shower", description="") engine.input_variables = [ fl.InputVariable(name="temp", description="", enabled=True, minimum=-20.000000000, maximum=20.000000000, lock_range=False, terms=[ fl.Trapezoid("cold", -30.000000000, -30.000000000, -15.000000000, 0.000000000), fl.Triangle("good", -10.000000000, 0.000000000, 10.000000000), fl.Trapezoid("hot", 0.000000000, 15.000000000, 30.000000000, 30.000000000) ]), fl.InputVariable(name="flow", description="", enabled=True, minimum=-1.000000000, maximum=1.000000000, lock_range=False, terms=[ fl.Trapezoid("soft", -3.000000000, -3.000000000, -0.800000000, 0.000000000), fl.Triangle("good", -0.400000000, 0.000000000, 0.400000000), fl.Trapezoid("hard", 0.000000000, 0.800000000, 3.000000000, 3.000000000)
import matplotlib.pyplot as plt from matplotlib import cm import numpy as np engine = fl.Engine(name="towercopter", description="landing a towercopter gently") engine.input_variables = [ fl.InputVariable( name="dist", description="distance to the ground", enabled=True, minimum=0.000, # Centimeters maximum=30.000, # Centimeters lock_range=True, terms=[ fl.Triangle("tocant", 0.000, 0.000, 2.000), fl.Trapezoid("a_prop", 0.000, 2.000, 4.000, 6.000), fl.Trapezoid("lluny", 4.000, 10.000, 15.000, 21.000), fl.Trapezoid("molt_lluny", 15.000, 17.000, 30.000, 30.000) ]), fl.InputVariable( name="var_dist", description= "distance variation, actual distance to the ground minus previous one", enabled=True, minimum=-10.000, # Centimetres maximum=3.000, # Centimetres lock_range=True, terms=[ fl.Trapezoid("molt_gran_neg", -10.000, -10.000, -7.000, -5.000), fl.Trapezoid("gran_neg", -7.000, -6.000, -4.000, -3.000),
import fuzzylite as fl engine = fl.Engine(name="SimpleDimmer", description="") engine.input_variables = [ fl.InputVariable(name="Ambient", description="", enabled=True, minimum=0.000, maximum=1.000, lock_range=False, terms=[ fl.Triangle("DARK", 0.000, 0.250, 0.500), fl.Triangle("MEDIUM", 0.250, 0.500, 0.750), fl.Triangle("BRIGHT", 0.500, 0.750, 1.000) ]) ] engine.output_variables = [ fl.OutputVariable(name="Power", description="", enabled=True, minimum=0.000, maximum=1.000, lock_range=False, aggregation=fl.Maximum(), defuzzifier=fl.Centroid(200), lock_previous=False, terms=[ fl.Triangle("LOW", 0.000, 0.250, 0.500), fl.Triangle("MEDIUM", 0.250, 0.500, 0.750), fl.Triangle("HIGH", 0.500, 0.750, 1.000) ])
import fuzzylite as fl engine = fl.Engine(name="Constant", description="obstacle avoidance for self-driving cars") engine.input_variables = [ fl.InputVariable(name="obstacle", description="location of obstacle relative to vehicle", enabled=True, minimum=0.000000000, maximum=1.000000000, lock_range=False, terms=[ fl.Triangle("left", 0.000000000, 0.333000000, 0.666000000), fl.Triangle("right", 0.333000000, 0.666000000, 1.000000000) ]) ] engine.output_variables = [ fl.OutputVariable(name="steer", description="direction to steer the vehicle to", enabled=True, minimum=0.000000000, maximum=1.000000000, lock_range=False, aggregation=None, defuzzifier=fl.WeightedAverage("TakagiSugeno"), lock_previous=False, terms=[ fl.Constant("left", 0.333000000), fl.Constant("right", 0.666500000)
def test_term(self) -> None: term = fl.Triangle("A", 0.0, 1.0, 2.0, 0.5) self.assertEqual(fl.FllExporter().to_string(term), fl.FllExporter().term(term)) self.assertEqual(fl.FllExporter().term(term), "term: A Triangle 0.000 1.000 2.000 0.500")