import numpy as np import skfuzzy as fuzz import matplotlib.pyplot as plt # Generate universe variables # * Quality and service on subjective ranges [0, 10] # * Tip has a range of [0, 25] in units of percentage points goals = np.arange(0, 35, 1) xGPerMatch = np.arange(0, 1, 0.01) shotsPerMatch=np.arange(0, 5, 0.01) onTargetPerMatch = np.arange(0, 5, 0.01) ocena=np.arange(0, 101, 1) # Generate fuzzy membership functions goals_low = fuzz.trapmf(goals, [0, 0, 10,15]) goals_md = fuzz.trimf(goals, [10, 15, 20]) goals_hi = fuzz.trapmf(goals, [15, 20, 35, 100]) xGPerMatch_lo = fuzz.trapmf(xGPerMatch, [0,0, 0.2, 0.5]) xGPerMatch_md = fuzz.trimf(xGPerMatch, [0.2, 0.5, 0.7]) xGPerMatch_hi = fuzz.trapmf(xGPerMatch, [0.5, 0.7, 2, 10]) shotsPerMatch_lo = fuzz.trapmf(shotsPerMatch, [0,0, 1, 2]) shotsPerMatch_md = fuzz.trapmf(shotsPerMatch, [1, 2, 3, 4]) shotsPerMatch_hi = fuzz.trapmf(shotsPerMatch, [3, 4, 4.5, 10]) onTargetPerMatch_lo = fuzz.trapmf(onTargetPerMatch, [0, 0, 0.5, 1]) onTargetPerMatch_md = fuzz.trimf(onTargetPerMatch, [0.5, 1, 1.5]) onTargetPerMatch_hi = fuzz.trimf(onTargetPerMatch, [1, 1.5, 5]) ocena_lo = fuzz.trapmf(ocena, [0, 0, 40,50]) ocena_md = fuzz.trapmf(ocena, [40, 50, 60, 80]) ocena_hi = fuzz.trapmf(ocena, [70, 80, 100, 100]) # Visualize these universes and membership functions fig, (ax0, ax1, ax2, ax3, ax4) = plt.subplots(nrows=5, figsize=(8, 9)) ax0.plot(goals, goals_low, 'b', linewidth=1.5, label='Mało') ax0.plot(goals, goals_md, 'g', linewidth=1.5, label='Średnio') ax0.plot(goals, goals_hi, 'r', linewidth=1.5, label='Dużo') ax0.set_title('Liczba bramek') ax0.legend() ax1.plot(xGPerMatch, xGPerMatch_lo, 'b', linewidth=1.5, label='Mało') ax1.plot(xGPerMatch, xGPerMatch_md, 'g', linewidth=1.5, label='Średno') ax1.plot(xGPerMatch, xGPerMatch_hi, 'r', linewidth=1.5, label='Dużo') ax1.set_title('Service quality') ax1.legend() ax2.plot(shotsPerMatch, shotsPerMatch_lo, 'b', linewidth=1.5, label='Mało') ax2.plot(shotsPerMatch, shotsPerMatch_md, 'g', linewidth=1.5, label='Średnio') ax2.plot(shotsPerMatch, shotsPerMatch_hi, 'r', linewidth=1.5, label='Dużo') ax2.set_title('Strzały na mecz') ax2.legend() ax3.plot(onTargetPerMatch, onTargetPerMatch_lo, 'b', linewidth=1.5, label='Mało') ax3.plot(onTargetPerMatch, onTargetPerMatch_md, 'g', linewidth=1.5, label='Średnio') ax3.plot(onTargetPerMatch, onTargetPerMatch_hi, 'r', linewidth=1.5, label='Dużo') ax3.set_title('Strzały w światlo bramki na mecz') ax3.legend() ax4.plot(ocena, ocena_lo, 'b', linewidth=1.5, label='Niska') ax4.plot(ocena, ocena_md, 'g', linewidth=1.5, label='Średnia') ax4.plot(ocena, ocena_hi, 'r', linewidth=1.5, label='Wysoka') ax4.set_title('Ocena') ax4.legend() # Turn off top/right axes for ax in (ax0, ax1, ax2, ax3, ax4): ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) ax.get_xaxis().tick_bottom() ax.get_yaxis().tick_left() plt.tight_layout() plt.show() goals_value=22 xGPerMatch_value=0.9 shotsPerMatch_value=4.43 onTargetPerMatch_value=1.57 goals_level_lo = fuzz.interp_membership(goals, goals_low, goals_value) goals_level_md = fuzz.interp_membership(goals, goals_md, goals_value) goals_level_hi = fuzz.interp_membership(goals, goals_hi, goals_value) xGPerMatch_level_lo = fuzz.interp_membership(xGPerMatch, xGPerMatch_lo, xGPerMatch_value) xGPerMatch_level_md = fuzz.interp_membership(xGPerMatch, xGPerMatch_md, xGPerMatch_value) xGPerMatch_level_hi = fuzz.interp_membership(xGPerMatch, xGPerMatch_hi, xGPerMatch_value) shotsPerMatch_level_lo = fuzz.interp_membership(shotsPerMatch, shotsPerMatch_lo, shotsPerMatch_value) shotsPerMatch_level_md = fuzz.interp_membership(shotsPerMatch, shotsPerMatch_md, shotsPerMatch_value) shotsPerMatch_level_hi = fuzz.interp_membership(shotsPerMatch, shotsPerMatch_hi, shotsPerMatch_value) onTargetPerMatch_level_lo = fuzz.interp_membership(onTargetPerMatch, onTargetPerMatch_lo, onTargetPerMatch_value) onTargetPerMatch_level_md = fuzz.interp_membership(onTargetPerMatch, onTargetPerMatch_md, onTargetPerMatch_value) onTargetPerMatch_level_hi = fuzz.interp_membership(onTargetPerMatch, onTargetPerMatch_hi, onTargetPerMatch_value) # Now we take our rules and apply them. Rule 1 concerns bad food OR service. # The OR operator means we take the maximum of these two. active_rule1 = np.fmax(goals_level_hi, xGPerMatch_level_hi) active_rule2=np.fmax(active_rule1, onTargetPerMatch_level_hi) # Now we apply this by clipping the top off the corresponding output # membership function with `np.fmin` ocena_activation_hi = np.fmin(active_rule2, ocena_hi) # removed entirely to 0 # For rule 2 we connect acceptable service to medium tipping active_rule3=np.fmax(np.fmin(goals_level_lo,xGPerMatch_level_hi),np.fmin(goals_level_lo, shotsPerMatch_level_hi)) ocena_activation_md = np.fmin(active_rule2, ocena_md) # For rule 3 we connect high service OR high food with high tipping ocena_activation_lo = np.fmin(goals_level_lo, ocena_lo) ocena0 = np.zeros_like(ocena) # Visualize this fig, ax0 = plt.subplots(figsize=(8, 3)) ax0.fill_between(ocena, ocena0, ocena_activation_lo, facecolor='b', alpha=0.7) ax0.plot(ocena, ocena_lo, 'b', linewidth=0.5, linestyle='--', ) ax0.fill_between(ocena, ocena0, ocena_activation_md, facecolor='g', alpha=0.7) ax0.plot(ocena, ocena_md, 'g', linewidth=0.5, linestyle='--') ax0.fill_between(ocena, ocena0, ocena_activation_hi, facecolor='r', alpha=0.7) ax0.plot(ocena, ocena_hi, 'r', linewidth=0.5, linestyle='--') ax0.set_title('Output membership activity') # Turn off top/right axes for ax in (ax0,): ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) ax.get_xaxis().tick_bottom() ax.get_yaxis().tick_left() plt.tight_layout() plt.show() aggregated = np.fmax(ocena_activation_lo, np.fmax(ocena_activation_md, ocena_activation_hi)) # Calculate defuzzified result ocena_output = fuzz.defuzz(ocena, aggregated, 'centroid') ocena_activation = fuzz.interp_membership(ocena, aggregated, ocena_output) # for plot # Visualize this fig, ax0 = plt.subplots(figsize=(8, 3)) ax0.plot(ocena, ocena_lo, 'b', linewidth=0.5, linestyle='--', ) ax0.plot(ocena, ocena_md, 'g', linewidth=0.5, linestyle='--') ax0.plot(ocena, ocena_hi, 'r', linewidth=0.5, linestyle='--') ax0.fill_between(ocena, ocena0, aggregated, facecolor='Orange', alpha=0.7) ax0.plot([ocena_output, ocena_output], [0, ocena_activation], 'k', linewidth=1.5, alpha=0.9) ax0.set_title('Aggregated membership and result (line)') # Turn off top/right axes for ax in (ax0,): ax.spines['top'].set_visible(False) ax.spines['right'].set_visible(False) ax.get_xaxis().tick_bottom() ax.get_yaxis().tick_left() plt.tight_layout() plt.show() print(ocena_output)