#include <libwccl/ops/functions/bool/predicates/weakagreement.h> namespace Wccl { std::string WeakAgreement::to_string(const Corpus2::Tagset& tagset) const { std::ostringstream ss; ss << name(tagset) << "(" << left_pos_expr_->to_string(tagset) << ", " << right_pos_expr_->to_string(tagset) << ", " << attribs_expr_->to_string(tagset) << ")"; return ss.str(); } std::ostream& WeakAgreement::write_to(std::ostream& os) const { return os << raw_name() << "(" << *left_pos_expr_ << ", " << *right_pos_expr_ << ", " << *attribs_expr_ << ")"; } WeakAgreement::BaseRetValPtr WeakAgreement::apply_internal(const FunExecContext& context) const { const SentenceContext& sc = context.sentence_context(); const boost::shared_ptr<const Position>& range_left = left_pos_expr_->apply(context); if (range_left->get_value() == Position::Nowhere) { return Predicate::False(context); } const boost::shared_ptr<const Position>& range_right = right_pos_expr_->apply(context); if (range_right->get_value() == Position::Nowhere) { return Predicate::False(context); } // Get absolute values for left and right extremes of the range. int abs_left = sc.get_abs_position(*range_left); int abs_right = sc.get_abs_position(*range_right); // Trim range to sentence boundaries if (abs_left < 0) { abs_left = 0; } if (abs_right >= sc.size()) { abs_right = sc.size() - 1; } // Proceed only if range isn't empty (range outside of sentence or empty sentence are covered) if (abs_left > abs_right) { return Predicate::False(context); } const boost::shared_ptr<const TSet>& attribs = attribs_expr_->apply(context); int min_card = attribs->categories_count(tagset_); for(int i = abs_left; i <= abs_right; ++i) { bool i_has_matched_tag = false; foreach (const Corpus2::Lexeme& i_lex, sc.at(i)->lexemes()) { const Corpus2::Tag& i_tag = i_lex.tag(); if (attribs->matching_categories(i_tag) >= min_card) { i_has_matched_tag = true; for(int j = abs_right; j > i; --j) { bool i_agrees_with_j = false; bool j_has_matched_tag = false; foreach(const Corpus2::Lexeme& j_lex, sc.at(j)->lexemes()) { const Corpus2::Tag& j_tag = j_lex.tag(); if (attribs->matching_categories(i_tag) >= min_card) { j_has_matched_tag = true; Corpus2::Tag intersection = i_tag.get_masked(j_tag); // if the intersection matches enough categories we have agreement if (attribs->matching_categories(intersection) >= min_card) { i_agrees_with_j = true; break; } } } if (j_has_matched_tag && !i_agrees_with_j) { return Predicate::False(context); } } } } if (!i_has_matched_tag && (i == abs_left || i == abs_right)) { return Predicate::False(context); } } return Predicate::True(context); } } /* end ns Wccl */