relations.hh

00001 // This file is a part of Aurelia.
00002 // Copyright (C) 2010  Valentin David
00003 // Copyright (C) 2010  University of Bergen
00004 //
00005 // This program is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017 #ifndef __RELATIONS_HH
00018 # define __RELATIONS_HH
00019 
00020 #include <algorithm>
00021 #include <unordered_map>
00022 #include <unordered_set>
00023 #include <iostream>
00024 
00025 namespace aurelia {
00026 
00027 template <typename T>
00028 struct set: std::unordered_set<T> {
00029 public:
00030   set() {}
00031 
00032   explicit set(const T& t): std::unordered_set<T>() {
00033     this->insert(t);
00034   }
00035 
00036   set(const set&) = default;
00037   set(set&&) = default;
00038   set& operator=(const set&) = default;
00039   set& operator=(set&& other) = default;
00040 
00041   set operator|(const set& other) const {
00042     set ret = *this;
00043     ret.insert(other.begin(), other.end());
00044     return ret;
00045   }
00046 
00047   set& operator|=(const set& other) {
00048     this->insert(other.begin(), other.end());
00049     return *this;
00050   }
00051 
00052   bool has(const T& t) const {
00053     return this->find(t) != this->end();
00054   }
00055 };
00056 
00057 template <typename T, typename U = T>
00058 struct rel_set: public std::unordered_multimap<T,U> {
00059 public:
00060   rel_set() {}
00061   explicit rel_set(const std::pair<T,U>& t)
00062     : std::unordered_multimap<T,U>() {
00063     this->insert(t);
00064   }
00065 
00066   rel_set(const rel_set&) = default;
00067   rel_set(rel_set&&) = default;
00068   rel_set& operator=(const rel_set&) = default;
00069   rel_set& operator=(rel_set&& other) = default;
00070 
00071   typename std::unordered_multimap<T,U>::iterator
00072   insert(const typename std::unordered_multimap<T,U>::value_type& v) {
00073     typename std::unordered_multimap<T,U>::iterator i = this->find(v.first);
00074     if (i == this->end())
00075       return this->std::unordered_multimap<T,U>::insert(v);
00076     for (;i != this->end(); ++i) {
00077       if ((*i).first != v.first)
00078         return this->std::unordered_multimap<T,U>::insert(v);
00079       if ((*i).second == v.second)
00080         return i;
00081     }
00082     return this->std::unordered_multimap<T,U>::insert(v);
00083   }
00084 
00085   typename std::unordered_multimap<T,U>::iterator
00086   insert(const typename std::unordered_multimap<T,U>::const_iterator&,
00087          const typename std::unordered_multimap<T,U>::value_type& v) {
00088     return this->insert(v);
00089   }
00090 
00091   template <typename Iterator>
00092   void insert(Iterator begin, Iterator end) {
00093     for (; begin != end; ++begin) {
00094       this->insert(*begin);
00095     }
00096   }
00097 
00098   rel_set operator|(const rel_set& other) const {
00099     rel_set ret = *this;
00100     ret.insert(other.begin(), other.end());
00101     return ret;
00102   }
00103 
00104   rel_set& operator|=(const rel_set& other) {
00105     this->insert(other.begin(), other.end());
00106     return *this;
00107   }
00108 
00109   set<U> operator[](const T& key) const {
00110     set<U> ret;
00111     for (typename std::unordered_multimap<T,U>::const_iterator i =
00112            this->find(key);
00113          i != this->end(); ++i) {
00114       if ((*i).first != key)
00115         break ;
00116       ret.insert((*i).second);
00117     }
00118     return ret;
00119   }
00120 
00121   rel_set operator*() const {
00122     rel_set<T> ret = *this;
00123     bool once_more = true;
00124     while (once_more) {
00125       once_more = false;
00126       rel_set<T> tmp = ret;
00127       for (typename rel_set<T>::iterator i = ret.begin();
00128            i != ret.end(); ++i) {
00129         for (typename rel_set<T>::iterator j =
00130                ret.find((*i).second);
00131              j != ret.end(); ++j) {
00132           if ((*j).first != (*i).second)
00133             break ;
00134           typename rel_set<T>::iterator k =
00135             ret.find((*i).first);
00136           for (; k != ret.end(); ++k) {
00137             if ((*k).first != (*i).first)
00138               break ;
00139             if ((*k).second == (*j).second)
00140               break ;
00141           }
00142           bool notfound = (k == ret.end());
00143           if (!notfound)
00144             notfound = ((*k).first != (*i).first);
00145           if (notfound) {
00146             tmp.insert(std::pair<T,T>((*i).first, (*j).second));
00147             once_more = true;
00148           }
00149         }
00150       }
00151       ret = tmp;
00152     }
00153     return ret;
00154   }
00155 };
00156 
00157 template <typename T>
00158 set<T> carrier(const rel_set<T>& m) {
00159   set<T> ret;
00160   std::for_each(m.begin(), m.end(),
00161                 [&ret](const std::pair<T,T>& in) {
00162                   ret.insert(in.first);
00163                   ret.insert(in.second);
00164                 });
00165   return std::move(ret);
00166 }
00167 
00168 template <typename Stream, typename T, typename U>
00169 Stream& operator<<(Stream& s, const std::pair<T, U>& p) {
00170   s << "<" << p.first << "," << p.second << ">";
00171   return s;
00172 }
00173 
00174 template <typename Stream, typename T, typename U>
00175 Stream& operator<<(Stream& s, const rel_set<T, U>& m) {
00176   bool first = true;
00177   s << "{";
00178   std::for_each(m.begin(), m.end(),
00179                 [&s, &first](const std::pair<T, U>& in) {
00180                   if (first) first = false;
00181                   else s << ",";
00182                   s << in;
00183                 });
00184   s << "}";
00185   return s;
00186 }
00187 
00188 template <typename Stream, typename T>
00189 Stream& operator<<(Stream& s, const set<T>& m) {
00190   bool first = true;
00191   s << "{";
00192   std::for_each(m.begin(), m.end(),
00193                 [&s, &first](const T& in) {
00194                   if (first) first = false;
00195                   else s << ",";
00196                   s << in;
00197                 });
00198   s << "}";
00199   return s;
00200 }
00201 
00202 template <typename T>
00203 set<T> top(const rel_set<T>& m) {
00204   set<T> ret;
00205   std::for_each(m.begin(), m.end(),
00206                 [&ret](const std::pair<T, T>& in) {
00207                   ret.insert(in.first);
00208                 });
00209   std::for_each(m.begin(), m.end(),
00210                 [&ret](const std::pair<T, T>& in) {
00211                   ret.erase(in.second);
00212                 });
00213   return std::move(ret);
00214 }
00215 
00216 template <typename T>
00217 set<T> bottom(const rel_set<T>& m) {
00218   set<T> ret;
00219   std::for_each(m.begin(), m.end(),
00220                 [&m, &ret](const std::pair<T, T>& in) {
00221                   if (m.find(in.second) == m.end())
00222                     ret.insert(in.second);
00223                 });
00224   return std::move(ret);
00225 }
00226 
00227 template <typename T, typename U, typename V>
00228 rel_set<T, V> operator*(const rel_set<T, U>& a, const rel_set<U, V>& b) {
00229   rel_set<T, V> ret;
00230 
00231   for (typename rel_set<T, U>::const_iterator i = a.begin();
00232        i != a.end(); ++i) {
00233     for (typename rel_set<U, V>::const_iterator j =
00234            b.find((*i).second);
00235          j != b.end(); ++j) {
00236       if ((*j).first != (*i).second)
00237         break ;
00238       ret.insert(std::pair<T,V>((*i).first, (*j).second));
00239     }
00240   }
00241 
00242   return std::move(ret);
00243 }
00244 
00245 template <typename T, typename U>
00246 rel_set<T, U> operator*(const set<T>& a, const set<U>& b) {
00247   rel_set<T, U> ret;
00248 
00249   for (typename set<T>::const_iterator i = a.begin();
00250        i != a.end(); ++i) {
00251     for (typename set<U>::const_iterator j = b.begin();
00252          j != b.end(); ++j) {
00253       ret.insert(std::pair<T,U>((*i), (*j)));
00254     }
00255   }
00256 
00257   return std::move(ret);
00258 }
00259 
00260 template <typename T, typename U>
00261 set<T> domain(const rel_set<T, U>& a) {
00262   set<T> ret;
00263   std::for_each(a.begin(), a.end(),
00264                 [&ret](const std::pair<T, U>& p) {
00265                   ret.insert(p.first);
00266                 });
00267   return std::move(ret);
00268 }
00269 
00270 template <typename T>
00271 set<T> operator-(const set<T>& a, const set<T>& b) {
00272   set<T> ret;
00273   std::for_each(a.begin(), a.end(),
00274                 [&b, &ret](const T& t) {
00275                   if (b.find(t) == b.end())
00276                     ret.insert(t);
00277                 });
00278   return std::move(ret);
00279 }
00280 
00281 template <typename T>
00282 set<T> reachX(const rel_set<T>& G, const set<T>& Start, const set<T>& Excl) {
00283   if (Start.empty())
00284     return Start;
00285   set<T> direct_reach;
00286   std::for_each(Start.begin(), Start.end(),
00287                 [&direct_reach, &G, &Excl](const T& in) {
00288                   direct_reach |= G[in] - Excl;
00289                 });
00290   return Start | reachX(G, std::move(direct_reach), Excl | Start);
00291 }
00292 
00293 }
00294 
00295 #endif