⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lattice.cc

📁 这是一款很好用的工具包
💻 CC
📖 第 1 页 / 共 5 页
字号:
/*
 * Lattice.cc --
 *	Word lattices
 *
 */

#ifndef lint
static char Copyright[] = "Copyright (c) 1997-2006 SRI International.  All Rights Reserved.";
static char RcsId[] = "@(#)$Header: /home/srilm/devel/lattice/src/RCS/Lattice.cc,v 1.118 2006/01/16 19:34:15 stolcke Exp $";
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>

#include "Lattice.h"

#include "SArray.cc"
#include "LHash.cc"
#include "Array.cc"
#include "WordAlign.h"                  /* for *_COST constants */
#include "NBest.h"			/* for phoneSeparator defn */

const char *LATTICE_OR		= "or";
const char *LATTICE_CONCATE	= "concatenate";
const char *LATTICE_NONAME	= "***NONAME***";

const char *NullNodeName	= "NULL";

#define DebugPrintFatalMessages         0 

#define DebugPrintFunctionality         1 
// for large functionality listed in options of the program
#define DebugPrintOutLoop               2
// for out loop of the large functions or small functions
#define DebugPrintInnerLoop             3
// for inner loop of the large functions or outloop of small functions

#ifdef INSTANTIATE_TEMPLATES
#ifdef USE_SARRAY
INSTANTIATE_SARRAY(NodeIndex,LatticeTransition);
#else
INSTANTIATE_LHASH(NodeIndex,LatticeTransition);
#endif
INSTANTIATE_LHASH(NodeIndex,LatticeNode);
INSTANTIATE_ARRAY(HTKWordInfo *);
#endif

/* **************************************************
   the queue related methods
   ************************************************** */

NodeQueue::~NodeQueue()
{
    while (is_empty() != true) {
	(void) popNodeQueue();
    }
}

NodeIndex NodeQueue::popNodeQueue()
{
    if (is_empty() == true) {
        dout() << "popNodeQueue() on an empty queue\n";
        exit(-1); 
    }

    QueueItem *pt = queueHead; 
    queueHead = queueHead->next;
    if (queueHead == 0) { 
	queueTail = 0;
    }
    NodeIndex retval = pt->item;
    delete pt;
    return retval;
} 

QueueItem * NodeQueue::popQueueItem()
{
    if (is_empty() == true) {
        dout() << "popQueueItem() on an empty queue\n";
        exit(-1); 
    }

    QueueItem *pt = queueHead; 
    queueHead = queueHead->next;

    return pt;
} 
    
Boolean NodeQueue::addToNodeQueue(NodeIndex nodeIndex, 
				  unsigned level, LogP weight)
{
    QueueItem *pt = new QueueItem(nodeIndex, level, weight);
    assert(pt != 0); 

    if (is_empty() == true) {
        queueHead = queueTail = pt;
    } else {
        queueTail->next = pt;
	queueTail = pt;
    }

    return true;
}

// add to NodeQueue if the previous element is not the same
// as the element to be added.
Boolean 
NodeQueue::addToNodeQueueNoSamePrev(NodeIndex nodeIndex, 
				    unsigned level, LogP weight)
{
    if (is_empty() == false && nodeIndex == queueTail->item) {
        if (debug(DebugPrintOutLoop)) {
	  dout() << "In addToNodeQueueNoSamePrev: skip the current nodeIndex ("
		 << nodeIndex << ")" << endl;
	}
        return true;
    }

    if (debug(DebugPrintOutLoop)) {
      dout() << "In addToNodeQueueNoSamePrev: add the current nodeIndex ("
	     << nodeIndex << ")" << endl;
    }
    QueueItem *pt = new QueueItem(nodeIndex, level, weight);
    assert(pt != 0); 

    if (is_empty() == true) {
        queueHead = queueTail = pt;
    } else {
        queueTail->next = pt;
	queueTail = pt;
    }

    return true;
}

Boolean NodeQueue::inNodeQueue(NodeIndex nodeIndex)
{
  
    QueueItem *pt = queueHead;

    while (pt != 0) {
	if (pt->item == nodeIndex) {
	    return true; 
	}
	pt = pt->next;
    }

    return false;
}

QueueItem::QueueItem(NodeIndex nodeIndex, unsigned clevel, LogP cweight)
{
    item = nodeIndex;
    level = clevel;
    weight = cweight; 
    next = 0; 
}


/* ************************************************************
   function definitions for class LatticeFollowIter
   ************************************************************ */

LatticeFollowIter::LatticeFollowIter(Lattice &lat, LatticeNode &node,
				     LHash<NodeIndex, LogP> *useVisitedNodes,
				     LogP startWeight)
    : lat(lat), transIter(node.outTransitions), subFollowIter(0),
      visitedNodes(useVisitedNodes), startWeight(startWeight)
{
    /*
     * Use shared visitedNodes table if passed from our recursive invoker,
     * otherwise create our own.
     */
    if (useVisitedNodes == 0) {
	visitedNodes = new LHash<NodeIndex, LogP>;
	assert(visitedNodes != 0);

	freeVisitedNodes = true;
    } else {
	freeVisitedNodes = false;
    }
}

LatticeFollowIter::~LatticeFollowIter()
{
    delete subFollowIter;

    if (freeVisitedNodes) {
	delete visitedNodes;
    }
}

void
LatticeFollowIter::init()
{
    /* 
     * terminate recursive iteration, if any
     */
    delete subFollowIter;
    subFollowIter = 0;

    /*
     * restart top-level iteration
     */
    transIter.init();

    /*
     * forget visited nodes 
     */
    if (freeVisitedNodes) {
	delete visitedNodes;
	visitedNodes = new LHash<NodeIndex, LogP>;
	assert(visitedNodes != 0);
    }
}

LatticeNode *
LatticeFollowIter::next(NodeIndex &followIndex, LogP &weight)
{
    LatticeNode *followNode;

    /*
     * if a recursive iteration is pending, continue it
     */
    if (subFollowIter != 0) {
	followNode = subFollowIter->next(followIndex, weight);

	if (followNode) {
	    return followNode;
	} else {
	    delete subFollowIter;
	    subFollowIter = 0;
	}
    }
	    
    /*
     * otherwise proceed with the next transition at this node
     */
    LatticeTransition *trans;
    Boolean visitedBefore;

    do {
	/*
	 * find next follow node that hasn't already been visited
	 */
	do {
	    trans = transIter.next(followIndex);

	    if (trans == 0) break;

	    /* record that node has been visited */
	    LogP *oldWeight = visitedNodes->insert(followIndex, visitedBefore);

	    /* if previous visit had lower weight, visit again */
	    if (visitedBefore && *oldWeight < startWeight + trans->weight) {
		visitedBefore = false;
	    }
		    
	    if (!visitedBefore) {
		/* record weight for this visit for future reference */
		*oldWeight = startWeight + trans->weight;
	    }
	} while (visitedBefore);

	if (trans == 0) {
	    /* no more transitions to follow, so stop */
	    break;
	} else {
	    LatticeNode *followNode = lat.findNode(followIndex);
	    assert(followNode != 0);

	    if (!lat.ignoreWord(followNode->word)) {
		weight = startWeight + trans->weight;
		return followNode;
	    } else {
		/*
		 * recursively iterate over following nodes, sharing
		 * visitedNodes table to avoid double visits and infinite loops.
		 */
		subFollowIter =
		    new LatticeFollowIter(lat, *followNode, visitedNodes,
					  startWeight + trans->weight);
		assert(subFollowIter != 0);

		LatticeNode *result = subFollowIter->next(followIndex, weight);
		if (result) {
		    return result;
		}
	    }
	}
    } while (1);

    /* end of iteration reached */
    return 0;
}


/* ************************************************************
   function definitions for class LatticeNode
   ************************************************************ */
LatticeNode::LatticeNode()
    : flags(0), word(Vocab_None), posterior(LogP_Zero), htkinfo(0)
{
}

/* ************************************************************
   function definitions for class LatticeTransition
   ************************************************************ */

/* ************************************************************
   function definitions for class Lattice
   ************************************************************ */

Lattice::Lattice(Vocab &vocab, const char *name)
    : name(strdup(name != 0 ? name : LATTICE_NONAME)),
      initial(NoNode), final(NoNode), maxIndex(0),
      duration(0.0), vocab(vocab), ignoreVocab(vocab),
      useUnk(false), limitIntlogs(false), noBackoffWeights(false), top(true)
{
    /*
     * Default is to ignore pause nodes (only)
     */
    if (vocab.pauseIndex() != Vocab_None) {
	ignoreVocab.addWord(vocab.pauseIndex());
    }
}

Lattice::Lattice(Vocab &vocab, const char *name, SubVocab &ignore)
    : name(strdup(name != 0 ? name : LATTICE_NONAME)),
      initial(NoNode), final(NoNode), maxIndex(0),
      duration(0.0), vocab(vocab), ignoreVocab(vocab),
      useUnk(false), limitIntlogs(false), noBackoffWeights(false), top(true)
{
    /*
     * Copy words-to-be-ignored locally
     */
    VocabIter ignoreIter(ignore);
    VocabIndex ignoreWord;
    while (ignoreIter.next(ignoreWord)) {
	ignoreVocab.addWord(ignoreWord);
    }
}

Lattice::~Lattice()
{
    free((void *)name);
    name = 0;

    LHashIter<NodeIndex, LatticeNode> nodeIter(nodes);
    NodeIndex nodeIndex;

    while (LatticeNode *node = nodeIter.next(nodeIndex)) {
	node->~LatticeNode();
    }

    for (unsigned i = 0; i < htkinfos.size(); i ++) {
	delete htkinfos[i];
    }
}

VocabString
Lattice::getWord(VocabIndex word)
{
    if (word == Vocab_None) {
	return NullNodeName;
    } else {
	return vocab.getWord(word);
    }
}

/* To insert a node with name *word in the NodeLattice */
Boolean 
Lattice::insertNode(const char *word, NodeIndex nodeIndex)
{
    VocabIndex windex;

    if (strcmp(word, NullNodeName) == 0) {
	windex = Vocab_None;
    } else if (useUnk) {
	windex = vocab.getIndex(word, vocab.unkIndex());
    } else {
	windex = vocab.addWord(word);
    }

    LatticeNode *node = nodes.insert(nodeIndex);

    node->word = windex;

    if (maxIndex <= nodeIndex) {
	maxIndex = nodeIndex + 1;
    }

    return true; 
}

/* duplicate a node with a same word name without making 
   any commitment on edges
   */
NodeIndex
Lattice::dupNode(VocabIndex windex, unsigned markedFlag, HTKWordInfo *htkinfo) 
{
    LatticeNode *node = nodes.insert(maxIndex);

    node->word = windex;
    node->flags = markedFlag; 
    node->htkinfo = htkinfo;

    return maxIndex++; 
}

/* remove the node and all of its edges (incoming and outgoing)
   and check to see whether it makes the graph disconnected
*/
Boolean 
Lattice::removeNode(NodeIndex nodeIndex) 
{
    LatticeNode *node = findNode(nodeIndex);
    if (!node) {
      if (debug(DebugPrintOutLoop)) {
	dout() << " In Lattice::removeNode: undefined node in graph " 
	       << nodeIndex << endl;
      }
      return false; 
    }

    // delete incoming transitions -- need do only the fromNode->outTransitions
    // node->inTransition will be freed shortly
    TRANSITER_T<NodeIndex,LatticeTransition> 
      inTransIter(node->inTransitions);
    NodeIndex fromNodeIndex;
    while (inTransIter.next(fromNodeIndex)) {
	LatticeNode *fromNode = findNode(fromNodeIndex);
	assert(fromNode != 0);
	fromNode->outTransitions.remove(nodeIndex);
    } 

    // delete outgoing transitions -- need do only the toNode->inTransitions
    // node->outTransition will be freed shortly
    TRANSITER_T<NodeIndex,LatticeTransition> 
      outTransIter(node->outTransitions);
    NodeIndex toNodeIndex;
    while (outTransIter.next(toNodeIndex)) {
	LatticeNode *toNode = findNode(toNodeIndex);
	assert(toNode != 0);
	toNode->inTransitions.remove(nodeIndex);
    } 

    // remove this node
    LatticeNode *removedNode = nodes.remove(nodeIndex);
    if (debug(DebugPrintOutLoop)) {
      dout() << "In Lattice::removeNode: remove node " << nodeIndex << endl; 
    }

    removedNode->~LatticeNode();

    if (nodeIndex == initial) {
	initial = NoNode;
    } 
    if (nodeIndex == final) {
	final = NoNode;
    } 
    
    return true;
}

void
Lattice::removeAll()
{
    LHashIter<NodeIndex, LatticeNode> nodeIter(nodes);
    NodeIndex nodeIndex;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -