#ifndef _VITERBI_ENVELOPE_H_ #define _VITERBI_ENVELOPE_H_ #include #include #include #include "hg.h" #include "sparse_vector.h" static const double kMinusInfinity = -std::numeric_limits::infinity(); static const double kPlusInfinity = std::numeric_limits::infinity(); struct Segment { Segment() : x(), m(), b() {} Segment(double _m, double _b) : x(kMinusInfinity), m(_m), b(_b) {} Segment(double _x, double _m, double _b, const boost::shared_ptr& p1_, const boost::shared_ptr& p2_) : x(_x), m(_m), b(_b), p1(p1_), p2(p2_) {} Segment(double _m, double _b, TRulePtr _rule) : x(kMinusInfinity), m(_m), b(_b), rule(_rule) {} double x; // x intersection with previous segment in env, or -inf if none double m; // this line's slope double b; // intercept with y-axis // we keep a pointer to the "parents" of this segment so we can reconstruct // the Viterbi translation corresponding to this segment boost::shared_ptr p1; boost::shared_ptr p2; // only Segments created from an edge using the ViterbiEnvelopeWeightFunction // have rules TRulePtr rule; // recursively recover the Viterbi translation that will result from setting // the weights to origin + axis * x, where x is any value from this->x up // until the next largest x in the containing ViterbiEnvelope void ConstructTranslation(std::vector* trans) const; }; // this is the semiring value type, // it defines constructors for 0, 1, and the operations + and * struct ViterbiEnvelope { // create semiring zero ViterbiEnvelope() : is_sorted(true) {} // zero // for debugging: ViterbiEnvelope(const std::vector >& s) : segs(s) { Sort(); } // create semiring 1 or 0 explicit ViterbiEnvelope(int i); ViterbiEnvelope(int n, Segment* seg) : is_sorted(true), segs(n, boost::shared_ptr(seg)) {} const ViterbiEnvelope& operator+=(const ViterbiEnvelope& other); const ViterbiEnvelope& operator*=(const ViterbiEnvelope& other); bool IsMultiplicativeIdentity() const { return size() == 1 && (segs[0]->b == 0.0 && segs[0]->m == 0.0) && (!segs[0]->rule); } const std::vector >& GetSortedSegs() const { if (!is_sorted) Sort(); return segs; } size_t size() const { return segs.size(); } private: bool IsEdgeEnvelope() const { return segs.size() == 1 && segs[0]->rule; } void Sort() const; mutable bool is_sorted; mutable std::vector > segs; }; std::ostream& operator<<(std::ostream& os, const ViterbiEnvelope& env); struct ViterbiEnvelopeWeightFunction { ViterbiEnvelopeWeightFunction(const SparseVector& ori, const SparseVector& dir) : origin(ori), direction(dir) {} ViterbiEnvelope operator()(const Hypergraph::Edge& e) const; const SparseVector origin; const SparseVector direction; }; #endif