void releasenode(Node* node) { if (node) { if (node->left) releasenode(node->left); if (node->right) releasenode(node->right); free(node); } }
Node * push_negation(Node *n) { Node *m; Assert(n->ntyp == NOT, n->ntyp); switch (n->lft->ntyp) { case TRUE: releasenode(0, n->lft); n->lft = ZN; n->ntyp = FALSE; break; case FALSE: releasenode(0, n->lft); n->lft = ZN; n->ntyp = TRUE; break; case NOT: m = n->lft->lft; releasenode(0, n->lft); n->lft = ZN; releasenode(0, n); n = m; break; case V_OPER: n->ntyp = U_OPER; goto same; case U_OPER: n->ntyp = V_OPER; goto same; #ifdef NXT case NEXT: n->ntyp = NEXT; n->lft->ntyp = NOT; n->lft = push_negation(n->lft); break; #endif case AND: n->ntyp = OR; goto same; case OR: n->ntyp = AND; same: m = n->lft->rgt; n->lft->rgt = ZN; n->rgt = Not(m); n->lft->ntyp = NOT; m = n->lft; n->lft = push_negation(m); break; } return rewrite(n); }
void releasenode(int all_levels, Node *n) { if (!n) return; if (all_levels) { releasenode(1, n->lft); n->lft = ZN; releasenode(1, n->rgt); n->rgt = ZN; } tfree((void *) n); }
Node *push_negation(Node *n, Miscellaneous *miscell, int *cnt, char *uform, int *tl_yychar) { Node *m; Assert(n->ntyp == NOT, n->ntyp); switch (n->lft->ntyp) { case TRUE: releasenode(0, n->lft); n->lft = ZN; n->ntyp = FALSE; break; case FALSE: releasenode(0, n->lft); n->lft = ZN; n->ntyp = TRUE; break; case NOT: m = n->lft->lft; releasenode(0, n->lft); n->lft = ZN; releasenode(0, n); n = m; break; case V_OPER: n = switchNotTempOper(n,U_OPER, miscell, cnt, uform, tl_yychar); break; case U_OPER: n = switchNotTempOper(n,V_OPER, miscell, cnt, uform, tl_yychar); break; case NEXT: n = switchNotTempOper(n,WEAKNEXT, miscell, cnt, uform, tl_yychar); break; case WEAKNEXT: n = switchNotTempOper(n,NEXT, miscell, cnt, uform, tl_yychar); break; case AND: n = switchNotTempOper(n,OR, miscell, cnt, uform, tl_yychar); break; case OR: n = switchNotTempOper(n,AND, miscell, cnt, uform, tl_yychar); break; } return n; /* return rewrite(n); do not forget to change this in parse*/ }
void trans(Node *p) { if (!p || tl_errs) return; if (tl_verbose || tl_terse) { fprintf(tl_out, "\t/* Normlzd: "); dump(p); fprintf(tl_out, " */\n"); } if (tl_terse) return; // Buddy might have been initialized by a third-party library. if (!bdd_isrunning()) { bdd_init(100000, 10000); // Disable the default GC handler. bdd_gbc_hook(0); } mk_alternating(p); if (!tl_hoaf || tl_hoaf > 1) { mk_generalized(); if ((!tl_spot_out || tl_spot_out > 2) && (!tl_hoaf || tl_hoaf > 2)) mk_buchi(); } releasenode(1, p); bdd_done(); }
Node *push_negation(Node *n) { Node *m; Assert(n->ntyp == NOT, n->ntyp); switch (n->lft->ntyp) { case TRUE: releasenode(0, n->lft); n->lft = ZN; n->ntyp = FALSE; break; case FALSE: releasenode(0, n->lft); n->lft = ZN; n->ntyp = TRUE; break; case NOT: m = n->lft->lft; releasenode(0, n->lft); n->lft = ZN; releasenode(0, n); n = m; break; case V_OPER: n = switchNotTempOper(n,U_OPER); break; case U_OPER: n = switchNotTempOper(n,V_OPER); break; case NEXT: n = switchNotTempOper(n,WEAKNEXT); break; case WEAKNEXT: n = switchNotTempOper(n,NEXT); break; case AND: n = switchNotTempOper(n,OR); break; case OR: n = switchNotTempOper(n,AND); break; } return n; }
static void marknode(int tok, Node *m) { if (m->ntyp != tok) { releasenode(0, m->rgt); m->rgt = ZN; } m->ntyp = -1; }
static int mergetrans(void) { State *b; Transition *s, *t; Node *nc; int cnt = 0; for (b = never; b; b = b->nxt) { if (!b->reachable) continue; for (s = b->trans; s; s = s->nxt) { if (s->redundant) continue; for (t = s->nxt; t; t = t->nxt) if (!t->redundant && !strcmp(s->name->name, t->name->name)) { if (tl_verbose) { printf("===\nstate %s, trans to %s redundant\n", b->name->name, s->name->name); showtrans(b); printf(" conditions "); dump(s->cond); printf(" <-> "); dump(t->cond); printf("\n"); } if (!s->cond) /* same as T */ { releasenode(1, t->cond); /* T or t */ nc = True; } else if (!t->cond) { releasenode(1, s->cond); nc = True; } else { nc = combination(s->cond, t->cond); } t->cond = rewrite(nc); t->merged = 1; s->redundant = 1; cnt++; break; } } } return cnt; }
static Node * Prune(Node *p) { if (p) switch (p->ntyp) { case PREDICATE: case NOT: case FALSE: case TRUE: #ifdef NXT case NEXT: #endif return p; case OR: p->lft = Prune(p->lft); if (!p->lft) { releasenode(1, p->rgt); return ZN; } p->rgt = Prune(p->rgt); if (!p->rgt) { releasenode(1, p->lft); return ZN; } return p; case AND: p->lft = Prune(p->lft); if (!p->lft) return Prune(p->rgt); p->rgt = Prune(p->rgt); if (!p->rgt) return p->lft; return p; } releasenode(1, p); return ZN; }
int main() { char rawbuf[4096] = {0},buf[4096] = {0},addbuf[1024] = {0}; char* tmpbuf; #ifndef ONLINE_JUDGE freopen("1.txt","r",stdin); #endif while (fgets(rawbuf,sizeof(rawbuf)-1,stdin) != NULL) { int leftparent = 0; char* ret; trimblank(rawbuf,buf); tmpbuf = buf; calcleftparent(tmpbuf,leftparent); while (leftparent) { fgets(rawbuf,sizeof(rawbuf)-1,stdin); trimblank(rawbuf,addbuf); tmpbuf = addbuf; calcleftparent(tmpbuf,leftparent); strcat(buf,addbuf); } int checksum = atoi(buf); char *nodeleftpa = strstr(buf,"("); char *noderightpa = buf + strlen(buf)-1; Node *root = NULL; mknode(nodeleftpa,noderightpa,&root); bool flag = false; existsum(checksum,root,flag); if (flag) { printf("yes\n"); } else { printf("no\n"); } releasenode(root); } return 0; }
void mk_alternating(tl_Node *p) /* generates an alternating automaton for p */ { if (tl_stats) { getrusage(RUSAGE_SELF, &tr_debut); } node_size = calculate_node_size(p) + 1; /* number of states in the automaton */ label = (tl_Node **) tl_emalloc(node_size * sizeof(tl_Node *)); transition = (ATrans **) tl_emalloc(node_size * sizeof(ATrans *)); node_size = node_size / (8 * sizeof(int)) + 1; sym_size = calculate_sym_size(p); /* number of predicates */ if (sym_size) { sym_table = (char **) tl_emalloc(sym_size * sizeof(char *)); } sym_size = sym_size / (8 * sizeof(int)) + 1; final_set = make_set(-1, 0); transition[0] = boolean(p); /* generates the alternating automaton */ if (tl_verbose) { fprintf(tl_out, "\nAlternating automaton before simplification\n"); print_alternating(); } if (tl_simp_diff) { simplify_astates(); /* keeps only accessible states */ if (tl_verbose) { fprintf(tl_out, "\nAlternating automaton after simplification\n"); print_alternating(); } } if (tl_stats) { getrusage(RUSAGE_SELF, &tr_fin); fprintf(tl_out, "\n%i states, %i transitions\n", astate_count, atrans_count); } releasenode(1, p); tfree(label); }
void mk_alternating(Node *p) /* generates an alternating automaton for p */ { if(tl_stats) getrusage(RUSAGE_SELF, &tr_debut); node_size = calculate_node_size(p) + 1; /* number of states in the automaton */ label = (Node **) tl_emalloc(node_size * sizeof(Node *)); transition = (ATrans **) tl_emalloc(node_size * sizeof(ATrans *)); node_size = node_size / (8 * sizeof(int)) + 1; sym_size = calculate_sym_size(p); /* number of predicates */ if(sym_size) sym_table = (char **) tl_emalloc(sym_size * sizeof(char *)); sym_size = sym_size / (8 * sizeof(int)) + 1; final_set = make_set(-1, 0); transition[0] = boolean(p); /* generates the alternating automaton */ if(tl_verbose) { fprintf(tl_out, "\nAlternating automaton before simplification\n"); print_alternating(); } if(tl_simp_diff) { simplify_astates(); /* keeps only accessible states */ if(tl_verbose) { fprintf(tl_out, "\nAlternating automaton after simplification\n"); print_alternating(); } } #ifndef __MINGW__ if(tl_stats) { getrusage(RUSAGE_SELF, &tr_fin); timeval_subtract (&t_diff, &tr_fin.ru_utime, &tr_debut.ru_utime); fprintf(tl_out, "\nBuilding and simplification of the alternating automaton: %i.%06is", t_diff.tv_sec, t_diff.tv_usec); fprintf(tl_out, "\n%i states, %i transitions\n", astate_count, atrans_count); } #endif releasenode(1, p); tfree(label); }
Node * cached(Node *n) { Cache *d; Node *m; if (!n) return n; if ((m = in_cache(n)) != ZN) return m; Caches++; d = (Cache *) tl_emalloc(sizeof(Cache)); d->before = dupnode(n); d->after = Canonical(n); /* n is released */ if (ismatch(d->before, d->after)) { d->same = 1; releasenode(1, d->after); d->after = d->before; } d->nxt = stored; stored = d; return dupnode(d->after); }
Node * push_negation(Node *n) { Node *m; Assert(n->ntyp == NOT, n->ntyp); switch (n->lft->ntyp) { case TRUE: Debug("!true => false\n"); releasenode(0, n->lft); n->lft = ZN; n->ntyp = FALSE; break; case FALSE: Debug("!false => true\n"); releasenode(0, n->lft); n->lft = ZN; n->ntyp = TRUE; break; case NOT: Debug("!!p => p\n"); m = n->lft->lft; releasenode(0, n->lft); n->lft = ZN; releasenode(0, n); n = m; break; case V_OPER: Debug("!(p V q) => (!p U !q)\n"); n->ntyp = U_OPER; goto same; case U_OPER: Debug("!(p U q) => (!p V !q)\n"); n->ntyp = V_OPER; goto same; #ifdef NXT case NEXT: Debug("!X -> X!\n"); n->ntyp = NEXT; n->lft->ntyp = NOT; n->lft = push_negation(n->lft); break; #endif case AND: Debug("!(p && q) => !p || !q\n"); n->ntyp = OR; goto same; case OR: Debug("!(p || q) => !p && !q\n"); n->ntyp = AND; same: m = n->lft->rgt; n->lft->rgt = ZN; n->rgt = Not(m); n->lft->ntyp = NOT; m = n->lft; n->lft = push_negation(m); break; } return rewrite(n); }
Node * Canonical(Node *n) { Node *m, *p, *k1, *k2, *prev, *dflt = ZN; int tok; if (!n) return n; tok = n->ntyp; if (tok != AND && tok != OR) return n; can = ZN; addcan(tok, n); #if 0 Debug("\nA0: "); Dump(can); Debug("\nA1: "); Dump(n); Debug("\n"); #endif releasenode(1, n); /* mark redundant nodes */ if (tok == AND) { for (m = can; m; m = (m->ntyp == AND) ? m->rgt : ZN) { k1 = (m->ntyp == AND) ? m->lft : m; if (k1->ntyp == TRUE) { marknode(AND, m); dflt = True; continue; } if (k1->ntyp == FALSE) { releasenode(1, can); can = False; goto out; } } for (m = can; m; m = (m->ntyp == AND) ? m->rgt : ZN) for (p = can; p; p = (p->ntyp == AND) ? p->rgt : ZN) { if (p == m || p->ntyp == -1 || m->ntyp == -1) continue; k1 = (m->ntyp == AND) ? m->lft : m; k2 = (p->ntyp == AND) ? p->lft : p; if (isequal(k1, k2)) { marknode(AND, p); continue; } if (anywhere(OR, k1, k2)) { marknode(AND, p); continue; } } } if (tok == OR) { for (m = can; m; m = (m->ntyp == OR) ? m->rgt : ZN) { k1 = (m->ntyp == OR) ? m->lft : m; if (k1->ntyp == FALSE) { marknode(OR, m); dflt = False; continue; } if (k1->ntyp == TRUE) { releasenode(1, can); can = True; goto out; } } for (m = can; m; m = (m->ntyp == OR) ? m->rgt : ZN) for (p = can; p; p = (p->ntyp == OR) ? p->rgt : ZN) { if (p == m || p->ntyp == -1 || m->ntyp == -1) continue; k1 = (m->ntyp == OR) ? m->lft : m; k2 = (p->ntyp == OR) ? p->lft : p; if (isequal(k1, k2)) { marknode(OR, p); continue; } if (anywhere(AND, k1, k2)) { marknode(OR, p); continue; } } } for (m = can, prev = ZN; m; ) /* remove marked nodes */ { if (m->ntyp == -1) { k2 = m->rgt; releasenode(0, m); if (!prev) { m = can = can->rgt; } else { m = prev->rgt = k2; /* if deleted the last node in a chain */ if (!prev->rgt && prev->lft && (prev->ntyp == AND || prev->ntyp == OR)) { k1 = prev->lft; prev->ntyp = prev->lft->ntyp; prev->sym = prev->lft->sym; prev->rgt = prev->lft->rgt; prev->lft = prev->lft->lft; releasenode(0, k1); } } continue; } prev = m; m = m->rgt; } out: #if 0 Debug("A2: "); Dump(can); Debug("\n"); #endif if (!can) { if (!dflt) fatal("cannot happen, Canonical", (char *) 0); return dflt; } return can; }
static void expand_g(Graph *g) { Node *now, *n1, *n2, *nx; int can_release; if (!g->New) { Debug2("\nDone with %s", g->name->name); if (tl_verbose) dump_graph(g); if (not_new(g)) { if (tl_verbose) printf("\tIs Not New\n"); return; } if (g->Next) { Debug(" Has Next ["); for (n1 = g->Next; n1; n1 = n1->nxt) { Dump(n1); Debug(", "); } Debug("]\n"); ng(ZS, getsym(g->name), g->Next, ZN, ZN); } return; } if (tl_verbose) { Symbol *z; printf("\nExpand %s, from ", g->name->name); for (z = g->incoming; z; z = z->next) printf("%s, ", z->name); printf("\n\thandle:\t"); Explain(g->New->ntyp); dump_graph(g); } if (g->New->ntyp == AND) { if (g->New->nxt) { n2 = g->New->rgt; while (n2->nxt) n2 = n2->nxt; n2->nxt = g->New->nxt; } n1 = n2 = g->New->lft; while (n2->nxt) n2 = n2->nxt; n2->nxt = g->New->rgt; releasenode(0, g->New); g->New = n1; push_stack(g); return; } can_release = 0; /* unless it need not go into Old */ now = g->New; g->New = g->New->nxt; now->nxt = ZN; if (now->ntyp != TRUE) { if (g->Old) { for (n1 = g->Old; n1->nxt; n1 = n1->nxt) if (isequal(now, n1)) { can_release = 1; goto out; } n1->nxt = now; } else g->Old = now; } out: switch (now->ntyp) { case FALSE: push_stack(g); break; case TRUE: releasenode(1, now); push_stack(g); break; case PREDICATE: case NOT: if (can_release) releasenode(1, now); push_stack(g); break; case V_OPER: Assert(now->rgt != ZN, now->ntyp); Assert(now->lft != ZN, now->ntyp); Assert(now->rgt->nxt == ZN, now->ntyp); Assert(now->lft->nxt == ZN, now->ntyp); n1 = now->rgt; n1->nxt = g->New; if (can_release) nx = now; else nx = getnode(now); /* now also appears in Old */ nx->nxt = g->Next; n2 = now->lft; n2->nxt = getnode(now->rgt); n2->nxt->nxt = g->New; g->New = flatten(n2); push_stack(g); ng(ZS, g->incoming, n1, g->Old, nx); break; case U_OPER: Assert(now->rgt->nxt == ZN, now->ntyp); Assert(now->lft->nxt == ZN, now->ntyp); n1 = now->lft; if (can_release) nx = now; else nx = getnode(now); /* now also appears in Old */ nx->nxt = g->Next; n2 = now->rgt; n2->nxt = g->New; goto common; #ifdef NXT case NEXT: Assert(now->lft != ZN, now->ntyp); nx = dupnode(now->lft); nx->nxt = g->Next; g->Next = nx; if (can_release) releasenode(0, now); push_stack(g); break; #endif case OR: Assert(now->rgt->nxt == ZN, now->ntyp); Assert(now->lft->nxt == ZN, now->ntyp); n1 = now->lft; nx = g->Next; n2 = now->rgt; n2->nxt = g->New; common: n1->nxt = g->New; ng(ZS, g->incoming, n1, g->Old, nx); g->New = flatten(n2); if (can_release) releasenode(1, now); push_stack(g); break; } }
static int not_new(Graph *g) { Graph *q1; Node *tmp, *n1, *n2; Mapping *map; tmp = flatten(g->Old); /* duplicate, collapse, normalize */ g->Other = g->Old; /* non normalized full version */ g->Old = tmp; g->oldstring = DoDump(g->Old); tmp = flatten(g->Next); g->nxtstring = DoDump(tmp); if (tl_verbose) dump_graph(g); Debug2("\tformula-old: [%s]\n", g->oldstring?g->oldstring->name:"true"); Debug2("\tformula-nxt: [%s]\n", g->nxtstring?g->nxtstring->name:"true"); for (q1 = Nodes_Set; q1; q1 = q1->nxt) { Debug2(" compare old to: %s", q1->name->name); Debug2(" [%s]", q1->oldstring?q1->oldstring->name:"true"); Debug2(" compare nxt to: %s", q1->name->name); Debug2(" [%s]", q1->nxtstring?q1->nxtstring->name:"true"); if (q1->oldstring != g->oldstring || q1->nxtstring != g->nxtstring) { Debug(" => different\n"); continue; } Debug(" => match\n"); if (g->incoming) q1->incoming = catSlist(g->incoming, q1->incoming); /* check if there's anything in g->Other that needs adding to q1->Other */ for (n2 = g->Other; n2; n2 = n2->nxt) { for (n1 = q1->Other; n1; n1 = n1->nxt) if (isequal(n1, n2)) break; if (!n1) { Node *n3 = dupnode(n2); /* don't mess up n2->nxt */ n3->nxt = q1->Other; q1->Other = n3; } } map = (Mapping *) tl_emalloc(sizeof(Mapping)); map->from = g->name->name; map->to = q1; map->nxt = Mapped; Mapped = map; for (n1 = g->Other; n1; n1 = n2) { n2 = n1->nxt; releasenode(1, n1); } for (n1 = g->Old; n1; n1 = n2) { n2 = n1->nxt; releasenode(1, n1); } for (n1 = g->Next; n1; n1 = n2) { n2 = n1->nxt; releasenode(1, n1); } return 1; } if (newstates) tl_verbose=1; Debug2(" New Node %s [", g->name->name); for (n1 = g->Old; n1; n1 = n1->nxt) { Dump(n1); Debug(", "); } Debug2("] nr %d\n", Base); if (newstates) tl_verbose=0; Base++; g->nxt = Nodes_Set; Nodes_Set = g; return 0; }