From c6301234e113b56a2d4627feddaffaf352e96b05 Mon Sep 17 00:00:00 2001 From: ampli Date: Wed, 17 Jul 2019 19:03:15 +0300 Subject: [PATCH 1/9] sat-encoder.cpp: Add GNUC_UNUSED for debug function pmodel() Prevent warnings in debug compilation. --- link-grammar/sat-solver/sat-encoder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/link-grammar/sat-solver/sat-encoder.cpp b/link-grammar/sat-solver/sat-encoder.cpp index e2e4dd3815..ea3386a73f 100644 --- a/link-grammar/sat-solver/sat-encoder.cpp +++ b/link-grammar/sat-solver/sat-encoder.cpp @@ -1001,11 +1001,11 @@ bool SATEncoder::connectivity_components(std::vector& components) { #ifdef SAT_DEBUG #define MVALUE(s, v) (s->model[v] == l_True?'T':(s->model[v] == l_False?'f':'u')) -static void pmodel(Solver *solver, int var) { +GNUC_UNUSED static void pmodel(Solver *solver, int var) { printf("%c\n", MVALUE(solver, var)); } -static void pmodel(Solver *solver, vec &clause) { +GNUC_UNUSED static void pmodel(Solver *solver, vec &clause) { vector t; for (int i = 0; i < clause.size(); i++) { int v = var(clause[i]); From 34d7042df2f3c9e28375ebb23adb9b4f537fa485 Mon Sep 17 00:00:00 2001 From: ampli Date: Thu, 11 Jul 2019 18:17:47 +0300 Subject: [PATCH 2/9] Exp_struct: Prepare for removing E_list 1. Add field "operand_next" to replace the current E_list 'next". 2. Rename "l" to "operand_first" for readability. 3. Use unnamed union (seems to me more readable here). --- link-grammar/connectors.c | 4 +- link-grammar/corpus/cluster.c | 6 +- link-grammar/dict-common/dict-impl.c | 8 +-- link-grammar/dict-common/dict-structures.h | 25 ++++---- link-grammar/dict-common/dict-utils.c | 28 ++++---- link-grammar/dict-common/idiom.c | 12 ++-- link-grammar/dict-common/print-dict.c | 12 ++-- link-grammar/dict-file/read-dict.c | 34 +++++----- link-grammar/dict-sql/read-sql.c | 10 +-- link-grammar/prepare/build-disjuncts.c | 22 +++---- link-grammar/prepare/exprune.c | 20 +++--- link-grammar/sat-solver/sat-encoder.cpp | 74 +++++++++++----------- link-grammar/sat-solver/util.cpp | 4 +- link-grammar/sat-solver/word-tag.cpp | 16 ++--- link-grammar/sat-solver/word-tag.hpp | 4 +- 15 files changed, 141 insertions(+), 138 deletions(-) diff --git a/link-grammar/connectors.c b/link-grammar/connectors.c index c8a7c38311..b075234d93 100644 --- a/link-grammar/connectors.c +++ b/link-grammar/connectors.c @@ -84,12 +84,12 @@ static size_t get_connectors_from_expression(condesc_t **conlist, const Exp *e) { if (e->type == CONNECTOR_type) { - if (NULL != conlist) *conlist = e->u.condesc; + if (NULL != conlist) *conlist = e->condesc; return 1; } size_t cl_size = 0; - for (E_list *l = e->u.l; l != NULL; l = l->next) + for (E_list *l = e->operand_first; l != NULL; l = l->next) { cl_size += get_connectors_from_expression(conlist, l->e); if (NULL != conlist) conlist++; diff --git a/link-grammar/corpus/cluster.c b/link-grammar/corpus/cluster.c index 204153804e..f07b44ed16 100644 --- a/link-grammar/corpus/cluster.c +++ b/link-grammar/corpus/cluster.c @@ -190,7 +190,7 @@ static Exp * make_exp(const char *djstr, double cost) lhead = l; e->type = AND_type; - e->u.l = lhead; + e->operand_first = lhead; return e; } @@ -219,7 +219,7 @@ static Exp * or_exp(Exp *p1, Exp *p2) l->e = p1; lhead = l; - e->u.l = lhead; + e->operand_first = lhead; return e; } #endif @@ -228,7 +228,7 @@ static void free_exp(Exp *e) { if (CONNECTOR_type != e->type) { - E_list *l = e->u.l; + E_list *l = e->operand_first; while(l) { E_list *ln = l->next; diff --git a/link-grammar/dict-common/dict-impl.c b/link-grammar/dict-common/dict-impl.c index bcff6b773a..d7e7fca729 100644 --- a/link-grammar/dict-common/dict-impl.c +++ b/link-grammar/dict-common/dict-impl.c @@ -186,7 +186,7 @@ const char * linkgrammar_get_dict_locale(Dictionary dict) goto locale_error; } - if (0 == strcmp(dn->exp->u.condesc->string, "C")) + if (0 == strcmp(dn->exp->condesc->string, "C")) { locale = string_set_add("C", dict->string_set); } @@ -194,7 +194,7 @@ const char * linkgrammar_get_dict_locale(Dictionary dict) { char c; char locale_ll[4], locale_cc[3]; - int locale_numelement = sscanf(dn->exp->u.condesc->string, "%3[A-Z]4%2[a-z]%c", + int locale_numelement = sscanf(dn->exp->condesc->string, "%3[A-Z]4%2[a-z]%c", locale_ll, locale_cc, &c); if (2 != locale_numelement) { @@ -202,7 +202,7 @@ const char * linkgrammar_get_dict_locale(Dictionary dict) "should be in the form LL4cc+\n" "\t(LL: language code; cc: territory code) " "\tor C+ for transliterated dictionaries.\n", - dn->exp->u.condesc->string); + dn->exp->condesc->string); goto locale_error; } @@ -268,7 +268,7 @@ const char * linkgrammar_get_dict_version(Dictionary dict) if (NULL == dn) return "[unknown]"; e = dn->exp; - ver = strdup(&e->u.condesc->string[1]); + ver = strdup(&e->condesc->string[1]); p = strchr(ver, 'v'); while (p) { diff --git a/link-grammar/dict-common/dict-structures.h b/link-grammar/dict-common/dict-structures.h index 221906fec7..acd97a1a4b 100644 --- a/link-grammar/dict-common/dict-structures.h +++ b/link-grammar/dict-common/dict-structures.h @@ -37,21 +37,24 @@ typedef enum } Exp_type; /** - * The E_list and Exp structures defined below comprise the expression - * trees that are stored in the dictionary. The expression has a type - * (OR_type, AND_type or CONNECTOR_type). If it is not a terminal it - * has a list (an E_list) of children. Else "condesc" is the connector - * descriptor, when "dir" indicates the connector direction. + * The Exp structure defined below comprises the expression trees that are + * stored in the dictionary. The expression has a type (OR_type, AND_type + * or CONNECTOR_type). If it is not a terminal "operand" points to its + * list of operands (when each of them points to the next one through + * "next"). Else "condesc" is the connector descriptor, when "dir" + * indicates the connector direction. */ struct Exp_struct { + Exp *operand_next; /* Next same-level operand. */ Exp_type type; /* One of three types: AND, OR, or connector. */ - char dir; /* The connector connects to: '-': the left; '+': the right */ - bool multi; /* TRUE if a multi-connector (for connector) */ - union { - E_list * l; /* Only needed for non-terminals */ - condesc_t * condesc; /* Only needed if it's a connector */ - } u; + char dir; /* The connector connects to the left ('-') or right ('+'). */ + bool multi; /* TRUE if a multi-connector (for connector). */ + union + { + E_list *operand_first; /* First operand (for non-terminals). */ + condesc_t *condesc; /* Only needed if it's a connector. */ + }; double cost; /* The cost of using this expression. */ }; diff --git a/link-grammar/dict-common/dict-utils.c b/link-grammar/dict-common/dict-utils.c index f75616f520..b097ee57c9 100644 --- a/link-grammar/dict-common/dict-utils.c +++ b/link-grammar/dict-common/dict-utils.c @@ -26,7 +26,7 @@ const char * lg_exp_get_string(const Exp* exp) { - return exp->u.condesc->string; + return exp->condesc->string; } /* ======================================================== */ @@ -39,7 +39,7 @@ void free_Exp(Exp * e) // SQL dict. if (NULL == e) return; if (e->type != CONNECTOR_type) { - free_E_list(e->u.l); + free_E_list(e->operand_first); } free(e); } @@ -59,7 +59,7 @@ int size_of_expression(Exp * e) E_list * l; if (e->type == CONNECTOR_type) return 1; size = 0; - for (l=e->u.l; l!=NULL; l=l->next) { + for (l=e->operand_first; l!=NULL; l=l->next) { size += size_of_expression(l->e); } return size; @@ -83,7 +83,7 @@ static E_list *copy_E_list(E_list *l, Pool_desc* mp[]) el->next = nl; el = nl; if (l->e->type != CONNECTOR_type) - nl->e->u.l = copy_E_list(l->e->u.l, mp); + nl->e->operand_first = copy_E_list(l->e->operand_first, mp); } el->next = NULL; @@ -98,7 +98,7 @@ Exp *copy_Exp(Exp *e, Pool_desc *E_list_pool, Pool_desc *Exp_pool) *ne = *e; if (CONNECTOR_type == e->type) return ne; - ne->u.l = copy_E_list(ne->u.l, (Pool_desc*[]){E_list_pool, Exp_pool}); + ne->operand_first = copy_E_list(ne->operand_first, (Pool_desc*[]){E_list_pool, Exp_pool}); return ne; } @@ -121,14 +121,14 @@ static bool exp_compare(Exp * e1, Exp * e2) { if (e1->dir != e2->dir) return 0; - /* printf("%s %s\n",e1->u.condesc->string,e2->u.condesc->string); */ - if (e1->u.condesc != e2->u.condesc) + /* printf("%s %s\n",e1->condesc->string,e2->condesc->string); */ + if (e1->condesc != e2->condesc) return 0; } else { - el1 = e1->u.l; - el2 = e2->u.l; + el1 = e1->operand_first; + el2 = e2->operand_first; /* while at least 1 is non-null */ for (;(el1!=NULL)||(el2!=NULL);) { /*fail if 1 is null */ @@ -167,7 +167,7 @@ static int exp_contains(Exp * super, Exp * sub) /* proceed through supers children and return 1 if sub is contained in any of them */ - for(el = super->u.l; el!=NULL; el=el->next) { + for(el = super->operand_first; el!=NULL; el=el->next) { if (exp_contains(el->e, sub)==1) return 1; } @@ -252,14 +252,14 @@ static bool exp_has_connector(const Exp * e, int depth, const char * cs, if (e->type == CONNECTOR_type) { if (direction != e->dir) return false; - return smart_match ? easy_match(e->u.condesc->string, cs) - : string_set_cmp(e->u.condesc->string, cs); + return smart_match ? easy_match(e->condesc->string, cs) + : string_set_cmp(e->condesc->string, cs); } if (depth == 0) return false; if (depth > 0) depth--; - for (el = e->u.l; el != NULL; el = el->next) + for (el = e->operand_first; el != NULL; el = el->next) { if (exp_has_connector(el->e, depth, cs, direction, smart_match)) return true; @@ -296,7 +296,7 @@ const char * word_only_connector(Dict_node * dn) { Exp * e = dn->exp; if (CONNECTOR_type == e->type) - return e->u.condesc->string; + return e->condesc->string; return NULL; } diff --git a/link-grammar/dict-common/idiom.c b/link-grammar/dict-common/idiom.c index a8d71fd6e0..9c2809482c 100644 --- a/link-grammar/dict-common/idiom.c +++ b/link-grammar/dict-common/idiom.c @@ -242,14 +242,14 @@ void insert_idiom(Dictionary dict, Dict_node * dn) /* ----- this code just sets up the node fields of the dn_list ----*/ nc = Exp_create(dict); - nc->u.condesc = condesc_add(&dict->contable, generate_id_connector(dict)); + nc->condesc = condesc_add(&dict->contable, generate_id_connector(dict)); nc->dir = '-'; nc->multi = false; nc->type = CONNECTOR_type; nc->cost = 0; n1 = Exp_create(dict); - n1->u.l = ell = pool_alloc(dict->Exp_pool); + n1->operand_first = ell = pool_alloc(dict->Exp_pool); ell->next = elr = pool_alloc(dict->Exp_pool); elr->next = NULL; ell->e = nc; @@ -268,12 +268,12 @@ void insert_idiom(Dictionary dict, Dict_node * dn) n1 = Exp_create(dict); n1->type = AND_type; n1->cost = 0; - n1->u.l = ell = pool_alloc(dict->E_list_pool); + n1->operand_first = ell = pool_alloc(dict->E_list_pool); ell->next = elr = pool_alloc(dict->E_list_pool); elr->next = NULL; nc = Exp_create(dict); - nc->u.condesc = condesc_add(&dict->contable, generate_id_connector(dict)); + nc->condesc = condesc_add(&dict->contable, generate_id_connector(dict)); nc->dir = '+'; nc->multi = false; nc->type = CONNECTOR_type; @@ -283,7 +283,7 @@ void insert_idiom(Dictionary dict, Dict_node * dn) increment_current_name(dict); nc = Exp_create(dict); - nc->u.condesc = condesc_add(&dict->contable, generate_id_connector(dict)); + nc->condesc = condesc_add(&dict->contable, generate_id_connector(dict)); nc->dir = '-'; nc->multi = false; nc->type = CONNECTOR_type; @@ -298,7 +298,7 @@ void insert_idiom(Dictionary dict, Dict_node * dn) /* now generate the last one */ nc = Exp_create(dict); - nc->u.condesc = condesc_add(&dict->contable, generate_id_connector(dict)); + nc->condesc = condesc_add(&dict->contable, generate_id_connector(dict)); nc->dir = '+'; nc->multi = false; nc->type = CONNECTOR_type; diff --git a/link-grammar/dict-common/print-dict.c b/link-grammar/dict-common/print-dict.c index 43161edb89..25b45387c2 100644 --- a/link-grammar/dict-common/print-dict.c +++ b/link-grammar/dict-common/print-dict.c @@ -57,7 +57,7 @@ void print_expression(Exp * n) if (icost == 0) printf("("); if (n->type == AND_type) printf("& "); if (n->type == OR_type) printf("or "); - for (el = n->u.l; el != NULL; el = el->next) + for (el = n->operand_first; el != NULL; el = el->next) { print_expression(el->e); } @@ -126,13 +126,13 @@ static dyn_str *print_expression_parens(dyn_str *e, { for (i=0; imulti) dyn_strcat(e, "@"); - append_string(e, "%s%c", n->u.condesc?n->u.condesc->string:"(null)", n->dir); + append_string(e, "%s%c", n->condesc?n->condesc->string:"(null)", n->dir); for (i=0; iu.l; + el = n->operand_first; if (el == NULL) { for (i=0; itype == OR_type) && el->e && - (el->e->type == AND_type) && el->e->cost == 0 && (NULL == el->e->u.l)) + (el->e->type == AND_type) && el->e->cost == 0 && (NULL == el->e->operand_first)) { dyn_strcat(e, "{"); if (NULL == el->next) dyn_strcat(e, "error-no-next"); @@ -295,13 +295,13 @@ static unsigned int count_clause(Exp *e) { /* multiplicative combinatorial explosion */ cnt = 1; - for (e_list = e->u.l; e_list != NULL; e_list = e_list->next) + for (e_list = e->operand_first; e_list != NULL; e_list = e_list->next) cnt *= count_clause(e_list->e); } else if (e->type == OR_type) { /* Just additive */ - for (e_list = e->u.l; e_list != NULL; e_list = e_list->next) + for (e_list = e->operand_first; e_list != NULL; e_list = e_list->next) cnt += count_clause(e_list->e); } else if (e->type == CONNECTOR_type) diff --git a/link-grammar/dict-file/read-dict.c b/link-grammar/dict-file/read-dict.c index 9c0bf3c4b6..647ff797bb 100644 --- a/link-grammar/dict-file/read-dict.c +++ b/link-grammar/dict-file/read-dict.c @@ -811,7 +811,7 @@ static Exp * make_zeroary_node(Dictionary dict) Exp * n = Exp_create(dict); n->type = AND_type; /* these must be AND types */ n->cost = 0.0; - n->u.l = NULL; + n->operand_first = NULL; return n; } @@ -825,9 +825,9 @@ static Exp * make_unary_node(Dictionary dict, Exp * e) n = Exp_create(dict); n->type = AND_type; /* these must be AND types */ n->cost = 0.0; - n->u.l = pool_alloc(dict->E_list_pool); - n->u.l->next = NULL; - n->u.l->e = e; + n->operand_first = pool_alloc(dict->E_list_pool); + n->operand_first->next = NULL; + n->operand_first->e = e; return n; } @@ -844,7 +844,7 @@ static Exp * make_and_node(Dictionary dict, Exp* nl, Exp* nr) n->type = AND_type; n->cost = 0.0; - n->u.l = ell = pool_alloc(dict->E_list_pool); + n->operand_first = ell = pool_alloc(dict->E_list_pool); ell->next = elr = pool_alloc(dict->E_list_pool); elr->next = NULL; @@ -858,7 +858,7 @@ static Exp *make_op_Exp(Dictionary dict, Exp_type t) Exp * n = Exp_create(dict); n->type = t; n->cost = 0.0; - n->u.l = NULL; + n->operand_first = NULL; return n; } @@ -886,7 +886,7 @@ static Exp * make_or_node(Dictionary dict, Exp* nl, Exp* nr) n->type = OR_type; n->cost = 0.0; - n->u.l = ell = pool_alloc(dict->E_list_pool); + n->operand_first = ell = pool_alloc(dict->E_list_pool); ell->next = elr = pool_alloc(dict->E_list_pool); elr->next = NULL; @@ -929,9 +929,9 @@ static Exp * make_dir_connector(Dictionary dict, int i) n->multi = false; } - n->u.condesc = condesc_add(&dict->contable, + n->condesc = condesc_add(&dict->contable, string_set_add(constring, dict->string_set)); - if (NULL == n->u.condesc) return NULL; /* Table ovf */ + if (NULL == n->condesc) return NULL; /* Table ovf */ n->type = CONNECTOR_type; n->cost = 0.0; return n; @@ -1034,7 +1034,7 @@ static Exp *make_or_node_from_pool(Sentence sent, Exp *nl, Exp *nr) n->type = OR_type; n->cost = 0.0; - n->u.l = ell = (E_list *) pool_alloc(sent->E_list_pool); + n->operand_first = ell = (E_list *) pool_alloc(sent->E_list_pool); ell->next = elr = (E_list *) pool_alloc(sent->E_list_pool); elr->next = NULL; @@ -1048,7 +1048,7 @@ static Exp *make_zeroary_node_from_pool(Sentence sent) Exp * n = pool_alloc(sent->Exp_pool); n->type = AND_type; /* these must be AND types */ n->cost = 0.0; - n->u.l = NULL; + n->operand_first = NULL; return n; } @@ -1083,7 +1083,7 @@ void add_empty_word(Sentence sent, X_node *x) /* zn points at {ZZZ+} */ zn = pool_alloc(sent->Exp_pool); zn->dir = '+'; - zn->u.condesc = condesc_add(&sent->dict->contable, ZZZ); + zn->condesc = condesc_add(&sent->dict->contable, ZZZ); zn->multi = false; zn->type = CONNECTOR_type; zn->cost = 0.0; @@ -1103,7 +1103,7 @@ void add_empty_word(Sentence sent, X_node *x) an = pool_alloc(sent->Exp_pool); an->type = AND_type; an->cost = 0.0; - an->u.l = elist; + an->operand_first = elist; x->exp = an; } @@ -1157,7 +1157,7 @@ static Exp *operator_exp(Dictionary dict, int type) dict_error(dict, "An \"or\" or \"and\" of nothing"); return NULL; } - n->u.l = first.next; + n->operand_first = first.next; return n; } @@ -1420,7 +1420,7 @@ static Exp *make_expression(Dictionary dict) else { e_head = make_op_Exp(dict, op); - e_head->u.l = make_E_list_val(dict, nl); + e_head->operand_first = make_E_list_val(dict, nl); } if (!link_advance(dict)) { @@ -1428,7 +1428,7 @@ static Exp *make_expression(Dictionary dict) } if (el_tail == NULL) - el_tail = e_head->u.l; + el_tail = e_head->operand_first; } /* unreachable */ } @@ -1545,7 +1545,7 @@ Dict_node *insert_dict(Dictionary dict, Dict_node *n, Dict_node *newnode) { if (NULL == n) return newnode; - static Exp null_exp = { .type = AND_type, .u.l = NULL }; + static Exp null_exp = { .type = AND_type, .operand_first = NULL }; int comp = dict_order_strict(newnode->string, n); if (0 == comp && /* Suppress reporting duplicate idioms until they are fixed. */ diff --git a/link-grammar/dict-sql/read-sql.c b/link-grammar/dict-sql/read-sql.c index 77358b1c9e..e904d524e4 100644 --- a/link-grammar/dict-sql/read-sql.c +++ b/link-grammar/dict-sql/read-sql.c @@ -91,7 +91,7 @@ static const char * make_expression(Dictionary dict, e->multi = false; } - e->u.condesc = condesc_add(&dict->contable, + e->condesc = condesc_add(&dict->contable, string_set_add(constr, dict->string_set)); *pex = e; } @@ -126,7 +126,7 @@ static const char * make_expression(Dictionary dict, Exp* join = Exp_create(dict); join->type = etype; join->cost = 0.0; - E_list *ell = join->u.l = pool_alloc(dict->E_list_pool); + E_list *ell = join->operand_first = pool_alloc(dict->E_list_pool); E_list *elr = ell->next = pool_alloc(dict->E_list_pool); elr->next = NULL; @@ -194,7 +194,7 @@ static int exp_cb(void *user_data, int argc, char **argv, char **colName) Exp* orn = Exp_create(dict); orn->type = OR_type; orn->cost = 0.0; - orn->u.l = ell = pool_alloc(dict->E_list_pool); + orn->operand_first = ell = pool_alloc(dict->E_list_pool); ell->next = elr = pool_alloc(dict->E_list_pool); elr->next = NULL; @@ -207,8 +207,8 @@ static int exp_cb(void *user_data, int argc, char **argv, char **colName) /* Extend the OR-chain for the third and later expressions. */ E_list* more = pool_alloc(dict->E_list_pool); more->e = exp; - more->next = bs->exp->u.l; - bs->exp->u.l = more; + more->next = bs->exp->operand_first; + bs->exp->operand_first = more; return 0; } diff --git a/link-grammar/prepare/build-disjuncts.c b/link-grammar/prepare/build-disjuncts.c index 4d2313c2ea..be4f620b18 100644 --- a/link-grammar/prepare/build-disjuncts.c +++ b/link-grammar/prepare/build-disjuncts.c @@ -165,7 +165,7 @@ static Clause * build_clause(Exp *e, clause_context *ct) c1->next = NULL; c1->cost = 0.0; c1->maxcost = 0.0; - for (e_list = e->u.l; e_list != NULL; e_list = e_list->next) + for (e_list = e->operand_first; e_list != NULL; e_list = e_list->next) { c2 = build_clause(e_list->e, ct); c_head = NULL; @@ -194,9 +194,9 @@ static Clause * build_clause(Exp *e, clause_context *ct) } else if (e->type == OR_type) { - c = build_clause(e->u.l->e, ct); + c = build_clause(e->operand_first->e, ct); /* we'll catenate the lists of clauses */ - for (e_list = e->u.l->next; e_list != NULL; e_list = e_list->next) + for (e_list = e->operand_first->next; e_list != NULL; e_list = e_list->next) { c1 = build_clause(e_list->e, ct); if (c1 == NULL) continue; @@ -278,7 +278,7 @@ build_disjunct(Sentence sent, Clause * cl, const char * string, /* Build a list of connectors from the Tconnectors. */ for (Tconnector *t = cl->c; t != NULL; t = t->next) { - Connector *n = connector_new(connector_pool, t->e->u.condesc, opts); + Connector *n = connector_new(connector_pool, t->e->condesc, opts); Connector **loc = ('-' == t->e->dir) ? &ndis->left : &ndis->right; n->multi = t->e->multi; @@ -328,7 +328,7 @@ static void print_Tconnector_list(Tconnector *t) for (; t != NULL; t = t->next) { if (t->e->multi) printf("@"); - printf("%s", t->e->u.condesc->string); + printf("%s", t->e->condesc->string); printf("%c", t->e->dir); if (t->next != NULL) printf(" "); } @@ -354,7 +354,7 @@ GNUC_UNUSED void prt_exp(Exp *e, int i) printf ("type=%d dir=%c multi=%d cost=%f\n", e->type, e->dir, e->multi, e->cost); if (e->type != CONNECTOR_type) { - E_list *l = e->u.l; + E_list *l = e->operand_first; while(l) { prt_exp(l->e, i+2); @@ -364,7 +364,7 @@ GNUC_UNUSED void prt_exp(Exp *e, int i) else { for(int j =0; ju.condesc->string); + printf("con=%s\n", e->condesc->string); } } @@ -391,15 +391,15 @@ GNUC_UNUSED void prt_exp_mem(Exp *e, int i) { E_list *l; for(int j =0; ju.l); - for (l = e->u.l; NULL != l; l = l->next) + printf("E_list=%p (", e->operand_first); + for (l = e->operand_first; NULL != l; l = l->next) { printf("%p", l->e); if (NULL != l->next) printf(" "); } printf(")\n"); - for (l = e->u.l; NULL != l; l = l->next) + for (l = e->operand_first; NULL != l; l = l->next) { prt_exp_mem(l->e, i+2); } @@ -408,7 +408,7 @@ GNUC_UNUSED void prt_exp_mem(Exp *e, int i) { for(int j =0; ju.condesc ? e->u.condesc->string : "(condesc=(null))", + e->condesc ? e->condesc->string : "(condesc=(null))", e->dir, e->multi); } } diff --git a/link-grammar/prepare/exprune.c b/link-grammar/prepare/exprune.c index 844286d74d..dfe9487545 100644 --- a/link-grammar/prepare/exprune.c +++ b/link-grammar/prepare/exprune.c @@ -219,7 +219,7 @@ static Exp* purge_Exp(exprune_context *ctxt, int w, Exp *e, char dir) { if (e->dir == dir) { - if (!matches_S(ctxt->ct, w, e->u.condesc)) + if (!matches_S(ctxt->ct, w, e->condesc)) { ctxt->N_deleted++; return NULL; @@ -231,24 +231,24 @@ static Exp* purge_Exp(exprune_context *ctxt, int w, Exp *e, char dir) if (e->type == AND_type) { - if (!and_purge_E_list(ctxt, w, e->u.l, dir)) + if (!and_purge_E_list(ctxt, w, e->operand_first, dir)) { return NULL; } } else /* if we are here, its OR_type */ { - e->u.l = or_purge_E_list(ctxt, w, e->u.l, dir); - if (e->u.l == NULL) + e->operand_first = or_purge_E_list(ctxt, w, e->operand_first, dir); + if (e->operand_first == NULL) { return NULL; } } /* Unary node elimination (for a slight performance improvement). */ - if ((e->u.l != NULL) && (e->u.l->next == NULL)) + if ((e->operand_first != NULL) && (e->operand_first->next == NULL)) { - Exp *ne = e->u.l->e; + Exp *ne = e->operand_first->e; ne->cost += e->cost; return ne; } @@ -302,19 +302,19 @@ static void insert_connectors(exprune_context *ctxt, int w, Exp * e, int dir) { if (e->dir == dir) { - assert(NULL != e->u.condesc, "NULL connector"); - Connector c = { .desc = e->u.condesc }; + assert(NULL != e->condesc, "NULL connector"); + Connector c = { .desc = e->condesc }; set_connector_length_limit(&c, ctxt->opts); int farthest_word = (dir == '-') ? -MAX(0, w-c.length_limit) : w+c.length_limit; - insert_connector(ctxt, farthest_word, e->u.condesc); + insert_connector(ctxt, farthest_word, e->condesc); } } else { E_list *l; - for (l=e->u.l; l!=NULL; l=l->next) + for (l=e->operand_first; l!=NULL; l=l->next) { insert_connectors(ctxt, w, l->e, dir); } diff --git a/link-grammar/sat-solver/sat-encoder.cpp b/link-grammar/sat-solver/sat-encoder.cpp index ea3386a73f..c981ca30ce 100644 --- a/link-grammar/sat-solver/sat-encoder.cpp +++ b/link-grammar/sat-solver/sat-encoder.cpp @@ -370,15 +370,15 @@ void SATEncoder::generate_satisfaction_for_expression(int w, int& dfs_position, } } else { if (e->type == AND_type) { - if (e->u.l == NULL) { + if (e->operand_first == NULL) { /* zeroary and */ _variables->string_cost(var, e->cost); if (total_cost > _cost_cutoff) { generate_literal(~Lit(_variables->string_cost(var, e->cost))); } - } else if (e->u.l->next == NULL) { + } else if (e->operand_first->next == NULL) { /* unary and - skip */ - generate_satisfaction_for_expression(w, dfs_position, e->u.l->e, var, total_cost); + generate_satisfaction_for_expression(w, dfs_position, e->operand_first->e, var, total_cost); } else { /* n-ary and */ int i; @@ -392,7 +392,7 @@ void SATEncoder::generate_satisfaction_for_expression(int w, int& dfs_position, } vec rhs; - for (i = 0, l=e->u.l; l!=NULL; l=l->next, i++) { + for (i = 0, l=e->operand_first; l!=NULL; l=l->next, i++) { // sprintf(new_var, "%sc%d", var, i) char* s = last_new_var; *s++ = 'c'; @@ -405,7 +405,7 @@ void SATEncoder::generate_satisfaction_for_expression(int w, int& dfs_position, /* Precedes */ int dfs_position_tmp = dfs_position; - for (l = e->u.l; l->next != NULL; l = l->next) { + for (l = e->operand_first; l->next != NULL; l = l->next) { Exp e_tmp, *e_rhs = &e_tmp; if (l->next->next == NULL) { @@ -435,14 +435,14 @@ void SATEncoder::generate_satisfaction_for_expression(int w, int& dfs_position, // Clause: -link_cw_(2_4_K)_6 -link_cw_(2_6_O*n)_5 // Clearly, they cannot be concluded transitively. e_rhs->type = AND_type; - e_rhs->u.l = l->next; + e_rhs->operand_first = l->next; e_rhs->cost = 0.0; }; generate_conjunct_order_constraints(w, l->e, e_rhs, dfs_position_tmp); } /* Recurse */ - for (i = 0, l=e->u.l; l!=NULL; l=l->next, i++) { + for (i = 0, l=e->operand_first; l!=NULL; l=l->next, i++) { // sprintf(new_var, "%sc%d", var, i) char* s = last_new_var; *s++ = 'c'; @@ -453,13 +453,13 @@ void SATEncoder::generate_satisfaction_for_expression(int w, int& dfs_position, } } } else if (e->type == OR_type) { - if (e->u.l == NULL) { + if (e->operand_first == NULL) { /* zeroary or */ cerr << "Zeroary OR" << endl; exit(EXIT_FAILURE); - } else if (e->u.l->next == NULL) { + } else if (e->operand_first->next == NULL) { /* unary or */ - generate_satisfaction_for_expression(w, dfs_position, e->u.l->e, var, total_cost); + generate_satisfaction_for_expression(w, dfs_position, e->operand_first->e, var, total_cost); } else { /* n-ary or */ int i; @@ -473,7 +473,7 @@ void SATEncoder::generate_satisfaction_for_expression(int w, int& dfs_position, } vec rhs; - for (i = 0, l=e->u.l; l!=NULL; l=l->next, i++) { + for (i = 0, l=e->operand_first; l!=NULL; l=l->next, i++) { // sprintf(new_var, "%sc%d", var, i) char* s = last_new_var; *s++ = 'd'; @@ -486,7 +486,7 @@ void SATEncoder::generate_satisfaction_for_expression(int w, int& dfs_position, generate_xor_conditions(rhs); /* Recurse */ - for (i = 0, l=e->u.l; l!=NULL; l=l->next, i++) { + for (i = 0, l=e->operand_first; l!=NULL; l=l->next, i++) { char* s = last_new_var; *s++ = 'd'; fast_sprintf(s, i); @@ -518,7 +518,7 @@ Exp* SATEncoder::join_alternatives(int w) } exp = (Exp*) malloc(sizeof(Exp)); exp->type = OR_type; - exp->u.l = or_list; + exp->operand_first = or_list; exp->cost = 0.0; return exp; @@ -526,7 +526,7 @@ Exp* SATEncoder::join_alternatives(int w) void SATEncoder::free_alternatives(Exp* exp) { - E_list *l = exp->u.l; + E_list *l = exp->operand_first; while (l != NULL) { E_list* next = l->next; free(l); @@ -539,7 +539,7 @@ void SATEncoder::free_alternatives(Exp* exp) void SATEncoder::generate_link_cw_ordinary_definition(size_t wi, int pi, Exp* e, size_t wj) { - const char* Ci = e->u.condesc->string; + const char* Ci = e->condesc->string; char dir = e->dir; double cost = e->cost; Lit lhs = Lit(_variables->link_cw(wj, wi, pi, Ci)); @@ -583,7 +583,7 @@ int SATEncoder::num_connectors(Exp* e) return 1; else { int num = 0; - for (E_list* l = e->u.l; l != NULL; l = l->next) { + for (E_list* l = e->operand_first; l != NULL; l = l->next) { num += num_connectors(l->e); } return num; @@ -595,13 +595,13 @@ int SATEncoder::empty_connectors(Exp* e, char dir) if (e->type == CONNECTOR_type) { return e->dir != dir; } else if (e->type == OR_type) { - for (E_list* l = e->u.l; l != NULL; l = l->next) { + for (E_list* l = e->operand_first; l != NULL; l = l->next) { if (empty_connectors(l->e, dir)) return true; } return false; } else if (e->type == AND_type) { - for (E_list* l = e->u.l; l != NULL; l = l->next) { + for (E_list* l = e->operand_first; l != NULL; l = l->next) { if (!empty_connectors(l->e, dir)) return false; } @@ -616,13 +616,13 @@ int SATEncoder::non_empty_connectors(Exp* e, char dir) if (e->type == CONNECTOR_type) { return e->dir == dir; } else if (e->type == OR_type) { - for (E_list* l = e->u.l; l != NULL; l = l->next) { + for (E_list* l = e->operand_first; l != NULL; l = l->next) { if (non_empty_connectors(l->e, dir)) return true; } return false; } else if (e->type == AND_type) { - for (E_list* l = e->u.l; l != NULL; l = l->next) { + for (E_list* l = e->operand_first; l != NULL; l = l->next) { if (non_empty_connectors(l->e, dir)) return true; } @@ -656,11 +656,11 @@ void SATEncoder::trailing_connectors(int w, Exp* exp, char dir, int& dfs_positio connectors.push_back(_word_tags[w].get(dfs_position)); } } else if (exp->type == OR_type) { - for (E_list* l = exp->u.l; l != NULL; l = l->next) { + for (E_list* l = exp->operand_first; l != NULL; l = l->next) { trailing_connectors(w, l->e, dir, dfs_position, connectors); } } else if (exp->type == AND_type) { - trailing_connectors_and_aux(w, exp->u.l, dir, dfs_position, connectors); + trailing_connectors_and_aux(w, exp->operand_first, dir, dfs_position, connectors); } } @@ -673,16 +673,16 @@ void SATEncoder::certainly_non_trailing(int w, Exp* exp, char dir, int& dfs_posi connectors.push_back(_word_tags[w].get(dfs_position)); } } else if (exp->type == OR_type) { - for (E_list* l = exp->u.l; l != NULL; l = l->next) { + for (E_list* l = exp->operand_first; l != NULL; l = l->next) { certainly_non_trailing(w, l->e, dir, dfs_position, connectors, has_right); } } else if (exp->type == AND_type) { if (has_right) { - for (E_list* l = exp->u.l; l != NULL; l = l->next) { + for (E_list* l = exp->operand_first; l != NULL; l = l->next) { certainly_non_trailing(w, l->e, dir, dfs_position, connectors, true); } } else { - for (E_list* l = exp->u.l; l != NULL; l = l->next) { + for (E_list* l = exp->operand_first; l != NULL; l = l->next) { has_right = false; for (E_list* m = l->next; m != NULL; m = m->next) { if (non_empty_connectors(m->e, dir) && !empty_connectors(m->e, dir)) { @@ -704,12 +704,12 @@ void SATEncoder::leading_connectors(int w, Exp* exp, char dir, int& dfs_position connectors.push_back(_word_tags[w].get(dfs_position)); } } else if (exp->type == OR_type) { - for (E_list* l = exp->u.l; l != NULL; l = l->next) { + for (E_list* l = exp->operand_first; l != NULL; l = l->next) { leading_connectors(w, l->e, dir, dfs_position, connectors); } } else if (exp->type == AND_type) { E_list* l; - for (l = exp->u.l; l != NULL; l = l->next) { + for (l = exp->operand_first; l != NULL; l = l->next) { leading_connectors(w, l->e, dir, dfs_position, connectors); if (!empty_connectors(l->e, dir)) break; @@ -1178,15 +1178,15 @@ bool SATEncoder::generate_epsilon_for_expression(int w, int& dfs_position, Exp* } } } else if (e->type == AND_type) { - if (e->u.l == NULL) { + if (e->operand_first == NULL) { /* zeroary and */ generate_equivalence_definition(Lit(_variables->string(var)), Lit(_variables->epsilon(var, dir))); return true; } else - if (e->u.l != NULL && e->u.l->next == NULL) { + if (e->operand_first != NULL && e->operand_first->next == NULL) { /* unary and - skip */ - return generate_epsilon_for_expression(w, dfs_position, e->u.l->e, var, root, dir); + return generate_epsilon_for_expression(w, dfs_position, e->operand_first->e, var, root, dir); } else { /* Recurse */ E_list* l; @@ -1202,7 +1202,7 @@ bool SATEncoder::generate_epsilon_for_expression(int w, int& dfs_position, Exp* } - for (i = 0, l = e->u.l; l != NULL; l = l->next, i++) { + for (i = 0, l = e->operand_first; l != NULL; l = l->next, i++) { // sprintf(new_var, "%sc%d", var, i) char* s = last_new_var; *s++ = 'c'; @@ -1222,7 +1222,7 @@ bool SATEncoder::generate_epsilon_for_expression(int w, int& dfs_position, Exp* if (!root && eps) { Lit lhs = Lit(_variables->epsilon(var, dir)); vec rhs; - for (i = 0, l=e->u.l; l!=NULL; l=l->next, i++) { + for (i = 0, l=e->operand_first; l!=NULL; l=l->next, i++) { // sprintf(new_var, "%sc%d", var, i) char* s = last_new_var; *s++ = 'c'; @@ -1234,9 +1234,9 @@ bool SATEncoder::generate_epsilon_for_expression(int w, int& dfs_position, Exp* return eps; } } else if (e->type == OR_type) { - if (e->u.l != NULL && e->u.l->next == NULL) { + if (e->operand_first != NULL && e->operand_first->next == NULL) { /* unary or - skip */ - return generate_epsilon_for_expression(w, dfs_position, e->u.l->e, var, root, dir); + return generate_epsilon_for_expression(w, dfs_position, e->operand_first->e, var, root, dir); } else { /* Recurse */ E_list* l; @@ -1252,7 +1252,7 @@ bool SATEncoder::generate_epsilon_for_expression(int w, int& dfs_position, Exp* } vec rhs; - for (i = 0, l = e->u.l; l != NULL; l = l->next, i++) { + for (i = 0, l = e->operand_first; l != NULL; l = l->next, i++) { // sprintf(new_var, "%sc%d", var, i) char* s = last_new_var; *s++ = 'd'; @@ -1715,7 +1715,7 @@ void SATEncoderConjunctionFreeSentences::determine_satisfaction(int w, char* nam void SATEncoderConjunctionFreeSentences::generate_satisfaction_for_connector( int wi, int pi, Exp *e, char* var) { - const char* Ci = e->u.condesc->string; + const char* Ci = e->condesc->string; char dir = e->dir; bool multi = e->multi; double cost = e->cost; @@ -1814,7 +1814,7 @@ Exp* SATEncoderConjunctionFreeSentences::PositionConnector2exp(const PositionCon e->type = CONNECTOR_type; e->dir = pc->dir; e->multi = pc->connector.multi; - e->u.condesc = (condesc_t *)pc->connector.desc; // FIXME - const + e->condesc = (condesc_t *)pc->connector.desc; // FIXME - const e->cost = pc->cost; return e; diff --git a/link-grammar/sat-solver/util.cpp b/link-grammar/sat-solver/util.cpp index f01445e965..b8f3645728 100644 --- a/link-grammar/sat-solver/util.cpp +++ b/link-grammar/sat-solver/util.cpp @@ -44,7 +44,7 @@ Exp* null_exp() static Exp e; if (e.type) return &e; - e.u.l = NULL; + e.operand_first = NULL; e.type = AND_type; return &e; } @@ -70,7 +70,7 @@ void add_anded_exp(Exp*& orig, Exp* addit) orig = (Exp*) malloc(sizeof(Exp)); orig->type = AND_type; orig->cost = 0.0; - orig->u.l = elist; + orig->operand_first = elist; } } diff --git a/link-grammar/sat-solver/word-tag.cpp b/link-grammar/sat-solver/word-tag.cpp index dd58523bc1..aac69c484f 100644 --- a/link-grammar/sat-solver/word-tag.cpp +++ b/link-grammar/sat-solver/word-tag.cpp @@ -61,7 +61,7 @@ void WordTag::insert_connectors(Exp* exp, int& dfs_position, throw std::string("Unknown connector direction: ") + exp->dir; } } else if (exp->type == AND_type) { - if (exp->u.l == NULL) { + if (exp->operand_first == NULL) { /* zeroary and */ if (cost != 0) { @@ -70,9 +70,9 @@ void WordTag::insert_connectors(Exp* exp, int& dfs_position, _empty_connectors.push_back(EmptyConnector(_variables->string(var),cost)); } } else - if (exp->u.l->next == NULL) { + if (exp->operand_first->next == NULL) { /* unary and - skip */ - insert_connectors(exp->u.l->e, dfs_position, leading_right, + insert_connectors(exp->operand_first->e, dfs_position, leading_right, leading_left, eps_right, eps_left, var, root, cost, parent_exp, word_xnode); } else { int i; @@ -86,7 +86,7 @@ void WordTag::insert_connectors(Exp* exp, int& dfs_position, last_var++; } - for (i = 0, l = exp->u.l; l != NULL; l = l->next, i++) { + for (i = 0, l = exp->operand_first; l != NULL; l = l->next, i++) { char* s = last_new_var; *s++ = 'c'; fast_sprintf(s, i); @@ -104,10 +104,10 @@ void WordTag::insert_connectors(Exp* exp, int& dfs_position, } } } else if (exp->type == OR_type) { - if (exp->u.l != NULL && exp->u.l->next == NULL) { + if (exp->operand_first != NULL && exp->operand_first->next == NULL) { /* unary or - skip */ - insert_connectors(exp->u.l->e, dfs_position, leading_right, leading_left, - eps_right, eps_left, var, root, cost, exp->u.l->e, word_xnode); + insert_connectors(exp->operand_first->e, dfs_position, leading_right, leading_left, + eps_right, eps_left, var, root, cost, exp->operand_first->e, word_xnode); } else { int i; E_list* l; @@ -129,7 +129,7 @@ void WordTag::insert_connectors(Exp* exp, int& dfs_position, } #endif - for (i = 0, l = exp->u.l; l != NULL; l = l->next, i++) { + for (i = 0, l = exp->operand_first; l != NULL; l = l->next, i++) { bool lr = leading_right, ll = leading_left; std::vector er = eps_right, el = eps_left; diff --git a/link-grammar/sat-solver/word-tag.hpp b/link-grammar/sat-solver/word-tag.hpp index 96b87325f5..b6a08d28aa 100644 --- a/link-grammar/sat-solver/word-tag.hpp +++ b/link-grammar/sat-solver/word-tag.hpp @@ -28,11 +28,11 @@ struct PositionConnector eps_right(er), eps_left(el), word_xnode(w_xnode) { if (word_xnode == NULL) { - cerr << "Internal error: Word" << w << ": " << "; connector: '" << e->u.condesc->string << "'; X_node: " << (word_xnode?word_xnode->string: "(null)") << endl; + cerr << "Internal error: Word" << w << ": " << "; connector: '" << e->condesc->string << "'; X_node: " << (word_xnode?word_xnode->string: "(null)") << endl; } // Initialize some fields in the connector struct. - connector.desc = e->u.condesc; + connector.desc = e->condesc; connector.multi = e->multi; set_connector_length_limit(&connector, opts); connector.originating_gword = &w_xnode->word->gword_set_head; From 6cfb6d8b21c8a3ffe3038c725372de3b02e684ce Mon Sep 17 00:00:00 2001 From: ampli Date: Thu, 11 Jul 2019 18:44:38 +0300 Subject: [PATCH 3/9] Eliminate E_list Implement that by merging Exp and E_list. --- link-grammar/api.c | 5 - link-grammar/connectors.c | 4 +- link-grammar/dict-common/dict-common.c | 1 - link-grammar/dict-common/dict-common.h | 2 - link-grammar/dict-common/dict-structures.h | 2 +- link-grammar/dict-common/dict-utils.c | 102 ++++--------- link-grammar/dict-common/dict-utils.h | 3 +- link-grammar/dict-common/idiom.c | 32 ++-- link-grammar/dict-common/print-dict.c | 43 +++--- link-grammar/dict-file/dictionary.c | 11 +- link-grammar/dict-file/read-dict.c | 140 ++++++++--------- link-grammar/dict-sql/read-sql.c | 27 ++-- link-grammar/prepare/build-disjuncts.c | 91 ++++++----- link-grammar/prepare/exprune.c | 113 ++++++++++---- link-grammar/sat-solver/sat-encoder.cpp | 167 +++++++++------------ link-grammar/sat-solver/sat-encoder.hpp | 7 +- link-grammar/sat-solver/util.cpp | 84 ++++++++--- link-grammar/sat-solver/util.hpp | 4 +- link-grammar/sat-solver/word-tag.cpp | 35 +++-- link-grammar/tokenize/tokenize.c | 2 +- 20 files changed, 449 insertions(+), 426 deletions(-) diff --git a/link-grammar/api.c b/link-grammar/api.c index c0ff3537f3..563dbfc2bd 100644 --- a/link-grammar/api.c +++ b/link-grammar/api.c @@ -436,9 +436,6 @@ Sentence sentence_create(const char *input_string, Dictionary dict) sent->dict = dict; sent->string_set = string_set_create(); sent->rand_state = global_rand_state; - sent->E_list_pool = pool_new(__func__, "E_list", /*num_elements*/4096, - sizeof(E_list), /*zero_out*/false, - /*align*/false, /*exact*/false); sent->Exp_pool = pool_new(__func__, "Exp", /*num_elements*/4096, sizeof(Exp), /*zero_out*/false, /*align*/false, /*exact*/false); @@ -533,13 +530,11 @@ void sentence_delete(Sentence sent) global_rand_state = sent->rand_state; pool_delete(sent->fm_Match_node); pool_delete(sent->Table_connector_pool); - pool_delete(sent->E_list_pool); pool_delete(sent->Exp_pool); pool_delete(sent->X_node_pool); if (IS_DB_DICT(sent->dict)) { condesc_reuse(sent->dict); - pool_reuse(sent->dict->E_list_pool); pool_reuse(sent->dict->Exp_pool); } diff --git a/link-grammar/connectors.c b/link-grammar/connectors.c index b075234d93..cab3656449 100644 --- a/link-grammar/connectors.c +++ b/link-grammar/connectors.c @@ -89,9 +89,9 @@ static size_t get_connectors_from_expression(condesc_t **conlist, const Exp *e) } size_t cl_size = 0; - for (E_list *l = e->operand_first; l != NULL; l = l->next) + for (Exp *opd = e->operand_first; opd != NULL; opd = opd->operand_next) { - cl_size += get_connectors_from_expression(conlist, l->e); + cl_size += get_connectors_from_expression(conlist, opd); if (NULL != conlist) conlist++; } diff --git a/link-grammar/dict-common/dict-common.c b/link-grammar/dict-common/dict-common.c index 6a1dd9ed21..cadb80f96a 100644 --- a/link-grammar/dict-common/dict-common.c +++ b/link-grammar/dict-common/dict-common.c @@ -260,7 +260,6 @@ static void free_dictionary(Dictionary dict) free_dict_node_recursive(dict->root); free_Word_file(dict->word_file_header); pool_delete(dict->Exp_pool); - pool_delete(dict->E_list_pool); } static void affix_list_delete(Dictionary dict) diff --git a/link-grammar/dict-common/dict-common.h b/link-grammar/dict-common/dict-common.h index be4f6d90a1..acd6942e69 100644 --- a/link-grammar/dict-common/dict-common.h +++ b/link-grammar/dict-common/dict-common.h @@ -115,9 +115,7 @@ struct Dictionary_s Word_file * word_file_header; ConTable contable; - /* Memory pools */ Pool_desc * Exp_pool; - Pool_desc * E_list_pool; /* Private data elements that come in play only while the * dictionary is being read, and are not otherwise used. diff --git a/link-grammar/dict-common/dict-structures.h b/link-grammar/dict-common/dict-structures.h index acd97a1a4b..8e86f5103e 100644 --- a/link-grammar/dict-common/dict-structures.h +++ b/link-grammar/dict-common/dict-structures.h @@ -52,7 +52,7 @@ struct Exp_struct bool multi; /* TRUE if a multi-connector (for connector). */ union { - E_list *operand_first; /* First operand (for non-terminals). */ + Exp *operand_first; /* First operand (for non-terminals). */ condesc_t *condesc; /* Only needed if it's a connector. */ }; double cost; /* The cost of using this expression. */ diff --git a/link-grammar/dict-common/dict-utils.c b/link-grammar/dict-common/dict-utils.c index b097ee57c9..c698500141 100644 --- a/link-grammar/dict-common/dict-utils.c +++ b/link-grammar/dict-common/dict-utils.c @@ -30,76 +30,42 @@ const char * lg_exp_get_string(const Exp* exp) } /* ======================================================== */ -/* Exp utilities ... */ - -void free_E_list(E_list *); -void free_Exp(Exp * e) +void free_Exp(Exp *e) { - // Exp might be null if the user has a bad dict. e.g. badly formed - // SQL dict. - if (NULL == e) return; - if (e->type != CONNECTOR_type) { - free_E_list(e->operand_first); + if (NULL == e) return; /* Exp might be null if the user has a bad dict. */ + if (e->type != CONNECTOR_type) + { + for (Exp *opd = e->operand_first; opd != NULL; opd = opd->operand_next) + free_Exp(opd); } free(e); } - -void free_E_list(E_list * l) -{ - if (l == NULL) return; - free_E_list(l->next); - free_Exp(l->e); - free(l); -} +/* Exp utilities ... */ /* Returns the number of connectors in the expression e */ int size_of_expression(Exp * e) { - int size; - E_list * l; - if (e->type == CONNECTOR_type) return 1; - size = 0; - for (l=e->operand_first; l!=NULL; l=l->next) { - size += size_of_expression(l->e); - } - return size; -} - -/** - * Build a copy of the given expression (don't copy strings, of course) - */ -static E_list *copy_E_list(E_list *l, Pool_desc* mp[]) -{ + int size = 0; - E_list el_head; - E_list *el = &el_head; - - for (; l != NULL; l = l->next) - { - E_list *nl = pool_alloc(mp[0]); - - nl->e = pool_alloc(mp[1]); - *nl->e = *l->e; - el->next = nl; - el = nl; - if (l->e->type != CONNECTOR_type) - nl->e->operand_first = copy_E_list(l->e->operand_first, mp); - } - el->next = NULL; + if (e->type == CONNECTOR_type) return 1; + for (Exp *opd = e->operand_first; opd != NULL; opd = opd->operand_next) + size += size_of_expression(opd); - return el_head.next; + return size; } -Exp *copy_Exp(Exp *e, Pool_desc *E_list_pool, Pool_desc *Exp_pool) +Exp *copy_Exp(Exp *e, Pool_desc *Exp_pool) { if (e == NULL) return NULL; - Exp *ne = pool_alloc(Exp_pool); + Exp *new_e = pool_alloc(Exp_pool); + + *new_e = *e; - *ne = *e; - if (CONNECTOR_type == e->type) return ne; + new_e->operand_next = copy_Exp(e->operand_next, Exp_pool); + if (CONNECTOR_type == e->type) return new_e; + new_e->operand_first = copy_Exp(e->operand_first, Exp_pool); - ne->operand_first = copy_E_list(ne->operand_first, (Pool_desc*[]){E_list_pool, Exp_pool}); - return ne; + return new_e; } /** @@ -107,8 +73,6 @@ Exp *copy_Exp(Exp *e, Pool_desc *E_list_pool, Pool_desc *Exp_pool) */ static bool exp_compare(Exp * e1, Exp * e2) { - E_list *el1, *el2; - if ((e1 == NULL) && (e2 == NULL)) return 1; /* they are equal */ if ((e1 == NULL) || (e2 == NULL)) @@ -127,18 +91,18 @@ static bool exp_compare(Exp * e1, Exp * e2) } else { - el1 = e1->operand_first; - el2 = e2->operand_first; + e1 = e1->operand_first; + e2 = e2->operand_first; /* while at least 1 is non-null */ - for (;(el1!=NULL)||(el2!=NULL);) { + for (;(e1!=NULL)||(e2!=NULL);) { /*fail if 1 is null */ - if ((el1==NULL)||(el2==NULL)) + if ((e1==NULL)||(e2==NULL)) return 0; /* fail if they are not compared */ - if (!exp_compare(el1->e, el2->e)) + if (!exp_compare(e1, e2)) return 0; - el1 = el1->next; - el2 = el2->next; + e1 = e1->operand_next; + e2 = e2->operand_next; } } return 1; /* if never returned 0, return 1 */ @@ -150,8 +114,6 @@ static bool exp_compare(Exp * e1, Exp * e2) */ static int exp_contains(Exp * super, Exp * sub) { - E_list * el; - #if 0 /* DEBUG */ printf("SUP: "); if (super) print_expression(super); @@ -167,8 +129,9 @@ static int exp_contains(Exp * super, Exp * sub) /* proceed through supers children and return 1 if sub is contained in any of them */ - for(el = super->operand_first; el!=NULL; el=el->next) { - if (exp_contains(el->e, sub)==1) + for(Exp *opd = super->operand_first; opd != NULL; opd = opd->operand_next) + { + if (exp_contains(opd, sub)==1) return 1; } return 0; @@ -248,7 +211,6 @@ bool word_has_connector(Dict_node * dn, const char * cs, char direction) static bool exp_has_connector(const Exp * e, int depth, const char * cs, char direction, bool smart_match) { - E_list * el; if (e->type == CONNECTOR_type) { if (direction != e->dir) return false; @@ -259,9 +221,9 @@ static bool exp_has_connector(const Exp * e, int depth, const char * cs, if (depth == 0) return false; if (depth > 0) depth--; - for (el = e->operand_first; el != NULL; el = el->next) + for (Exp *opd = e->operand_first; opd != NULL; opd = opd->operand_next) { - if (exp_has_connector(el->e, depth, cs, direction, smart_match)) + if (exp_has_connector(opd, depth, cs, direction, smart_match)) return true; } return false; diff --git a/link-grammar/dict-common/dict-utils.h b/link-grammar/dict-common/dict-utils.h index 58e04818d2..a6f0a76161 100644 --- a/link-grammar/dict-common/dict-utils.h +++ b/link-grammar/dict-common/dict-utils.h @@ -18,9 +18,8 @@ /* Exp utilities ... */ void free_Exp(Exp *); -void free_E_list(E_list *); int size_of_expression(Exp *); -Exp * copy_Exp(Exp *, Pool_desc *, Pool_desc *); +Exp * copy_Exp(Exp *, Pool_desc *); bool is_exp_like_empty_word(Dictionary dict, Exp *); /* X_node utilities ... */ diff --git a/link-grammar/dict-common/idiom.c b/link-grammar/dict-common/idiom.c index 9c2809482c..1d594bacab 100644 --- a/link-grammar/dict-common/idiom.c +++ b/link-grammar/dict-common/idiom.c @@ -216,7 +216,6 @@ static const char * generate_id_connector(Dictionary dict) void insert_idiom(Dictionary dict, Dict_node * dn) { Exp * nc, * no, * n1; - E_list *ell, *elr; const char * s; Dict_node * dn_list, * xdn, * start_dn_list; @@ -246,15 +245,13 @@ void insert_idiom(Dictionary dict, Dict_node * dn) nc->dir = '-'; nc->multi = false; nc->type = CONNECTOR_type; + nc->operand_next = no; nc->cost = 0; n1 = Exp_create(dict); - n1->operand_first = ell = pool_alloc(dict->Exp_pool); - ell->next = elr = pool_alloc(dict->Exp_pool); - elr->next = NULL; - ell->e = nc; - elr->e = no; + n1->operand_first = nc; n1->type = AND_type; + n1->operand_next = NULL; n1->cost = 0; dn_list->exp = n1; @@ -267,29 +264,29 @@ void insert_idiom(Dictionary dict, Dict_node * dn) n1 = Exp_create(dict); n1->type = AND_type; + n1->operand_next = NULL; n1->cost = 0; - n1->operand_first = ell = pool_alloc(dict->E_list_pool); - ell->next = elr = pool_alloc(dict->E_list_pool); - elr->next = NULL; nc = Exp_create(dict); nc->condesc = condesc_add(&dict->contable, generate_id_connector(dict)); nc->dir = '+'; nc->multi = false; nc->type = CONNECTOR_type; + nc->operand_next = NULL; nc->cost = 0; - elr->e = nc; + n1->operand_first = nc; increment_current_name(dict); - nc = Exp_create(dict); - nc->condesc = condesc_add(&dict->contable, generate_id_connector(dict)); - nc->dir = '-'; - nc->multi = false; - nc->type = CONNECTOR_type; - nc->cost = 0; + no = Exp_create(dict); + no->condesc = condesc_add(&dict->contable, generate_id_connector(dict)); + no->dir = '-'; + no->multi = false; + no->type = CONNECTOR_type; + no->operand_next = NULL; + no->cost = 0; - ell->e = nc; + nc->operand_next = no; dn_list->exp = n1; @@ -302,6 +299,7 @@ void insert_idiom(Dictionary dict, Dict_node * dn) nc->dir = '+'; nc->multi = false; nc->type = CONNECTOR_type; + nc->operand_next = NULL; nc->cost = 0; dn_list->exp = nc; diff --git a/link-grammar/dict-common/print-dict.c b/link-grammar/dict-common/print-dict.c index 25b45387c2..40fcaf41da 100644 --- a/link-grammar/dict-common/print-dict.c +++ b/link-grammar/dict-common/print-dict.c @@ -76,7 +76,7 @@ void print_expression(Exp * n) static dyn_str *print_expression_parens(dyn_str *e, const Exp * n, int need_parens) { - E_list * el; + Exp *operand; int i, icost; double dcost; @@ -132,8 +132,8 @@ static dyn_str *print_expression_parens(dyn_str *e, return e; } - el = n->operand_first; - if (el == NULL) + operand = n->operand_first; + if (operand == NULL) { for (i=0; itype == OR_type) && el->e && - (el->e->type == AND_type) && el->e->cost == 0 && (NULL == el->e->operand_first)) + if ((n->type == OR_type) && operand && (operand->type == AND_type) && + operand->cost == 0 && (NULL == operand->operand_first)) { dyn_strcat(e, "{"); - if (NULL == el->next) dyn_strcat(e, "error-no-next"); - else print_expression_parens(e, el->next->e, false); + if (NULL == operand->operand_next) dyn_strcat(e, "error-no-next"); + else print_expression_parens(e, operand->operand_next, false); dyn_strcat(e, "}"); for (i=0; ie, true); + print_expression_parens(e, operand, true); /* get a funny "and optional" when it's a named expression thing. */ - if ((n->type == AND_type) && (el->next == NULL)) + if ((n->type == AND_type) && (operand->operand_next == NULL)) { for (i=0; itype == OR_type) dyn_strcat(e, " or "); /* print right side of binary expr */ - el = el->next; - if (el == NULL) + operand = operand->operand_next; + if (operand == NULL) { if (n->type == OR_type) dyn_strcat(e, "error-no-next"); @@ -187,22 +187,22 @@ static dyn_str *print_expression_parens(dyn_str *e, { do { - if (el->e->type == n->type) + if (operand->type == n->type) { - print_expression_parens(e, el->e, false); + print_expression_parens(e, operand, false); } else { - print_expression_parens(e, el->e, true); + print_expression_parens(e, operand, true); } - el = el->next; - if (el != NULL) + operand = operand->operand_next; + if (operand != NULL) { if (n->type == AND_type) dyn_strcat(e, " & "); if (n->type == OR_type) dyn_strcat(e, " or "); } - } while (el != NULL); + } while (operand != NULL); } for (i=0; itype == AND_type) { /* multiplicative combinatorial explosion */ cnt = 1; - for (e_list = e->operand_first; e_list != NULL; e_list = e_list->next) - cnt *= count_clause(e_list->e); + for (Exp *opd = e->operand_first; opd != NULL; opd = opd->operand_next) + cnt *= count_clause(opd); } else if (e->type == OR_type) { /* Just additive */ - for (e_list = e->operand_first; e_list != NULL; e_list = e_list->next) - cnt += count_clause(e_list->e); + for (Exp *opd = e->operand_first; opd != NULL; opd = opd->operand_next) + cnt += count_clause(opd); } else if (e->type == CONNECTOR_type) { diff --git a/link-grammar/dict-file/dictionary.c b/link-grammar/dict-file/dictionary.c index bb981ea484..5899143167 100644 --- a/link-grammar/dict-file/dictionary.c +++ b/link-grammar/dict-file/dictionary.c @@ -106,7 +106,7 @@ dictionary_six_str(const char * lang, { const char * t; Dictionary dict; - size_t E_pool_size; /* Exp & E_list memory pool sizes. */ + size_t Exp_pool_size; dict = (Dictionary) malloc(sizeof(struct Dictionary_s)); memset(dict, 0, sizeof(struct Dictionary_s)); @@ -137,7 +137,7 @@ dictionary_six_str(const char * lang, dict->free_lookup = free_llist; dict->lookup = file_boolean_lookup; condesc_init(dict, 1<<13); - E_pool_size = 1<<13; + Exp_pool_size = 1<<13; } else { @@ -148,15 +148,12 @@ dictionary_six_str(const char * lang, dict->insert_entry = load_affix; dict->lookup = return_true; condesc_init(dict, 1<<9); - E_pool_size = 1<<5; + Exp_pool_size = 1<<5; } - dict->Exp_pool = pool_new(__func__, "Exp", /*num_elements*/E_pool_size, + dict->Exp_pool = pool_new(__func__, "Exp", /*num_elements*/Exp_pool_size, sizeof(Exp), /*zero_out*/false, /*align*/false, /*exact*/false); - dict->E_list_pool = pool_new(__func__, "E_list", /*num_elements*/E_pool_size, - sizeof(E_list), /*zero_out*/false, - /*align*/false, /*exact*/false); /* Read dictionary from the input string. */ diff --git a/link-grammar/dict-file/read-dict.c b/link-grammar/dict-file/read-dict.c index 647ff797bb..45477b2e61 100644 --- a/link-grammar/dict-file/read-dict.c +++ b/link-grammar/dict-file/read-dict.c @@ -802,6 +802,20 @@ Exp *Exp_create(Dictionary dict) return e; } +/** + * Duplicate the given Exp node. + * This is needed in case it is to be participate more than once in a + * single expression. + */ +static Exp *Exp_create_dup(Dictionary dict, Exp *old_e) +{ + Exp *new_e = Exp_create(dict); + + *new_e = *old_e; + + return new_e; +} + /** * This creates a node with zero children. Initializes * the cost to zero. @@ -812,6 +826,7 @@ static Exp * make_zeroary_node(Dictionary dict) n->type = AND_type; /* these must be AND types */ n->cost = 0.0; n->operand_first = NULL; + n->operand_next = NULL; return n; } @@ -824,10 +839,9 @@ static Exp * make_unary_node(Dictionary dict, Exp * e) Exp * n; n = Exp_create(dict); n->type = AND_type; /* these must be AND types */ + n->operand_next = NULL; n->cost = 0.0; - n->operand_first = pool_alloc(dict->E_list_pool); - n->operand_first->next = NULL; - n->operand_first->e = e; + n->operand_first = e; return n; } @@ -837,19 +851,17 @@ static Exp * make_unary_node(Dictionary dict, Exp * e) */ static Exp * make_and_node(Dictionary dict, Exp* nl, Exp* nr) { - E_list *ell, *elr; Exp* n; n = Exp_create(dict); n->type = AND_type; + n->operand_next = NULL; n->cost = 0.0; - n->operand_first = ell = pool_alloc(dict->E_list_pool); - ell->next = elr = pool_alloc(dict->E_list_pool); - elr->next = NULL; + n->operand_first = nl; + nl->operand_next = nr; + nr->operand_next = NULL; - ell->e = nl; - elr->e = nr; return n; } @@ -857,41 +869,30 @@ static Exp *make_op_Exp(Dictionary dict, Exp_type t) { Exp * n = Exp_create(dict); n->type = t; + n->operand_next = NULL; n->cost = 0.0; - n->operand_first = NULL; + /* The caller is supposed to assign n->operand. */ return n; } -static E_list *make_E_list_val(Dictionary dict, Exp* nr) -{ - E_list *elr = pool_alloc(dict->E_list_pool); - - elr->e = nr; - elr->next = NULL; - - return elr; -} - /** * Create an OR_type expression. The expressions nl, nr will be * OR-ed together. */ static Exp * make_or_node(Dictionary dict, Exp* nl, Exp* nr) { - E_list *ell, *elr; Exp* n; n = Exp_create(dict); n->type = OR_type; + n->operand_next = NULL; n->cost = 0.0; - n->operand_first = ell = pool_alloc(dict->E_list_pool); - ell->next = elr = pool_alloc(dict->E_list_pool); - elr->next = NULL; + n->operand_first = nl; + nl->operand_next = nr; + nr->operand_next = NULL; - ell->e = nl; - elr->e = nr; return n; } @@ -930,9 +931,10 @@ static Exp * make_dir_connector(Dictionary dict, int i) } n->condesc = condesc_add(&dict->contable, - string_set_add(constring, dict->string_set)); + string_set_add(constring, dict->string_set)); if (NULL == n->condesc) return NULL; /* Table ovf */ n->type = CONNECTOR_type; + n->operand_next = NULL; /* unused, but accessed by copy_Exp() and some more */ n->cost = 0.0; return n; } @@ -1023,23 +1025,21 @@ static Exp * make_connector(Dictionary dict) /** Expression-creating function versions that use the Sentence * expression memory pools. - * (See the description of the similar functions above.) + * (FIXME: Unify with the similar functions above.) */ static Exp *make_or_node_from_pool(Sentence sent, Exp *nl, Exp *nr) { - E_list *ell, *elr; Exp* n; n = pool_alloc(sent->Exp_pool); n->type = OR_type; + n->operand_next = NULL; n->cost = 0.0; - n->operand_first = ell = (E_list *) pool_alloc(sent->E_list_pool); - ell->next = elr = (E_list *) pool_alloc(sent->E_list_pool); - elr->next = NULL; + n->operand_first = nl; + nl->operand_next = nr; + nr->operand_next = NULL; - ell->e = nl; - elr->e = nr; return n; } @@ -1047,8 +1047,10 @@ static Exp *make_zeroary_node_from_pool(Sentence sent) { Exp * n = pool_alloc(sent->Exp_pool); n->type = AND_type; /* these must be AND types */ + n->operand_next = NULL; n->cost = 0.0; n->operand_first = NULL; + return n; } @@ -1065,7 +1067,6 @@ static Exp *make_optional_node_from_pool(Sentence sent, Exp *e) void add_empty_word(Sentence sent, X_node *x) { Exp *zn, *an; - E_list *elist, *flist; const char *ZZZ = string_set_lookup(EMPTY_CONNECTOR, sent->dict->string_set); /* This function is called only if ZZZ is in the dictionary. */ @@ -1086,24 +1087,17 @@ void add_empty_word(Sentence sent, X_node *x) zn->condesc = condesc_add(&sent->dict->contable, ZZZ); zn->multi = false; zn->type = CONNECTOR_type; + zn->operand_next = NULL; /* unused, but to be on the safe side */ zn->cost = 0.0; zn = make_optional_node_from_pool(sent, zn); - /* flist is plain-word-exp */ - flist = (E_list *) pool_alloc(sent->E_list_pool); - flist->next = NULL; - flist->e = x->exp; - - /* elist is {ZZZ+} , (plain-word-exp) */ - elist = (E_list *) pool_alloc(sent->E_list_pool); - elist->next = flist; - elist->e = zn; - /* an will be {ZZZ+} & (plain-word-exp) */ an = pool_alloc(sent->Exp_pool); an->type = AND_type; + an->operand_next = NULL; an->cost = 0.0; - an->operand_first = elist; + an->operand_first = zn; + zn->operand_next = x->exp; x->exp = an; } @@ -1257,7 +1251,7 @@ static Exp *make_expression(Dictionary dict) { Exp *nl = NULL; Exp *e_head = NULL; - E_list *el_tail = NULL; /* last part of the expression */ + Exp *e_tail = NULL; /* last part of the expression */ bool is_sym_and = false; while (true) @@ -1361,28 +1355,29 @@ static Exp *make_expression(Dictionary dict) if (is_sym_and) { - /* Part 2/2 of SYM_AND processing */ + /* Part 2/2 of SYM_AND processing. */ /* Expand A ^ B into the expr ((A & B) or (B & A)). */ - - Exp *na = make_and_node(dict, el_tail->e, nl); - Exp *nb = make_and_node(dict, nl, el_tail->e); + Exp *na = make_and_node(dict, + Exp_create_dup(dict, e_tail), + Exp_create_dup(dict, nl)); + Exp *nb = make_and_node(dict, + Exp_create_dup(dict, nl), + Exp_create_dup(dict, e_tail)); Exp *or = make_or_node(dict, na, nb); - el_tail->e = or; + *e_tail = *or; /* SYM_AND result */ is_sym_and = false; } - else if (el_tail != NULL) + else if (e_tail != NULL) { /* This is Non-commuting AND or Commuting OR. - * Append the just read expression (nl) to its E_list chain. */ - el_tail->next = make_E_list_val(dict, nl); - el_tail = el_tail->next; + * Append the just read expression (nl) to its operand chain. */ + e_tail->operand_next = nl; + e_tail = nl; } - /* If (el_tail == NULL), handle_basic_op() below will create an - * E_list element with nl. Else it will just validate that the - * current operation is consistent with the current expression level. */ + /* Extract the operator. */ Exp_type op; @@ -1409,7 +1404,15 @@ static Exp *make_expression(Dictionary dict) return nl; } - if (e_head != NULL) + /* If this is the first operand, use nl for it. Else just validate + * that the current operator is consistent with that of the current + * expression level. */ + if (e_head == NULL) + { + e_head = make_op_Exp(dict, op); + e_head->operand_first = nl; + } + else { if (e_head->type != op) { @@ -1417,18 +1420,13 @@ static Exp *make_expression(Dictionary dict) return NULL; } } - else - { - e_head = make_op_Exp(dict, op); - e_head->operand_first = make_E_list_val(dict, nl); - } if (!link_advance(dict)) { return NULL; } - if (el_tail == NULL) - el_tail = e_head->operand_first; + if (e_tail == NULL) + e_tail = e_head->operand_first; } /* unreachable */ } @@ -1545,8 +1543,14 @@ Dict_node *insert_dict(Dictionary dict, Dict_node *n, Dict_node *newnode) { if (NULL == n) return newnode; - static Exp null_exp = { .type = AND_type, .operand_first = NULL }; + static Exp null_exp = + { + .type = AND_type, + .operand_first = NULL, + .operand_next = NULL, + }; int comp = dict_order_strict(newnode->string, n); + if (0 == comp && /* Suppress reporting duplicate idioms until they are fixed. */ (!contains_underbar(newnode->string) || test_enabled("dup-idioms"))) diff --git a/link-grammar/dict-sql/read-sql.c b/link-grammar/dict-sql/read-sql.c index e904d524e4..6daafce771 100644 --- a/link-grammar/dict-sql/read-sql.c +++ b/link-grammar/dict-sql/read-sql.c @@ -78,6 +78,7 @@ static const char * make_expression(Dictionary dict, Exp* e = Exp_create(dict); e->dir = *p; e->type = CONNECTOR_type; + e->operand_next = NULL; e->cost = 0.0; char * constr = NULL; if ('@' == *con_start) @@ -125,13 +126,13 @@ static const char * make_expression(Dictionary dict, /* Join it all together. */ Exp* join = Exp_create(dict); join->type = etype; + join->operand_next = NULL; join->cost = 0.0; - E_list *ell = join->operand_first = pool_alloc(dict->E_list_pool); - E_list *elr = ell->next = pool_alloc(dict->E_list_pool); - elr->next = NULL; - ell->e = *pex; - elr->e = rest; + join->operand_first = *pex; + (*pex)->operand_next = rest; + rest->operand_next = NULL; + *pex = join; return p; @@ -190,25 +191,18 @@ static int exp_cb(void *user_data, int argc, char **argv, char **colName) /* If the second expression, OR-it with the existing expression. */ if (OR_type != bs->exp->type) { - E_list *ell, *elr; Exp* orn = Exp_create(dict); orn->type = OR_type; orn->cost = 0.0; - orn->operand_first = ell = pool_alloc(dict->E_list_pool); - ell->next = elr = pool_alloc(dict->E_list_pool); - elr->next = NULL; - ell->e = exp; - elr->e = bs->exp; + orn->operand_first = exp; + exp->operand_next = bs->exp; bs->exp = orn; return 0; } /* Extend the OR-chain for the third and later expressions. */ - E_list* more = pool_alloc(dict->E_list_pool); - more->e = exp; - more->next = bs->exp->operand_first; - bs->exp->operand_first = more; + bs->exp->operand_next = exp; return 0; } @@ -493,9 +487,6 @@ Dictionary dictionary_create_from_db(const char *lang) dict->Exp_pool = pool_new(__func__, "Exp", /*num_elements*/4096, sizeof(Exp), /*zero_out*/false, /*align*/false, /*exact*/false); - dict->E_list_pool = pool_new(__func__, "E_list", /*num_elements*/4096, - sizeof(E_list), /*zero_out*/false, - /*align*/false, /*exact*/false); /* Setup the affix table */ char *affix_name = join_path (lang, "4.0.affix"); diff --git a/link-grammar/prepare/build-disjuncts.c b/link-grammar/prepare/build-disjuncts.c index be4f620b18..101f014915 100644 --- a/link-grammar/prepare/build-disjuncts.c +++ b/link-grammar/prepare/build-disjuncts.c @@ -155,7 +155,6 @@ static Tconnector * build_terminal(Exp *e, Pool_desc *tp) static Clause * build_clause(Exp *e, clause_context *ct) { Clause *c = NULL, *c1, *c2, *c3, *c4, *c_head; - E_list * e_list; assert(e != NULL, "build_clause called with null parameter"); if (e->type == AND_type) @@ -165,9 +164,9 @@ static Clause * build_clause(Exp *e, clause_context *ct) c1->next = NULL; c1->cost = 0.0; c1->maxcost = 0.0; - for (e_list = e->operand_first; e_list != NULL; e_list = e_list->next) + for (Exp *opd = e->operand_first; opd != NULL; opd = opd->operand_next) { - c2 = build_clause(e_list->e, ct); + c2 = build_clause(opd, ct); c_head = NULL; for (c3 = c1; c3 != NULL; c3 = c3->next) { @@ -194,11 +193,11 @@ static Clause * build_clause(Exp *e, clause_context *ct) } else if (e->type == OR_type) { - c = build_clause(e->operand_first->e, ct); + c = build_clause(e->operand_first, ct); /* we'll catenate the lists of clauses */ - for (e_list = e->operand_first->next; e_list != NULL; e_list = e_list->next) + for (Exp *opd = e->operand_first->operand_next; opd != NULL; opd = opd->operand_next) { - c1 = build_clause(e_list->e, ct); + c1 = build_clause(opd, ct); if (c1 == NULL) continue; if (c == NULL) { @@ -351,15 +350,11 @@ GNUC_UNUSED void prt_exp(Exp *e, int i) if (e == NULL) return; for(int j =0; jtype, e->dir, e->multi, e->cost); + printf ("type=%d dir=%c multi=%d cost=%f\n", + e->type, e->dir, e->multi, e->cost); if (e->type != CONNECTOR_type) { - E_list *l = e->operand_first; - while(l) - { - prt_exp(l->e, i+2); - l = l->next; - } + for (e = e->operand_next; e != NULL; e = e->operand_next) prt_exp(e, i+2); } else { @@ -368,48 +363,74 @@ GNUC_UNUSED void prt_exp(Exp *e, int i) } } -GNUC_UNUSED void prt_exp_mem(Exp *e, int i) +static const char *stringify_Exp_type(Exp_type type) { - char unknown_type[32] = ""; - const char *type; + static TLS char unknown_type[32] = ""; + const char *type_str; - if (e == NULL) return; - - if (e->type > 0 && e->type <= 3) + if (type > 0 && type <= 3) { - type = ((const char *[]) {"OR_type", "AND_type", "CONNECTOR_type"}) [e->type-1]; + type_str = ((const char *[]) {"OR", "AND", "CONNECTOR"}) [type-1]; } else { - snprintf(unknown_type, sizeof(unknown_type)-1, "unknown-%d", e->type); - type = unknown_type; + snprintf(unknown_type, sizeof(unknown_type)-1, "unknown_type-%d", type); + type_str = unknown_type; + } + + return type_str; +} + +static bool is_ASAN_uninitialized(uintptr_t a) +{ + static const uintptr_t asan_uninitialized = 0xbebebebebebebebe; + + return (a == asan_uninitialized); +} + +GNUC_UNUSED void prt_exp_mem(Exp *e, int i) +{ + if (is_ASAN_uninitialized((uintptr_t)e)) + { + printf ("e=UNINITIALIZED\n"); + return; } + if (e == NULL) return; for(int j =0; jcost); + printf ("e=%p: %s", e, stringify_Exp_type(e->type)); + + if (is_ASAN_uninitialized((uintptr_t)e->operand_first)) + printf(" (UNINITIALIZED operand)"); + if (is_ASAN_uninitialized((uintptr_t)e->operand_next)) + printf(" (UNINITIALIZED next)"); + if (e->type != CONNECTOR_type) { - E_list *l; - for(int j =0; joperand_first); - for (l = e->operand_first; NULL != l; l = l->next) + int operand_count = 0; + for (Exp *opd = e->operand_first; NULL != opd; opd = opd->operand_next) { - printf("%p", l->e); - if (NULL != l->next) printf(" "); + operand_count++; + if (is_ASAN_uninitialized((uintptr_t)opd->operand_next)) + { + printf(" (operand %d: UNINITIALIZED next)\n", operand_count); + return; + } } - printf(")\n"); + printf(" (%d operand%s) cost=%f\n", operand_count, + operand_count == 1 ? "" : "s", e->cost); - for (l = e->operand_first; NULL != l; l = l->next) + for (Exp *opd = e->operand_first; NULL != opd; opd = opd->operand_next) { - prt_exp_mem(l->e, i+2); + prt_exp_mem(opd, i+2); } } else { - for(int j =0; jmulti ? "@" : "", e->condesc ? e->condesc->string : "(condesc=(null))", - e->dir, e->multi); + e->dir, e->cost); } } #endif /* DEBUG */ diff --git a/link-grammar/prepare/exprune.c b/link-grammar/prepare/exprune.c index dfe9487545..ea98729cca 100644 --- a/link-grammar/prepare/exprune.c +++ b/link-grammar/prepare/exprune.c @@ -12,6 +12,9 @@ /*************************************************************************/ #include "api-structures.h" // for Sentence_s +#ifdef DEBUG +#include "build-disjuncts.h" // allow using prt_exp_mem +#endif #include "connectors.h" #include "dict-common/dict-api.h" // expression_stringify #include "dict-common/dict-utils.h" // size_of_expression @@ -177,33 +180,85 @@ static Exp* purge_Exp(exprune_context *ctxt, int, Exp *, char); /** * Get rid of the current_elements with null expressions */ -static E_list * or_purge_E_list(exprune_context *ctxt, int w, E_list *l, char dir) +static bool or_purge_operands(exprune_context *ctxt, int w, Exp *e, char dir) { - E_list * el; - if (l == NULL) return NULL; - if ((l->e = purge_Exp(ctxt, w, l->e, dir)) == NULL) +#if NOTYET + const double nullexp_nonexistence = -9999; + double nullexp_mincost = nullexp_nonexistence; + int nullexp_count = 0; +#endif + + for (Exp **opdp = &e->operand_first; *opdp != NULL; /* See: NEXT */) { - el = or_purge_E_list(ctxt, w, l->next, dir); - return el; + Exp *opd = *opdp; + +#if NOTYET + if ((opd->type == AND_type) && (opd->operand_first == NULL)) + { + if (opd->cost > nullexp_mincost) nullexp_mincost = opd->cost; + nullexp_count++; + } + else +#endif + if (purge_Exp(ctxt, w, opd, dir) == NULL) + { + *opdp = opd->operand_next; /* Discard element + NEXT */ + continue; + } + + opdp = &opd->operand_next; /* NEXT */ + }; + +#if NOTYET + if ((nullexp_count > 1) && (nullexp_mincost != nullexp_nonexistence)) + { + bool nullexp_retained = false; + + for (Exp **opdp = &e->operand_first; *opdp != NULL; /* See: NEXT */) + { + Exp *opd = *opdp; + + if ((opd->type == AND_type) && (opd->operand_first == NULL)) + { + if (!nullexp_retained && opd->cost == nullexp_mincost) + { + nullexp_retained = true; + } + else + { + *opdp = opd->operand_next; /* Discard element + NEXT */ + continue; + } + } + + opdp = &opd->operand_next; /* NEXT */ + } } - l->next = or_purge_E_list(ctxt, w, l->next, dir); - return l; +#endif + + return (e->operand_first != NULL); } /** * Returns true iff the length of the disjunct list is 0. * If this is the case, it frees the structure rooted at l. */ -static bool and_purge_E_list(exprune_context *ctxt, int w, E_list *l, char dir) +static bool and_purge_operands(exprune_context *ctxt, int w, Exp *e, char dir) { - if (l == NULL) return true; - if ((l->e = purge_Exp(ctxt, w, l->e, dir)) == NULL) - { - return false; - } - if (!and_purge_E_list(ctxt, w, l->next, dir)) + for (Exp **opdp = &e->operand_first; *opdp != NULL; /* See: NEXT */) { - return false; + Exp *opd = *opdp; + +#ifdef NOTYET + if ((opd->type == AND_type) && (opd->operand_first == NULL)) + { + e->cost += opd->cost; + *opdp = opd->operand_next; /* Discard element + NEXT */ + } +#endif + + if (purge_Exp(ctxt, w, opd, dir) == NULL) return false; + opdp = &opd->operand_next; /* NEXT */ } return true; } @@ -231,26 +286,20 @@ static Exp* purge_Exp(exprune_context *ctxt, int w, Exp *e, char dir) if (e->type == AND_type) { - if (!and_purge_E_list(ctxt, w, e->operand_first, dir)) - { - return NULL; - } + if (!and_purge_operands(ctxt, w, e, dir)) return NULL; } else /* if we are here, its OR_type */ { - e->operand_first = or_purge_E_list(ctxt, w, e->operand_first, dir); - if (e->operand_first == NULL) - { - return NULL; - } + if (!or_purge_operands(ctxt, w, e, dir)) return NULL; } /* Unary node elimination (for a slight performance improvement). */ - if ((e->operand_first != NULL) && (e->operand_first->next == NULL)) + if ((e->operand_first != NULL) && (e->operand_first->operand_next == NULL)) { - Exp *ne = e->operand_first->e; - ne->cost += e->cost; - return ne; + Exp *opd = e->operand_first; + opd->cost += e->cost; + opd->operand_next = e->operand_next; + *e = *opd; } return e; @@ -313,10 +362,9 @@ static void insert_connectors(exprune_context *ctxt, int w, Exp * e, int dir) } else { - E_list *l; - for (l=e->operand_first; l!=NULL; l=l->next) + for (Exp *opd = e->operand_first; opd != NULL; opd = opd->operand_next) { - insert_connectors(ctxt, w, l->e, dir); + insert_connectors(ctxt, w, opd, dir); } } } @@ -366,6 +414,7 @@ void expression_prune(Sentence sent, Parse_Options opts) X_node *x = *xp; DBG(pass, w, "l->r pass before purging"); + //if (pass == 0 && w == 0) {printf("Exp: ");prt_exp_mem(x->exp, 0);} x->exp = purge_Exp(&ctxt, w, x->exp, '-'); DBG(pass, w, "l->r pass after purging"); diff --git a/link-grammar/sat-solver/sat-encoder.cpp b/link-grammar/sat-solver/sat-encoder.cpp index c981ca30ce..a7d4e3059e 100644 --- a/link-grammar/sat-solver/sat-encoder.cpp +++ b/link-grammar/sat-solver/sat-encoder.cpp @@ -27,7 +27,6 @@ extern "C" { extern "C" { #include "dict-common/dict-api.h" // for print_expression() -#include "dict-common/dict-utils.h" // for free_Exp() #include "disjunct-utils.h" #include "linkage/analyze-linkage.h" // for compute_link_names() #include "linkage/linkage.h" @@ -270,9 +269,6 @@ void SATEncoder::build_word_tags() _word_tags[w].insert_connectors(exp, dfs_position, leading_right, leading_left, eps_right, eps_left, name, true, 0, NULL, _sent->word[w].x); - - if (join) - free_alternatives(exp); } for (size_t wl = 0; wl < _sent->length - 1; wl++) { @@ -346,9 +342,6 @@ void SATEncoder::generate_satisfaction_conditions() int dfs_position = 0; generate_satisfaction_for_expression(w, dfs_position, exp, name, 0); - - if (join) - free_alternatives(exp); } } @@ -356,7 +349,7 @@ void SATEncoder::generate_satisfaction_conditions() void SATEncoder::generate_satisfaction_for_expression(int w, int& dfs_position, Exp* e, char* var, double parent_cost) { - E_list *l; + Exp *opd; double total_cost = parent_cost + e->cost; if (e->type == CONNECTOR_type) { @@ -376,9 +369,9 @@ void SATEncoder::generate_satisfaction_for_expression(int w, int& dfs_position, if (total_cost > _cost_cutoff) { generate_literal(~Lit(_variables->string_cost(var, e->cost))); } - } else if (e->operand_first->next == NULL) { + } else if (e->operand_first->operand_next == NULL) { /* unary and - skip */ - generate_satisfaction_for_expression(w, dfs_position, e->operand_first->e, var, total_cost); + generate_satisfaction_for_expression(w, dfs_position, e->operand_first, var, total_cost); } else { /* n-ary and */ int i; @@ -392,7 +385,7 @@ void SATEncoder::generate_satisfaction_for_expression(int w, int& dfs_position, } vec rhs; - for (i = 0, l=e->operand_first; l!=NULL; l=l->next, i++) { + for (i = 0, opd=e->operand_first; opd!=NULL; opd=opd->operand_next, i++) { // sprintf(new_var, "%sc%d", var, i) char* s = last_new_var; *s++ = 'c'; @@ -405,11 +398,11 @@ void SATEncoder::generate_satisfaction_for_expression(int w, int& dfs_position, /* Precedes */ int dfs_position_tmp = dfs_position; - for (l = e->operand_first; l->next != NULL; l = l->next) { + for (opd = e->operand_first; opd->operand_next != NULL; opd = opd->operand_next) { Exp e_tmp, *e_rhs = &e_tmp; - if (l->next->next == NULL) { - e_rhs = l->next->e; + if (opd->operand_next->operand_next == NULL) { + e_rhs = opd->operand_next; } else { // A workaround for issue #932: @@ -435,21 +428,21 @@ void SATEncoder::generate_satisfaction_for_expression(int w, int& dfs_position, // Clause: -link_cw_(2_4_K)_6 -link_cw_(2_6_O*n)_5 // Clearly, they cannot be concluded transitively. e_rhs->type = AND_type; - e_rhs->operand_first = l->next; + e_rhs->operand_first = opd->operand_next; e_rhs->cost = 0.0; }; - generate_conjunct_order_constraints(w, l->e, e_rhs, dfs_position_tmp); + generate_conjunct_order_constraints(w, opd, e_rhs, dfs_position_tmp); } /* Recurse */ - for (i = 0, l=e->operand_first; l!=NULL; l=l->next, i++) { + for (i = 0, opd=e->operand_first; opd!=NULL; opd=opd->operand_next, i++) { // sprintf(new_var, "%sc%d", var, i) char* s = last_new_var; *s++ = 'c'; fast_sprintf(s, i); /* if (i != 0) total_cost = 0; */ // This interferes with the cost cutoff - generate_satisfaction_for_expression(w, dfs_position, l->e, new_var, total_cost); + generate_satisfaction_for_expression(w, dfs_position, opd, new_var, total_cost); } } } else if (e->type == OR_type) { @@ -457,9 +450,9 @@ void SATEncoder::generate_satisfaction_for_expression(int w, int& dfs_position, /* zeroary or */ cerr << "Zeroary OR" << endl; exit(EXIT_FAILURE); - } else if (e->operand_first->next == NULL) { + } else if (e->operand_first->operand_next == NULL) { /* unary or */ - generate_satisfaction_for_expression(w, dfs_position, e->operand_first->e, var, total_cost); + generate_satisfaction_for_expression(w, dfs_position, e->operand_first, var, total_cost); } else { /* n-ary or */ int i; @@ -473,7 +466,7 @@ void SATEncoder::generate_satisfaction_for_expression(int w, int& dfs_position, } vec rhs; - for (i = 0, l=e->operand_first; l!=NULL; l=l->next, i++) { + for (i = 0, opd=e->operand_first; opd!=NULL; opd=opd->operand_next, i++) { // sprintf(new_var, "%sc%d", var, i) char* s = last_new_var; *s++ = 'd'; @@ -486,55 +479,38 @@ void SATEncoder::generate_satisfaction_for_expression(int w, int& dfs_position, generate_xor_conditions(rhs); /* Recurse */ - for (i = 0, l=e->operand_first; l!=NULL; l=l->next, i++) { + for (i = 0, opd=e->operand_first; opd!=NULL; opd=opd->operand_next, i++) { char* s = last_new_var; *s++ = 'd'; fast_sprintf(s, i); - generate_satisfaction_for_expression(w, dfs_position, l->e, new_var, total_cost); + generate_satisfaction_for_expression(w, dfs_position, opd, new_var, total_cost); } } } } } +/** + * Join all alternatives using an OR_type node. + */ Exp* SATEncoder::join_alternatives(int w) { - // join all alternatives using an OR_type node - Exp* exp; - E_list* or_list = NULL;; - for (X_node* x = _sent->word[w].x; x != NULL; x = x->next) { - E_list* new_node = (E_list*) malloc(sizeof(E_list)); - new_node->e = x->exp; - new_node->next = NULL; - if (or_list == NULL) { - or_list = new_node; - } else { - E_list *y; - for (y = or_list; y->next != NULL; y = y->next) - ; - y->next = new_node; - } - } - exp = (Exp*) malloc(sizeof(Exp)); + Exp* exp = Exp_create(_sent); exp->type = OR_type; - exp->operand_first = or_list; exp->cost = 0.0; - return exp; -} + Exp** opdp = &exp->operand_first; -void SATEncoder::free_alternatives(Exp* exp) -{ - E_list *l = exp->operand_first; - while (l != NULL) { - E_list* next = l->next; - free(l); - l = next; + for (X_node* x = _sent->word[w].x; x != NULL; x = x->next) + { + *opdp = Exp_create_dup(_sent, x->exp); + opdp = &(*opdp)->operand_next; } - free(exp); -} + *opdp = NULL; + return exp; +} void SATEncoder::generate_link_cw_ordinary_definition(size_t wi, int pi, Exp* e, size_t wj) @@ -583,8 +559,8 @@ int SATEncoder::num_connectors(Exp* e) return 1; else { int num = 0; - for (E_list* l = e->operand_first; l != NULL; l = l->next) { - num += num_connectors(l->e); + for (Exp* opd = e->operand_first; opd != NULL; opd = opd->operand_next) { + num += num_connectors(opd); } return num; } @@ -595,14 +571,14 @@ int SATEncoder::empty_connectors(Exp* e, char dir) if (e->type == CONNECTOR_type) { return e->dir != dir; } else if (e->type == OR_type) { - for (E_list* l = e->operand_first; l != NULL; l = l->next) { - if (empty_connectors(l->e, dir)) + for (Exp* opd = e->operand_first; opd != NULL; opd = opd->operand_next) { + if (empty_connectors(opd, dir)) return true; } return false; } else if (e->type == AND_type) { - for (E_list* l = e->operand_first; l != NULL; l = l->next) { - if (!empty_connectors(l->e, dir)) + for (Exp* opd = e->operand_first; opd != NULL; opd = opd->operand_next) { + if (!empty_connectors(opd, dir)) return false; } return true; @@ -632,18 +608,18 @@ int SATEncoder::non_empty_connectors(Exp* e, char dir) } #endif -bool SATEncoder::trailing_connectors_and_aux(int w, E_list* l, char dir, int& dfs_position, +bool SATEncoder::trailing_connectors_and_aux(int w, Exp *opd, char dir, int& dfs_position, std::vector& connectors) { - if (l == NULL) { + if (opd == NULL) { return true; } else { int dfs_position_in = dfs_position; - dfs_position += num_connectors(l->e); - if (trailing_connectors_and_aux(w, l->next, dir, dfs_position, connectors)) { - trailing_connectors(w, l->e, dir, dfs_position_in, connectors); + dfs_position += num_connectors(opd); + if (trailing_connectors_and_aux(w, opd->operand_next, dir, dfs_position, connectors)) { + trailing_connectors(w, opd, dir, dfs_position_in, connectors); } - return empty_connectors(l->e, dir); + return empty_connectors(opd, dir); } } @@ -656,8 +632,8 @@ void SATEncoder::trailing_connectors(int w, Exp* exp, char dir, int& dfs_positio connectors.push_back(_word_tags[w].get(dfs_position)); } } else if (exp->type == OR_type) { - for (E_list* l = exp->operand_first; l != NULL; l = l->next) { - trailing_connectors(w, l->e, dir, dfs_position, connectors); + for (Exp* opd = exp->operand_first; opd != NULL; opd = opd->operand_next) { + trailing_connectors(w, opd, dir, dfs_position, connectors); } } else if (exp->type == AND_type) { trailing_connectors_and_aux(w, exp->operand_first, dir, dfs_position, connectors); @@ -704,20 +680,20 @@ void SATEncoder::leading_connectors(int w, Exp* exp, char dir, int& dfs_position connectors.push_back(_word_tags[w].get(dfs_position)); } } else if (exp->type == OR_type) { - for (E_list* l = exp->operand_first; l != NULL; l = l->next) { - leading_connectors(w, l->e, dir, dfs_position, connectors); + for (Exp* opd = exp->operand_first; opd != NULL; opd = opd->operand_next) { + leading_connectors(w, opd, dir, dfs_position, connectors); } } else if (exp->type == AND_type) { - E_list* l; - for (l = exp->operand_first; l != NULL; l = l->next) { - leading_connectors(w, l->e, dir, dfs_position, connectors); - if (!empty_connectors(l->e, dir)) + Exp* opd; + for (opd = exp->operand_first; opd != NULL; opd = opd->operand_next) { + leading_connectors(w, opd, dir, dfs_position, connectors); + if (!empty_connectors(opd, dir)) break; } - if (l != NULL) { - for (l = l->next; l != NULL; l = l->next) - dfs_position += num_connectors(l->e); + if (opd != NULL) { + for (opd = opd->operand_next; opd != NULL; opd = opd->operand_next) + dfs_position += num_connectors(opd); } } } @@ -1156,9 +1132,6 @@ void SATEncoder::generate_epsilon_definitions() dfs_position = 0; generate_epsilon_for_expression(w, dfs_position, exp, name, true, '-'); - - if (join) - free_alternatives(exp); } } @@ -1184,12 +1157,12 @@ bool SATEncoder::generate_epsilon_for_expression(int w, int& dfs_position, Exp* Lit(_variables->epsilon(var, dir))); return true; } else - if (e->operand_first != NULL && e->operand_first->next == NULL) { + if (e->operand_first != NULL && e->operand_first->operand_next == NULL) { /* unary and - skip */ - return generate_epsilon_for_expression(w, dfs_position, e->operand_first->e, var, root, dir); + return generate_epsilon_for_expression(w, dfs_position, e->operand_first, var, root, dir); } else { /* Recurse */ - E_list* l; + Exp* opd; int i; bool eps = true; @@ -1202,27 +1175,27 @@ bool SATEncoder::generate_epsilon_for_expression(int w, int& dfs_position, Exp* } - for (i = 0, l = e->operand_first; l != NULL; l = l->next, i++) { + for (i = 0, opd = e->operand_first; opd != NULL; opd = opd->operand_next, i++) { // sprintf(new_var, "%sc%d", var, i) char* s = last_new_var; *s++ = 'c'; fast_sprintf(s, i); - if (!generate_epsilon_for_expression(w, dfs_position, l->e, new_var, false, dir)) { + if (!generate_epsilon_for_expression(w, dfs_position, opd, new_var, false, dir)) { eps = false; break; } } - if (l != NULL) { - for (l = l->next; l != NULL; l = l->next) - dfs_position += num_connectors(l->e); + if (opd != NULL) { + for (opd = opd->operand_next; opd != NULL; opd = opd->operand_next) + dfs_position += num_connectors(opd); } if (!root && eps) { Lit lhs = Lit(_variables->epsilon(var, dir)); vec rhs; - for (i = 0, l=e->operand_first; l!=NULL; l=l->next, i++) { + for (i = 0, opd = e->operand_first; opd != NULL; opd = opd->operand_next, i++) { // sprintf(new_var, "%sc%d", var, i) char* s = last_new_var; *s++ = 'c'; @@ -1234,12 +1207,12 @@ bool SATEncoder::generate_epsilon_for_expression(int w, int& dfs_position, Exp* return eps; } } else if (e->type == OR_type) { - if (e->operand_first != NULL && e->operand_first->next == NULL) { + if (e->operand_first != NULL && e->operand_first->operand_next == NULL) { /* unary or - skip */ - return generate_epsilon_for_expression(w, dfs_position, e->operand_first->e, var, root, dir); + return generate_epsilon_for_expression(w, dfs_position, e->operand_first, var, root, dir); } else { /* Recurse */ - E_list* l; + Exp* opd; int i; bool eps = false; @@ -1252,13 +1225,13 @@ bool SATEncoder::generate_epsilon_for_expression(int w, int& dfs_position, Exp* } vec rhs; - for (i = 0, l = e->operand_first; l != NULL; l = l->next, i++) { + for (i = 0, opd = e->operand_first; opd != NULL; opd = opd->operand_next, i++) { // sprintf(new_var, "%sc%d", var, i) char* s = last_new_var; *s++ = 'd'; fast_sprintf(s, i); - if (generate_epsilon_for_expression(w, dfs_position, l->e, new_var, false, dir) && !root) { + if (generate_epsilon_for_expression(w, dfs_position, opd, new_var, false, dir) && !root) { rhs.push(Lit(_variables->epsilon(new_var, dir))); eps = true; } @@ -1366,9 +1339,6 @@ void SATEncoder::power_prune() certainly_non_trailing(w, exp, '+', dfs_position, certainly_deep_right[w], false); dfs_position = 0; certainly_non_trailing(w, exp, '-', dfs_position, certainly_deep_left[w], false); - - if (join) - free_alternatives(exp); } for (size_t w = 0; w < _sent->length; w++) { @@ -1810,7 +1780,7 @@ void SATEncoderConjunctionFreeSentences::generate_linked_definitions() Exp* SATEncoderConjunctionFreeSentences::PositionConnector2exp(const PositionConnector* pc) { - Exp* e = (Exp*) malloc(sizeof(Exp)); + Exp* e = Exp_create(_sent); e->type = CONNECTOR_type; e->dir = pc->dir; e->multi = pc->connector.multi; @@ -1863,8 +1833,8 @@ bool SATEncoderConjunctionFreeSentences::sat_extract_links(Linkage lkg) Exp* lcexp = PositionConnector2exp(lpc); Exp* rcexp = PositionConnector2exp(rpc); - add_anded_exp(exp_word[var->left_word], lcexp); - add_anded_exp(exp_word[var->right_word], rcexp); + add_anded_exp(_sent, exp_word[var->left_word], lcexp); + add_anded_exp(_sent, exp_word[var->right_word], rcexp); if (verbosity_level(D_SAT)) { //cout<< "Lexp[" <word->subword <<"]: "; print_expression(var->left_exp); @@ -1921,7 +1891,6 @@ bool SATEncoderConjunctionFreeSentences::sat_extract_links(Linkage lkg) cost_cutoff = 1000.0; #endif // LIMIT_TOTAL_LINKAGE_COST d = build_disjuncts_for_exp(NULL, de, xnode_word[wi]->string, cost_cutoff, _opts); - free_Exp(de); if (d == NULL) { diff --git a/link-grammar/sat-solver/sat-encoder.hpp b/link-grammar/sat-solver/sat-encoder.hpp index 89b3f5f00e..04166c4558 100644 --- a/link-grammar/sat-solver/sat-encoder.hpp +++ b/link-grammar/sat-solver/sat-encoder.hpp @@ -100,7 +100,7 @@ class SATEncoder // Trailing connectors of a given direction in the given expression void trailing_connectors(int w, Exp* exp, char dir, int& dfs_position, std::vector& connectors); - bool trailing_connectors_and_aux(int w, E_list* l, char dir, int& dfs_position, + bool trailing_connectors_and_aux(int w, Exp* opd, char dir, int& dfs_position, std::vector& connectors); // Connectors of the given direction that cannot be trailing @@ -265,11 +265,6 @@ class SATEncoder // entries of a word into a single expression. Exp* join_alternatives(int w); - // Erase auxiliary expression tree nodes obtained by joining several - // expressions into one. - void free_alternatives(Exp* e); - - /** * Decoding */ diff --git a/link-grammar/sat-solver/util.cpp b/link-grammar/sat-solver/util.cpp index b8f3645728..d6eb6d6051 100644 --- a/link-grammar/sat-solver/util.cpp +++ b/link-grammar/sat-solver/util.cpp @@ -4,6 +4,7 @@ extern "C" { #include "api-structures.h" #include "disjunct-utils.h" #include "linkage/linkage.h" +#include "memory-pool.h" #include "utilities.h" }; @@ -41,37 +42,76 @@ void sat_free_linkages(Sentence sent, LinkageIdx next_linkage_index) Exp* null_exp() { - static Exp e; + static Exp e = + { + .operand_next = NULL, + .type = AND_type, + .operand_first = NULL, + }; - if (e.type) return &e; - e.operand_first = NULL; - e.type = AND_type; return &e; } -void add_anded_exp(Exp*& orig, Exp* addit) +/* FIXME: + * 1. Remove unused Exp functions when disjuncts are directly built. + * 2. Unify remaining Exp functions with the similar ones in read-dict.c. */ + +/** + * Allocate a new Exp node. + */ +Exp* Exp_create(Sentence sent) +{ + Exp* e = (Exp*)pool_alloc(sent->Exp_pool); + return e; +} + +static Exp* make_unary_node(Sentence sent, Exp* e) +{ + Exp* n; + n = Exp_create(sent); + n->type = AND_type; /* these must be AND types */ + n->operand_next = NULL; + n->cost = 0.0; + n->operand_first = e; + return n; +} + +/** + * Duplicate the given Exp node. + * This is needed in case it is to be participate more than once in an + * expression (one or more), so its operand_first and operand_next may be + * different. + */ +Exp *Exp_create_dup(Sentence sent, Exp *old_e) +{ + Exp *new_e = Exp_create(sent); + + *new_e = *old_e; + + return new_e; +} + +/** + * Prepend the CONNECTOR node addit to the AND node orig. + * (If orig is NULL, first create an AND node.) + * Return the result. + */ +void add_anded_exp(Sentence sent, Exp*& orig, Exp* addit) { if (orig == NULL) { - orig = addit; - } else + orig = make_unary_node(sent, Exp_create_dup(sent, addit)); + orig->operand_first->operand_next = NULL; + } + else { - // flist is orig - E_list* flist = (E_list*) malloc(sizeof(E_list)); - flist->e = orig; - flist->next = NULL; - - // elist is addit, orig - E_list* elist = (E_list*) malloc(sizeof(E_list)); - elist->next = flist; - elist->e = addit; - - // The updated orig is addit & orig - orig = (Exp*) malloc(sizeof(Exp)); - orig->type = AND_type; - orig->cost = 0.0; - orig->operand_first = elist; + // Prepend addit to the existing operands + Exp *orig_operand_first = orig->operand_first; + orig->operand_first = Exp_create_dup(sent, addit); + orig->operand_first->operand_next = orig_operand_first; } + + // The updated orig is addit & orig } #if 0 diff --git a/link-grammar/sat-solver/util.hpp b/link-grammar/sat-solver/util.hpp index 6482eaf30d..7c7963d068 100644 --- a/link-grammar/sat-solver/util.hpp +++ b/link-grammar/sat-solver/util.hpp @@ -13,6 +13,8 @@ void free_linkage_connectors_and_disjuncts(Linkage); void sat_free_linkages(Sentence, LinkageIdx); void sat_free_linkages(Sentence); Exp* null_exp(); -void add_anded_exp(Exp*&, Exp*); +void add_anded_exp(Sentence, Exp*&, Exp*); +Exp* Exp_create(Sentence); +Exp *Exp_create_dup(Sentence, Exp *old); #endif diff --git a/link-grammar/sat-solver/word-tag.cpp b/link-grammar/sat-solver/word-tag.cpp index aac69c484f..710e47abf5 100644 --- a/link-grammar/sat-solver/word-tag.cpp +++ b/link-grammar/sat-solver/word-tag.cpp @@ -70,13 +70,13 @@ void WordTag::insert_connectors(Exp* exp, int& dfs_position, _empty_connectors.push_back(EmptyConnector(_variables->string(var),cost)); } } else - if (exp->operand_first->next == NULL) { + if (exp->operand_first->operand_next == NULL) { /* unary and - skip */ - insert_connectors(exp->operand_first->e, dfs_position, leading_right, + insert_connectors(exp->operand_first, dfs_position, leading_right, leading_left, eps_right, eps_left, var, root, cost, parent_exp, word_xnode); } else { int i; - E_list* l; + Exp* opd; char new_var[MAX_VARIABLE_NAME]; char* last_new_var = new_var; @@ -86,13 +86,13 @@ void WordTag::insert_connectors(Exp* exp, int& dfs_position, last_var++; } - for (i = 0, l = exp->operand_first; l != NULL; l = l->next, i++) { + for (i = 0, opd = exp->operand_first; opd != NULL; opd = opd->operand_next, i++) { char* s = last_new_var; *s++ = 'c'; fast_sprintf(s, i); double and_cost = (i == 0) ? cost : 0; - insert_connectors(l->e, dfs_position, leading_right, leading_left, + insert_connectors(opd, dfs_position, leading_right, leading_left, eps_right, eps_left, new_var, false, and_cost, parent_exp, word_xnode); if (leading_right) { @@ -104,13 +104,13 @@ void WordTag::insert_connectors(Exp* exp, int& dfs_position, } } } else if (exp->type == OR_type) { - if (exp->operand_first != NULL && exp->operand_first->next == NULL) { + if (exp->operand_first != NULL && exp->operand_first->operand_next == NULL) { /* unary or - skip */ - insert_connectors(exp->operand_first->e, dfs_position, leading_right, leading_left, - eps_right, eps_left, var, root, cost, exp->operand_first->e, word_xnode); + insert_connectors(exp->operand_first, dfs_position, leading_right, leading_left, + eps_right, eps_left, var, root, cost, exp->operand_first, word_xnode); } else { int i; - E_list* l; + Exp* opd; bool ll_true = false; bool lr_true = false; @@ -129,7 +129,7 @@ void WordTag::insert_connectors(Exp* exp, int& dfs_position, } #endif - for (i = 0, l = exp->operand_first; l != NULL; l = l->next, i++) { + for (i = 0, opd = exp->operand_first; opd != NULL; opd = opd->operand_next, i++) { bool lr = leading_right, ll = leading_left; std::vector er = eps_right, el = eps_left; @@ -137,13 +137,18 @@ void WordTag::insert_connectors(Exp* exp, int& dfs_position, *s++ = 'd'; fast_sprintf(s, i); - lgdebug(+D_IC, "Word%d: var: %s; exp%d=%p; X_node: %s\n", - _word, var, i, l, word_xnode ? word_xnode->word->subword : "NULL X_node"); assert(word_xnode != NULL, "NULL X_node for var %s", new_var); - if ((NULL != word_xnode->next) && (l->e == word_xnode->next->exp)) - word_xnode = word_xnode->next; + if (root) + { + lgdebug(+D_IC, "Word%d: var: %s; exp%d=%p; X_node: %s\n", + _word, new_var, i, opd, word_xnode->word->subword); + } - insert_connectors(l->e, dfs_position, lr, ll, er, el, new_var, false, cost, l->e, word_xnode); + insert_connectors(opd, dfs_position, lr, ll, er, el, new_var, false, cost, opd, word_xnode); + + /* For the toplevel X_node-joined OR_type, get the next X_node. */ + if (root && (word_xnode->next != NULL)) + word_xnode = word_xnode->next; if (lr) lr_true = true; diff --git a/link-grammar/tokenize/tokenize.c b/link-grammar/tokenize/tokenize.c index e39470fc17..f95edff21e 100644 --- a/link-grammar/tokenize/tokenize.c +++ b/link-grammar/tokenize/tokenize.c @@ -2996,7 +2996,7 @@ static X_node * build_word_expressions(Sentence sent, const Gword *w, const char y = (X_node *) pool_alloc(sent->X_node_pool); y->next = x; x = y; - x->exp = copy_Exp(dn->exp, sent->E_list_pool, sent->Exp_pool); + x->exp = copy_Exp(dn->exp, sent->Exp_pool); if (NULL == s) { x->string = dn->string; From 9578c0da2d0893d1d5b71a9f89dea65b0863e9dd Mon Sep 17 00:00:00 2001 From: ampli Date: Thu, 11 Jul 2019 18:48:36 +0300 Subject: [PATCH 4/9] Remove remaining E_list definitions --- link-grammar/api-structures.h | 1 - link-grammar/dict-common/dict-structures.h | 7 ------- 2 files changed, 8 deletions(-) diff --git a/link-grammar/api-structures.h b/link-grammar/api-structures.h index 6a5ddda009..6857c0944a 100644 --- a/link-grammar/api-structures.h +++ b/link-grammar/api-structures.h @@ -127,7 +127,6 @@ struct Sentence_s String_set * string_set; /* Used for assorted strings */ Pool_desc * fm_Match_node; /* Fast-matcher Match_node memory pool */ Pool_desc * Table_connector_pool; /* Count memoizing memory pool */ - Pool_desc * E_list_pool; Pool_desc * Exp_pool; Pool_desc * X_node_pool; Pool_desc * Disjunct_pool; diff --git a/link-grammar/dict-common/dict-structures.h b/link-grammar/dict-common/dict-structures.h index 8e86f5103e..caf172a145 100644 --- a/link-grammar/dict-common/dict-structures.h +++ b/link-grammar/dict-common/dict-structures.h @@ -22,7 +22,6 @@ LINK_BEGIN_DECLS /* Forward decls */ typedef struct Dict_node_struct Dict_node; typedef struct Exp_struct Exp; -typedef struct E_list_struct E_list; typedef struct Word_file_struct Word_file; typedef struct condesc_struct condesc_t; @@ -58,12 +57,6 @@ struct Exp_struct double cost; /* The cost of using this expression. */ }; -struct E_list_struct -{ - E_list * next; - Exp * e; -}; - /* API to access the above structure. */ static inline Exp_type lg_exp_get_type(const Exp* exp) { return exp->type; } static inline char lg_exp_get_dir(const Exp* exp) { return exp->dir; } From 5fffc4172a1f6ac1c74d18ee35e81de8f2da3c15 Mon Sep 17 00:00:00 2001 From: ampli Date: Thu, 11 Jul 2019 19:42:44 +0300 Subject: [PATCH 5/9] exp_compare(): Simplify and prevent deep recursion --- link-grammar/dict-common/dict-utils.c | 37 ++++++++++++--------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/link-grammar/dict-common/dict-utils.c b/link-grammar/dict-common/dict-utils.c index c698500141..3260272985 100644 --- a/link-grammar/dict-common/dict-utils.c +++ b/link-grammar/dict-common/dict-utils.c @@ -69,43 +69,38 @@ Exp *copy_Exp(Exp *e, Pool_desc *Exp_pool) } /** - * Compare two expressions, return true for equal, false for unequal + * Compare two expressions, return true for equal, false for unequal. */ -static bool exp_compare(Exp * e1, Exp * e2) +static bool exp_compare(Exp *e1, Exp *e2) { if ((e1 == NULL) && (e2 == NULL)) - return 1; /* they are equal */ + return true; if ((e1 == NULL) || (e2 == NULL)) - return 0; /* they are not equal */ + return false; if (e1->type != e2->type) - return 0; + return false; if (fabs (e1->cost - e2->cost) > 0.001) - return 0; + return false; + if (e1->type == CONNECTOR_type) { if (e1->dir != e2->dir) - return 0; - /* printf("%s %s\n",e1->condesc->string,e2->condesc->string); */ + return false; if (e1->condesc != e2->condesc) - return 0; + return false; } else { - e1 = e1->operand_first; - e2 = e2->operand_first; - /* while at least 1 is non-null */ - for (;(e1!=NULL)||(e2!=NULL);) { - /*fail if 1 is null */ - if ((e1==NULL)||(e2==NULL)) - return 0; - /* fail if they are not compared */ + /* Iterate operands to avoid a deep recursion due to a lot of operands. */ + for (e1 = e1->operand_first, e2 = e2->operand_first; + e1 != NULL || e2 != NULL; + e1 = e1->operand_next, e2 = e2->operand_next) + { if (!exp_compare(e1, e2)) - return 0; - e1 = e1->operand_next; - e2 = e2->operand_next; + return false; } } - return 1; /* if never returned 0, return 1 */ + return true; } /** From 819548ed0bd4e2a749e7f5c72058b37d2119d88e Mon Sep 17 00:00:00 2001 From: ampli Date: Fri, 12 Jul 2019 22:58:25 +0300 Subject: [PATCH 6/9] exp_compare(): Optimize connector checking order --- link-grammar/dict-common/dict-utils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/link-grammar/dict-common/dict-utils.c b/link-grammar/dict-common/dict-utils.c index 3260272985..e0e6eed61b 100644 --- a/link-grammar/dict-common/dict-utils.c +++ b/link-grammar/dict-common/dict-utils.c @@ -84,10 +84,10 @@ static bool exp_compare(Exp *e1, Exp *e2) if (e1->type == CONNECTOR_type) { - if (e1->dir != e2->dir) - return false; if (e1->condesc != e2->condesc) return false; + if (e1->dir != e2->dir) + return false; } else { From 6766538548fec1f06e0d73d65081df364a72ff89 Mon Sep 17 00:00:00 2001 From: ampli Date: Fri, 12 Jul 2019 23:44:03 +0300 Subject: [PATCH 7/9] copy_Exp(): Iterate operands --- link-grammar/dict-common/dict-utils.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/link-grammar/dict-common/dict-utils.c b/link-grammar/dict-common/dict-utils.c index e0e6eed61b..95cda2e0d7 100644 --- a/link-grammar/dict-common/dict-utils.c +++ b/link-grammar/dict-common/dict-utils.c @@ -61,9 +61,22 @@ Exp *copy_Exp(Exp *e, Pool_desc *Exp_pool) *new_e = *e; +#if 0 /* Not used - left here for documentation. */ new_e->operand_next = copy_Exp(e->operand_next, Exp_pool); if (CONNECTOR_type == e->type) return new_e; new_e->operand_first = copy_Exp(e->operand_first, Exp_pool); +#else + if (CONNECTOR_type == e->type) return new_e; + + /* Iterate operands to avoid a deep recursion due to a lot of operands. */ + Exp **tmp_e_a = &new_e->operand_first; + for(Exp *opd = e->operand_first; opd != NULL; opd = opd->operand_next) + { + *tmp_e_a = copy_Exp(opd, Exp_pool); + tmp_e_a = &(*tmp_e_a)->operand_next; + } + *tmp_e_a = NULL; +#endif return new_e; } From a1df0ca84bad34875d58b95d36173c7eb3b804bc Mon Sep 17 00:00:00 2001 From: ampli Date: Fri, 12 Jul 2019 23:56:00 +0300 Subject: [PATCH 8/9] Add API for Exp traversal --- link-grammar/dict-common/dict-structures.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/link-grammar/dict-common/dict-structures.h b/link-grammar/dict-common/dict-structures.h index caf172a145..3bb4fd63c3 100644 --- a/link-grammar/dict-common/dict-structures.h +++ b/link-grammar/dict-common/dict-structures.h @@ -63,6 +63,8 @@ static inline char lg_exp_get_dir(const Exp* exp) { return exp->dir; } static inline bool lg_exp_get_multi(const Exp* exp) { return exp->multi; } const char* lg_exp_get_string(const Exp*); static inline double lg_exp_get_cost(const Exp* exp) { return exp->cost; } +static inline Exp* lg_exp_operand_first(Exp* exp) { return exp->operand_first; } +static inline Exp* lg_exp_operand_next(Exp* exp) { return exp->operand_next; } /** * The dictionary is stored as a binary tree comprised of the following From d9252e457f026b9778095b7a560e87609a09090b Mon Sep 17 00:00:00 2001 From: ampli Date: Thu, 18 Jul 2019 21:27:22 +0300 Subject: [PATCH 9/9] WordTag::find_matches(): Fix debug message to print a string - not an address --- link-grammar/sat-solver/word-tag.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/link-grammar/sat-solver/word-tag.cpp b/link-grammar/sat-solver/word-tag.cpp index 710e47abf5..409d5419b1 100644 --- a/link-grammar/sat-solver/word-tag.cpp +++ b/link-grammar/sat-solver/word-tag.cpp @@ -164,7 +164,7 @@ void WordTag::insert_connectors(Exp* exp, int& dfs_position, void WordTag::find_matches(int w, Connector* search_cntr, char dir, std::vector& matches) { - // cout << "Look connection on: ." << _word << ". ." << w << ". " << search_cntr << dir << endl; + // cout << "Look connection on: ." << _word << ". ." << w << ". " << connector_string(search_cntr) << dir << endl; std::vector* connectors; switch(dir) {