diff options
Diffstat (limited to 'decoder')
| -rwxr-xr-x | decoder/cfg.cc | 12 | ||||
| -rwxr-xr-x | decoder/cfg.h | 8 | ||||
| -rwxr-xr-x | decoder/cfg_format.h | 36 | ||||
| -rwxr-xr-x | decoder/program_options.h | 283 | ||||
| -rw-r--r-- | decoder/stringlib.h | 28 | ||||
| -rw-r--r-- | decoder/trule.cc | 24 | ||||
| -rw-r--r-- | decoder/trule.h | 2 | 
7 files changed, 388 insertions, 5 deletions
| diff --git a/decoder/cfg.cc b/decoder/cfg.cc index 0f20ba0f..b83fc54d 100755 --- a/decoder/cfg.cc +++ b/decoder/cfg.cc @@ -1,5 +1,6 @@  #include "cfg.h"  #include "hg.h" +#include "cfg_format.h"  using namespace std; @@ -10,6 +11,7 @@ void CFG::Init(Hypergraph const& hg,bool target_side,bool copy_features,bool pus    pushed_inside=push_weights ? goal_inside : prob_t(1);    int nn=hg.nodes_.size(),ne=hg.edges_.size();    nts.resize(nn); +  goal_nt=nn-1;    rules.resize(ne);    for (int i=0;i<nn;++i)      nts[i].ruleids=hg.nodes_[i].in_edges_; @@ -40,3 +42,13 @@ void CFG::Init(Hypergraph const& hg,bool target_side,bool copy_features,bool pus      }    }  } + +namespace { +} + +void CFG::Print(std::ostream &o,CFGFormat const& f) const { +  char const* partsep=" ||| "; +  if (!f.goal_nt_name.empty()) +    o << '['<<f.goal_nt_name <<']' << partsep; // print rhs +  //TODO: +} diff --git a/decoder/cfg.h b/decoder/cfg.h index 9e1b2837..8d7a5eee 100755 --- a/decoder/cfg.h +++ b/decoder/cfg.h @@ -27,9 +27,7 @@  #include "small_vector.h"  class Hypergraph; -class CFG; - - +class CFGFormat; // #include "cfg_format.h"  struct CFG {    typedef int RuleHandle; @@ -48,7 +46,7 @@ struct CFG {    };    struct NT { -    Ruleids ruleids; // index into CFG rules with this lhs +    Ruleids ruleids; // index into CFG rules with lhs = this NT.  aka in_edges_    };    CFG() : hg_() {  } @@ -58,6 +56,7 @@ struct CFG {      Init(hg,target_side,copy_features,push_weights);    }    void Init(Hypergraph const& hg,bool target_side=true,bool copy_features=false,bool push_weights=true); +  void Print(std::ostream &o,CFGFormat const& format) const; // see cfg_format.h  protected:    Hypergraph const* hg_; // shouldn't be used for anything, esp. after binarization    prob_t goal_inside,pushed_inside; // when we push viterbi weights to goal, we store the removed probability in pushed_inside @@ -66,6 +65,7 @@ protected:    Rules rules;    typedef std::vector<NT> NTs;    NTs nts; +  int goal_nt;  };  #endif diff --git a/decoder/cfg_format.h b/decoder/cfg_format.h new file mode 100755 index 00000000..1bce3d06 --- /dev/null +++ b/decoder/cfg_format.h @@ -0,0 +1,36 @@ +#ifndef CFG_FORMAT_H +#define CFG_FORMAT_H + +#include <program_options.h> +#include <string> + +struct CFGFormat { +  bool identity_scfg;bool features;bool logprob_feat;bool cfg_comma_nt;std::string goal_nt_name;std::string nt_prefix; +  template <class Opts> // template to support both printable_opts and boost nonprintable +  void AddOptions(Opts *opts) { +    using namespace boost::program_options; +    using namespace std; +    opts->add_options() +      ("identity_scfg",defaulted_value(&identity_scfg),"output an identity SCFG: add an identity target side - '[X12] ||| [X13,1] a ||| [1] a ||| feat= ...' - the redundant target '[1] a |||' is omitted otherwise.") +      ("features",defaulted_value(&features),"print the CFG feature vector") +      ("logprob_feat",defaulted_value(&logprob_feat),"print a LogProb=-1.5 feature irrespective of --features.") +      ("cfg_comma_nt",defaulted_value(&cfg_comma_nt),"if false, omit the usual [NP,1] ',1' variable index in the source side") +      ("goal_nt_name",defaulted_value(&goal_nt_name),"if nonempty, the first production will be '[goal_nt_name] ||| [x123] ||| LogProb=y' where x123 is the actual goal nt, and y is the pushed prob, if any") +      ("nt_prefix",defaulted_value(&nt_prefix),"NTs are [<nt_prefix>123] where 123 is the node number starting at 0, and the highest node (last in file) is the goal node in an acyclic hypergraph") +      ; +  } +  void set_defaults() { +    identity_scfg=false; +    features=true; +    logprob_feat=true; +    cfg_comma_nt=true; +    goal_nt_name="S"; +    nt_prefix=""; +  } +  CFGFormat() { +    set_defaults(); +  } +}; + + +#endif diff --git a/decoder/program_options.h b/decoder/program_options.h new file mode 100755 index 00000000..251f5680 --- /dev/null +++ b/decoder/program_options.h @@ -0,0 +1,283 @@ +#ifndef PROGRAM_OPTIONS_H +#define PROGRAM_OPTIONS_H + +/* wraps boost options_description as printable_opts - show the options values used as well as defaults in usage or log messages.  boost program options library lacks any concept of printing configured values; it only supports parsing them from strings */ + +#ifdef _WIN32 +#include <iso646.h> +#endif +#include <boost/program_options.hpp> +#include <boost/function.hpp> +#include <boost/shared_ptr.hpp> +#include <stdexcept> +#include <iosfwd> + + +template <class T> +boost::program_options::typed_value<T>* +defaulted_value(T *v) +{ +  return boost::program_options::value<T>(v)->default_value(*v); +} + +inline void program_options_fatal(std::string const& msg) { +  throw std::runtime_error(msg); +} + + +inline std::string const& get_single_arg(boost::any& v,std::vector<std::string> const& values) +{ +  boost::program_options::validators::check_first_occurrence(v); +  return boost::program_options::validators::get_single_string(values); +} + +template <class I> +void must_complete_read(I &in,std::string const& msg="Couldn't parse") +{ +  char c; +  if (in.bad()) +    program_options_fatal(msg + " - failed input"); +  if (in >> c) +    program_options_fatal(msg + " - got extra char: " + std::string(c,1)); +} + +template <class Ostream> +struct any_printer  : public boost::function<void (Ostream &,boost::any const&)> +{ +  typedef boost::function<void (Ostream &,boost::any const&)> F; + +  template <class T> +  struct typed_print +  { +    void operator()(Ostream &o,boost::any const& t) const +    { +      o << *boost::any_cast<T const>(&t); +    } +  }; + +  template <class T> +  static +  void typed_print_template(Ostream &o,boost::any const& t) +  { +    o << *boost::any_cast<T const>(&t); +  } + +  any_printer() {} + +  any_printer(const any_printer& x) +    : F(static_cast<F const&>(x)) +  {} + +  template <class T> +  explicit any_printer(T const* tag) : F(typed_print<T>()) { +  } + +  template <class T> +  void set() +  { +    F f(typed_print<T>()); +    swap(f); +  } +}; + +// have to wrap regular options_description and store our own tables because +// author didn't make enough stuff protected/public or add a virtual print +// method to value_semantic +template <class Ostream> +struct printable_options_description +  : public boost::program_options::options_description +{ +  typedef printable_options_description<Ostream> self_type; +  typedef boost::program_options::options_description options_description; +  typedef boost::program_options::option_description option_description; +  typedef boost::shared_ptr<self_type> group_type; +  typedef std::vector<group_type > groups_type; + +  struct printable_option +  { +    typedef boost::shared_ptr<option_description> OD; + +    any_printer<Ostream> print; +    OD od; +    bool in_group; + +    std::string const& name() +    { return od->long_name(); } + +    std::string const& description() +    { return od->description(); } + +    std::string const& vmkey() +    { +      return od->key(name()); +    } +    template <class T> +    printable_option(T *tag, OD const& od) : print(tag),od(od),in_group(false) {} +    printable_option() : in_group(false) {} +  }; +  typedef std::vector<printable_option > options_type; +  BOOST_STATIC_CONSTANT(unsigned,default_linewrap=80); // options_description::m_default_line_length +  printable_options_description(unsigned line_length = default_linewrap) : +    options_description(line_length) {} + +  printable_options_description(const std::string& caption, +                                unsigned line_length = default_linewrap) +    : options_description(caption,line_length), caption(caption) {} + +  self_type &add_options() +  { return *this; } + +  template <class T,class C> +  self_type & +  operator()(char const* name, +             boost::program_options::typed_value<T,C> *val, +             char const*description=NULL) +  { +    printable_option opt((T *)0,simple_add(name,val,description)); +    pr_options.push_back(opt); +    return *this; +  } + +  self_type& +  add(self_type const& desc) +  { +    options_description::add(desc); +    groups.push_back(group_type(new self_type(desc))); +    for (typename options_type::const_iterator i=desc.pr_options.begin(),e=desc.pr_options.end(); +         i!=e;++i) { +      pr_options.push_back(*i); +      pr_options.back().in_group=true; +    } +    return *this; +  } + +  void print_option(Ostream &o, +                    printable_option &opt, +                    boost::program_options::variable_value const & var, +                    bool only_value=false) +  { +    using namespace boost; +    using namespace boost::program_options; +    using namespace std; +    string const& name=opt.name(); +    if (!only_value) { +      if (var.defaulted()) +        o << "#DEFAULTED# "; +      if (var.empty()) { +        o << "#EMPTY# "<<name; +        return; +      } +      o << name<<" = "; +    } +    opt.print(o,var.value()); +  } + +  enum { SHOW_DEFAULTED=0x1 +         , SHOW_EMPTY=0x2 +         , SHOW_DESCRIPTION=0x4 +         ,  SHOW_HIERARCHY=0x8 +         ,  SHOW_ALL=0x0FFF +         ,  SHOW_HELP=0x1000 +  }; + +  void print(Ostream &o, +             boost::program_options::variables_map &vm, +             int show_flags=SHOW_DESCRIPTION & SHOW_DEFAULTED & SHOW_HIERARCHY) +  { +    const bool show_defaulted=bool(show_flags & SHOW_DEFAULTED); +    const bool show_description=bool(show_flags & SHOW_DESCRIPTION); +    const bool hierarchy=bool(show_flags & SHOW_HIERARCHY); +    const bool show_empty=bool(show_flags & SHOW_EMPTY); +    const bool show_help=bool(show_flags & SHOW_HELP); + +    using namespace boost::program_options; +    using namespace std; +    o << "### " << caption << endl; +    for (typename options_type::iterator i=pr_options.begin(),e=pr_options.end(); +         i!=e;++i) { +      printable_option & opt=*i; +      if (!show_help && opt.name()=="help") +        continue; +      if (hierarchy and opt.in_group) +        continue; +      variable_value const & var=vm[opt.vmkey()]; +      if (var.defaulted() && !show_defaulted) +        continue; +      if (var.empty() && !show_empty) +        continue; +      if (show_description) +        o << "# " << opt.description() << endl; +      print_option(o,opt,var); +      o << endl; +    } +    o << endl; +    if (hierarchy) +      for (typename groups_type::iterator i=groups.begin(),e=groups.end(); +           i!=e;++i) +        (*i)->print(o,vm,show_flags); +  } + +/// parses arguments, then stores/notifies from opts->vm.  returns unparsed +/// options and positional arguments, but if not empty, throws exception unless +/// allow_unrecognized_positional is true +  std::vector<std::string> +  parse_options(int argc,char **argv, +                boost::program_options::variables_map &vm, +                boost::program_options::positional_options_description *po=NULL, +                bool allow_unrecognized_positional=false, +                bool allow_unrecognized_opts=false) +  { +    using namespace boost::program_options; +    using namespace std; +    command_line_parser cl(argc,argv); +    cl.options(*this); +    if (po) +      cl.positional(*po); +    if (allow_unrecognized_opts) +      cl.allow_unregistered(); +    parsed_options parsed=cl.run(); +    vector<string> unparsed=collect_unrecognized(parsed.options, +                                                 po ? exclude_positional : include_positional); +    if (!allow_unrecognized_positional) { +      if (!unparsed.empty()) +        program_options_fatal("Unrecognized argument: "+unparsed.front()); +    } +    store(parsed,vm); +    notify(vm); +    return unparsed; +  } + +  std::vector<std::string> +  parse_options(int argc,char const*argv[], +                boost::program_options::variables_map &vm, +                boost::program_options::positional_options_description *po=NULL, +                bool allow_unrecognized_positional=false, +                bool allow_unrecognized_opts=false) +  { +    return parse_options(argc,const_cast<char **>(argv),vm,po +                         ,allow_unrecognized_positional,allow_unrecognized_opts); +  } + +private: +  groups_type groups; +  options_type pr_options; +  std::string caption; +  boost::shared_ptr<option_description> +  simple_add(const char* name, +             const boost::program_options::value_semantic* s, +             const char * description = NULL) +  { +    typedef option_description OD; +    boost::shared_ptr<OD> od( +      (description ? new OD(name,s,description) : new OD(name,s)) +      ); +    options_description::add(od); +    return od; +  } +}; + +typedef printable_options_description<std::ostream> printable_opts; + + + +#endif diff --git a/decoder/stringlib.h b/decoder/stringlib.h index 53e6fe50..84e95d44 100644 --- a/decoder/stringlib.h +++ b/decoder/stringlib.h @@ -20,6 +20,34 @@  #include <sstream>  #include <algorithm> +inline std::size_t skip_ws(std::string const& s,std::size_t starting=0,char const* ws=" \t\n\r") { +  return s.find_first_not_of(ws,starting); +} + +// returns position of end of all non-ws chars before ending, i.e. string(s.begin()+skip_ws(s),s.begin()+trailing_ws(s)) strips both ends +inline std::size_t trailing_ws(std::string const& s,std::size_t ending=std::string::npos,char const* ws=" \t\n\r") { +  std::size_t n=s.find_last_not_of(ws,ending); +  if (n==std::string::npos) return n; +  else return n+1; +} + +//TEST: if string is all whitespace, make sure that string(a+npos,a+npos) can't segfault (i.e. won't access any memory because begin==end) +inline std::string strip_ws(std::string const& s) { +  return std::string(s.begin()+skip_ws(s),s.begin()+trailing_ws(s)); +} + + +inline bool is_single_line(std::string const& line) { +  return std::count(line.begin(),line.end(),'\n')==0; // but we want to allow terminal newlines/blanks +} + +// is_single_line(strip_ws(line)) +inline bool is_single_line_stripped(std::string const& line) { +  std::size_t b=skip_ws(line),e=trailing_ws(line); +  std::size_t n=line.find('\n',b); +  return n==std::string::npos || n>=e; +} +  struct toupperc {    inline char operator()(char c) const {      return std::toupper(c); diff --git a/decoder/trule.cc b/decoder/trule.cc index 170e3a95..330db67f 100644 --- a/decoder/trule.cc +++ b/decoder/trule.cc @@ -4,6 +4,8 @@  #include "stringlib.h"  #include "tdict.h" +#include "rule_lexer.h" +#include "threadlocal.h"  using namespace std; @@ -91,7 +93,29 @@ TRule* TRule::CreateRuleMonolingual(const string& rule) {    return new TRule(rule, false, true);  } +namespace { +// callback for lexer +THREADLOCAL int n_assigned=0; +void assign_trule(const TRulePtr& new_rule, const unsigned int ctf_level, const TRulePtr& coarse_rule, void* extra) { +  TRule *assignto=(TRule *)extra; +  *assignto=*new_rule; +} + +} +  bool TRule::ReadFromString(const string& line, bool strict, bool mono) { +  if (!is_single_line_stripped(line)) +    std::cerr<<"\nWARNING: building rule from multi-line string "<<line<<".\n"; +  if (!(mono||strict)) { +    // use lexer +    istringstream il(line); +    n_assigned=0; +    RuleLexer::ReadRules(&il,assign_trule,this); +    if (n_assigned>1) +      std::cerr<<"\nWARNING: more than one rule parsed from multi-line string; kept last: "<<line<<".\n"; +    return n_assigned; +  } +    e_.clear();    f_.clear();    scores_.clear(); diff --git a/decoder/trule.h b/decoder/trule.h index 6b98a8fa..04058a41 100644 --- a/decoder/trule.h +++ b/decoder/trule.h @@ -37,7 +37,7 @@ class TRule {    TRule(const TRule& other) :      e_(other.e_), f_(other.f_), lhs_(other.lhs_), scores_(other.scores_), arity_(other.arity_), prev_i(-1), prev_j(-1) {} -  // deprecated - this will be private soon +  // if mono or strict is true, then lexer won't be used, and //FIXME: > 9 variables won't work    explicit TRule(const std::string& text, bool strict = false, bool mono = false) : prev_i(-1), prev_j(-1) {      ReadFromString(text, strict, mono);    } | 
