/****************************************************************** This software package delivers a scoring tool, called lf_evaluator, for Logic Form Identification (LFI). Usage: lf_evaluator gold_standard_file.lf evaluated_file.lf where: - gold_standard_file.lf is a file containing the correct logic forms - evaluated_file.lf is a file that is to be evaluated Output: lf_evaluator reports four measures: - predicate level precision - predicate level recall - argument level precision - argument level recall ******************************************************************/ #include #include #include #define MAX_INPUT_LINE 4096 #define MAX_ARGUMENTS 128 #define MAX_PREDICATES 128 typedef struct predicate{ char wordPredicate[MAX_INPUT_LINE]; char pos[MAX_INPUT_LINE]; char arguments [MAX_ARGUMENTS][6]; int nrOfArguments; int valid; } Predicate; typedef struct predicates{ Predicate *predicates[MAX_PREDICATES]; int nrOfPredicates; } Predicates; typedef struct mapping{ char argFirst[6]; char argSecond[6]; } Mapping; typedef struct results{ int overallMatchingAtPosition; int overallGoldArguments; int overallEvaluatedArguments; int overallGoldPredicates; int overallEvaluatedPredicates; int overallMatchingPredicates; } Results; /********************************************************** * TITLE: initPredicate * * DESCRIPTION: initializes a structure of type Predicate * PARAMETERS: predicate - pointer to the structure to * be initialized * RETURN VALUE: none * * DATE VERSION AUTHOR * ====================================== * | 02/07/2001 | 0.1 | Vasile Rus | * ====================================== * **********************************************************/ void initPredicate(Predicate *predicate){ int i; strcpy(predicate -> wordPredicate, ""); strcpy(predicate -> pos, ""); for (i = 0; i < MAX_ARGUMENTS; i++){ strcpy (predicate -> arguments [i], ""); } predicate -> nrOfArguments = 0; predicate -> valid = 1; // at first, every predicate is considered valid return; } /********************************************************** * TITLE: displayPredicate * * DESCRIPTION: displays a structure of type Predicate * PARAMETERS: predicate - pointer to the structure * to be displayed * RETURN VALUE: none * * DATE VERSION AUTHOR * ====================================== * | 02/07/2001 | 0.1 | Vasile Rus | * ====================================== * **********************************************************/ void displayPredicate(Predicate *predicate){ int i; printf("%s:%s_", predicate -> wordPredicate, predicate -> pos); printf("("); for (i = 0; i < predicate -> nrOfArguments; i++){ if ( 0 == i) printf("%s", predicate -> arguments [i]); else printf(", %s", predicate -> arguments [i]); } printf(")"); return; } /********************************************************** * TITLE: initPredicates * * DESCRIPTION: initializes a structure of type Predicates * PARAMETERS: predicates - pointer to the structure * to be initialized * RETURN VALUE: none * * DATE VERSION AUTHOR * ====================================== * | 02/07/2001 | 0.1 | Vasile Rus | * ====================================== * **********************************************************/ void initPredicates(Predicates *predicates){ int i; for(i=0; i predicates [i] = NULL; } predicates -> nrOfPredicates = 0; return; } /********************************************************** * TITLE: freePredicates * * DESCRIPTION: frees a structure of type Predicates * PARAMETERS: predicates - pointer to the structure * to be freed * RETURN VALUE: none * * DATE VERSION AUTHOR * ====================================== * | 02/07/2001 | 0.1 | Vasile Rus | * ====================================== * **********************************************************/ void freePredicates(Predicates *predicates){ int i; for(i=0; i nrOfPredicates; i++){ if ( NULL != predicates -> predicates [i] ) free(predicates -> predicates [i]); } predicates -> nrOfPredicates = 0; return; } /********************************************************** * TITLE: displayPredicates * * DESCRIPTION: displays a structure of type Predicates * PARAMETERS: predicates - pointer to the structure * to be displayed * RETURN VALUE: none * * DATE VERSION AUTHOR * ====================================== * | 02/07/2001 | 0.1 | Vasile Rus | * ====================================== * **********************************************************/ void displayPredicates(Predicates *predicates){ int i; printf("The predicates are: "); for(i=0; i nrOfPredicates; i++){ if ( NULL != predicates -> predicates [i] ){ displayPredicate(predicates -> predicates [i]); printf(" "); } } printf("\n"); return; } /********************************************************** * TITLE: getPredicates * * DESCRIPTION: extracts from input parameter line * predicates and places them in a structure * of type Predicates * PARAMETERS: predicates - pointer to the structure * to be filled (output parameter) * line - a line containing a sentence in LF * RETURN VALUE: none * * DATE VERSION AUTHOR * ====================================== * | 02/07/2001 | 0.1 | Vasile Rus | * ====================================== * **********************************************************/ void getPredicates(Predicates *predicates, char *line){ char *startPredicate, *endPredicate, *currPtr, *pc; char predicate [MAX_INPUT_LINE]; char wordPredicate[MAX_INPUT_LINE]; char pos[MAX_INPUT_LINE]; int firstTime; currPtr = line; startPredicate = currPtr; endPredicate = currPtr; // extract predicate firstTime = 1; while (*currPtr != '\0'){ // skip white spaces while ( (*currPtr != '\0') && (isspace(*currPtr)) ) currPtr++ ; if ( (*currPtr == '\0') && (firstTime) ){ printf("There is a sudden termination of line %s. Exit.", line); printf("Warning: No empty lines are allowed in input files\n."); exit(0); } startPredicate = currPtr; // locate end of predicate while ( (*currPtr != '\0') && (*currPtr != ')') ) currPtr ++; if ( (*currPtr == '\0') && (firstTime) ){ printf("There is a ) missing in line %s. Exit", line); exit(0); } else // if end of input was reached // then avoid processing any further predicates if ( *currPtr != '\0'){ endPredicate = currPtr; // move after '(' currPtr++; strcpy(predicate, ""); strncpy(predicate, startPredicate, endPredicate - startPredicate + 1); predicate [endPredicate - startPredicate + 1] = '\0'; // printf ("Processing predicate %s (%d)", predicate, predicates -> nrOfPredicates + 1); // printf ("\n"); predicates -> nrOfPredicates = predicates -> nrOfPredicates + 1; if ( NULL == (predicates -> predicates [predicates -> nrOfPredicates - 1] = (Predicate *) malloc (sizeof(Predicate)))){ printf("Out of Memory. Exit.\n"); exit(0); }; initPredicate(predicates -> predicates [predicates -> nrOfPredicates - 1]); strcpy(wordPredicate, ""); strcpy(pos, ""); // extract word predicate pc = startPredicate; while ( (*pc != '(') && (*pc != ')') && (*pc != ':') && (*pc != ' ') ) pc ++; endPredicate = pc; strncpy(wordPredicate, startPredicate, endPredicate - startPredicate); wordPredicate [endPredicate - startPredicate] = '\0'; strcpy(predicates -> predicates [predicates -> nrOfPredicates - 1] -> wordPredicate, wordPredicate); //printf ("Found word predicate %s", wordPredicate); //printf ("\n"); // locate pos if any pc = startPredicate; while ( (*pc != '(') && (*pc != ')') && (*pc != ':') ) pc ++; if ( *pc == ':'){ strncpy(pos, pc + 1, 1); pos [1] = '\0'; } strcpy(predicates -> predicates [predicates -> nrOfPredicates - 1] -> pos, pos); //printf ("Found pos %s", pos); //printf ("\n"); // extract arguments starting from where the pos was found while ( (*pc != '\0') && (*pc != ')') ){ while ( (*pc != '\0') && (*pc != 'x') && (*pc != 'e') ) pc ++; startPredicate = pc; while ( (*pc != '\0') && (*pc != ')') && (*pc != ',') ) pc ++; endPredicate = pc; strncpy(pos, startPredicate, endPredicate - startPredicate); pos [endPredicate - startPredicate] = '\0'; predicates -> predicates [predicates -> nrOfPredicates - 1] -> nrOfArguments = predicates -> predicates [predicates -> nrOfPredicates - 1] -> nrOfArguments + 1; strcpy(predicates -> predicates [predicates -> nrOfPredicates - 1] -> arguments [predicates -> predicates [predicates -> nrOfPredicates - 1] -> nrOfArguments - 1] , pos); //printf ("Found argument %s", pos); //printf ("\n"); } } firstTime = 0; } return; } /********************************************************** * TITLE: getScore * * DESCRIPTION: retrieves necessary data from a Predicates * structure to compute the scores * PARAMETERS: goldPredicates - pointer to the structure * containg the gold/perfect * predicates * evaluatedPredicates - pointer to the * structure containing the * predicates to be scored * overallResults - pointer to a Results * structure that will record the * scoring data * RETURN VALUE: none * * DATE VERSION AUTHOR * ====================================== * | 02/07/2001 | 0.1 | Vasile Rus | * ====================================== * **********************************************************/ void getScore(Predicates *goldPredicates, Predicates *evaluatedPredicates, Results *overallResults){ int i, j, k; Mapping mappings[MAX_ARGUMENTS]; int nrOfMappings; int nrOfEvaluatedArguments = 0, nrOfNotGoldedEvaluatedArguments = 0; int nrOfMatchingAtPositionArguments = 0; // initialize mappings for (i=0; i nrOfPredicates; i++){ overallResults -> overallEvaluatedPredicates = overallResults -> overallEvaluatedPredicates + 1; for(j = 0; j nrOfPredicates; j++){ if ( (strcmp(evaluatedPredicates -> predicates [i] -> wordPredicate, goldPredicates -> predicates [j] -> wordPredicate) == 0) && (strcmp(evaluatedPredicates -> predicates [i] -> pos, goldPredicates -> predicates [j] -> pos) == 0 ) // not already matched && (1 == evaluatedPredicates -> predicates [i] -> valid) && (1 == goldPredicates -> predicates [j] -> valid) ) { evaluatedPredicates -> predicates [i] -> valid ++ ; goldPredicates -> predicates [j] -> valid ++ ; overallResults -> overallMatchingPredicates = overallResults -> overallMatchingPredicates + 1; // check arguments only for validated predicates in evaluatedPredicates for(k=0; k predicates [i] -> arguments [0]) == 0) break; } if (k == nrOfMappings){ // add new mapping // NOTE: if multiple predicates with the same name are in // gold predicates, they are matched in order: first with the first // second with the second, and so on. nrOfMappings = nrOfMappings + 1; strcpy(mappings[nrOfMappings - 1].argFirst, evaluatedPredicates -> predicates [i] -> arguments [0]); strcpy(mappings[nrOfMappings - 1].argSecond, goldPredicates -> predicates [j] -> arguments [0]); } } } } // displayMapping // printf("******* MAPPING ********\n"); // for (i = 0; i < nrOfMappings; i++){ // printf("%s -> %s\n", mappings [i] . argFirst, mappings [i] . argSecond); // } // printf("******* END OF MAPPING ********\n"); // do the mapping for (i = 0; i nrOfPredicates; i++){ if ( 2 == evaluatedPredicates -> predicates [i] -> valid) for(j = 0; j predicates[i] -> nrOfArguments; j++){ // find the mapping of current argument for(k=0; k predicates [i] -> arguments [j]) == 0){ strcpy(evaluatedPredicates -> predicates [i] -> arguments [j], "g"); strcat(evaluatedPredicates -> predicates [i] -> arguments [j], mappings[k].argSecond); } } } } // displayPredicates(evaluatedPredicates); // count how many positions are not golded nrOfNotGoldedEvaluatedArguments = 0; nrOfEvaluatedArguments = 0; for (i = 0; i nrOfPredicates; i++){ for(j = 0; j predicates[i] -> nrOfArguments; j++){ if (evaluatedPredicates -> predicates [i] -> arguments [j][0] != 'g') nrOfNotGoldedEvaluatedArguments = nrOfNotGoldedEvaluatedArguments + 1; nrOfEvaluatedArguments = nrOfEvaluatedArguments + 1; } } // count arguments and positions // validate predicates and do mapping based on // first argument of each predicate nrOfMatchingAtPositionArguments = 0; for (i = 0; i nrOfPredicates; i++){ for(j = 0; j nrOfPredicates; j++){ if ( (strcmp(evaluatedPredicates -> predicates [i] -> wordPredicate, goldPredicates -> predicates [j] -> wordPredicate) == 0) && (strcmp(evaluatedPredicates -> predicates [i] -> pos, goldPredicates -> predicates [j] -> pos) == 0 ) ) { // check if arguments and positions match, one by one for (k = 0; k < evaluatedPredicates -> predicates [i] -> nrOfArguments; k++){ if (k < goldPredicates -> predicates [j] -> nrOfArguments) if ( evaluatedPredicates -> predicates [i] -> arguments [k][0] == 'g' ) if ( 0 == strcmp(evaluatedPredicates -> predicates [i] -> arguments[k] + 1, goldPredicates -> predicates [j] -> arguments [k]) ) { // this is a match nrOfMatchingAtPositionArguments = nrOfMatchingAtPositionArguments + 1; } } } } } // printf("Results:\n--------\n"); // printf("%d(~g) %d(evAll) %d(@)\n", nrOfNotGoldedEvaluatedArguments, nrOfEvaluatedArguments, nrOfMatchingAtPositionArguments); overallResults -> overallEvaluatedArguments = overallResults -> overallEvaluatedArguments + nrOfEvaluatedArguments; overallResults -> overallMatchingAtPosition = overallResults -> overallMatchingAtPosition + nrOfMatchingAtPositionArguments; for(i = 0; i nrOfPredicates; i++){ overallResults -> overallGoldPredicates = overallResults -> overallGoldPredicates + 1; for (k = 0; k < goldPredicates -> predicates [i] -> nrOfArguments; k++){ overallResults -> overallGoldArguments = overallResults -> overallGoldArguments + 1; } } return; } /********************************************************** * TITLE: main * * DESCRIPTION: main entry of the lf_evaluator tool. * It displays the scores. * PARAMETERS: arg 1 - gold standard file * arg 2 - evaluated file * RETURN VALUE: 0 - when successfully finished. * * DATE VERSION AUTHOR * ====================================== * | 02/07/2001 | 0.1 | Vasile Rus | * ====================================== * **********************************************************/ int main(int argc, char *argv[]){ FILE *fp_goldStandardFile, *fp_evaluatedFile; char goldStandardLine[MAX_INPUT_LINE], evaluatedLine[MAX_INPUT_LINE]; Predicates goldPredicates, evaluatedPredicates; Results overallResults; if (argc != 3){ printf("Wrong number of arguments.\n"); printf("Usage: lf_evaluator gold_standard_file.lf evaluated_file.lf\n"); exit(0); } if ( NULL == (fp_goldStandardFile = fopen(argv[1], "r")) ){ printf("Could open file %s\n. Exit.\n", argv[1]); exit(0); } if ( NULL == (fp_evaluatedFile = fopen(argv[2], "r")) ){ printf("Could open file %s\n. Exit.\n", argv[2]); exit(0); } overallResults . overallEvaluatedArguments = 0; overallResults . overallMatchingAtPosition = 0; overallResults . overallGoldArguments = 0; overallResults . overallEvaluatedPredicates = 0; overallResults . overallGoldPredicates = 0; overallResults . overallMatchingPredicates = 0; while( (NULL != fgets(goldStandardLine, MAX_INPUT_LINE, fp_goldStandardFile)) && (NULL != fgets(evaluatedLine, MAX_INPUT_LINE, fp_evaluatedFile)) ){ goldStandardLine [strlen(goldStandardLine)] = '\0'; printf("From %s: %s", argv[1], goldStandardLine); initPredicates(&goldPredicates); getPredicates( &goldPredicates, goldStandardLine); // displayPredicates( &goldPredicates); printf("From %s: %s", argv[2], evaluatedLine); evaluatedLine [strlen(evaluatedLine)] = '\0'; initPredicates(&evaluatedPredicates); getPredicates( &evaluatedPredicates, evaluatedLine); // displayPredicates ( &evaluatedPredicates); // score getScore( &goldPredicates, &evaluatedPredicates, &overallResults); freePredicates(&goldPredicates); freePredicates(&evaluatedPredicates); printf("\n"); strcpy(goldStandardLine, ""); strcpy(evaluatedLine, ""); } printf("\n==============================\n"); printf("Argument Precision = %f\n", ((float) overallResults.overallMatchingAtPosition)/overallResults.overallEvaluatedArguments); printf("Argument Recall = %f\n", ((float) overallResults.overallMatchingAtPosition)/overallResults.overallGoldArguments); printf("Predicate Precision = %f\n", ((float) overallResults.overallMatchingPredicates)/overallResults.overallEvaluatedPredicates); printf("Predicate Recall = %f\n", ((float) overallResults.overallMatchingPredicates)/overallResults.overallGoldPredicates); printf("==============================\n"); fclose(fp_goldStandardFile); fclose(fp_evaluatedFile); return 0; }