📄 hrec.c
字号:
}#ifdef SANITY if (path!=0 && inst->exit->n>0 && inst->exit->tok.path!=inst->exit->set[0].path) HError(8590,"CollectPaths: Top path mismatch in state N");#endif for (k=1;k<inst->exit->n;k++) { path=inst->exit->set[k].path; if (path && !path->used) { if (path->usage!=0) MovePathYesRef(path); path->used=TRUE; } } align=inst->exit->tok.align; if (align && !align->used) { if (align->usage!=0) MoveAlignYesRef(align); align->used=TRUE; } } for (path=pri->pNoRef.link;path->link!=NULL;path=plink) { if (!path->used) { if (path->align!=NULL) DeRefAlign(path->align); DeRefPathPrev(path); plink=path->link; UnlinkPath(path); } else { path->used=FALSE; plink=path->link; } } for (path=pri->pYesRef.link;path->link!=NULL;path=path->link) { if (!path->used) break; path->used=FALSE; } pri->cpth=pri->npth; for (align=pri->aNoRef.link;align->link!=NULL;align=alink) { if (!align->used) { if (align->prev!=NULL) DeRefAlign(align->prev); alink=align->link; UnlinkAlign(align); } else { align->used=FALSE; alink=align->link; } } for (align=pri->aYesRef.link;align->link!=NULL;align=align->link) { if (!align->used) break; align->used=FALSE; } pri->calign=pri->nalign;}static void StepWord1(NetNode *node) /* Just invalidate the tokens */{ node->inst->state->tok=null_token; node->inst->state->n=((pri->nToks>1)?1:0); node->inst->exit->tok=null_token; node->inst->exit->n=((pri->nToks>1)?1:0); node->inst->max=LZERO;}static void StepWord2(NetNode *node) /* Update the path - may be repeated */{ NetInst *inst; Path *newpth,*oldpth; RelToken *cur; NxtPath *rth; int i,k; inst=node->inst; if (node->info.pron==NULL && node->tag==NULL) { inst->exit->tok=inst->state->tok; inst->exit->n=inst->state->n; for (k=0;k<inst->exit->n;k++) inst->exit->set[k]=inst->state->set[k]; } else { inst->exit->tok=inst->state->tok; if (node->info.pron!=NULL) { inst->exit->tok.like+=pri->wordpen; inst->exit->tok.like+=node->info.pron->prob*pri->pscale; } newpth=NewNRefPath(); newpth->node=node; newpth->usage=0; newpth->frame=pri->frame; newpth->like=inst->exit->tok.like; newpth->lm=inst->exit->tok.lm; if ((newpth->align=inst->exit->tok.align)!=NULL) RefAlign(newpth->align); inst->exit->tok.path=newpth; inst->exit->tok.lm=0.0; inst->exit->tok.align=NULL; oldpth=inst->state->tok.path; if ((newpth->prev=oldpth)!=NULL) RefPath(oldpth); if (pri->nToks>1) { inst->exit->n=1; inst->exit->set[0].path=newpth; cur=inst->state->set+1; if (inst->state->n>1) { rth=(NxtPath*) New(&pri->rPthHeap,0); newpth->chain=rth; rth->chain=NULL; rth->like=newpth->like+cur->like; rth->lm=cur->lm; if ((rth->prev=cur->path)!=NULL) RefPath(cur->path); for (i=2,cur++;i<inst->state->n;i++,cur++) { rth->chain=(NxtPath*) New(&pri->rPthHeap,0); rth=rth->chain; rth->chain=NULL; rth->like=newpth->like+cur->like; rth->lm=cur->lm; if ((rth->prev=cur->path)!=NULL) RefPath(cur->path); } } } else { inst->exit->n=0; newpth->chain=NULL; } }}static void MoveToRecent(NetInst *inst){ if (inst->node==NULL) return; /* If we are about to move the instance that is used to determine the */ /* next instance to be stepped (to the most recent end of the list) we */ /* must use the previous instance to determine the next one to step !! */ if (inst==pri->nxtInst) pri->nxtInst=inst->knil; inst->link->knil=inst->knil; inst->knil->link=inst->link; inst->link=&pri->tail; inst->knil=pri->tail.knil; inst->link->knil=inst; inst->knil->link=inst; inst->pxd=FALSE; inst->ooo=TRUE;#ifdef SANITY if (inst==pri->start_inst) HError(8521,"MoveToRecent: Loop resulted in circular move"); inst->ipos=pri->ipos++;#endif}static void ReOrderList(NetNode *node){ NetLink *dest; int i; if (node->inst!=NULL?!node->inst->ooo:TRUE) return; node->inst->ooo=FALSE; for (i=0,dest=node->links;i<node->nlinks;i++,dest++) { if (!node_tr0(dest->node)) break; if (dest->node->inst!=NULL) MoveToRecent(dest->node->inst); } for (i=0,dest=node->links;i<node->nlinks;i++,dest++) { if (!node_tr0(dest->node)) break; if (dest->node->inst!=NULL) ReOrderList(dest->node); }}static LogFloat LikeToWord(NetNode *node){ NetLink *dest; HMMDef *hmm; LogFloat like,best; int i,N; best=LZERO; for (i=0,dest=node->links;i<node->nlinks;i++,dest++) { if (!node_tr0(dest->node)) break; like=dest->like*pri->scale; if (like<=best) continue; if (node_word(dest->node)) { if (like>best) best=like; } else if (node_wd0(dest->node)) { /* Must be tee hmm */ if (dest->node->type!=(n_hmm+n_tr0+n_wd0)) HError(8521,"LikeToWord: Node should be hmm & tr0 & wd0 (%d)", node->type); hmm=dest->node->info.hmm; N=hmm->numStates; like+=hmm->transP[1][N]; like+=LikeToWord(dest->node); if (like>best) best=like; } } return(best);} static void AttachInst(NetNode *node){ TokenSet *cur; NetInst *inst; int i,n; inst=(NetInst*) New(&pri->instHeap,0); if (node_hmm(node)) n=node->info.hmm->numStates-1; else n=1;#ifdef SANITY if (pri->psi->stHeapIdx[n]<0) HError(8592,"AttachInst: State heap not created for %d states",n);#endif inst->node=node; inst->state=(TokenSet*) New(pri->stHeap+pri->psi->stHeapIdx[n],0); inst->exit=(TokenSet*) New(pri->stHeap+pri->psi->stHeapIdx[1],0); inst->exit->tok=null_token; if (pri->nToks>1) { inst->exit->set=(RelToken*) New(&pri->rTokHeap,0); inst->exit->n=1; inst->exit->set[0]=rmax; } else { inst->exit->n=0; } for (i=1,cur=inst->state;i<=n;i++,cur++) { cur->tok=null_token; if (pri->nToks>1) { cur->set=(RelToken*) New(&pri->rTokHeap,0); cur->n=1; cur->set[0]=rmax; } else { cur->n=0; } } inst->max=LZERO; inst->link=&pri->tail; inst->knil=pri->tail.knil; inst->link->knil=inst; inst->knil->link=inst; node->inst=inst; if (node_wd0(node)) inst->wdlk=LikeToWord(inst->node); else inst->wdlk=LZERO; pri->nact++; /* New node needs any currently alive following insts moved */ /* to be more recent than it to ensure tokens propagated in */ /* correct order. */ inst->ooo=TRUE; /* Need keep list in propagation order */#ifdef SANITY inst->ipos=pri->ipos++; pri->start_inst=inst;#endif ReOrderList(node);}static void DetachInst(NetNode *node){ TokenSet *cur; NetInst *inst; int i,n; inst=node->inst; pri->nact--;#ifdef SANITY if (inst->node!=node) HError(8591,"DetachInst: Node/Inst mismatch");#endif inst->link->knil=inst->knil; inst->knil->link=inst->link; if (node_hmm(node)) n=node->info.hmm->numStates-1; else n=1; if (pri->nToks>1) { for (i=0,cur=inst->state;i<n;i++,cur++) Dispose(&pri->rTokHeap,cur->set); Dispose(&pri->rTokHeap,inst->exit->set); } Dispose(pri->stHeap+pri->psi->stHeapIdx[n],inst->state); Dispose(pri->stHeap+pri->psi->stHeapIdx[1],inst->exit);#ifdef SANITY inst->state=NULL; inst->exit=NULL;#endif Dispose(&pri->instHeap,inst); node->inst=0;}static void SetEntryState(NetNode *node,TokenSet *src){ NetInst *inst; TokenSet *res; if (node->inst==NULL) AttachInst(node); inst=node->inst; res=inst->state;#ifdef SANITY if ((res->n==0 && src->n!=0) || (res->n!=0 && src->n==0)) HError(8590,"SetEntryState: TokenSet size mismatch"); /* if (src->tok.like>LSMALL && src->tok.path!=NULL && src->tok.path->node->info.pron==NULL) HError(8590,"SetEntryState: NULL word propagated into path"); */#endif if (res->n==0) { if (src->tok.like > res->tok.like) res->tok=src->tok; } else TokSetMerge(res,&src->tok,src); if (res->tok.like>inst->max) inst->max=res->tok.like; if (node->type==n_word && (pri->wordMaxNode==NULL || pri->wordMaxNode->inst==NULL || res->tok.like > pri->wordMaxNode->inst->max)) pri->wordMaxNode=node;}static void StepInst1(NetNode *node) /* First pass of token propagation (Internal) */{ if (node_hmm(node)) StepHMM1(node); /* Advance tokens within HMM instance t => t-1 */ /* Entry tokens valid for t-1, do states 2..N */ else StepWord1(node); node->inst->pxd=FALSE;}static void StepInst2(NetNode *node) /* Second pass of token propagation (External) */ /* Must be able to survive doing this twice !! */{ Token tok; TokenSet xtok; RelToken rtoks[MAX_TOKS]; NetLink *dest; LogFloat lm; int i,k; if (node_word(node)) StepWord2(node); /* Merge tokens and update traceback */ else if (node_tr0(node) /* && node_hmm(node) */) StepHMM2(node); /* Advance tokens within HMM instance t => t-1 */ /* Entry token valid for t, only do state N */ tok=node->inst->exit->tok; xtok.tok=tok; xtok.n=node->inst->exit->n; xtok.set=rtoks; for (k=0;k<xtok.n;k++) xtok.set[k]=node->inst->exit->set[k]; if (node_word(node)) if (tok.like<pri->wordThresh) tok=null_token; if (tok.like>pri->genThresh) { for(i=0,dest=node->links;i<node->nlinks;i++,dest++) { lm=dest->like; xtok.tok.like=tok.like+lm*pri->scale; xtok.tok.lm=tok.lm+lm; for (k=0;k<xtok.n;k++) xtok.set[k].lm=node->inst->exit->set[k].lm+lm; if (xtok.tok.like>pri->genThresh) { SetEntryState(dest->node,&xtok); /* Transfer set of tokens to node, activating when necessary */ /* choosing N most likely after adding transition likelihood */ } } } node->inst->pxd=TRUE;}static void CreateSEIndex(PSetInfo *psi,HLink hmm){ SMatrix trP; short **se; /* Actually (*se)[2] */ int j,min,max,N; trP=hmm->transP; N=hmm->numStates; se=psi->seIndexes[hmm->tIdx]; if (se==NULL) { se=(short**) New(&psi->heap,(N-1)*sizeof(short*)); se-=2; for (j=2;j<=N;j++) { se[j]=(short*) New(&psi->heap,2*sizeof(short)); for (min=(j==N)?2:1;min<N;min++) /* Don't want tee transitions */ if (trP[min][j]>LSMALL) break; for (max=N-1;max>1;max--) if (trP[max][j]>LSMALL) break;#ifdef SANITY if (min>max) { HError(-8520,"CreateSEIndex: No transitions to state %d",j); min=(j==N)?2:1; max=N-1; }#endif se[j][0]=min; se[j][1]=max; } psi->seIndexes[hmm->tIdx]=se; }}/* Prepare HMMSet for recognition. Allocates seIndex and preComp from *//* hmmset heap.*/PSetInfo *InitPSetInfo(HMMSet *hset){ PSetInfo *psi; RelToken *rtoks; int n,h,i; HLink hmm; MLink q; PreComp *pre; char name[80]; static int psid=0; psi=(PSetInfo*) New(&gcheap,sizeof(PSetInfo));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -