`scales.h`

/* This is the header file for the Scales module. It is also included by the Cases, Adjuster and Odometer modules. */ /* external functions */externvoidZero_Weight( weight_type *weight_pointer);externvoidWrite_Weights_Table( file weights_stream, area *area_pointer);externvoidWeight_Attributes( file weights_stream, file log_stream, case_law_specification case_law, boolean inputable_latex);

`scales.c`

/* This is the implementation file for the Scales module. */ #include<stdio.h> #include<stdlib.h> #include"shyster.h" #include"cases.h" #include"scales.h"staticvoiderror_exit( file stream,conststring message) { Write_Error_Message_And_Exit(stream, "Scales", message); }staticvoidwarning( file stream,conststring message) { Write_Warning_Message(stream, "Scales", message, Top_Level); }externvoidZero_Weight( weight_type *weight_pointer) /* Sets the weight pointed to by weight_pointer to zero. */ { weight_pointer->infinite = FALSE; weight_pointer->finite = 0.0; }staticboolean calculate_mean_and_centroids( file log_stream, result *result_head, attribute *attribute_pointer) /* Calculates the mean (and, for each result, centroid element) for the attribute pointed to by attribute_pointer. Returns TRUE, iff the attribute has known values. */ { result *result_pointer; kase *case_pointer; matrix_element *matrix_pointer; centroid_element *centroid_pointer; floating_point sum, temp; cardinal count, total_count = 0; attribute_pointer->mean = 0.0; matrix_pointer = attribute_pointer->matrix_head; /* for every result ... */for(result_pointer = result_head; result_pointer != NULL; result_pointer = result_pointer->next) { sum = 0.0; count = 0; /* sum the attribute values for this attribute for each case with this result */for(case_pointer = result_pointer->case_head; (case_pointer != NULL) && (matrix_pointer != NULL); case_pointer = case_pointer->next) {if(Attribute_Value(matrix_pointer->attribute_value, &temp)) { sum += temp; count++; } matrix_pointer = matrix_pointer->attribute_next; }if(result_pointer->centroid_head == NULL) { /* allocate memory for this centroid element (the first in the list) */if((result_pointer->centroid_head = (centroid_element *) malloc(sizeof(centroid_element))) == NULL) error_exit(log_stream, "malloc failed during centroid building"); centroid_pointer = result_pointer->centroid_head; }else{ /* go to the end of the centroid */for(centroid_pointer = result_pointer->centroid_head; centroid_pointer->next != NULL; centroid_pointer = centroid_pointer->next); /* allocate memory for this centroid element */if((centroid_pointer->next = (centroid_element *) malloc(sizeof(centroid_element))) == NULL) error_exit(log_stream, "malloc failed during centroid building"); centroid_pointer = centroid_pointer->next; }if(!(centroid_pointer->unknown = count == 0)) centroid_pointer->value = sum / (floating_point) count; centroid_pointer->next = NULL; attribute_pointer->mean += sum; total_count += count; }if(total_count == 0) /* the attribute has no known values */returnFALSE;else{ attribute_pointer->mean = attribute_pointer->mean / (floating_point) total_count;returnTRUE; } }staticvoidcalculate_weights( file log_stream, area *area_pointer) /* Calculates the weight of each attribute in the area pointed to by area_pointer. (The weight is the inverse of the variance of the attribute values.) */ { attribute *attribute_pointer; cardinal count; floating_point variance;charmessage[Max_Error_Message_Length]; count = 1; /* for every attribute ... */for(attribute_pointer = area_pointer->attribute_head; attribute_pointer != NULL; attribute_pointer = attribute_pointer->next) { variance = 0.0; Zero_Weight(&attribute_pointer->weight);if(!calculate_mean_and_centroids(log_stream, area_pointer->result_head, attribute_pointer)) { /* the attribute has no known values */ sprintf(message, "A%u in %s area has no weight", count, area_pointer->identifier); warning(log_stream, message); }else{ /* the attribute has known values, so determine its weight */ variance = attribute_pointer->mean - (attribute_pointer->mean * attribute_pointer->mean);if(attribute_pointer->weight.infinite = Is_Zero(variance)) { sprintf(message, "A%u in %s area has infinite weight", count, area_pointer->identifier); warning(log_stream, message); area_pointer->infinite_weight = TRUE; }elseattribute_pointer->weight.finite = 1 / variance; } count++; } }staticvoidcalculate_result_weights( file log_stream, area *area_pointer) /* Calculates the result weight for each attribute in the area pointed to by area_pointer. (The result weight is the inverse of the variance of the attribute values for that result.) */ { attribute *attribute_pointer; result *result_pointer; centroid_element *centroid_pointer; cardinal count; floating_point variance; weight_list_element *weights_pointer; boolean zero_result_weight = FALSE;charmessage[Max_Error_Message_Length]; /* for every attribute ... */for(attribute_pointer = area_pointer->attribute_head; attribute_pointer != NULL; attribute_pointer = attribute_pointer->next) /* for every result ... */for(result_pointer = area_pointer->result_head; result_pointer != NULL; result_pointer = result_pointer->next) { /* find, in the centroid for this result, the mean for this attribute */ centroid_pointer = result_pointer->centroid_head;for(count = 1; count < attribute_pointer->number; count++) centroid_pointer = centroid_pointer->next;if(attribute_pointer->weights_head == NULL) { /* allocate memory for this result weight (the first in the list) */if((attribute_pointer->weights_head = (weight_list_element *) malloc(sizeof(weight_list_element))) == NULL) error_exit(log_stream, "malloc failed during weights building"); weights_pointer = attribute_pointer->weights_head; }else{ /* allocate memory for this result weight */if((weights_pointer->next = (weight_list_element *) malloc(sizeof(weight_list_element))) == NULL) error_exit(log_stream, "malloc failed during weights building"); weights_pointer = weights_pointer->next; } Zero_Weight(&weights_pointer->weight);if(centroid_pointer->unknown && (attribute_pointer->weight.infinite || !Is_Zero(attribute_pointer->weight.finite))) /* the result weight is zero, but the weight for the whole attribute is not zero, so ensure a warning is issued later (if the weight for the whole attribute is zero, a warning has already been issued) */ zero_result_weight = TRUE;elseif(attribute_pointer->weight.infinite) /* this attribute has infinite weight, so make this result weight infinite too */ weights_pointer->weight.infinite = TRUE;else{ /* the attribute has known values, so determine the result weight */ variance = centroid_pointer->value - (centroid_pointer->value * centroid_pointer->value);if(!(weights_pointer->weight.infinite = Is_Zero(variance))) weights_pointer->weight.finite = 1 / variance; } weights_pointer->next = NULL; }if(zero_result_weight) { sprintf(message, "one or more attributes in %s area has a zero result weight", area_pointer->identifier); warning(log_stream, message); } }externvoidWrite_Weights_Table( file weights_stream, area *area_pointer) /* Writes a table of weights for the area pointed to by area_pointer. */ { result *result_pointer; attribute *attribute_pointer; centroid_element *centroid_pointer; cardinal centroid_count; weight_list_element *weights_pointer; Indent(weights_stream, 1); fprintf(weights_stream, "\\begin{small}\n"); Indent(weights_stream, 2); fprintf(weights_stream, "\\begin{tabular}{|c|*{%u}{c@{\\hspace{%s}}c@{\\hspace{%s}}r|}}" "\\hline\n", area_pointer->number_of_results + 1, Column_Separation, Column_Separation); Indent(weights_stream, 3); fprintf(weights_stream, "&"); /* write the column headings */for(result_pointer = area_pointer->result_head; result_pointer != NULL; result_pointer = result_pointer->next) fprintf(weights_stream, "\\multicolumn{3}{c|}{%s %s}&", Identifier_Font, result_pointer->identifier); fprintf(weights_stream, "&&\\\\\n"); Indent(weights_stream, 3); fprintf(weights_stream, "\\smash{\\raisebox{%s}{\\it Attr.}}&", Raise_Height);for(result_pointer = area_pointer->result_head; result_pointer != NULL; result_pointer = result_pointer->next) fprintf(weights_stream, "$\\mu$&$\\sigma^2$&\\multicolumn{1}{c|}{$w$}&"); fprintf(weights_stream, "\\smash{\\raisebox{%s}{$\\mu$}}&" "\\smash{\\raisebox{%s}{$\\sigma^2$}}&" "\\multicolumn{1}{c|}{\\smash{\\raisebox{%s}{$w$}}}" "\\\\\\hline\\hline", Raise_Height, Raise_Height, Raise_Height); /* for every attribute ... */for(attribute_pointer = area_pointer->attribute_head; attribute_pointer != NULL; attribute_pointer = attribute_pointer->next) { weights_pointer = attribute_pointer->weights_head; fprintf(weights_stream, "\n"); Indent(weights_stream, 3); fprintf(weights_stream, "$A_{%u}$&", attribute_pointer->number); /* for every result ... */for(result_pointer = area_pointer->result_head; result_pointer != NULL; result_pointer = result_pointer->next) { /* find, in the centroid for this result, the mean for this attribute */ centroid_pointer = result_pointer->centroid_head;for(centroid_count = 1; centroid_count < attribute_pointer->number; centroid_count++) centroid_pointer = centroid_pointer->next; /* write the mean and the variance for this result and attribute */if(centroid_pointer->unknown) fprintf(weights_stream, "\\footnotesize?&\\footnotesize?&");else{ Write_Floating_Point(weights_stream, centroid_pointer->value, Empty_String); fprintf(weights_stream, "&"); Write_Floating_Point(weights_stream, centroid_pointer->value - (centroid_pointer->value * centroid_pointer->value), Empty_String); fprintf(weights_stream, "&"); } /* write the result weight for this attribute */if(weights_pointer->weight.infinite) fprintf(weights_stream, "\\multicolumn{1}{c|}{$\\infty$}");elseif(Is_Zero(weights_pointer->weight.finite)) fprintf(weights_stream, "\\multicolumn{1}{c|}{--}");elseWrite_Floating_Point(weights_stream, weights_pointer->weight.finite, Empty_String); fprintf(weights_stream, "&"); weights_pointer = weights_pointer->next; } /* write the mean and the variance for this attribute */ Write_Floating_Point(weights_stream, attribute_pointer->mean, Empty_String); fprintf(weights_stream, "&"); Write_Floating_Point(weights_stream, attribute_pointer->mean - (attribute_pointer->mean * attribute_pointer->mean), Empty_String); fprintf(weights_stream, "&"); /* write the weight for this attribute */if(attribute_pointer->weight.infinite) fprintf(weights_stream, "\\multicolumn{1}{c|}{$\\infty$}");elseif(Is_Zero(attribute_pointer->weight.finite)) fprintf(weights_stream, "\\multicolumn{1}{c|}{--}");elseWrite_Floating_Point(weights_stream, attribute_pointer->weight.finite, Empty_String); fprintf(weights_stream, "\\\\"); } fprintf(weights_stream, "\\hline\n"); Indent(weights_stream, 2); fprintf(weights_stream, "\\end{tabular}\n"); Indent(weights_stream, 1); fprintf(weights_stream, "\\end{small}\n\n"); }externvoidWeight_Attributes( file weights_stream, file log_stream, case_law_specification case_law, boolean inputable_latex) /* Calculates the weights for each area in the specification case_law, and writes a table of weights for each area to weights_stream (if it is not NULL). Writes LaTeX code that can be included in another LaTeX document (i.e. not stand-alone code), if inputable_latex is TRUE. */ { area *area_pointer;if(weights_stream != NULL) { fprintf(weights_stream, "%% Weights file\n\n"); Write_LaTeX_Header(weights_stream, inputable_latex); } /* for every area ... */for(area_pointer = case_law.area_head; area_pointer != NULL; area_pointer = area_pointer->next) {if(weights_stream != NULL) fprintf(weights_stream, "%s{%s area}\n\n", Heading, area_pointer->identifier); area_pointer->infinite_weight = FALSE; calculate_weights(log_stream, area_pointer); calculate_result_weights(log_stream, area_pointer);if(weights_stream != NULL) Write_Weights_Table(weights_stream, area_pointer); }if(weights_stream != NULL) Write_LaTeX_Trailer(weights_stream, inputable_latex); }

Other SHYSTER modules: Shyster, Statutes, Cases, Tokenizer, Parser, Dumper, Checker, Adjuster, Consultant, Odometer and Reporter.

Home page: | <http://www.popple.net/james/> |

E-mail: | <james@popple.net> |

Last modified: | 30 April 1995 |