ADAPT / src / utility.c
utility.c
Raw
#define _XOPEN_SOURCE 500

#include "utility.h"
#include <string.h>
#include <stdlib.h>

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);
}