Source code for ex_fuzzy.persistence

'''
Load the rules of a fuzzy rules system using plain text format.

'''
import numpy as np
import re

modifier_string_pattern = r'\(MOD\s+(\w+)\)'

try:
    from . import fuzzy_sets as fs
    from . import rules
    from . import maintenance as mnt

except ImportError:
    import fuzzy_sets as fs
    import rules
    import maintenance as mnt


def _extract_mod_word(text):
    pattern = r'\(MOD\s+([^)]+)\)'
    match = re.search(pattern, text)
    if match:
        return match.group(1)
    return None


def _remove_mod_completely(text):
    pattern = r'\(MOD\s+([^)]+)\)'
    replacement = ''
    return re.sub(pattern, replacement, text)


import re

def remove_parentheses(text):
    return re.sub(r'\(.*?\)', '', text)


[docs] def load_fuzzy_rules(rules_printed: str, fuzzy_variables: list) -> rules.MasterRuleBase: ''' Load the rules from a string. :param rules_printed: string with the rules. Follows the specification given by the same printing method of rules.MasterRuleBase :param fuzzy_variables: list with the linguistic variables. Objects of FuzzyVariable class. :return mrule_base: object of MasterRuleBase class that contains the rules. ''' if mnt.save_usage_flag: mnt.usage_data[mnt.usage_categories.Persistence]['persistence_read'] += 1 consequent = 0 linguistic_variables_names = [linguistic_variable.name for linguistic_variable in fuzzy_variables] value_names = [x.name for x in fuzzy_variables[0]] fz_type = fuzzy_variables[0].fuzzy_type() consequent_names = [] detected_modifiers = False for line in rules_printed.splitlines(): if line.startswith('IF'): #Is a rule antecedents , consequent_ds = line.split('WITH') # Try to look for weight and accuracy in the rule rule_acc = None rule_weight = None for jx, stat in enumerate(consequent_ds.split(',')): if 'ACC' in stat: rule_acc = stat.strip() elif 'WGHT' in stat: rule_weight = stat.strip() consequent_ds = remove_parentheses(consequent_ds) consequent_ds = consequent_ds.split(',')[0].strip() modifiers = np.ones((len(fuzzy_variables),)) init_rule_antecedents = np.zeros( (len(fuzzy_variables),)) - 1 # -1 is dont care for lx, antecedent in enumerate(antecedents.split('AND')): antecedent = antecedent.replace('IF', '').strip() if 'MOD' in antecedent: detected_modifiers = True modifier_value = _extract_mod_word(antecedent) antecedent = _remove_mod_completely(antecedent) if modifier_value in rules.modifiers_names.keys(): modifiers[lx] = rules.modifiers_names[modifier_value] antecedent_name, antecedent_value = antecedent.split('IS') antecedent_name = antecedent_name.strip() antecedent_value = antecedent_value.strip() antecedent_index = linguistic_variables_names.index(antecedent_name) antecedent_value_index = value_names.index(antecedent_value) init_rule_antecedents[antecedent_index] = antecedent_value_index rule_simple = rules.RuleSimple(init_rule_antecedents, 0) rule_simple.score = float(consequent_ds[3:].strip()) # We remove the 'DS ' and the last space rule_simple.accuracy = float(rule_acc[4:].strip()) # We remove the 'ACC ' and the last space try: rule_simple.weight = float(rule_weight[4:].strip()) ds_mode = 2 except: ds_mode = 0 rule_simple.modifiers = modifiers reconstructed_rules.append(rule_simple) elif line.startswith('Rules'): #New consequent consequent_name = line.split(':')[-1].strip() consequent_names.append(consequent_name) if consequent > 0: if fz_type == fs.FUZZY_SETS.t1: rule_base = rules.RuleBaseT1(fuzzy_variables, reconstructed_rules) elif fz_type == fs.FUZZY_SETS.t2: rule_base = rules.RuleBaseT2(fuzzy_variables, reconstructed_rules) elif fz_type == fs.FUZZY_SETS.gt2: rule_base = rules.RuleBaseGT2(fuzzy_variables, reconstructed_rules) if consequent == 1: mrule_base = rules.MasterRuleBase([rule_base], ds_mode=ds_mode) elif consequent > 1: mrule_base.add_rule_base(rule_base) reconstructed_rules = [] consequent += 1 # We add the last rule base if fz_type == fs.FUZZY_SETS.t1: rule_base = rules.RuleBaseT1(fuzzy_variables, reconstructed_rules) elif fz_type == fs.FUZZY_SETS.t2: rule_base = rules.RuleBaseT2(fuzzy_variables, reconstructed_rules) elif fz_type == fs.FUZZY_SETS.gt2: rule_base = rules.RuleBaseGT2(fuzzy_variables, reconstructed_rules) mrule_base.add_rule_base(rule_base) mrule_base.rename_cons(consequent_names) return mrule_base
[docs] def load_fuzzy_variables(fuzzy_variables_printed: str) -> list: ''' Load the linguistic variables from a string. :param fuzzy_variables_printed: string with the linguistic variables. Follows the specification given by the same printing method of FuzzyVariable class. :return fuzzy_variables: list with the linguistic variables. Objects of FuzzyVariable class. ''' if mnt.save_usage_flag: mnt.usage_data[mnt.usage_categories.Persistence]['persistence_read'] += 1 fuzzy_set_type = fs.FUZZY_SETS.t1 fuzzy_variables = [] active_linguistic_variables = False for line in fuzzy_variables_printed.splitlines(): if line.startswith('$$$') or line.startswith('$Fuzzy'): #New linguistic variable if active_linguistic_variables: object_fvar = fs.fuzzyVariable(linguistic_variable_name, linguistic_var_fuzzy_sets, fvar_units) fuzzy_variables.append(object_fvar) linguistic_var_fuzzy_sets = [] linguistic_variable_name = line.split(':')[1].strip() try: fvar_units = line.split(':')[2].strip() except: fvar_units = None active_linguistic_variables = True elif line == '': pass else: processes_line = line.split(';') if processes_line[1] == 'Categorical': categories = processes_line[0].split(',') if fuzzy_set_type == fs.FUZZY_SETS.t1: fscat_categories = [fs.categoricalFS(category, category) for category in categories] elif fuzzy_set_type == fs.FUZZY_SETS.t2: fscat_categories = [fs.categoricalFS(category, category) for category in categories] #We know there is one categorical variable active for fscat in fscat_categories: linguistic_var_fuzzy_sets.append(fscat) else: #We know there is one fuzzy variable active fields = processes_line if len(fields) == 4: name, domain, membership_type, mem1 = fields elif len(fields) > 4: name, domain, membership_type, mem1, mem2, height = fields fuzzy_set_type = fs.FUZZY_SETS.t2 mem2 = [float(x) for x in mem2.split(',')] height = float(height) domain = [float(x) for x in domain.split(',')] mem = [float(x) for x in mem1.split(',')] if membership_type == 'gauss': if fuzzy_set_type == fs.FUZZY_SETS.t1: constructed_fs = fs.gaussianFS(name, mem, domain) elif fuzzy_set_type == fs.FUZZY_SETS.t2: constructed_fs = fs.gaussianIVFS(name, mem1, mem2, domain, height) elif membership_type == 'trap': if fuzzy_set_type == fs.FUZZY_SETS.t1: constructed_fs = fs.FS(name, mem, domain) elif fuzzy_set_type == fs.FUZZY_SETS.t2: constructed_fs = fs.IVFS(name, mem, mem2, domain, height) linguistic_var_fuzzy_sets.append(constructed_fs) if active_linguistic_variables: object_fvar = fs.fuzzyVariable(linguistic_variable_name, linguistic_var_fuzzy_sets, fvar_units) fuzzy_variables.append(object_fvar) return fuzzy_variables
[docs] def save_fuzzy_variables(fuzzy_variables: list) -> str: ''' Save the linguistic variables to a string. :param fuzzy_variables: list with the linguistic variables. Objects of FuzzyVariable class. :return fuzzy_variables_printed: string with the linguistic variables. Follows the specification given by the same printing method of FuzzyVariable class. ''' if mnt.save_usage_flag: mnt.usage_data[mnt.usage_categories.Persistence]['persistence_write'] += 1 fuzzy_variables_printed = '' for fvar in fuzzy_variables: fuzzy_variables_printed += print_fuzzy_variable(fvar) + '\n' return fuzzy_variables_printed