From 5593c9fa1450d14fa45c3c02623676113d6a44ae Mon Sep 17 00:00:00 2001 From: fanyq <2629791115@qq.com> Date: Tue, 20 Dec 2022 21:06:20 +0800 Subject: [PATCH] init --- .vscode/settings.json | 3 + ans.csv | 13 +++ 洗衣机.py | 200 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 216 insertions(+) create mode 100644 .vscode/settings.json create mode 100644 ans.csv create mode 100644 洗衣机.py diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..de288e1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.formatting.provider": "black" +} \ No newline at end of file diff --git a/ans.csv b/ans.csv new file mode 100644 index 0000000..739d176 --- /dev/null +++ b/ans.csv @@ -0,0 +1,13 @@ +脏的数量0-100,越大越脏;脏的类型0-100,越大油脂越多 +脏的数量,脏的类型,清洗时间/min +0.00,0.00,10.00,10.00,10.00 +10.00,10.00,17.14,16.85,15.59 +50.00,10.00,22.00,21.92,22.41 +10.00,50.00,30.00,30.00,30.00 +50.00,50.00,30.00,30.00,30.00 +10.00,70.00,34.29,34.28,34.19 +50.00,70.00,34.00,33.96,34.19 +70.00,10.00,24.29,24.78,26.13 +70.00,50.00,34.00,33.96,34.19 +70.00,70.00,38.89,38.81,38.78 +100.00,100.00,50.00,50.00,50.00 diff --git a/洗衣机.py b/洗衣机.py new file mode 100644 index 0000000..6fa1839 --- /dev/null +++ b/洗衣机.py @@ -0,0 +1,200 @@ +from enum import Enum +from functools import reduce +from scipy import integrate +import itertools + +DELIMETER = "," + + +class DirtType(Enum): + Greasy = 0 + Medium = 1 + NotGreasy = 2 + + def membership_grade(self, dirtness: float) -> float: + if self is DirtType.NotGreasy: + return max(0, 1 - 1 / 50 * dirtness) + elif self is DirtType.Medium: + if dirtness < 50: + return 1 / 50 * dirtness + else: + return 2 - 1 / 50 * dirtness + else: + return max(0, 1 / 50 * (dirtness - 50)) + + @classmethod + def membership_grades(cls, dirness: float) -> dict["DirtType", float]: + ans = {} + for v in cls: + ans[v] = v.membership_grade(dirness) + return ans + + +class DirtQuality(Enum): + Small = 0 + Medium = 1 + Large = 2 + + def membership_grade(self, type_of_dirt: float) -> float: + if self is DirtQuality.Small: + return max(0, 1 - 1 / 50 * type_of_dirt) + elif self is DirtQuality.Medium: + if type_of_dirt < 50: + return 1 / 50 * type_of_dirt + else: + return 2 - 1 / 50 * type_of_dirt + else: + return max(0, 1 / 50 * (type_of_dirt - 50)) + + @classmethod + def membership_grades(cls, dirness: float) -> dict["DirtQuality", float]: + ans = {} + for v in cls: + ans[v] = v.membership_grade(dirness) + return ans + + +class WashTime(Enum): + VS = 0 + S = 1 + M = 2 + L = 3 + VL = 4 + + def reverse_membership_grade(self) -> float: + v = [10, 20, 30, 40, 50] + return v[self.value] + + def membership_grade(self, wash_time: float) -> float: + fns = { + WashTime.VS: lambda t: min(1 / 10 * t, -1 / 10 * (t - 20)), + WashTime.S: lambda t: min(1 / 10 * (t - 10), -1 / 10 * (t - 30)), + WashTime.M: lambda t: min(1 / 10 * (t - 20), -1 / 10 * (t - 40)), + WashTime.L: lambda t: min(1 / 10 * (t - 30), -1 / 10 * (t - 50)), + WashTime.VL: lambda t: min(1 / 10 * (t - 40), -1 / 10 * (t - 60)), + } + return max(0, fns[self](wash_time)) + + +class Rule: + def __init__( + self, dirtness: DirtQuality, type_of_dirt: DirtType, wash_time: WashTime + ) -> None: + self.dirtness = dirtness + self.type_of_dirt = type_of_dirt + self.wash_time = wash_time + + def rule_support(self, dirtness: float, type_of_dirt: float) -> float: + # 计算隶属度 + dirtness_grade = self.dirtness.membership_grade(dirtness) + type_of_dirt_grade = self.type_of_dirt.membership_grade(type_of_dirt) + # 计算t范数 min + return min(dirtness_grade, type_of_dirt_grade) + + +class InferenceEngine: + def __init__(self, rules: list[Rule]) -> None: + self.rules = rules + + def output( + self, dirtness: float, type_of_dirt: float + ) -> list[tuple[float, WashTime]]: + # 使用规则 + ans = map( + lambda rule: (rule.rule_support(dirtness, type_of_dirt), rule.wash_time), + self.rules, + ) + ans = list(ans) + return ans + + +# 聚合模糊输出,使用离散的质心计算方式,数学积 +def aggregate_discret_AP(pairs: list[tuple[float, WashTime]]) -> float: + return sum( + map(lambda pair: pair[0] * pair[1].reverse_membership_grade(), pairs) + ) / sum(map(lambda pair: pair[0], pairs)) + + +# 使用连续的质心计算方式,数学积和代数和 +def aggregate_continue_AP(pairs: list[tuple[float, WashTime]]) -> float: + def f(time: float) -> float: + return S_AS(map(lambda pair: pair[0] * pair[1].membership_grade(time), pairs)) + + base = integrate.quad(f, 0, 60)[0] + return integrate.quad(lambda v: v * f(v), 0, 60)[0] / base + + +def S_AS(iter) -> float: + "代数和,输入数组" + ans = 0 + iter = tuple(iter) + for i in range(len(iter)): + n = i + 1 + if n & 1: + flag = 1 + else: + flag = -1 + # 选择n个数,相乘再相加 + for collection in itertools.combinations(iter, n): + ans += flag * reduce(lambda x, y: x * y, collection) + return ans + + +# 标准交 +def aggregate_continue_SI(pairs: list[tuple[float, WashTime]]) -> float: + """lambda: fi=min(alpha, mu), f=max(fi)""" + + def f(time: float) -> float: + return max( + map(lambda pair: min(pair[0], pair[1].membership_grade(time)), pairs) + ) + + return integrate.quad(lambda v: v * f(v), 0, 60)[0] / integrate.quad(f, 0, 60)[0] + + +rules = [ + Rule(DirtQuality.Small, DirtType.Greasy, WashTime.L), + Rule(DirtQuality.Medium, DirtType.Greasy, WashTime.L), + Rule(DirtQuality.Large, DirtType.Greasy, WashTime.VL), + Rule(DirtQuality.Small, DirtType.Medium, WashTime.M), + Rule(DirtQuality.Medium, DirtType.Medium, WashTime.M), + Rule(DirtQuality.Large, DirtType.Medium, WashTime.L), + Rule(DirtQuality.Small, DirtType.NotGreasy, WashTime.VS), + Rule(DirtQuality.Medium, DirtType.NotGreasy, WashTime.S), + Rule(DirtQuality.Large, DirtType.NotGreasy, WashTime.S), +] + +inputs = [ + [0, 0], + [10, 10], + [50, 10], + [10, 50], + [50, 50], + [10, 70], + [50, 70], + [70, 10], + [70, 50], + [70, 70], + [100, 100], +] + + +def main(inputs, rules): + print("脏的数量0-100,越大越脏;脏的类型0-100,越大油脂越多") + print(DELIMETER.join(["脏的数量", "脏的类型", "清洗时间/min"])) + engine = InferenceEngine(rules) + for input in inputs: + # print("脏的程度", input[0], "脏的类型", input[1]) + outputs = engine.output(input[0], input[1]) + output = aggregate_discret_AP(outputs) + output1 = aggregate_continue_AP(outputs) + output2 = aggregate_continue_SI(outputs) + print( + DELIMETER.join(["{:.2f}"] * 5).format( + input[0], input[1], output, output1, output2 + ) + ) + + +if __name__ == "__main__": + main(inputs, rules)