//TODO: 0 size state != rule-local feature, i.e. still may depend on source span loc/context. identify truly rule-local features so if we want they can be added to grammar rules (minor speedup) #include "ff.h" #include "tdict.h" #include "hg.h" using namespace std; FeatureFunction::~FeatureFunction() {} void FeatureFunction::FinalTraversalFeatures(const void* ant_state, SparseVector* features) const { (void) ant_state; (void) features; } // Hiero and Joshua use log_10(e) as the value, so I do to WordPenalty::WordPenalty(const string& param) : fid_(FD::Convert("WordPenalty")), value_(-1.0 / log(10)) { if (!param.empty()) { cerr << "Warning WordPenalty ignoring parameter: " << param << endl; } } void WordPenalty::TraversalFeaturesImpl(const SentenceMetadata& smeta, const Hypergraph::Edge& edge, const std::vector& ant_states, SparseVector* features, SparseVector* estimated_features, void* state) const { (void) smeta; (void) ant_states; (void) state; (void) estimated_features; features->set_value(fid_, edge.rule_->EWords() * value_); } SourceWordPenalty::SourceWordPenalty(const string& param) : fid_(FD::Convert("SourceWordPenalty")), value_(-1.0 / log(10)) { if (!param.empty()) { cerr << "Warning SourceWordPenalty ignoring parameter: " << param << endl; } } void SourceWordPenalty::TraversalFeaturesImpl(const SentenceMetadata& smeta, const Hypergraph::Edge& edge, const std::vector& ant_states, SparseVector* features, SparseVector* estimated_features, void* state) const { (void) smeta; (void) ant_states; (void) state; (void) estimated_features; features->set_value(fid_, edge.rule_->FWords() * value_); } ArityPenalty::ArityPenalty(const std::string& /* param */) : value_(-1.0 / log(10)) { string fname = "Arity_X"; for (int i = 0; i < 10; ++i) { fname[6]=i + '0'; fids_[i] = FD::Convert(fname); } } void ArityPenalty::TraversalFeaturesImpl(const SentenceMetadata& smeta, const Hypergraph::Edge& edge, const std::vector& ant_states, SparseVector* features, SparseVector* estimated_features, void* state) const { (void) smeta; (void) ant_states; (void) state; (void) estimated_features; features->set_value(fids_[edge.Arity()], value_); } ModelSet::ModelSet(const vector& w, const vector& models) : models_(models), weights_(w), state_size_(0), model_state_pos_(models.size()) { for (int i = 0; i < models_.size(); ++i) { model_state_pos_[i] = state_size_; state_size_ += models_[i]->NumBytesContext(); } } void ModelSet::AddFeaturesToEdge(const SentenceMetadata& smeta, const Hypergraph& hg, const vector& node_states, Hypergraph::Edge* edge, string* context, prob_t* combination_cost_estimate) const { context->resize(state_size_); memset(&(*context)[0], 0, state_size_); SparseVector est_vals; // only computed if combination_cost_estimate is non-NULL if (combination_cost_estimate) *combination_cost_estimate = prob_t::One(); for (int i = 0; i < models_.size(); ++i) { const FeatureFunction& ff = *models_[i]; void* cur_ff_context = NULL; vector ants(edge->tail_nodes_.size()); bool has_context = ff.NumBytesContext() > 0; if (has_context) { int spos = model_state_pos_[i]; cur_ff_context = &(*context)[spos]; for (int i = 0; i < ants.size(); ++i) { ants[i] = &node_states[edge->tail_nodes_[i]][spos]; } } ff.TraversalFeatures(smeta, *edge, ants, &edge->feature_values_, &est_vals, cur_ff_context); } if (combination_cost_estimate) combination_cost_estimate->logeq(est_vals.dot(weights_)); edge->edge_prob_.logeq(edge->feature_values_.dot(weights_)); } void ModelSet::AddFinalFeatures(const std::string& state, Hypergraph::Edge* edge) const { assert(1 == edge->rule_->Arity()); for (int i = 0; i < models_.size(); ++i) { const FeatureFunction& ff = *models_[i]; const void* ant_state = NULL; bool has_context = ff.NumBytesContext() > 0; if (has_context) { int spos = model_state_pos_[i]; ant_state = &state[spos]; } ff.FinalTraversalFeatures(ant_state, &edge->feature_values_); } edge->edge_prob_.logeq(edge->feature_values_.dot(weights_)); }