#define _XOPEN_SOURCE 500 #include "utility.h" #include #include void utility_score_init(struct utility_score *u_s, char *option, double value) { u_s->option = strdup(option); u_s->value = value; } void utility_score_destroy(struct utility_score *u_s) { free(u_s->option); } int compare_utility_scores(const void *e1, const void *e2) { const struct utility_score *us1 = e1; const struct utility_score *us2 = e2; if(us1->value < us2->value) { return 1; } else if(us1->value > us2->value) { return -1; } else { return 0; } } //MAKE A ARC_VALUE COPY FUNCTION static void copy_value(struct arc_value *value, struct arc_value *copy) { copy->type = value->type; switch (copy->type) { case V_INT: copy->v_int = value->v_int; break; case V_DOUBLE: copy->v_dbl = value->v_dbl; break; case V_STRING: copy->v_str = strdup(value->v_str); break; default: copy->v_int = value->v_int; break; } } void decision_alternative_init(struct decision_alternative *a, char *name, struct arc_value *values, size_t n_v) { //Do we want to copy the values? Otherwise this cannot be allocated on the stack a->name = strdup(name); a->values = malloc(n_v*sizeof(struct arc_value)); for(size_t i = 0; i < n_v ; i++) { copy_value(&values[i], &a->values[i]); } a->num_values = n_v; a->utility = 0; } void decision_alternative_cleanup(struct decision_alternative *a) { free(a->name); for(size_t i = 0 ; i < a->num_values;i++) { if(a->values[i].type == V_STRING) { free(a->values[i].v_str); } } free(a->values); } void utility_concern_init(struct utility_concern *u_c, char *name, double weight, value_fn u_f) { u_c->name = strdup(name); u_c->weight = weight; u_c->u_f = u_f; } void utility_concern_destroy(struct utility_concern *u_c) { free(u_c->name); } void utility_decision_init(struct utility_decision *u_d, size_t max_concerns) { u_d->max_concerns = max_concerns; u_d->num_concerns = 0; u_d->concerns = malloc(u_d->max_concerns * sizeof(struct utility_concern)); u_d->max_alternatives = MAX_INIT_ALTERNATIVES; u_d->options = malloc(u_d->max_alternatives * sizeof(struct decision_alternative)); u_d->num_alternatives = 0; } void utility_decision_destroy(struct utility_decision *u_d) { for(size_t i = 0 ; i < u_d->num_concerns; i++) { utility_concern_destroy(&u_d->concerns[i]); } free(u_d->concerns); for(size_t i = 0 ; i < u_d->num_alternatives;i++) { decision_alternative_cleanup(&u_d->options[i]); } free(u_d->options); } bool utility_decision_add_concern(struct utility_decision *u_d, char *name, double weight, value_fn fn) { if(u_d->num_concerns >= u_d->max_concerns) { //We're full so do nothing return false; } utility_concern_init(&u_d->concerns[u_d->num_concerns], name, weight,fn); u_d->num_concerns++; return true; } bool utility_decision_add_option(struct utility_decision *u_d, char *name, struct arc_value *vals, size_t n_v) { if(n_v != u_d->num_concerns) { return false; } if(u_d->num_alternatives >= u_d->max_alternatives) { u_d->max_alternatives *=2; size_t nbytes = u_d->max_alternatives*sizeof(struct decision_alternative); //Buggy if realloc fails u_d->options = realloc(u_d->options, nbytes); } decision_alternative_init(&u_d->options[u_d->num_alternatives], name, vals, u_d->num_concerns); u_d->num_alternatives++; return true; } void decision_alternative_eval(struct decision_alternative *a, struct utility_decision *d) { if(d->max_concerns != a->num_values) { return; } a->utility = 0; for(size_t i = 0 ; i < d->max_concerns;i++) { a->utility += d->concerns[i].weight*d->concerns[i].u_f(&a->values[i]); } } void utility_decision_clear_options(struct utility_decision *u_d) { //Do we need to do any cleanup here? for(size_t i = 0; i < u_d->num_alternatives;i++) { decision_alternative_cleanup(&u_d->options[i]); } u_d->num_alternatives = 0; } static int cmp_options(const void *o1, const void *o2) { const struct decision_alternative *a1 = o1; const struct decision_alternative *a2 = o2; if(a1->utility < a2->utility) { return 1; } else if (a1->utility > a2->utility) { return -1; } else { return 0; } } void utility_decision_rank(struct utility_decision *u_d) { for(size_t i = 0 ; i < u_d->max_alternatives; i++) { decision_alternative_eval(&u_d->options[i], u_d); } qsort(u_d->options,u_d->max_alternatives, sizeof(struct decision_alternative), cmp_options); }