MappingBase.h

00001 #ifndef FUNCTION_H_
00002 #define FUNCTION_H_
00003 
00004 #include <omnetpp.h>
00005 #include <map>
00006 #include <set>
00007 #include <string>
00008 #include <algorithm>
00009 #include <assert.h>
00010 #include <FWMath.h>
00011 
00012 #include "Interpolation.h"
00013 
00014 
00030 class Dimension {
00031 protected:
00033   typedef std::map<std::string, int>DimensionIDMap;
00035   typedef std::map<int, std::string>DimensionNameMap;
00036 
00043   static DimensionIDMap& dimensionIDs();
00044 
00051   static DimensionNameMap& dimensionNames();
00052 
00059   static int& nextFreeID();
00060 
00065   static int getDimensionID(const std::string& name);
00066 
00068   int id;
00069 
00070 protected:
00071 
00072 public:
00075   static const Dimension time;
00076 
00079   static const Dimension frequency;
00080 
00081 public:
00082   Dimension():
00083     id(0)
00084   {}
00085 
00090   Dimension(const std::string& name);
00091 
00100   static Dimension& time_static();
00101 
00110   static Dimension& frequency_static();
00111 
00115   bool operator==(const Dimension& other) const;
00116 
00123   bool operator<(const Dimension& other) const;
00124 
00126   bool operator<=(const Dimension& other) const { return id <= other.id; }
00128   bool operator>(const Dimension& other) const { return id > other.id; }
00130   bool operator>=(const Dimension& other) const { return id >= other.id; }
00132   bool operator!=(const Dimension& other) const { return id != other.id; }
00133 
00137   std::string getName() const{
00138     static DimensionNameMap& dimensionNames = Dimension::dimensionNames();
00139     return dimensionNames.find(id)->second;
00140   }
00141 
00150   int getID() const { return id; }
00151 
00153   friend std::ostream& operator<<(std::ostream& out, const Dimension& d) {
00154       return (out << d.getName() << "(" << d.id << ")");
00155     }
00156 };
00157 
00173 class DimensionSet:public std::set<Dimension> {
00174 public:
00176   static const DimensionSet timeDomain;
00177 
00179   static const DimensionSet timeFreqDomain;
00180 public:
00184   DimensionSet() {}
00185 
00190   DimensionSet(const Dimension& d){
00191     this->insert(d);
00192   }
00197   DimensionSet(const Dimension& d1, const Dimension& d2){
00198     this->insert(d1);
00199     this->insert(d2);
00200   }
00205   DimensionSet(const Dimension& d1, const Dimension& d2, const Dimension& d3){
00206     this->insert(d1);
00207     this->insert(d2);
00208     this->insert(d3);
00209   }
00210 
00219   bool isSubSet(const DimensionSet& other) const{
00220     if(this->size() < other.size())
00221       return false;
00222 
00223     return std::includes(this->begin(), this->end(), other.begin(), other.end());
00224   }
00225 
00235   bool isRealSubSet(const DimensionSet& other) const{
00236     if(this->size() <= other.size())
00237       return false;
00238 
00239     return std::includes(this->begin(), this->end(), other.begin(), other.end());
00240   }
00241 
00245   void addDimension(const Dimension& d) {
00246     this->insert(d);
00247   }
00248 
00252   bool hasDimension(const Dimension& d) const{
00253     return this->count(d) > 0;
00254   }
00255 
00259   bool operator==(const DimensionSet& o){
00260     if(size() != o.size())
00261       return false;
00262 
00263     return std::equal(begin(), end(), o.begin());
00264   }
00265 };
00266 
00279 class Argument{
00280 protected:
00281 
00283   simtime_t time;
00284 
00286   std::pair<Dimension, double> values[10];
00287 
00289   unsigned int count;
00290 
00291 public:
00293   typedef std::pair<Dimension, double>* iterator;
00295   typedef const std::pair<Dimension, double>* const_iterator;
00296 
00297 protected:
00311   iterator insertValue(iterator pos, const Dimension& dim, double value, bool ignoreUnknown = false);
00312 
00313 public:
00318   Argument(simtime_t timeVal = 0);
00319 
00325   Argument(const DimensionSet& dims, simtime_t timeVal = 0);
00326 
00330   simtime_t getTime() const;
00331 
00335   void setTime(simtime_t time);
00336 
00341   bool hasArgVal(const Dimension& dim) const;
00342 
00352   double getArgValue(const Dimension& dim) const;
00353 
00363   void setArgValue(const Dimension& dim, double value);
00364 
00375   void setArgValues(const Argument& o, bool ignoreUnknown = false);
00376 
00387   bool isSamePosition(const Argument& other) const;
00388 
00393   bool operator==(const Argument& o) const;
00394 
00400   bool isClose(const Argument& o, double epsilon = 0.000001) const;
00401 
00415   bool operator<(const Argument& o) const;
00416 
00428   double compare(const Argument& o, const DimensionSet& dims) const;
00429 
00437   DimensionSet getDimensions() const {
00438     DimensionSet res(Dimension::time_static());
00439 
00440     for(unsigned int i = 0; i < count; i++)
00441       res.addDimension(values[i].first);
00442 
00443     return res;
00444   }
00445 
00451   friend std::ostream& operator<<(std::ostream& out, const Argument& d) {
00452     out << "(" << d.time;
00453 
00454     for(unsigned int i = 0; i < d.count; i++){
00455       out << ", " << d.values[i].second;
00456     }
00457       return (out << ")");
00458     }
00459 
00464   void operator=(const Argument& o);
00465 
00469   iterator begin() { return values; }
00473   const_iterator begin() const { return values; }
00474 
00475 
00479   iterator end() { return values + count; }
00483   const_iterator end() const { return values + count; }
00484 
00490   iterator find(const Dimension& dim);
00496   const_iterator find(const Dimension& dim) const;
00497 
00502   iterator lower_bound(const Dimension& dim);
00507   const_iterator lower_bound(const Dimension& dim) const;
00508 };
00509 
00521 class NoNextIteratorException {};
00522 
00543 class ConstMappingIterator {
00544 public:
00545   virtual ~ConstMappingIterator() {}
00546 
00551   virtual const Argument& getNextPosition() const = 0;
00552 
00558   virtual void jumpTo(const Argument& pos) = 0;
00559 
00568   virtual void jumpToBegin() = 0;
00569 
00576   virtual void iterateTo(const Argument& pos) = 0;
00577 
00585   virtual void next() = 0;
00586 
00594   virtual bool inRange() const = 0;
00595 
00600   virtual bool hasNext() const = 0;
00601 
00605   virtual const Argument& getPosition() const = 0;
00606 
00614   virtual double getValue() const = 0;
00615 };
00616 
00617 class Mapping;
00618 
00630 class ConstMapping {
00631 protected:
00633   DimensionSet dimensions;
00634 
00635 private:
00636   template<class T>
00637   std::string toString(T v, unsigned int length){
00638     char* tmp = new char[255];
00639     sprintf(tmp, "%.2f", v);
00640 
00641     std::string result(tmp);
00642     delete[] tmp;
00643     while(result.length() < length)
00644       result += " ";
00645     return result;
00646   }
00647 
00648   std::string toString(simtime_t v, unsigned int length){
00649     return toString(SIMTIME_DBL(v), length);
00650   }
00651 
00652 public:
00653 
00657   ConstMapping():
00658     dimensions(Dimension::time_static()) {}
00659 
00666   ConstMapping(const DimensionSet& dimSet):
00667     dimensions(dimSet) {
00668 
00669     assert(dimSet.hasDimension(Dimension::time_static()));
00670   }
00671 
00672   virtual ~ConstMapping() {}
00673 
00680   virtual double getValue(const Argument& pos) const = 0;
00681 
00688   virtual ConstMappingIterator* createConstIterator() = 0;
00689 
00696   virtual ConstMappingIterator* createConstIterator(const Argument& pos) = 0;
00697 
00701   virtual ConstMapping* constClone() const = 0;
00702 
00707   double operator[](const Argument& pos) const {
00708     return getValue(pos);
00709   }
00710 
00714   const DimensionSet& getDimensionSet() const {
00715     return dimensions;
00716   }
00717 
00724   template<class stream>
00725   void print(stream& out) {
00726     ConstMapping& m = *this;
00727     Dimension otherDim;
00728     const DimensionSet& dims = m.getDimensionSet();
00729     out << "Mapping domain: time";
00730     for(DimensionSet::iterator it = dims.begin(); it != dims.end(); ++it) {
00731       if(*it != Dimension::time){
00732         otherDim = *it;
00733         out << ", " << *it;
00734       }
00735     }
00736     out << endl;
00737 
00738     ConstMappingIterator* it = m.createConstIterator();
00739 
00740     if(!it->inRange()) {
00741       out << "Mapping is empty." << endl;
00742       return;
00743     }
00744 
00745     Argument min = it->getPosition();
00746     Argument max = it->getPosition();
00747 
00748     std::set<simtime_t> timePositions;
00749     std::set<double> otherPositions;
00750 
00751     timePositions.insert(it->getPosition().getTime());
00752     if(dims.size() == 2){
00753       otherPositions.insert(it->getPosition().begin()->second);
00754     }
00755 
00756     while(it->hasNext()) {
00757       it->next();
00758       const Argument& pos = it->getPosition();
00759 
00760       min.setTime(std::min(min.getTime(), pos.getTime()));
00761       max.setTime(std::max(max.getTime(), pos.getTime()));
00762 
00763       timePositions.insert(pos.getTime());
00764 
00765       for(Argument::const_iterator itA = pos.begin(); itA != pos.end(); ++itA) {
00766         if(dims.size() == 2){
00767           otherPositions.insert(itA->second);
00768         }
00769         min.setArgValue(itA->first, std::min(min.getArgValue(itA->first), itA->second));
00770         max.setArgValue(itA->first, std::max(max.getArgValue(itA->first), itA->second));
00771       }
00772     }
00773     delete it;
00774 
00775     if(dims.size() > 2) {
00776       out << "domain - min=" << min << " max=" << max << endl;
00777       return;
00778     }
00779 
00780     out << "------+---------------------------------------------------------" << endl;
00781     out << "o\\t   | ";
00782     std::set<simtime_t>::const_iterator tIt;
00783     for(tIt = timePositions.begin();
00784       tIt != timePositions.end(); ++tIt)
00785     {
00786       out << m.toString(*tIt * 1000, 6) << " ";
00787     }
00788     out << endl;
00789     out << "------+---------------------------------------------------------" << endl;
00790 
00791     it = m.createConstIterator();
00792 
00793 
00794     if(dims.size() == 1) {
00795       out << "value" << " | ";
00796       while(it->inRange()) {
00797         out << m.toString(FWMath::mW2dBm(it->getValue()), 6) << " ";
00798 
00799         if(!it->hasNext()) {
00800           break;
00801         }
00802         it->next();
00803       }
00804     } else {
00805       tIt = timePositions.begin();
00806       std::set<double>::const_iterator fIt = otherPositions.begin();
00807       out << m.toString(*fIt, 5) << " | ";
00808       while(it->inRange()) {
00809         if(*fIt != it->getPosition().getArgValue(otherDim)) {
00810           ++fIt;
00811           out << endl << m.toString(*fIt, 5) << " | ";
00812           tIt = timePositions.begin();
00813           assert(*fIt == it->getPosition().getArgValue(otherDim));
00814         }
00815 
00816         while(*tIt < it->getPosition().getTime()){
00817           ++tIt;
00818           out << "      ";
00819         }
00820 
00821         out << m.toString(FWMath::mW2dBm(it->getValue()), 6) << " ";
00822 
00823         if(!it->hasNext()) {
00824           break;
00825         }
00826         it->next();
00827       }
00828     }
00829     out << endl << "------+---------------------------------------------------------" << endl;
00830 
00831   }
00832 };
00833 
00834 
00848 class MappingIterator:public ConstMappingIterator {
00849 
00850 public:
00851   virtual ~MappingIterator() {}
00859   virtual void setValue(double value) = 0;
00860 };
00861 
00862 
00874 class Mapping:public ConstMapping {
00875 public:
00877   enum InterpolationMethod {
00879     STEPS,
00881     NEAREST,
00884     LINEAR
00885   };
00886 
00887 protected:
00888 
00889 public:
00890 
00896   Mapping(const DimensionSet& dims):
00897     ConstMapping(dims) {}
00898 
00902   Mapping():
00903       ConstMapping() {}
00904 
00905   virtual ~Mapping() {}
00906 
00913   virtual void setValue(const Argument& pos, double value) = 0;
00914 
00928   virtual void appendValue(const Argument& pos, double value) {
00929     setValue(pos, value);
00930   }
00931 
00936   virtual MappingIterator* createIterator() = 0;
00937 
00944   virtual MappingIterator* createIterator(const Argument& pos) = 0;
00945 
00952   virtual ConstMappingIterator* createConstIterator() {
00953     return createIterator();
00954   }
00955 
00962   virtual ConstMappingIterator* createConstIterator(const Argument& pos) {
00963     return createIterator(pos);
00964   }
00965 
00966 
00967 
00971   virtual Mapping* clone() const = 0;
00972 
00977   virtual ConstMapping* constClone() const { return clone(); }
00978 
00979 
00980 };
00981 
00982 
00983 //###################################################################################
00984 //#                     default Mapping implementations                              #
00985 //###################################################################################
00986 
01002 class SimpleConstMappingIterator:public ConstMappingIterator {
01003 protected:
01005   ConstMapping* mapping;
01006 
01008   DimensionSet dimensions;
01009 
01011   Argument position;
01012 
01014   typedef std::set<Argument> KeyEntrySet;
01015 
01019   const KeyEntrySet* keyEntries;
01020 
01023   KeyEntrySet::const_iterator nextEntry;
01024 
01025 public:
01034   SimpleConstMappingIterator(ConstMapping* mapping,
01035                  const std::set<Argument>* keyEntries,
01036                  const Argument& start);
01037 
01045   SimpleConstMappingIterator(ConstMapping* mapping,
01046                  const std::set<Argument>* keyEntries);
01047 
01055   virtual const Argument& getNextPosition() const {
01056     if(nextEntry == keyEntries->end())
01057       throw NoNextIteratorException();
01058 
01059     return *nextEntry;
01060   }
01061 
01067   virtual void jumpTo(const Argument& pos) {
01068     position.setArgValues(pos, true);
01069     nextEntry = keyEntries->upper_bound(position);
01070   }
01071 
01078   virtual void jumpToBegin(){
01079     nextEntry = keyEntries->begin();
01080 
01081     if(nextEntry == keyEntries->end()) {
01082       position = Argument(dimensions);
01083     } else {
01084       position = *nextEntry;
01085       ++nextEntry;
01086     }
01087   }
01088 
01098   virtual void iterateTo(const Argument& pos) {
01099     position.setArgValues(pos, true);
01100     while(nextEntry != keyEntries->end() && !(position < *nextEntry))
01101       ++nextEntry;
01102 
01103   }
01104 
01112   virtual void next() {
01113     if(nextEntry == keyEntries->end())
01114       throw NoNextIteratorException();
01115 
01116     position = *nextEntry;
01117     ++nextEntry;
01118   }
01119 
01127   virtual bool inRange() const {
01128     return !(keyEntries->empty()
01129          || (*(keyEntries->rbegin()) < position)
01130          || (position < *(keyEntries->begin())));
01131   }
01132 
01138   virtual bool hasNext() const { return nextEntry != keyEntries->end(); }
01139 
01145   virtual const Argument& getPosition() const { return position; }
01146 
01154   virtual double getValue() const { return mapping->getValue(position); }
01155 };
01156 
01176 class SimpleConstMapping:public ConstMapping {
01177 protected:
01179   typedef std::set<Argument> KeyEntrySet;
01180 
01183   KeyEntrySet keyEntries;
01184 
01185 protected:
01186 
01191   void createKeyEntries(const Argument& from, const Argument& to, const Argument& step, Argument& pos);
01192 
01197   void createKeyEntries(const Argument& from, const Argument& to, const Argument& step,
01198               DimensionSet::const_iterator curDim, Argument& pos);
01199 
01200 public:
01207   virtual ConstMappingIterator* createConstIterator() {
01208     return new SimpleConstMappingIterator(this, &keyEntries);
01209   }
01210 
01217   virtual ConstMappingIterator* createConstIterator(const Argument& pos) {
01218     return new SimpleConstMappingIterator(this, &keyEntries, pos);
01219   }
01220 
01221 public:
01226   SimpleConstMapping(const DimensionSet& dims):
01227     ConstMapping(dims) {}
01228 
01236   SimpleConstMapping(const DimensionSet& dims,
01237              const Argument& key):
01238     ConstMapping(dims){
01239 
01240     initializeArguments(key);
01241   }
01242 
01250   SimpleConstMapping(const DimensionSet& dims,
01251              const Argument& key1, const Argument& key2):
01252     ConstMapping(dims){
01253 
01254     initializeArguments(key1, key2);
01255   }
01256 
01264   SimpleConstMapping(const DimensionSet& dims,
01265              const Argument& min, const Argument& max, const Argument& interval):
01266     ConstMapping(dims){
01267 
01268     initializeArguments(min, max, interval);
01269   }
01270 
01277   void initializeArguments(const Argument& key){
01278     keyEntries.clear();
01279     keyEntries.insert(key);
01280   }
01281 
01288   void initializeArguments(const Argument& key1, const Argument& key2){
01289     keyEntries.clear();
01290     keyEntries.insert(key1);
01291     keyEntries.insert(key2);
01292   }
01293 
01301   void initializeArguments(const Argument& min,
01302                const Argument& max,
01303                const Argument& interval);
01304 
01311   virtual double getValue(const Argument& pos) const = 0;
01312 
01318   ConstMapping* constClone() const  = 0;
01319 };
01320 
01321 
01322 
01323 
01324 #endif /*FUNCTION_H_*/