2023-01-27 18:26:45 +01:00
|
|
|
import simpful as sf
|
|
|
|
import numpy as np
|
|
|
|
import matplotlib.pylab as plt
|
|
|
|
|
|
|
|
|
2023-01-29 17:25:12 +01:00
|
|
|
# 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'
|
|
|
|
|
|
|
|
|
2023-01-27 18:26:45 +01:00
|
|
|
def fuzzy_controler_popularity(price: float, game_length: int, rating: float, number_of_owners: int) -> float:
|
2023-01-29 17:25:12 +01:00
|
|
|
FS = FuzzySystem(show_banner=False)
|
2023-01-27 18:26:45 +01:00
|
|
|
|
|
|
|
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)
|
2023-01-29 17:25:12 +01:00
|
|
|
popularity = FS.Sugeno_inference(["Popularity"], ignore_warnings=True)
|
2023-01-27 18:26:45 +01:00
|
|
|
return round(popularity["Popularity"], 2)
|
|
|
|
|
|
|
|
|
|
|
|
def fuzzy_controler_similiarity(categorical_data: str, numerical_data: str, vector_distance: float, show_graph: bool)\
|
|
|
|
-> float:
|
2023-01-29 17:25:12 +01:00
|
|
|
FSS = FuzzySystem(show_banner=False)
|
2023-01-27 18:26:45 +01:00
|
|
|
|
|
|
|
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)
|
|
|
|
|
2023-01-31 19:26:24 +01:00
|
|
|
FSS.set_variable("Categorical_similarity", vector_distance)
|
2023-01-27 18:26:45 +01:00
|
|
|
FSS.set_variable("Numerical_difference", numerical_data)
|
2023-01-29 17:25:12 +01:00
|
|
|
popularity = FSS.Sugeno_inference(["Similarity"], ignore_warnings=True)
|
2023-01-27 18:26:45 +01:00
|
|
|
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()
|