import simpful as sf import numpy as np import matplotlib.pylab as plt # Fix for the "detected Sugeno model type" spam - overwrite the annoying method from simpful class FuzzySystem(sf.FuzzySystem): def _set_model_type(self, model_type): if self._detected_type == "inconsistent": return if self._detected_type is None: self._detected_type = model_type # Just commenting the line below! #print(" * Detected %s model type" % model_type) elif self._detected_type != model_type: print("WARNING: model type is unclear (simpful detected %s, but a %s output was specified)" % ( self._detected_type, model_type)) self._detected_type = 'inconsistent' def fuzzy_controler_popularity(price: float, game_length: int, rating: float, number_of_owners: int) -> float: FS = FuzzySystem(show_banner=False) S_1 = sf.FuzzySet(points=[[0., 1.], [30., 0.]], term="negative") S_2 = sf.FuzzySet(points=[[35., 0.], [40., 1.], [60., 1.], [70., 0.]], term="average") S_3 = sf.FuzzySet(points=[[80., 0.], [90., 1.]], term="positive") FS.add_linguistic_variable("Rating", sf.LinguisticVariable([S_1, S_2, S_3], concept="Rating")) S_1 = sf.FuzzySet(points=[[0., 1.], [50000., 0.]], term="small") S_2 = sf.FuzzySet(points=[[100000., 0.], [300000., 1.], [3000000., 1.], [5000000., 0.]], term="average") S_3 = sf.FuzzySet(points=[[10000000., 0.], [30000000., 1.]], term="big") FS.add_linguistic_variable("Number_of_owners", sf.LinguisticVariable([S_1, S_2, S_3], concept="Number_of_owners")) S_1 = sf.FuzzySet(points=[[0., 1.], [10., 0.]], term="cheap") S_2 = sf.FuzzySet(points=[[10., 0.], [15., 1.], [20., 1.], [25., 0.]], term="average") S_3 = sf.FuzzySet(points=[[25., 0.], [35., 1.]], term="expensive") FS.add_linguistic_variable("Price", sf.LinguisticVariable([S_1, S_2, S_3], concept="Price")) F_1 = sf.FuzzySet(points=[[200., 1.], [300., 0.]], term="short") F_2 = sf.FuzzySet(points=[[300., 0.], [360., 1.], [420., 1.], [500., 0.]], term="average") F_3 = sf.FuzzySet(points=[[500., 0.], [550., 1.]], term="long") FS.add_linguistic_variable("Game_length", sf.LinguisticVariable([F_1, F_2, F_3], concept="Game_length")) FS.set_crisp_output_value("small", 0) FS.set_crisp_output_value("average", 0.5) FS.set_crisp_output_value("big", 1) R1 = "IF (Price IS average) OR (Game_length IS average) OR (Rating IS average) OR (Number_of_owners IS average) " \ "THEN (Popularity IS average)" R2 = "IF (Price IS expensive) AND (Game_length IS long) AND (Rating IS positive) THEN (Popularity IS big)" R3 = "IF (Price IS expensive) AND (Game_length IS short) THEN (Popularity IS small)" R4 = "IF (Price IS cheap) THEN (Popularity IS big)" R5 = "IF (Rating IS negative) THEN (Popularity IS small)" R6 = "IF (Rating IS positive) AND (Number_of_owners IS small) THEN (Popularity IS average)" R7 = "IF (Rating IS average) AND (Price IS cheap) THEN (Popularity IS big)" FS.add_rules([R1, R2, R3, R4, R5, R6, R7]) FS.set_variable("Price", price) FS.set_variable("Game_length", game_length) FS.set_variable("Rating", rating) FS.set_variable("Number_of_owners", number_of_owners) popularity = FS.Sugeno_inference(["Popularity"], ignore_warnings=True) return round(popularity["Popularity"], 2) def fuzzy_controler_similiarity(categorical_data: str, numerical_data: str, vector_distance: float, show_graph: bool)\ -> float: FSS = FuzzySystem(show_banner=False) S_1 = sf.FuzzySet(points=[[.20, 1.], [.30, 0.]], term="small") S_2 = sf.FuzzySet(points=[[.30, 0.], [.55, 1.], [.65, 1.], [.85, 0.]], term="average") S_3 = sf.FuzzySet(points=[[.85, 0.], [.90, 1.]], term="big") FSS.add_linguistic_variable("Categorical_similarity", sf.LinguisticVariable([S_1, S_2, S_3], concept="Categorical similarity")) S_1 = sf.FuzzySet(points=[[.30, 1.], [.40, 0.]], term="small") S_2 = sf.FuzzySet(points=[[.40, 0.], [.50, 1.], [.60, 1.], [.70, 0.]], term="average") S_3 = sf.FuzzySet(points=[[.70, 0.], [.90, 1.]], term="big") FSS.add_linguistic_variable("Numerical_difference", sf.LinguisticVariable([S_1, S_2, S_3], concept="Numerical difference")) S_1 = sf.FuzzySet(points=[[.20, 1.], [.30, 0.]], term="small") S_2 = sf.FuzzySet(points=[[.30, 0.], [.55, 1.], [.65, 1.], [.85, 0.]], term="average") S_3 = sf.FuzzySet(points=[[.85, 0.], [.90, 1.]], term="big") FSS.add_linguistic_variable("Word_vector_distance", sf.LinguisticVariable([S_1, S_2, S_3], concept="Word vector distance")) FSS.set_crisp_output_value("small", 0) FSS.set_crisp_output_value("average", 0.5) FSS.set_crisp_output_value("big", 1) # TODO: add Word_vector_distance to rules R1 = "IF (Categorical_similarity IS average) OR (Numerical_difference IS average) THEN (Similarity IS average)" R2 = "IF (Categorical_similarity IS small) OR (Numerical_difference IS big) THEN (Similarity IS small)" R3 = "IF (Categorical_similarity IS big) OR (Numerical_difference IS small) THEN (Similarity IS big)" FSS.add_rules([R1, R2, R3]) # show graph for two variables if show_graph: plot_graphs(FS=FSS) FSS.set_variable("Categorical_similarity", vector_distance) FSS.set_variable("Numerical_difference", numerical_data) popularity = FSS.Sugeno_inference(["Similarity"], ignore_warnings=True) return round(popularity["Similarity"], 2) def plot_graphs(FS: sf.FuzzySystem): xs = [] ys = [] zs = [] for x in np.linspace(0, 1): for y in np.linspace(0, 1): FS.set_variable("Categorical_similarity", x) FS.set_variable("Numerical_difference", y) tip = FS.inference()['Similarity'] xs.append(x) ys.append(y) zs.append(tip) xs = np.array(xs) ys = np.array(ys) zs = np.array(zs) fig = plt.figure() ax = fig.add_subplot(111, projection='3d') xx, yy = plt.meshgrid(xs, ys) ax.plot_trisurf(xs, ys, zs, vmin=0, vmax=100) ax.set_xlabel("Categorical_similarity") ax.set_ylabel("Numerical_difference") ax.set_zlabel("Similarity") ax.set_zlim(0, 1) plt.tight_layout() plt.show()