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_header(self) -> None: engine = fl.Engine( input_variables=[ fl.InputVariable("A"), fl.InputVariable("B") ], output_variables=[ fl.OutputVariable("X"), fl.OutputVariable("Y"), fl.OutputVariable("Z") ] ) self.assertEqual("A B X Y Z", fl.FldExporter().header(engine)) self.assertEqual("A\tB\tX\tY\tZ", fl.FldExporter(separator="\t").header(engine))
def test_write(self) -> None: # Empty write writer = io.StringIO() fl.FldExporter().write(fl.Engine(), writer, [], set()) self.assertEqual("\n", writer.getvalue()) # Not enough values with self.assertRaisesRegex(ValueError, "not enough input values"): fl.FldExporter().write( fl.Engine(input_variables=[fl.InputVariable()]), writer, [], set()) # input and output values writer = io.StringIO() from fuzzylite.examples.mamdani.SimpleDimmer import engine fl.FldExporter(input_values=True, output_values=True).write(engine, writer, [0.25], set(engine.input_variables)) self.assertEqual("0.250 0.750\n", writer.getvalue()) # input values only writer = io.StringIO() fl.FldExporter(input_values=True, output_values=False).write(engine, writer, [0.25], set(engine.input_variables)) self.assertEqual("0.250\n", writer.getvalue()) # output values only writer = io.StringIO() fl.FldExporter(input_values=False, output_values=True).write(engine, writer, [0.25], set(engine.input_variables)) self.assertEqual("0.750\n", writer.getvalue()) # no values writer = io.StringIO() engine.process = MagicMock() # type: ignore fl.FldExporter(input_values=False, output_values=False).write(engine, writer, [0.25], set(engine.input_variables)) self.assertEqual("\n", writer.getvalue()) engine.process.assert_called_once() # type: ignore # active variables writer = io.StringIO() engine.input_variables[0].value = 0.250 test_variable = fl.InputVariable("test") test_variable.value = 0.0 engine.input_variables.append(test_variable) fl.FldExporter().write(engine, writer, [fl.inf, fl.inf], set([test_variable])) self.assertEqual("0.250 inf 0.750\n", writer.getvalue())
def test_inputs(self) -> None: flc = fl.Engine("name", "description", [fl.InputVariable("A"), fl.InputVariable("B")]) EngineAssert(self, flc) \ .has_name("name").has_description("description") \ .has_n_inputs(2).has_inputs(["A", "B"]) flc.input_variables = [] EngineAssert(self, flc).has_n_inputs(0).has_inputs([]) flc.input_variables = [fl.InputVariable("X"), fl.InputVariable("Y"), fl.InputVariable("Z")] EngineAssert(self, flc).has_n_inputs(3).has_inputs(["X", "Y", "Z"]) names = ["X", "Y", "Z"] for i, iv in enumerate(flc.input_variables): self.assertEqual(iv.name, names[i])
def test_single_line_indent(self) -> None: engine = fl.Engine("engine", "single line export to FLL", [fl.InputVariable("A", "variable A")], [fl.OutputVariable("Z", "variable Z")], [fl.RuleBlock("R", "rule block R")]) self.assertEqual( fl.FllExporter(separator="; ", indent='\t').engine(engine), "Engine: engine; " "\tdescription: single line export to FLL; " "InputVariable: A; " "\tdescription: variable A; " "\tenabled: true; " "\trange: -inf inf; " "\tlock-range: false; " "OutputVariable: Z; " "\tdescription: variable Z; " "\tenabled: true; " "\trange: -inf inf; " "\tlock-range: false; " "\taggregation: none; " "\tdefuzzifier: none; " "\tdefault: nan; " "\tlock-previous: false; " "RuleBlock: R; " "\tdescription: rule block R; " "\tenabled: true; " "\tconjunction: none; " "\tdisjunction: none; " "\timplication: none; " "\tactivation: none; ")
def test_to_string(self) -> None: with self.assertRaisesRegex(ValueError, "expected an Engine, but got object"): fl.FldExporter().to_string(object()) exporter = fl.FldExporter() exporter.to_string_from_scope = MagicMock() # type: ignore exporter.to_string(fl.Engine(input_variables=[fl.InputVariable("A")])) exporter.to_string_from_scope.assert_called_once() # type: ignore
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_write_from_reader_empty_engine_not_empty(self) -> None: engine = fl.Engine( input_variables=[fl.InputVariable("Input")], output_variables=[fl.OutputVariable("Output")] ) writer = io.StringIO() fl.FldExporter().write_from_reader(engine, writer, io.StringIO()) self.assertEqual("Input Output\n", writer.getvalue()) writer = io.StringIO() fl.FldExporter(headers=False).write_from_reader(engine, writer, io.StringIO()) self.assertEqual("", writer.getvalue())
def test_input_variable(self) -> None: variable = fl.InputVariable(name="input_variable", description="an input variable", minimum=0, maximum=1, terms=[fl.Triangle("A")]) self.assertEqual(fl.FllExporter().to_string(variable), fl.FllExporter().input_variable(variable)) self.assertEqual(fl.FllExporter().input_variable(variable), """\ InputVariable: input_variable description: an input variable enabled: true range: 0 1 lock-range: false term: A Triangle nan nan nan""")
def test_constructor(self) -> None: InputVariableAssert(self, fl.InputVariable("name", "description")) \ .exports_fll("\n".join(["InputVariable: name", " description: description", " enabled: true", " range: -inf inf", " lock-range: false" ])) InputVariableAssert(self, fl.InputVariable(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(["InputVariable: 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_to_string(self) -> None: with self.assertRaisesRegex(ValueError, "expected an Engine, but got InputVariable"): fl.FldExporter().to_string(fl.InputVariable()) from fuzzylite.examples.takagi_sugeno import SimpleDimmer engine = fl.FllImporter().from_string(str(SimpleDimmer.engine)) obtained = fl.FldExporter().to_string(engine) self.assertEqual(1025 + 1, len(obtained.split("\n"))) self.assertEqual("""\ Ambient Power 0.000 nan 0.001 0.750 0.002 0.750 0.003 0.750""", '\n'.join(obtained.split("\n")[:5]))
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", })
import fuzzylite as fl engine = fl.Engine(name="ObstacleAvoidance", description="") engine.input_variables = [ fl.InputVariable( name="obstacle", description="", enabled=True, minimum=0.000, maximum=1.000, lock_range=False, terms=[fl.Ramp("left", 1.000, 0.000), fl.Ramp("right", 0.000, 1.000)]) ] engine.output_variables = [ fl.OutputVariable( name="mSteer", description="", enabled=True, minimum=0.000, maximum=1.000, lock_range=False, aggregation=fl.Maximum(), defuzzifier=fl.Centroid(100), lock_previous=False, terms=[fl.Ramp("left", 1.000, 0.000), fl.Ramp("right", 0.000, 1.000)]), fl.OutputVariable( name="tsSteer", description="", enabled=True,
import fuzzylite as fl engine = fl.Engine(name="sugeno1", description="") engine.input_variables = [ fl.InputVariable(name="input", description="", enabled=True, minimum=-5.000, maximum=5.000, lock_range=False, terms=[ fl.Gaussian("low", -5.000, 4.000), fl.Gaussian("high", 5.000, 4.000) ]) ] engine.output_variables = [ fl.OutputVariable(name="output", description="", enabled=True, minimum=0.000, maximum=1.000, lock_range=False, aggregation=None, defuzzifier=fl.WeightedAverage("TakagiSugeno"), lock_previous=False, terms=[ fl.Linear("line1", [-1.000, -1.000], engine), fl.Linear("line2", [1.000, -1.000], engine) ]) ] engine.rule_blocks = [
import fuzzylite as fl engine = fl.Engine(name="mam21", description="") engine.input_variables = [ fl.InputVariable(name="angle", description="", enabled=True, minimum=-5.000, maximum=5.000, lock_range=False, terms=[ fl.Bell("small", -5.000, 5.000, 8.000), fl.Bell("big", 5.000, 5.000, 8.000) ]), fl.InputVariable(name="velocity", description="", enabled=True, minimum=-5.000, maximum=5.000, lock_range=False, terms=[ fl.Bell("small", -5.000, 5.000, 2.000), fl.Bell("big", 5.000, 5.000, 2.000) ]) ] engine.output_variables = [ fl.OutputVariable(name="force", description="", enabled=True, minimum=-5.000, maximum=5.000,
import fuzzylite as fl engine = fl.Engine(name="sltbu_fl", description="") engine.input_variables = [ fl.InputVariable(name="distance", description="", enabled=True, minimum=0.000, maximum=25.000, lock_range=False, terms=[ fl.ZShape("near", 1.000, 2.000), fl.SShape("far", 1.000, 2.000) ]), fl.InputVariable(name="control1", description="", enabled=True, minimum=-0.785, maximum=0.785, lock_range=False), fl.InputVariable(name="control2", description="", enabled=True, minimum=-0.785, maximum=0.785, lock_range=False) ] engine.output_variables = [ fl.OutputVariable(name="control", description="", enabled=True,
import fuzzylite as fl engine = fl.Engine( name="heart_disease_risk", description="" ) engine.input_variables = [ fl.InputVariable( name="LDLLevel", description="", enabled=True, minimum=0.000, maximum=300.000, lock_range=False, terms=[ fl.Trapezoid("Low", -1.000, 0.000, 90.000, 110.000), fl.Trapezoid("LowBorderline", 90.000, 110.000, 120.000, 140.000), fl.Trapezoid("Borderline", 120.000, 140.000, 150.000, 170.000), fl.Trapezoid("HighBorderline", 150.000, 170.000, 180.000, 200.000), fl.Trapezoid("High", 180.000, 200.000, 300.000, 301.000) ] ), fl.InputVariable( name="HDLLevel", description="", enabled=True, minimum=0.000, maximum=100.000, lock_range=False, terms=[ fl.Trapezoid("LowHDL", -1.000, 0.000, 35.000, 45.000),
import fuzzylite as fl engine = fl.Engine(name="invkine2", description="") engine.input_variables = [ fl.InputVariable(name="input1", description="", enabled=True, minimum=-6.287, maximum=17.000, lock_range=False, terms=[ fl.Bell("in1mf1", -5.763, 3.015, 1.851), fl.Bell("in1mf2", -1.624, 3.130, 2.111), fl.Bell("in1mf3", 3.552, 3.193, 2.104), fl.Bell("in1mf4", 8.273, 2.907, 1.985), fl.Bell("in1mf5", 13.232, 2.708, 2.056), fl.Bell("in1mf6", 17.783, 1.635, 1.897) ]), fl.InputVariable(name="input2", description="", enabled=True, minimum=0.000, maximum=16.972, lock_range=False, terms=[ fl.Bell("in2mf1", 0.005, 1.877, 1.995), fl.Bell("in2mf2", 3.312, 2.017, 1.829), fl.Bell("in2mf3", 6.568, 2.261, 1.793), fl.Bell("in2mf4", 10.111, 2.741, 1.978), fl.Bell("in2mf5", 14.952, 2.045, 1.783), fl.Bell("in2mf6", 17.910, 0.824, 1.734)
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="slcpp1", description="") engine.input_variables = [ fl.InputVariable(name="in1", description="", enabled=True, minimum=-0.300, maximum=0.300, lock_range=False), fl.InputVariable(name="in2", description="", enabled=True, minimum=-1.000, maximum=1.000, lock_range=False), fl.InputVariable(name="in3", description="", enabled=True, minimum=-3.000, maximum=3.000, lock_range=False), fl.InputVariable(name="in4", description="", enabled=True, minimum=-3.000, maximum=3.000, lock_range=False), fl.InputVariable(name="in5", description="", enabled=True,
import fuzzylite as fl 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) ]
import fuzzylite as fl engine = fl.Engine(name="mamdani_tip_calculator", description="") engine.input_variables = [ fl.InputVariable(name="FoodQuality", description="", enabled=True, minimum=1.000, maximum=10.000, lock_range=False, terms=[ fl.Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000), fl.Trapezoid("Good", 3.000, 7.000, 10.000, 11.000) ]), fl.InputVariable(name="Service", description="", enabled=True, minimum=1.000, maximum=10.000, lock_range=False, terms=[ fl.Trapezoid("Bad", 0.000, 1.000, 3.000, 7.000), fl.Trapezoid("Good", 3.000, 7.000, 10.000, 11.000) ]) ] engine.output_variables = [ fl.OutputVariable(name="Tip", description="", enabled=True, minimum=0.000, maximum=30.000,
import fuzzylite as fl engine = fl.Engine( name="tsukamoto", description="" ) engine.input_variables = [ fl.InputVariable( name="X", description="", enabled=True, minimum=-10.000, maximum=10.000, lock_range=False, terms=[ fl.Bell("small", -10.000, 5.000, 3.000), fl.Bell("medium", 0.000, 5.000, 3.000), fl.Bell("large", 10.000, 5.000, 3.000) ] ) ] engine.output_variables = [ fl.OutputVariable( name="Ramps", description="", enabled=True, minimum=0.000, maximum=1.000, lock_range=False, aggregation=None, defuzzifier=fl.WeightedAverage("Automatic"),
import fuzzylite as fl avoidance_engine = fl.Engine( 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),
import fuzzylite as fl engine = fl.Engine(name="tanksg", description="") engine.input_variables = [ fl.InputVariable(name="level", description="", enabled=True, minimum=-1.000, maximum=1.000, lock_range=False, terms=[ fl.Gaussian("high", -1.000, 0.300), fl.Gaussian("okay", 0.004, 0.300), fl.Gaussian("low", 1.000, 0.300) ]), fl.InputVariable(name="rate", description="", enabled=True, minimum=-0.100, maximum=0.100, lock_range=False, terms=[ fl.Gaussian("negative", -0.100, 0.030), fl.Gaussian("none", 0.000, 0.030), fl.Gaussian("positive", 0.100, 0.030) ]) ] engine.output_variables = [ fl.OutputVariable(name="valve", description="", enabled=True,
import fuzzylite as fl 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) ]
import fuzzylite as fl engine = fl.Engine( name="invkine1", description="" ) engine.input_variables = [ fl.InputVariable( name="input1", description="", enabled=True, minimum=-6.287, maximum=17.000, lock_range=False, terms=[ fl.Bell("in1mf1", -6.122, 2.259, 1.761), fl.Bell("in1mf2", -2.181, 2.095, 2.232), fl.Bell("in1mf3", 2.080, 2.157, 1.314), fl.Bell("in1mf4", 4.962, 2.790, 2.508), fl.Bell("in1mf5", 9.338, 2.506, 1.812), fl.Bell("in1mf6", 13.150, 2.363, 2.267), fl.Bell("in1mf7", 17.789, 1.310, 1.756) ] ), fl.InputVariable( name="input2", description="", enabled=True, minimum=0.000, maximum=16.972, lock_range=False,
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)
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), fl.SigmoidProduct("Q", 5.250, 20.000, -10.000, 5.750), fl.Ramp("R", 5.500, 6.500), fl.SShape("S", 5.500, 6.500), fl.Sigmoid("T", 6.000, 20.000) ])