Example #1
0
    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)
Example #2
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)
Example #3
0
    def test_minimum(self) -> None:
        NormAssert(self, fl.Minimum()) \
            .is_t_norm() \
            .evaluates(
            {
                (0.00, 0.00): 0.00,
                (0.00, 0.25): 0.00,
                (0.00, 0.50): 0.00,
                (0.00, 0.75): 0.00,
                (0.00, 1.00): 0.00,

                (0.50, 0.25): 0.25,
                (0.50, 0.50): 0.50,
                (0.50, 0.75): 0.50,

                (1.00, 0.00): 0.00,
                (1.00, 0.25): 0.25,
                (1.00, 0.50): 0.50,
                (1.00, 0.75): 0.75,
                (1.00, 1.00): 1.00,
            })
Example #4
0
        lock_previous=False,
        terms=[
            fl.Constant("cheap", 5.000),
            fl.Constant("average", 15.000),
            fl.Constant("generous", 25.000)
        ]
    )
]
engine.rule_blocks = [
    fl.RuleBlock(
        name="mamdani",
        description="Mamdani inference",
        enabled=True,
        conjunction=fl.AlgebraicProduct(),
        disjunction=fl.AlgebraicSum(),
        implication=fl.Minimum(),
        activation=fl.General(),
        rules=[
            fl.Rule.create("if service is poor or food is rancid then mTip is cheap", engine),
            fl.Rule.create("if service is good then mTip is average", engine),
            fl.Rule.create("if service is excellent or food is delicious then mTip is generous with 0.500", engine),
            fl.Rule.create("if service is excellent and food is delicious then mTip is generous", engine)
        ]
    ),
    fl.RuleBlock(
        name="takagiSugeno",
        description="Takagi-Sugeno inference",
        enabled=True,
        conjunction=fl.AlgebraicProduct(),
        disjunction=fl.AlgebraicSum(),
        implication=None,
        terms=[
            fl.Ramp('reverse', 0, -.5),
            fl.Triangle('stop', -.05, 0, .05),
            fl.Triangle('slow', 0, .1, .2),
            fl.Triangle('normal', .1, .3, .5), 
            fl.Ramp('fast', .4, .6)
        ]
    ),
]

avoidance_engine.rule_blocks = [
    fl.RuleBlock(
        name="mamdani",
        description="",
        enabled=True,
        conjunction=fl.Minimum(),
        disjunction=fl.Maximum(),
        implication=fl.Minimum(),
        activation=fl.General(),
        rules=[
            # Left laser near section
            fl.Rule.create("if Left_Laser is near and Right_Laser is near and Front_Laser is near \
                            then Rotation is very_right and Velocity is reverse", avoidance_engine),
            fl.Rule.create("if Left_Laser is near and Right_Laser is near and Front_Laser is medium \
                            then Rotation is straight_ahead and Velocity is normal", avoidance_engine),
            fl.Rule.create("if Left_Laser is near and Right_Laser is near and Front_Laser is far \
                            then Rotation is straight_ahead and Velocity is fast", avoidance_engine),
            fl.Rule.create("if Left_Laser is near and Right_Laser is medium and Front_Laser is near \
                            then Rotation is very_right and Velocity is reverse", avoidance_engine),
            fl.Rule.create("if Left_Laser is near and Right_Laser is medium and Front_Laser is medium \
                            then Rotation is right and Velocity is slow", avoidance_engine),
        lock_previous=False,
        terms=[
            fl.Constant("NoRisk", 0.000),
            fl.Constant("LowRisk", 2.500),
            fl.Constant("MediumRisk", 5.000),
            fl.Constant("HighRisk", 7.500),
            fl.Constant("ExtremeRisk", 10.000)
        ]
    )
]
engine.rule_blocks = [
    fl.RuleBlock(
        name="",
        description="",
        enabled=True,
        conjunction=fl.Minimum(),
        disjunction=None,
        implication=None,
        activation=fl.General(),
        rules=[
            fl.Rule.create("if LDLLevel is Low and HDLLevel is LowHDL then HeartDiseaseRisk is MediumRisk", engine),
            fl.Rule.create("if LDLLevel is Low and HDLLevel is ModerateHDL then HeartDiseaseRisk is LowRisk", engine),
            fl.Rule.create("if LDLLevel is Low and HDLLevel is HighHDL then HeartDiseaseRisk is NoRisk", engine),
            fl.Rule.create("if LDLLevel is LowBorderline and HDLLevel is LowHDL then HeartDiseaseRisk is MediumRisk", engine),
            fl.Rule.create("if LDLLevel is LowBorderline and HDLLevel is ModerateHDL then HeartDiseaseRisk is LowRisk", engine),
            fl.Rule.create("if LDLLevel is LowBorderline and HDLLevel is HighHDL then HeartDiseaseRisk is LowRisk", engine),
            fl.Rule.create("if LDLLevel is Borderline and HDLLevel is LowHDL then HeartDiseaseRisk is HighRisk", engine),
            fl.Rule.create("if LDLLevel is Borderline and HDLLevel is ModerateHDL then HeartDiseaseRisk is MediumRisk", engine),
            fl.Rule.create("if LDLLevel is Borderline and HDLLevel is HighHDL then HeartDiseaseRisk is LowRisk", engine),
            fl.Rule.create("if LDLLevel is HighBorderline and HDLLevel is LowHDL then HeartDiseaseRisk is HighRisk", engine),
            fl.Rule.create("if LDLLevel is HighBorderline and HDLLevel is ModerateHDL then HeartDiseaseRisk is HighRisk", engine),
Example #7
0
    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)