neighbor.h

00001 /*
00002  * ASTL - the Automaton Standard Template Library.
00003  * C++ generic components for Finite State Automata handling.
00004  * Copyright (C) 2000-2003 Vincent Le Maout (vincent.lemaout@chello.fr).
00005  * 
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  * 
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  * 
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 #ifndef ASTL_NEIGHBOR_H
00023 #define ASTL_NEIGHBOR_H
00024 
00025 #include <astl.h>
00026 #include <stack>
00027 #include <vector>
00028 #include <utility>
00029 #include <iostream>
00030 #include <cstring>   // strlen
00031 
00032 using namespace std;
00033 
00034 namespace astl {
00035 
00036 template <typename CharType>
00037 struct default_costs
00038 {
00039   int distance(const CharType &x, const CharType &y) const {
00040     return x == y ? 0 : 1000;
00041   }
00042 
00043   template <typename RandomAccessIterator>
00044   int insertion(RandomAccessIterator last, RandomAccessIterator where, const CharType &c) const {
00045     return 1000;
00046   }
00047 
00048   template <typename RandomAccessIterator>
00049   int deletion(RandomAccessIterator last, RandomAccessIterator where) const {
00050     return 1000;
00051   }
00052 
00053   template <typename RandomAccessIterator>
00054   int deletion_suffix(RandomAccessIterator first, RandomAccessIterator last) const {
00055     return 1000;
00056   }
00057 };
00058 
00059 // template <typename CharType>
00060 // struct default_distance 
00061 //   : public binary_function<CharType, CharType, int>
00062 // {
00063 //   // x is a word's letter, y is a transition letter:
00064 //   int operator()(const CharType& x, const CharType& y) const {
00065 //     return x == y ? 0 : 1000;
00066 //   }
00067 // };
00068 
00069 // template <int Insertion = 1000, int Deletion = 1000, 
00070 //   int Del_last = Deletion> 
00071 // struct edition_cost_traits
00072 // {
00073 //   static const int INSERTION;
00074 //   static const int DELETION;
00075 //   static const int DELETION_LAST;
00076 // };
00077 
00078 // template <int Insertion, int Deletion, int Del_last> 
00079 // const int edition_cost_traits<Insertion, Deletion, Del_last>::INSERTION = Insertion;
00080 // template <int Insertion, int Deletion, int Del_last> 
00081 // const int edition_cost_traits<Insertion, Deletion, Del_last>::DELETION = Deletion;
00082 // template <int Insertion, int Deletion, int Del_last> 
00083 // const int edition_cost_traits<Insertion, Deletion, Del_last>::DELETION_LAST = Del_last;
00084 
00085 template <typename ForwardCursor, typename RandomAccessIterator, 
00086           //      typename DistanceFunction = default_distance<typename ForwardCursor::char_type>, 
00087           //      typename CostTraits = edition_cost_traits<> >
00088           typename Costs = default_costs<typename ForwardCursor::char_type> >
00089 class neighbor_cursor : public forward_cursor_concept
00090 {
00091 protected:
00092   ForwardCursor x;
00093   RandomAccessIterator last; 
00094   typedef vector<pair<RandomAccessIterator, int> > container; // position, distance 
00095   container d;    
00096 
00097 public:
00098   typedef neighbor_cursor          self;
00099   typedef typename ForwardCursor::tag_type    tag_type;
00100   typedef typename ForwardCursor::char_type   char_type;  
00101   typedef typename ForwardCursor::char_traits char_traits;
00102   typedef typename ForwardCursor::state_type  state_type;
00103 
00104   neighbor_cursor(const ForwardCursor& c, RandomAccessIterator i, 
00105                   RandomAccessIterator j, int dist)
00106     : x(c), last(j) { 
00107     d.reserve(64);
00108     d.push_back(make_pair(i, dist));
00109   }
00110 
00111   neighbor_cursor()
00112   { }
00113   
00114   neighbor_cursor(const self &n) 
00115     : x(n.x), last(n.last) {
00116     d.reserve(64);
00117     for(typename container::const_iterator i = n.d.begin();
00118         i != n.d.end(); ++i)
00119       if (i->second >= 0) d.push_back(*i);
00120   }
00121 
00122   state_type src() const {
00123     return x.src();
00124   }
00125 
00126   const ForwardCursor& cursor() const {
00127     return x;
00128   }
00129 
00130   bool sink() const {
00131     return x.sink();
00132   }
00133 
00134   state_type sink_state() const {
00135     return x.sink_state();
00136   }
00137 
00138   bool forward(const char_type &a) {
00139     typename container::size_type i, j = d.size();
00140     bool ok = false;
00141 
00142     if (x.forward(a))
00143       for(i = 0; i < j; ++i) {
00144         // substitution & deletion
00145         int dist = d[i].second;
00146         for(RandomAccessIterator first = d[i].first; 
00147             first != last && dist >= 0; 
00148             dist -= Costs().deletion(last, first++)) {
00149           //        ++first, dist -= CostTraits::DELETION) { 
00150           //      int delta = DistanceFunction()(*first, a);
00151           int delta = Costs().distance(*first, a);
00152           if (dist >= delta) {
00153             ok = true;
00154             d.push_back(make_pair(first + 1, dist - delta));
00155           }
00156         }
00157         // insertion:
00158         //      d[i].second -= CostTraits::INSERTION;
00159         //      int delta = Costs().insertion(last, d[i].first, a);
00160         d[i].second -= Costs().insertion(last, d[i].first, a);
00161         ok = ok || d[i].second >= 0;
00162       }
00163     return ok;
00164   }
00165 
00166   void forward() {
00167     typename container::size_type i, j = d.size();
00168 
00169     for(i = 0; i < j; ++i) {
00170       // substitution & deletion
00171       int dist = d[i].second;
00172       for(RandomAccessIterator first = d[i].first; 
00173           first != last && dist >= 0; 
00174             dist -= Costs().deletion(last, first++)) {
00175           //      ++first, dist -= CostTraits::DELETION) {
00176         //      int delta = DistanceFunction()(*first, x.letter());
00177         int delta = Costs().distance(*first, x.letter());
00178         if (dist >= delta)
00179           d.push_back(make_pair(first + 1, dist - delta));
00180       }
00181       // insertion:
00182       //      d[i].second -= CostTraits::INSERTION;
00183       d[i].second -= Costs().insertion(last, d[i].first, x.letter());
00184     }
00185     x.forward();
00186   }
00187 
00188   bool src_final() const {
00189     if (x.src_final())
00190       for(typename container::const_iterator i = d.begin(); i != d.end(); ++i)
00191         //      if (i->second >= (last - i->first) *
00192         //      CostTraits::DELETION_LAST) 
00193         if (i->second >= Costs().deletion_suffix(i->first, last))
00194           return true;
00195     return false;
00196   }
00197     
00198   tag_type src_tag() const {
00199     return x.src_tag();
00200   }
00201 
00202   bool exists(const char_type &a) const {
00203     if (x.exists(a)) 
00204       for(typename container::const_iterator i = d.begin(); i != d.end(); ++i)
00205         //      if (i->second >= CostTraits::INSERTION || 
00206         if (i->second >= Costs().insertion(last, i->first, a) || 
00207             (i->first != last 
00208              //      && i->second >= DistanceFunction()(*i->first,
00209              //      a))) 
00210              && i->second >= Costs().distance(*i->first, a))) 
00211           return true;
00212     return false;
00213   }
00214 
00215   bool operator==(const self &s) const {
00216     return x == s.x;
00217   }
00218 
00219   char_type letter() const {
00220     return x.letter();
00221   }
00222 
00223   bool first() {
00224     if (x.first())
00225       do
00226         for(typename container::const_iterator i = d.begin(); 
00227             i != d.end(); ++i) {
00228           if (i->first != last) {
00229             //      if (i->second >= DistanceFunction()(*i->first,
00230             //      x.letter())) 
00231             if (i->second >= Costs().distance(*i->first, x.letter())) 
00232               return true;
00233           }
00234     //    else if (i->second >= CostTraits::INSERTION) return true;
00235           if (i->second >= Costs().insertion(last, i->first, x.letter()))
00236                    return true;
00237         }
00238       while (x.next());
00239     return false;
00240   }
00241   
00242   bool next() {
00243     while (x.next())
00244       for(typename container::const_iterator i = d.begin(); i != d.end(); ++i) {
00245         if (i->first != last) {
00246           //      if (i->second >= DistanceFunction()(*i->first,
00247           //      x.letter())) 
00248           if (i->second >= Costs().distance(*i->first, x.letter())) 
00249             return true;
00250         }
00251     //  else if (i->second >= CostTraits::INSERTION) return true;
00252         if (i->second >= Costs().insertion(last, i->first, x.letter()))
00253                  return true;
00254       }
00255     return false;
00256   }
00257 
00258   bool find(const char_type &a) {
00259     return true;     // todo
00260   }
00261 
00262   state_type aim() const {
00263     return x.aim();
00264   }
00265 
00266   bool aim_final() const {
00267     self tmp = *this;
00268     tmp.forward();
00269     return tmp.src_final();
00270   }
00271 
00272   tag_type aim_tag() const {
00273     return x.aim_tag();
00274   }
00275 
00276   // WARNING: call is only allowed if the cursor is dereferenceable
00277   int distance() const {
00278     self tmp = *this;
00279     tmp.forward();
00280     typename container::const_iterator i, m = tmp.d.begin(); 
00281     for(i = tmp.d.begin() + 1; i != tmp.d.end(); ++i)
00282       if (i->second > m->second) m = i;
00283     
00284     return m->second;
00285   }
00286    
00287 };
00288 
00289 // template <typename ForwardCursor, typename ForwardIterator>
00290 // inline
00291 // neighbor_cursor<ForwardCursor, ForwardIterator>
00292 // neighborc(const ForwardCursor& x, 
00293 //        ForwardIterator i, ForwardIterator j, int d) {
00294 //   return neighbor_cursor<ForwardCursor, ForwardIterator>(x, i, j, d);
00295 // }
00296 
00297 template <typename ForwardCursor, typename ForwardIterator, typename Distance>
00298 inline
00299 neighbor_cursor<ForwardCursor, ForwardIterator, Distance>
00300 neighborc(const ForwardCursor& x, 
00301           ForwardIterator i, ForwardIterator j, int d, const Distance&) {
00302   return neighbor_cursor<ForwardCursor, ForwardIterator, Distance>
00303     (x, i, j, d);
00304 }
00305 
00306 template <typename ForwardCursor>
00307 inline
00308 neighbor_cursor<ForwardCursor, const char*>
00309 neighborc(const ForwardCursor& x, const char *word, int d) {
00310   return neighbor_cursor<ForwardCursor, const char*>
00311     (x, word, word + strlen(word), d);
00312 }
00313 
00314 } // namespace astl
00315 
00316 #endif

Generated on Sun Mar 8 02:41:34 2009 for ASTL by  doxygen 1.5.7.1