deba@1703: /* -*- C++ -*- deba@1703: * lemon/static_map.h - Part of LEMON, a generic C++ optimization library deba@1703: * alpar@1875: * Copyright (C) 2006 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport deba@1703: * (Egervary Research Group on Combinatorial Optimization, EGRES). deba@1703: * deba@1703: * Permission to use, modify and distribute this software is granted deba@1703: * provided that this copyright notice appears in all copies. For deba@1703: * precise terms see the accompanying LICENSE file. deba@1703: * deba@1703: * This software is provided "AS IS" with no warranty of any kind, deba@1703: * express or implied, and with no claim as to its suitability for any deba@1703: * purpose. deba@1703: * deba@1703: */ deba@1703: deba@1703: #ifndef LEMON_STATIC_MAP_H deba@1703: #define LEMON_STATIC_MAP_H deba@1703: deba@1703: #include deba@1703: #include deba@1703: deba@1703: #include deba@1810: #include deba@1703: #include deba@1703: #include deba@1703: #include deba@1703: #include deba@1703: deba@1703: /// \ingroup graphmaps deba@1703: /// deba@1703: ///\file deba@1703: ///\brief Static sized graph maps. deba@1703: deba@1703: namespace lemon { deba@1703: deba@1703: /// \ingroup graphmaps deba@1703: /// deba@1703: /// \brief Graph map with static sized storage. deba@1703: /// deba@1703: /// The StaticMap template class is graph map structure what deba@1703: /// does not update automatically the map when a key is added to or deba@1703: /// erased from the map rather it throws an exception. This map factory deba@1703: /// uses the allocators to implement the container functionality. deba@1703: /// deba@1703: /// \param Registry The AlterationNotifier that will notify this map. deba@1703: /// \param Item The item type of the graph items. deba@1703: /// \param Value The value type of the map. deba@1703: /// deba@1703: /// \author Balazs Dezso deba@1703: deba@1703: deba@1703: template deba@1703: class StaticMap : public AlterationNotifier<_Item>::ObserverBase { deba@1703: public: deba@1703: deba@1703: /// \brief Exception class for unsupported exceptions. deba@1703: class UnsupportedOperation : public lemon::LogicError { deba@1703: public: deba@1703: virtual const char* exceptionName() const { deba@1703: return "lemon::StaticMap::UnsupportedOperation"; deba@1703: } deba@1703: }; deba@1703: deba@1719: private: deba@1703: deba@1719: typedef std::vector<_Value> Container; deba@1719: deba@1719: public: deba@1719: deba@1703: /// The graph type of the map. deba@1703: typedef _Graph Graph; deba@1719: /// The reference map tag. deba@1719: typedef True ReferenceMapTag; deba@1719: deba@1703: /// The key type of the map. deba@1703: typedef _Item Key; deba@1703: /// The value type of the map. deba@1703: typedef _Value Value; deba@1719: /// The const reference type of the map. deba@1719: typedef typename Container::const_reference ConstReference; deba@1719: /// The reference type of the map. deba@1719: typedef typename Container::reference Reference; deba@1719: deba@1719: typedef const Value ConstValue; deba@1719: typedef Value* Pointer; deba@1719: typedef const Value* ConstPointer; deba@1719: deba@1719: typedef AlterationNotifier<_Item> Registry; deba@1703: deba@1703: /// The map type. deba@1703: typedef StaticMap Map; deba@1703: /// The base class of the map. deba@1703: typedef typename Registry::ObserverBase Parent; deba@1703: deba@1703: /// \brief Constructor to attach the new map into the registry. deba@1703: /// deba@1703: /// It constructs a map and attachs it into the registry. deba@1703: /// It adds all the items of the graph to the map. deba@1703: StaticMap(const Graph& _g) : graph(&_g) { deba@1703: attach(_g.getNotifier(_Item())); deba@1703: build(); deba@1703: } deba@1703: deba@1703: /// \brief Constructor uses given value to initialize the map. deba@1703: /// deba@1703: /// It constructs a map uses a given value to initialize the map. deba@1703: /// It adds all the items of the graph to the map. deba@1703: StaticMap(const Graph& _g, const Value& _v) : graph(&_g) { deba@1703: attach(_g.getNotifier(_Item())); deba@1703: unsigned size = graph->maxId(_Item()) + 1; deba@1703: container.reserve(size); deba@1703: container.resize(size, _v); deba@1703: } deba@1703: deba@1703: /// \brief Copy constructor deba@1703: /// deba@1703: /// Copy constructor. deba@1703: StaticMap(const StaticMap& _copy) : Parent(), graph(_copy.getGraph()) { deba@1703: if (_copy.attached()) { deba@1703: attach(*_copy.getRegistry()); deba@1703: container = _copy.container; deba@1703: } deba@1703: } deba@1703: deba@1703: /// \brief Destrcutor deba@1703: /// deba@1703: /// Destructor. deba@1703: virtual ~StaticMap() { deba@1703: clear(); deba@1703: if (attached()) { deba@1703: detach(); deba@1703: } deba@1703: } deba@1703: deba@1703: deba@1703: private: deba@1703: deba@1703: StaticMap& operator=(const StaticMap&); deba@1703: deba@1703: protected: deba@1703: deba@1703: using Parent::attach; deba@1703: using Parent::detach; deba@1703: using Parent::attached; deba@1703: deba@1703: const Graph* getGraph() const { deba@1703: return graph; deba@1703: } deba@1703: deba@1703: public: deba@1703: deba@1703: /// \brief The subcript operator. deba@1703: /// deba@1703: /// The subscript operator. The map can be subscripted by the deba@1703: /// actual items of the graph. deba@1703: deba@1703: Reference operator[](const Key& key) { deba@1703: return container[graph->id(key)]; deba@1703: } deba@1703: deba@1703: /// \brief The const subcript operator. deba@1703: /// deba@1703: /// The const subscript operator. The map can be subscripted by the deba@1703: /// actual items of the graph. deba@1703: deba@1703: ConstReference operator[](const Key& key) const { deba@1703: return container[graph->id(key)]; deba@1703: } deba@1703: deba@1703: deba@1703: /// \brief The setter function of the map. deba@1703: /// deba@1703: /// It the same as operator[](key) = value expression. deba@1703: /// deba@1703: void set(const Key& key, const Value& value) { deba@1703: (*this)[key] = value; deba@1703: } deba@1703: deba@1703: protected: deba@1703: deba@1703: /// \brief Adds a new key to the map. deba@1703: /// deba@1703: /// It adds a new key to the map. It called by the observer registry deba@1703: /// and it overrides the add() member function of the observer base. deba@1703: deba@1703: void add(const Key&) { deba@1703: throw UnsupportedOperation(); deba@1703: } deba@1703: deba@1703: /// \brief Erases a key from the map. deba@1703: /// deba@1703: /// Erase a key from the map. It called by the observer registry deba@1703: /// and it overrides the erase() member function of the observer base. deba@1703: void erase(const Key&) { deba@1703: throw UnsupportedOperation(); deba@1703: } deba@1703: deba@1703: /// Buildes the map. deba@1703: deba@1703: /// It buildes the map. It called by the observer registry deba@1703: /// and it overrides the build() member function of the observer base. deba@1703: deba@1703: void build() { deba@1703: int size = graph->maxId(_Item()) + 1; deba@1703: container.reserve(size); deba@1703: container.resize(size); deba@1703: } deba@1703: deba@1703: /// Clear the map. deba@1703: deba@1703: /// It erase all items from the map. It called by the observer registry deba@1703: /// and it overrides the clear() member function of the observer base. deba@1703: void clear() { deba@1703: container.clear(); deba@1703: } deba@1703: deba@1703: private: deba@1703: deba@1703: Container container; deba@1703: const Graph *graph; deba@1703: deba@1703: }; deba@1703: deba@1703: /// \e deba@1703: template deba@1703: class StaticMappableGraphExtender : public _Base { deba@1703: public: deba@1703: deba@1703: typedef StaticMappableGraphExtender<_Base> Graph; deba@1703: typedef _Base Parent; deba@1703: deba@1703: typedef typename Parent::Node Node; deba@1703: typedef typename Parent::NodeIt NodeIt; deba@1703: deba@1703: typedef typename Parent::Edge Edge; deba@1703: typedef typename Parent::EdgeIt EdgeIt; deba@1703: deba@1703: deba@1703: template deba@1703: class NodeMap deba@1703: : public IterableMapExtender > { deba@1703: public: deba@1703: typedef StaticMappableGraphExtender Graph; deba@1703: typedef IterableMapExtender > Parent; deba@1703: deba@1703: NodeMap(const Graph& _g) deba@1703: : Parent(_g) {} deba@1703: NodeMap(const Graph& _g, const _Value& _v) deba@1703: : Parent(_g, _v) {} deba@1703: deba@1703: NodeMap& operator=(const NodeMap& cmap) { deba@1703: return operator=(cmap); deba@1703: } deba@1703: deba@1703: deba@1703: /// \brief Template assign operator. deba@1703: /// deba@1703: /// The given parameter should be conform to the ReadMap deba@1703: /// concecpt and could be indiced by the current item set of deba@1703: /// the NodeMap. In this case the value for each item deba@1703: /// is assigned by the value of the given ReadMap. deba@1703: template deba@1703: NodeMap& operator=(const CMap& cmap) { deba@1703: checkConcept, CMap>(); deba@1703: const typename Parent::Graph* graph = Parent::getGraph(); deba@1703: Node it; deba@1703: for (graph->first(it); it != INVALID; graph->next(it)) { deba@1703: Parent::set(it, cmap[it]); deba@1703: } deba@1703: return *this; deba@1703: } deba@1703: deba@1703: }; deba@1703: deba@1703: template deba@1703: class EdgeMap deba@1703: : public IterableMapExtender > { deba@1703: public: deba@1703: typedef StaticMappableGraphExtender Graph; deba@1703: typedef IterableMapExtender > Parent; deba@1703: deba@1703: EdgeMap(const Graph& _g) deba@1703: : Parent(_g) {} deba@1703: EdgeMap(const Graph& _g, const _Value& _v) deba@1703: : Parent(_g, _v) {} deba@1703: deba@1703: EdgeMap& operator=(const EdgeMap& cmap) { deba@1703: return operator=(cmap); deba@1703: } deba@1703: deba@1703: template deba@1703: EdgeMap& operator=(const CMap& cmap) { deba@1703: checkConcept, CMap>(); deba@1703: const typename Parent::Graph* graph = Parent::getGraph(); deba@1703: Edge it; deba@1703: for (graph->first(it); it != INVALID; graph->next(it)) { deba@1703: Parent::set(it, cmap[it]); deba@1703: } deba@1703: return *this; deba@1703: } deba@1703: }; deba@1703: deba@1703: }; deba@1703: deba@1703: /// \e deba@1703: template deba@1703: class StaticMappableUndirGraphExtender : deba@1703: public StaticMappableGraphExtender<_Base> { deba@1703: public: deba@1703: deba@1703: typedef StaticMappableUndirGraphExtender Graph; deba@1703: typedef StaticMappableGraphExtender<_Base> Parent; deba@1703: deba@1703: typedef typename Parent::UndirEdge UndirEdge; deba@1703: deba@1703: template deba@1703: class UndirEdgeMap deba@1703: : public IterableMapExtender > { deba@1703: public: deba@1703: typedef StaticMappableUndirGraphExtender Graph; deba@1703: typedef IterableMapExtender< deba@1703: StaticMap > Parent; deba@1703: deba@1703: UndirEdgeMap(const Graph& _g) deba@1703: : Parent(_g) {} deba@1703: UndirEdgeMap(const Graph& _g, const _Value& _v) deba@1703: : Parent(_g, _v) {} deba@1703: deba@1703: UndirEdgeMap& operator=(const UndirEdgeMap& cmap) { deba@1703: return operator=(cmap); deba@1703: } deba@1703: deba@1703: template deba@1703: UndirEdgeMap& operator=(const CMap& cmap) { deba@1703: checkConcept, CMap>(); deba@1703: const typename Parent::Graph* graph = Parent::getGraph(); deba@1703: UndirEdge it; deba@1703: for (graph->first(it); it != INVALID; graph->next(it)) { deba@1703: Parent::set(it, cmap[it]); deba@1703: } deba@1703: return *this; deba@1703: } deba@1703: }; deba@1703: deba@1828: }; deba@1703: deba@1828: template deba@1828: class StaticMappableUndirBipartiteGraphExtender : public _Base { deba@1828: public: deba@1828: deba@1828: typedef _Base Parent; deba@1828: typedef StaticMappableUndirBipartiteGraphExtender Graph; deba@1828: deba@1828: typedef typename Parent::Node Node; deba@1828: typedef typename Parent::UpperNode UpperNode; deba@1828: typedef typename Parent::LowerNode LowerNode; deba@1828: typedef typename Parent::Edge Edge; deba@1828: typedef typename Parent::UndirEdge UndirEdge; deba@1828: deba@1828: template deba@1828: class UpperNodeMap deba@1828: : public IterableMapExtender > { deba@1828: public: deba@1828: typedef StaticMappableUndirBipartiteGraphExtender Graph; deba@1828: typedef IterableMapExtender > deba@1828: Parent; deba@1828: deba@1828: UpperNodeMap(const Graph& _g) deba@1828: : Parent(_g) {} deba@1828: UpperNodeMap(const Graph& _g, const _Value& _v) deba@1828: : Parent(_g, _v) {} deba@1828: deba@1828: UpperNodeMap& operator=(const UpperNodeMap& cmap) { deba@1828: return operator=(cmap); deba@1828: } deba@1828: deba@1828: deba@1828: /// \brief Template assign operator. deba@1828: /// deba@1828: /// The given parameter should be conform to the ReadMap deba@1828: /// concept and could be indiced by the current item set of deba@1828: /// the UpperNodeMap. In this case the value for each item deba@1828: /// is assigned by the value of the given ReadMap. deba@1828: template deba@1828: UpperNodeMap& operator=(const CMap& cmap) { deba@1828: checkConcept, CMap>(); deba@1828: const typename Parent::Graph* graph = Parent::getGraph(); deba@1828: UpperNode it; deba@1828: for (graph->first(it); it != INVALID; graph->next(it)) { deba@1828: Parent::set(it, cmap[it]); deba@1828: } deba@1828: return *this; deba@1828: } deba@1828: deba@1828: }; deba@1828: deba@1828: template deba@1828: class LowerNodeMap deba@1828: : public IterableMapExtender > { deba@1828: public: deba@1828: typedef StaticMappableUndirBipartiteGraphExtender Graph; deba@1828: typedef IterableMapExtender > deba@1828: Parent; deba@1828: deba@1828: LowerNodeMap(const Graph& _g) deba@1828: : Parent(_g) {} deba@1828: LowerNodeMap(const Graph& _g, const _Value& _v) deba@1828: : Parent(_g, _v) {} deba@1828: deba@1828: LowerNodeMap& operator=(const LowerNodeMap& cmap) { deba@1828: return operator=(cmap); deba@1828: } deba@1828: deba@1828: deba@1828: /// \brief Template assign operator. deba@1828: /// deba@1828: /// The given parameter should be conform to the ReadMap deba@1828: /// concept and could be indiced by the current item set of deba@1828: /// the LowerNodeMap. In this case the value for each item deba@1828: /// is assigned by the value of the given ReadMap. deba@1828: template deba@1828: LowerNodeMap& operator=(const CMap& cmap) { deba@1828: checkConcept, CMap>(); deba@1828: const typename Parent::Graph* graph = Parent::getGraph(); deba@1828: LowerNode it; deba@1828: for (graph->first(it); it != INVALID; graph->next(it)) { deba@1828: Parent::set(it, cmap[it]); deba@1828: } deba@1828: return *this; deba@1828: } deba@1828: deba@1828: }; deba@1828: deba@1828: protected: deba@1828: deba@1828: template deba@1828: class NodeMapBase : public Parent::NodeNotifier::ObserverBase { deba@1828: public: deba@1828: typedef StaticMappableUndirBipartiteGraphExtender Graph; deba@1828: deba@1828: typedef Node Key; deba@1828: typedef _Value Value; deba@1828: deba@1828: /// The reference type of the map; deba@1828: typedef typename LowerNodeMap<_Value>::Reference Reference; deba@1828: /// The pointer type of the map; deba@1828: typedef typename LowerNodeMap<_Value>::Pointer Pointer; deba@1828: deba@1828: /// The const value type of the map. deba@1828: typedef const Value ConstValue; deba@1828: /// The const reference type of the map; deba@1828: typedef typename LowerNodeMap<_Value>::ConstReference ConstReference; deba@1828: /// The pointer type of the map; deba@1828: typedef typename LowerNodeMap<_Value>::ConstPointer ConstPointer; deba@1828: deba@1828: typedef True ReferenceMapTag; deba@1828: deba@1828: NodeMapBase(const Graph& _g) deba@1828: : graph(&_g), lowerMap(_g), upperMap(_g) { deba@1828: Parent::NodeNotifier::ObserverBase::attach(_g.getNotifier(Node())); deba@1828: } deba@1828: NodeMapBase(const Graph& _g, const _Value& _v) deba@1828: : graph(&_g), lowerMap(_g, _v), deba@1828: upperMap(_g, _v) { deba@1828: Parent::NodeNotifier::ObserverBase::attach(_g.getNotifier(Node())); deba@1828: } deba@1828: deba@1828: virtual ~NodeMapBase() { deba@1828: if (Parent::NodeNotifier::ObserverBase::attached()) { deba@1828: Parent::NodeNotifier::ObserverBase::detach(); deba@1828: } deba@1828: } deba@1828: deba@1828: ConstReference operator[](const Key& node) const { deba@1828: if (Parent::upper(node)) { deba@1828: return upperMap[node]; deba@1828: } else { deba@1828: return lowerMap[node]; deba@1828: } deba@1828: } deba@1828: deba@1828: Reference operator[](const Key& node) { deba@1828: if (Parent::upper(node)) { deba@1828: return upperMap[node]; deba@1828: } else { deba@1828: return lowerMap[node]; deba@1828: } deba@1828: } deba@1828: deba@1828: void set(const Key& node, const Value& value) { deba@1828: if (Parent::upper(node)) { deba@1828: upperMap.set(node, value); deba@1828: } else { deba@1828: lowerMap.set(node, value); deba@1828: } deba@1828: } deba@1828: deba@1828: protected: deba@1828: deba@1828: virtual void add(const Node&) {} deba@1828: virtual void erase(const Node&) {} deba@1828: virtual void clear() {} deba@1828: virtual void build() {} deba@1828: deba@1828: const Graph* getGraph() const { return graph; } deba@1828: deba@1828: private: deba@1828: const Graph* graph; deba@1828: LowerNodeMap<_Value> lowerMap; deba@1828: UpperNodeMap<_Value> upperMap; deba@1828: }; deba@1828: deba@1828: public: deba@1828: deba@1828: template deba@1828: class NodeMap deba@1828: : public IterableMapExtender > { deba@1828: public: deba@1828: typedef StaticMappableUndirBipartiteGraphExtender Graph; deba@1828: typedef IterableMapExtender< NodeMapBase<_Value> > Parent; deba@1828: deba@1828: NodeMap(const Graph& _g) deba@1828: : Parent(_g) {} deba@1828: NodeMap(const Graph& _g, const _Value& _v) deba@1828: : Parent(_g, _v) {} deba@1828: deba@1828: NodeMap& operator=(const NodeMap& cmap) { deba@1828: return operator=(cmap); deba@1828: } deba@1828: deba@1828: deba@1828: /// \brief Template assign operator. deba@1828: /// deba@1828: /// The given parameter should be conform to the ReadMap deba@1828: /// concept and could be indiced by the current item set of deba@1828: /// the NodeMap. In this case the value for each item deba@1828: /// is assigned by the value of the given ReadMap. deba@1828: template deba@1828: NodeMap& operator=(const CMap& cmap) { deba@1828: checkConcept, CMap>(); deba@1828: const typename Parent::Graph* graph = Parent::getGraph(); deba@1828: Node it; deba@1828: for (graph->first(it); it != INVALID; graph->next(it)) { deba@1828: Parent::set(it, cmap[it]); deba@1828: } deba@1828: return *this; deba@1828: } deba@1828: deba@1828: }; deba@1828: deba@1828: deba@1828: deba@1828: template deba@1828: class EdgeMap deba@1828: : public IterableMapExtender > { deba@1828: public: deba@1828: typedef StaticMappableUndirBipartiteGraphExtender Graph; deba@1828: typedef IterableMapExtender > Parent; deba@1828: deba@1828: EdgeMap(const Graph& _g) deba@1828: : Parent(_g) {} deba@1828: EdgeMap(const Graph& _g, const _Value& _v) deba@1828: : Parent(_g, _v) {} deba@1828: deba@1828: EdgeMap& operator=(const EdgeMap& cmap) { deba@1828: return operator=(cmap); deba@1828: } deba@1828: deba@1828: template deba@1828: EdgeMap& operator=(const CMap& cmap) { deba@1828: checkConcept, CMap>(); deba@1828: const typename Parent::Graph* graph = Parent::getGraph(); deba@1828: Edge it; deba@1828: for (graph->first(it); it != INVALID; graph->next(it)) { deba@1828: Parent::set(it, cmap[it]); deba@1828: } deba@1828: return *this; deba@1828: } deba@1828: }; deba@1828: deba@1828: template deba@1828: class UndirEdgeMap deba@1828: : public IterableMapExtender > { deba@1828: public: deba@1828: typedef StaticMappableUndirBipartiteGraphExtender Graph; deba@1828: typedef IterableMapExtender > deba@1828: Parent; deba@1828: deba@1828: UndirEdgeMap(const Graph& _g) deba@1828: : Parent(_g) {} deba@1828: UndirEdgeMap(const Graph& _g, const _Value& _v) deba@1828: : Parent(_g, _v) {} deba@1828: deba@1828: UndirEdgeMap& operator=(const UndirEdgeMap& cmap) { deba@1828: return operator=(cmap); deba@1828: } deba@1828: deba@1828: template deba@1828: UndirEdgeMap& operator=(const CMap& cmap) { deba@1828: checkConcept, CMap>(); deba@1828: const typename Parent::Graph* graph = Parent::getGraph(); deba@1828: UndirEdge it; deba@1828: for (graph->first(it); it != INVALID; graph->next(it)) { deba@1828: Parent::set(it, cmap[it]); deba@1828: } deba@1828: return *this; deba@1828: } deba@1828: }; deba@1828: deba@1703: }; deba@1703: deba@1703: } deba@1703: deba@1703: #endif