struct sml_variables_list * sml_fuzzy_variables_list_new(struct sml_fuzzy *fuzzy, struct sol_vector *indexes) { fl::Engine *engine = (fl::Engine*)fuzzy->engine; uint16_t i, *idx; void *v; std::vector<fl::OutputVariable*> *changed = new (std::nothrow) std::vector<fl::OutputVariable*>(); if (!changed) { sml_critical("Could not alloc the variables list!"); return NULL; } if (indexes) { try { SOL_VECTOR_FOREACH_IDX(indexes, v, i) { idx = (uint16_t *)v; changed->push_back(engine->getOutputVariable(*idx)); } } catch (const std::out_of_range &oor) { sml_critical("Array out of bounds. error:%s", oor.what()); goto err_exit; } } return (struct sml_variables_list *)changed; err_exit: delete changed; return NULL; }
static int _sml_fuzzy_fill_membership_values(struct sml_matrix *variables, struct sml_variables_list *list) { uint16_t i, j, len; float f, *ptr; len = sml_fuzzy_variables_list_get_length(list); try { for (i = 0; i < len; i++) { struct sml_variable *variable = sml_fuzzy_variables_list_index(list, i); uint16_t terms_len = sml_fuzzy_variable_terms_count(variable); for (j = 0; j < terms_len; j++) { fl::Term *term = (fl::Term *) sml_fuzzy_variable_get_term(variable, j); f = term->membership(sml_fuzzy_variable_get_value(variable)); ptr = (float*) sml_matrix_insert(variables, i, j); if (!ptr) { sml_critical("Could not fill membership to variable"); return -ENOMEM; } *ptr = f; } } } catch (fl::Exception e) { sml_critical("%s", e.getWhat().c_str()); return SML_INTERNAL_ERROR; } return 0; }
bool sml_fuzzy_load_file(struct sml_fuzzy *fuzzy, const char *filename) { fl::Engine *engine; uint16_t i, len; void *width; try { fl::FllImporter importer; engine = importer.fromFile(filename); } catch (fl::Exception e) { sml_critical("%s", e.getWhat().c_str()); return false; } if (engine->numberOfInputVariables() == 0 || engine->numberOfOutputVariables() == 0) { sml_critical("Input and output variables must be provided!"); goto error; } if (engine->numberOfRuleBlocks() == 0) { sml_critical("Rule blocks must be provided!"); goto error; } if (fuzzy->engine) delete (fl::Engine*) fuzzy->engine; fuzzy->engine = engine; fuzzy->input_list = (struct sml_variables_list*)&(engine->inputVariables()); fuzzy->output_list = (struct sml_variables_list*)&(engine->outputVariables()); fuzzy->input_terms_count = _calc_terms_count(engine->inputVariables()); fuzzy->output_terms_count = _calc_terms_count(engine->outputVariables()); _remove_rule_blocks(engine); sol_vector_clear(&fuzzy->input_terms_width); sol_vector_clear(&fuzzy->output_terms_width); len = engine->inputVariables().size(); for (i = 0; i < len; i++) { width = sol_vector_append(&fuzzy->input_terms_width); ON_NULL_RETURN_VAL(width, false); } len = engine->outputVariables().size(); for (i = 0; i < len; i++) { width = sol_vector_append(&fuzzy->output_terms_width); ON_NULL_RETURN_VAL(width, false); } return true; error: delete engine; return false; }
bool sml_fuzzy_bridge_output_set_defuzzifier(struct sml_variable *variable, enum sml_fuzzy_defuzzifier defuzzifier, int defuzzifier_resolution) { fl::Variable *fl_var = (fl::Variable*) variable; fl::Defuzzifier *fl_defuzzifier = NULL; fl::OutputVariable *output_var = dynamic_cast<fl::OutputVariable*>(fl_var); if (!output_var) { sml_critical("Not a output variable!"); return false; } switch (defuzzifier) { case SML_FUZZY_DEFUZZIFIER_BISECTOR: fl_defuzzifier = new (std::nothrow) fl::Bisector(defuzzifier_resolution); break; case SML_FUZZY_DEFUZZIFIER_CENTROID: fl_defuzzifier = new (std::nothrow) fl::Centroid(defuzzifier_resolution); break; case SML_FUZZY_DEFUZZIFIER_LARGEST_OF_MAXIMUM: fl_defuzzifier = new (std::nothrow) fl::LargestOfMaximum(defuzzifier_resolution); break; case SML_FUZZY_DEFUZZIFIER_MEAN_OF_MAXIMUM: fl_defuzzifier = new (std::nothrow) fl::MeanOfMaximum(defuzzifier_resolution); break; case SML_FUZZY_DEFUZZIFIER_SMALLEST_OF_MAXIMUM: fl_defuzzifier = new (std::nothrow) fl::SmallestOfMaximum(defuzzifier_resolution); break; case SML_FUZZY_DEFUZZIFIER_WEIGHTED_AVERAGE: fl_defuzzifier = new (std::nothrow) fl::WeightedAverage(); break; case SML_FUZZY_DEFUZZIFIER_WEIGHTED_SUM: fl_defuzzifier = new (std::nothrow) fl::WeightedSum(); break; default: sml_critical("Unknown defuzzifier %d", defuzzifier); } if (!fl_defuzzifier) { sml_critical("Failed to create defuzzifier"); return false; } output_var->setDefuzzifier(fl_defuzzifier); return true; }
static fl::SNorm * _get_snorm(enum sml_fuzzy_snorm norm) { fl::SNorm *fl_norm; switch (norm) { case SML_FUZZY_SNORM_ALGEBRAIC_SUM: sml_debug("SNorm is algebraic sum"); fl_norm = new (std::nothrow) fl::AlgebraicSum(); break; case SML_FUZZY_SNORM_BOUNDED_SUM: sml_debug("SNorm is bounded sum"); fl_norm = new (std::nothrow) fl::BoundedSum(); break; case SML_FUZZY_SNORM_DRASTIC_SUM: sml_debug("SNorm is drastic sum"); fl_norm = new (std::nothrow) fl::DrasticSum(); break; case SML_FUZZY_SNORM_EINSTEIN_SUM: sml_debug("SNorm is einstein sum"); fl_norm = new (std::nothrow) fl::EinsteinSum(); break; case SML_FUZZY_SNORM_HAMACHER_SUM: sml_debug("SNorm is hamacher sum"); fl_norm = new (std::nothrow) fl::HamacherSum(); break; case SML_FUZZY_SNORM_MAXIMUM: sml_debug("SNorm is maximum"); fl_norm = new (std::nothrow) fl::Maximum(); break; case SML_FUZZY_SNORM_NILPOTENT_MAXIMUM: sml_debug("SNorm is nilpotent maximum"); fl_norm = new (std::nothrow) fl::NilpotentMaximum(); break; case SML_FUZZY_SNORM_NORMALIZED_SUM: sml_debug("SNorm is normalized sum"); fl_norm = new (std::nothrow) fl::NormalizedSum(); break; default: sml_critical("Unknown SNorm %d", norm); return NULL; } if (!fl_norm) sml_critical("Could not alloc the snorm"); return fl_norm; }
API_EXPORT bool sml_fuzzy_set_variable_terms_auto_balance(struct sml_object *sml, bool variable_terms_auto_balance) { sml_critical("Fuzzy engine not supported."); return false; }
bool sml_fuzzy_remove_variable(struct sml_fuzzy *fuzzy, struct sml_variable *variable) { fl::Variable *fl_var = (fl::Variable*) variable; fl::Variable *removed_var = NULL; fl::Engine *engine = (fl::Engine*)fuzzy->engine; uint16_t index; bool ret = true; if (_find_variable((std::vector<fl::Variable*> *) fuzzy->input_list, fl_var, &index)) { removed_var = engine->removeInputVariable(index); fuzzy->input_terms_count -= removed_var->numberOfTerms(); if (sol_vector_del(&fuzzy->input_terms_width, index)) ret = false; } else if (_find_variable((std::vector<fl::Variable*> *) fuzzy->output_list, fl_var, &index)) { removed_var = engine->removeOutputVariable(index); fuzzy->output_terms_count -= removed_var->numberOfTerms(); if (sol_vector_del(&fuzzy->output_terms_width, index)) ret = false; } else { sml_critical("Variable is not a valid input or output"); return false; } delete removed_var; return ret; }
struct sml_fuzzy_term* sml_fuzzy_bridge_variable_add_term_cosine(struct sml_fuzzy *fuzzy, struct sml_variable *variable, const char *name, float center, float width) { fl::Variable *fl_var = (fl::Variable*) variable; fl::Term *term; if (!_check_name(name)) return NULL; term = new (std::nothrow) fl::Cosine(name, center, width, 1.0); if (!term) { sml_critical("Failed to create term"); return NULL; } if (sml_fuzzy_is_input(fuzzy, variable, NULL)) fuzzy->input_terms_count++; else if (sml_fuzzy_is_output(fuzzy, variable, NULL)) fuzzy->output_terms_count++; else { delete term; return NULL; } fl_var->addTerm(term); return (struct sml_fuzzy_term *) term; }
static bool _sml_ann_bridge_calculate_confidence_interval(struct sml_ann_bridge *iann, struct sml_variables_list *inputs, unsigned int observations) { unsigned int i, j, inputs_len; float mean, sd, value; struct sml_variable *var; Confidence_Interval *ci; char var_name[SML_VARIABLE_NAME_MAX_LEN + 1]; sml_debug("Calculating confidence interval"); inputs_len = sml_ann_variables_list_get_length(inputs); for (i = 0; i < inputs_len; i++) { mean = sd = 0.0; var = sml_ann_variables_list_index(inputs, i); ci = sol_vector_append(&iann->confidence_intervals); if (!ci) { sml_critical("Could not alloc the Confidence_Interval"); goto err_exit; } for (j = 0; j < observations; j++) { value = sml_ann_variable_get_value_by_index(var, j); if (isnan(value)) sml_ann_variable_get_range(var, &value, NULL); mean += value; } mean /= observations; //Now the standard deviation for (j = 0; j < observations; j++) { value = sml_ann_variable_get_value_by_index(var, j); if (isnan(value)) sml_ann_variable_get_range(var, &value, NULL); sd += pow(value - mean, 2.0); } sd /= observations; sd = sqrt(sd); //Confidence interval of 95% ci->lower_limit = mean - (1.96 * (sd / sqrt(observations))); ci->upper_limit = mean + (1.96 * (sd / sqrt(observations))); iann->ci_length_sum += (ci->upper_limit - ci->lower_limit); if (sml_ann_variable_get_name(var, var_name, sizeof(var_name))) { sml_warning("Failed to get variable name for %p", var); continue; } sml_debug("Variable:%s mean:%f sd:%f lower:%f upper:%f", var_name, mean, sd, ci->lower_limit, ci->upper_limit); } return true; err_exit: sol_vector_clear(&iann->confidence_intervals); return false; }
API_EXPORT bool sml_fuzzy_set_rule_weight_threshold(struct sml_object *sml, float weight_threshold) { sml_critical("Fuzzy engine not supported."); return false; }
bool sml_matrix_equals(struct sml_matrix *m1, struct sml_matrix *m2, struct sol_vector *changed, sml_cmp_cb cmp_cb) { uint16_t i, j, len_i, len_j, *idx; struct sol_vector *vec1, *vec2; bool r = false; len_i = max(m1->data.len, m2->data.len); for (i = 0; i < len_i; i++) { vec1 = sol_vector_get(&m1->data, i); vec2 = sol_vector_get(&m2->data, i); len_j = max((vec1 ? vec1->len : 0), (vec2 ? vec2->len : 0)); for (j = 0; j < len_j; j++) { if (!cmp_cb(sol_vector_get(vec1, j), sol_vector_get(vec2, j))) { if (changed) { idx = sol_vector_append(changed); if (!idx) { sml_critical("Could not append the index:%d to the" \ " changed vector", i); return false; } *idx = i; } r = true; break; } } } return r; }
struct sml_fuzzy_term* sml_fuzzy_bridge_variable_add_term_gaussian(struct sml_fuzzy *fuzzy, struct sml_variable *variable, const char *name, float mean, float standard_deviation) { fl::Variable *fl_var = (fl::Variable*) variable; fl::Term *term; if (!_check_name(name)) return NULL; term = new (std::nothrow) fl::Gaussian(name, mean, standard_deviation, 1.0); if (!term) { sml_critical("Failed to create term"); return NULL; } if (sml_fuzzy_is_input(fuzzy, variable, NULL)) fuzzy->input_terms_count++; else if (sml_fuzzy_is_output(fuzzy, variable, NULL)) fuzzy->output_terms_count++; else { delete term; return NULL; } fl_var->addTerm(term); return (struct sml_fuzzy_term *) term; }
API_EXPORT bool sml_fuzzy_variable_remove_term(struct sml_object *sml, struct sml_variable *var, struct sml_fuzzy_term *term) { sml_critical("Fuzzy engine not supported."); return false; }
API_EXPORT bool sml_fuzzy_output_set_default_value(struct sml_object *sml, struct sml_variable *var, float default_value) { sml_critical("Fuzzy engine not supported."); return false; }
API_EXPORT bool sml_fuzzy_output_set_accumulation(struct sml_object *sml, struct sml_variable *var, enum sml_fuzzy_snorm accumulation) { sml_critical("Fuzzy engine not supported."); return false; }
API_EXPORT bool sml_fuzzy_output_set_defuzzifier(struct sml_object *sml, struct sml_variable *var, enum sml_fuzzy_defuzzifier defuzzifier, int defuzzifier_resolution) { sml_critical("Fuzzy engine not supported."); return false; }
API_EXPORT struct sml_fuzzy_term * sml_fuzzy_variable_add_term_gaussian(struct sml_object *sml, struct sml_variable *variable, const char *name, float mean, float standard_deviation, float height) { sml_critical("Fuzzy engine not supported."); return NULL; }
API_EXPORT struct sml_fuzzy_term * sml_fuzzy_variable_add_term_cosine(struct sml_object *sml, struct sml_variable *variable, const char *name, float center, float width, float height) { sml_critical("Fuzzy engine not supported."); return NULL; }
API_EXPORT struct sml_fuzzy_term * sml_fuzzy_variable_add_term_rectangle(struct sml_object *sml, struct sml_variable *variable, const char *name, float start, float end, float height) { sml_critical("Fuzzy engine not supported."); return NULL; }
int main(int argc, char **argv) { Air_Conditioner_Controller acc; struct sml_variable *temp, *presence, *power; struct sml_object *sml; _initialize_acc(&acc); if (argc != 2) { fprintf(stderr, "Usage: %s <engine_type (0 fuzzy, 1 ann)>\n", argv[0]); fprintf(stderr, "Fuzzy Test: %s 0\n", argv[0]); fprintf(stderr, "Ann Test: %s 1\n", argv[0]); return -1; } sml = _sml_new(atoi(argv[1])); if (!sml) { sml_critical("Failed to create sml"); return -1; } sml_main_loop_init(); //Set stabilization hits and initial required obs to a low value because //this is a simulation and we don't want to wait for a long time before //getting interesting results sml_set_stabilization_hits(sml, STABILIZATION_HITS); sml_ann_set_initial_required_observations(sml, INITIAL_REQUIRED_OBS); //Create temperature input temp = sml_new_input(sml, "Temperature"); sml_variable_set_range(sml, temp, 0, 48); sml_fuzzy_variable_set_default_term_width(sml, temp, 16); //Create presence input presence = sml_new_input(sml, "Presence"); sml_variable_set_range(sml, presence, 0, 1); sml_fuzzy_variable_set_default_term_width(sml, presence, 0.5); //Create power output power = sml_new_output(sml, "Power"); sml_variable_set_range(sml, power, 0, 3); sml_fuzzy_variable_set_default_term_width(sml, power, 1); sml_fuzzy_variable_set_is_id(sml, power, true); //set SML callbacks sml_set_read_state_callback(sml, _read_state_cb, &acc); sml_main_loop_schedule_sml_process(sml, READ_TIMEOUT); sml_set_output_state_changed_callback(sml, _output_state_changed_cb, &acc); sml_main_loop_run(); sml_free(sml); sml_main_loop_shutdown(); return 0; }
static fl::TNorm * _get_tnorm(enum sml_fuzzy_tnorm norm) { fl::TNorm *fl_norm; switch (norm) { case SML_FUZZY_TNORM_ALGEBRAIC_PRODUCT: sml_debug("Conjunction set to algebraic product"); fl_norm = new (std::nothrow) fl::AlgebraicProduct(); break; case SML_FUZZY_TNORM_BOUNDED_DIFFERENCE: sml_debug("Conjunction set to bounded difference"); fl_norm = new (std::nothrow) fl::BoundedDifference(); break; case SML_FUZZY_TNORM_DRASTIC_PRODUCT: sml_debug("Conjunction set to drastic product"); fl_norm = new (std::nothrow) fl::DrasticProduct(); break; case SML_FUZZY_TNORM_EINSTEIN_PRODUCT: sml_debug("Conjunction set to einstein product"); fl_norm = new (std::nothrow) fl::EinsteinProduct(); break; case SML_FUZZY_TNORM_HAMACHER_PRODUCT: sml_debug("Conjunction set to hamacher product"); fl_norm = new (std::nothrow) fl::HamacherProduct(); break; case SML_FUZZY_TNORM_MINIMUM: sml_debug("Conjunction set to minimum"); fl_norm = new (std::nothrow) fl::Minimum(); break; case SML_FUZZY_TNORM_NILPOTENT_MINIMUM: sml_debug("Conjunction set to nilpotent minimum"); fl_norm = new (std::nothrow) fl::NilpotentMinimum(); break; default: sml_critical("Unknown TNorm %d", norm); return NULL; } if (!fl_norm) sml_critical("Could not alloc the tnorm"); return fl_norm; }
int sml_fuzzy_process_output(struct sml_fuzzy *fuzzy) { fl::Engine *engine = (fl::Engine*)fuzzy->engine; try { engine->process(); } catch (fl::Exception e) { sml_critical("%s", e.getWhat().c_str()); return SML_INTERNAL_ERROR; } return 0; }
static struct sml_ann_bridge * _sml_ann_bridge_new(struct fann *ann, bool trained) { struct sml_ann_bridge *iann = calloc(1, sizeof(struct sml_ann_bridge)); if (!iann) { sml_critical("Could not create an struct sml_ann_bridge"); return NULL; } sol_vector_init(&iann->confidence_intervals, sizeof(Confidence_Interval)); iann->ann = ann; iann->trained = trained; iann->last_train_error = NAN; return iann; }
bool sml_fuzzy_bridge_output_set_accumulation(struct sml_variable *variable, enum sml_fuzzy_snorm accumulation) { fl::Variable *fl_var = (fl::Variable*) variable; fl::OutputVariable *output_var = dynamic_cast<fl::OutputVariable*>(fl_var); if (!output_var) { sml_critical("Not a output variable!"); return false; } output_var->fuzzyOutput()->setAccumulation(_get_snorm(accumulation)); return true; }
struct sml_fuzzy * sml_fuzzy_bridge_new(void) { struct sml_fuzzy *fuzzy = (struct sml_fuzzy *) calloc(1, sizeof(struct sml_fuzzy)); fl::Engine *engine = NULL; if (!fuzzy) { sml_critical("Failed to create fuzzy"); return NULL; } engine = new (std::nothrow) fl::Engine(); if (!engine) goto new_error; if (!_create_rule_block(engine)) { sml_critical("Could not alloc the rule block"); goto new_error; } engine->setName("EngineDefault"); fuzzy->engine = engine; fuzzy->input_list = (struct sml_variables_list*) &(engine->inputVariables()); fuzzy->output_list = (struct sml_variables_list*) &(engine->outputVariables()); sol_vector_init(&fuzzy->input_terms_width, sizeof(struct terms_width)); sol_vector_init(&fuzzy->output_terms_width, sizeof(struct terms_width)); return fuzzy; new_error: free(fuzzy); delete engine; return NULL; }
bool sml_fuzzy_bridge_conjunction_set(struct sml_fuzzy *fuzzy, enum sml_fuzzy_tnorm norm) { fl::TNorm *fl_norm = _get_tnorm(norm); fl::Engine *engine = (fl::Engine*)fuzzy->engine; if (!fl_norm) return false; if (!_create_rule_block(engine)) { sml_critical("Could not alloc the rule block"); return false; } engine->getRuleBlock(0)->setConjunction(fl_norm); return true; }
struct sml_fuzzy_rule * sml_fuzzy_rule_add(struct sml_fuzzy *fuzzy, const char *rule) { fl::Engine *engine = (fl::Engine*)fuzzy->engine; fl::RuleBlock *block = engine->getRuleBlock(0); fl::Rule *rule_obj; try { rule_obj = fl::Rule::parse(rule, engine); block->addRule(rule_obj); } catch (fl::Exception e) { sml_critical("%s", e.getWhat().c_str()); return NULL; } return (struct sml_fuzzy_rule *) rule_obj; }
API_EXPORT struct sml_object * sml_fuzzy_new(void) { sml_critical("Fuzzy engine not supported."); return NULL; }
API_EXPORT bool sml_is_fuzzy(struct sml_object *sml) { sml_critical("Fuzzy engine not supported."); return false; }
API_EXPORT bool sml_fuzzy_disjunction_set(struct sml_object *sml, enum sml_fuzzy_snorm norm) { sml_critical("Fuzzy engine not supported."); return false; }