diff --git a/link-grammar/dict-common/dict-structures.h b/link-grammar/dict-common/dict-structures.h index ad758713cc..5cb85ac559 100644 --- a/link-grammar/dict-common/dict-structures.h +++ b/link-grammar/dict-common/dict-structures.h @@ -38,7 +38,7 @@ typedef enum } Exp_type; #ifndef SWIG -#define COST_MAX_DEC_PLACES 3 /* Max. decimal places when printing. */ +#define COST_MAX_DEC_PLACES 5 /* Max. decimal places when printing. */ static const float cost_epsilon = 1E-5f; #define EXPTAG_SZ 100 /* Initial size for the Exptag array. */ diff --git a/link-grammar/linkage/score.c b/link-grammar/linkage/score.c index 43fb61c6e9..0f374a49bc 100644 --- a/link-grammar/linkage/score.c +++ b/link-grammar/linkage/score.c @@ -13,6 +13,7 @@ #include #include "api-structures.h" // Needed for Parse_Options +#include "connectors.h" #include "disjunct-utils.h" // Needed for Disjunct #include "linkage.h" #include "score.h" @@ -68,10 +69,64 @@ static float compute_disjunct_cost(Linkage lkg) return lcost; } +/// Compute the extra cost of a multi-connector being used multiple +/// times. Any cost on that multi-connector needs to be added for each +/// usage of it. +static float compute_multi_cost(Linkage lkg) +{ + size_t lword = 0; + float mcost = 0.0; + for (size_t i = 0; i < lkg->num_words; i++) + { + Disjunct * dj = lkg->chosen_disjuncts[i]; + if (NULL == dj) continue; + + // Look at the right-going connectors. + for (Connector* rcon = dj->right; rcon; rcon=rcon->next) + { + // No-op if not a multi-connector. + if (false == rcon->multi) continue; + + // If the multi-connector does not have a cost, then skip. +// XXX at this time, there is no cncost in the condesc. + // if (0.0 == rcon->desc->cncost) continue; + + // Initial offset; this will be immediately cancelled + // by the first use. + // mcost -= rcon->desc->cncost; +mcost -= 1.0; + + // Find the links using this connector. + for (size_t l = 0; l < lkg->num_links; l++) + { + // The link is not even for this word. Ignore it. + if (lword != lkg->link_array[l].lw) continue; + + // Find the links that are using our multi-connector. + for (Connector* wrc = lkg->link_array[l].rc; wrc; wrc=wrc->next) + { + // Skip if no match. + if (strcmp(rcon->desc->string, wrc->desc->string)) continue; + + // Increment for each use. + // mcost += rcon->desc->cncost; +mcost += 1.0; + } + } + } + lword++; // increment only if disjunct is non-null. + } +mcost *= -0.00001; + return mcost; +} + /** Assign parse score (cost) to linkage, used for parse ranking. */ void linkage_score(Linkage lkg, Parse_Options opts) { + lkg->lifo.unused_word_cost = unused_word_cost(lkg); lkg->lifo.disjunct_cost = compute_disjunct_cost(lkg); lkg->lifo.link_cost = compute_link_cost(lkg); + + lkg->lifo.disjunct_cost += compute_multi_cost(lkg); } diff --git a/link-parser/link-parser.c b/link-parser/link-parser.c index f52ba8f26f..8c7e5b9809 100644 --- a/link-parser/link-parser.c +++ b/link-parser/link-parser.c @@ -329,7 +329,7 @@ static const char *process_some_linkages(FILE *in, Sentence sent, fprintf(stdout, "\tLinkage %d, ", num_displayed+1); } - fprintf(stdout, "cost vector = (UNUSED=%d DIS=%5.2f LEN=%d)\n", + fprintf(stdout, "cost vector = (UNUSED=%d DIS=%5.5f LEN=%d)\n", linkage_unused_word_cost(linkage), linkage_disjunct_cost(linkage), linkage_link_cost(linkage));