Esempio n. 1
0
    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())
Esempio n. 2
0
 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; ")
Esempio n. 3
0
 def test_empty_engine(self) -> None:
     flc = fl.Engine("name", "description")
     EngineAssert(self, flc) \
         .has_name("name").has_description("description") \
         .has_n_inputs(0).has_inputs([]) \
         .has_n_outputs(0).has_outputs([]) \
         .has_n_blocks(0).has_blocks([])
Esempio n. 4
0
 def test_write_from_scope_all_variables_on_empty_engine(self) -> None:
     engine = fl.Engine()
     writer = io.StringIO()
     with self.assertRaisesRegex(ValueError, "expected input variables in engine, but got none"):
         fl.FldExporter().write_from_scope(
             engine, writer, values=16,
             scope=fl.FldExporter.ScopeOfValues.AllVariables,
             active_variables=set(engine.input_variables))
Esempio n. 5
0
    def test_write_from_reader_empty_or_commented(self) -> None:
        reader = """\

# commented line 0.000
            """
        writer = io.StringIO()
        fl.FldExporter().write_from_reader(fl.Engine(), writer, io.StringIO(reader))
        self.assertEqual("\n", writer.getvalue())
Esempio n. 6
0
    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
Esempio n. 7
0
    def test_write_from_reader_empty_engine_empty(self) -> None:
        engine = fl.Engine()

        writer = io.StringIO()
        fl.FldExporter().write_from_reader(engine, writer, io.StringIO())
        self.assertEqual("\n", writer.getvalue())

        writer = io.StringIO()
        fl.FldExporter(headers=False).write_from_reader(engine, writer, io.StringIO())
        self.assertEqual("", writer.getvalue())
Esempio n. 8
0
    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
""")
Esempio n. 9
0
 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))
Esempio n. 10
0
    def test_term(self) -> None:
        term = "term: left Triangle 0.000 0.333 0.666"
        self.assertEqual(term, str(fl.FllImporter().term(term)))
        engine = fl.Engine()
        term = "term: function Function 1 + 1"
        self.assertEqual(term, str(fl.FllImporter().term(term)))
        self.assertEqual(None, cast(fl.Function, fl.FllImporter().term(term)).engine)
        self.assertEqual(engine, cast(fl.Function, fl.FllImporter().term(term, engine)).engine)

        with self.assertRaisesRegex(SyntaxError, re.escape(
                "expected format 'term: name Term [parameters]', but got 'term: name'")):
            fl.FllImporter().term("term: name")
Esempio n. 11
0
    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())
Esempio n. 12
0
    def test_from_file(self) -> None:
        importer = fl.Importer()
        importer.from_string = MagicMock(  # type: ignore
            side_effect=lambda string: fl.Engine(description=string))

        path = tempfile.mkstemp(text=True)[1]
        with io.open(path, 'w') as file:
            file.write(BELL_FLL)

        engine = importer.from_file(path)

        self.assertEqual(BELL_FLL, engine.description)

        os.remove(path)
Esempio n. 13
0
    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])
Esempio n. 14
0
    def test_empty_engine(self) -> None:
        engine = fl.Engine(name="engine", description="an engine")
        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 = []
engine.output_variables = []
engine.rule_blocks = []
""")
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,
""" Establishes the fuzzy logic controller for collision avoidance """

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,
Esempio n. 17
0
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"),
Esempio n. 18
0
import fuzzylite as fl

engine = fl.Engine(name="Gaussian",
                   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=fl.Maximum(),
                      defuzzifier=fl.Centroid(100),
                      lock_previous=False,
                      terms=[
                          fl.Gaussian("left", 0.333000000, 0.143534483),
                          fl.Gaussian("right", 0.666500000, 0.143750000)
Esempio n. 19
0
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,
Esempio n. 20
0
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)
        ]
Esempio n. 21
0
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="sugeno_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)
        ]
    )
Esempio n. 23
0
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),
Esempio n. 24
0
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)
Esempio n. 25
0
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)
                      ])
Esempio n. 26
0
import fuzzylite as fl

engine = fl.Engine(
    name="ZSShape",
    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=fl.Maximum(),
        defuzzifier=fl.Centroid(100),
        lock_previous=False,
Esempio n. 27
0
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)
        ]
Esempio n. 28
0
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,
Esempio n. 29
0
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)
Esempio n. 30
0
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 = [