#ifndef FF_FROM_FSA_H #define FF_FROM_FSA_H #include "ff_fsa.h" #define FSA_FF_DEBUG #ifdef FSA_FF_DEBUG # define FSAFFDBG(x) do { if (debug) { std::cerr << x; } } while(0) #else # define FSAFFDBG(x) #endif /* regular bottom up scorer from Fsa feature uses guarantee about markov order=N to score ASAP encoding of state: if less than N-1 (ctxlen) words either: struct FF : public FsaImpl,FeatureFunctionFromFsa (more efficient) or: struct FF : public FsaFeatureFunctionDynamic,FeatureFunctionFromFsa (code sharing, but double dynamic dispatch) */ template class FeatureFunctionFromFsa : public FeatureFunction { typedef void const* SP; typedef WordID *W; typedef WordID const* WP; public: FeatureFunctionFromFsa(std::string const& param) : ff(param) { Init(); } static std::string usage(bool args,bool verbose) { return Impl::usage(args,verbose); } Features features() const { return ff.features(); } //TODO: add source span to Fsa FF interface, pass along //TODO: read/debug VERY CAREFULLY void TraversalFeaturesImpl(const SentenceMetadata& smeta, const Hypergraph::Edge& edge, const std::vector& ant_contexts, FeatureVector* features, FeatureVector* estimated_features, void* out_state) const { FSAFFDBG("(FromFsa) "< fsa(ff,smeta); TRule const& rule=*edge.rule_; Sentence const& e = rule.e(); for (int j = 0; j < e.size(); ++j) { // items in target side of rule if (e[j] < 1) { // variable SP a = ant_contexts[-e[j]]; FSAFFDBG(' '<M) // child had full state already (had a "gap"); if nw==M then we already reached the same state via left word heuristic scan above fsa.reset(fsa_state(a)); } else { // single word WordID ew=e[j]; FSAFFDBG(' '< score(full left unscored phrase) AccumFeatures(ff,smeta,begin(ends),end(ends),final_features,rst); // e.g. [ctx for last M words] score("") } else { // all we have is a single short phrase < M words before adding ends int nl=lend-l; Sentence whole(ends.size()+nl); WordID *w=begin(whole); wordcpy(w,l,nl); wordcpy(w+nl,begin(ends),ends.size()); // whole = left-words + end-phrase AccumFeatures(ff,smeta,w,end(whole),final_features,ss); } FSAFFDBG("Final "<left;--e) if (e[-1]!=TD::none) break; //post: [left,e] are the seen left words return e; } inline WP left_end(SP ant) const { return left_end((WP)ant,(WP)fsa_state(ant)); } inline WP left_end_full(SP ant) const { return (WP)fsa_state(ant); } inline SP fsa_state(SP ant) const { return ((char const*)ant+state_offset); } inline void *fsa_state(void * ant) const { return ((char *)ant+state_offset); } void clear_fsa_state(void *ant) const { // when state is unknown std::memset(fsa_state(ant),0,ssz); } inline void fstatecpy(void *ant,void const* src) const { std::memcpy(fsa_state(ant),src,ssz); } }; #ifdef TEST_FSA # include "tdict.cc" # include "ff_sample_fsa.h" int main() { std::cerr<<"Testing left_end...\n"; std::cerr<<"sizeof(FeatureVector)="<