#ifndef TYPES_H
#define TYPES_H
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/adj_list_serialize.hpp>
#include <boost/graph/filtered_graph.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/deque.hpp>
#include <boost/serialization/variant.hpp>
#include <boost/variant.hpp>
#include <boost/ref.hpp>
using namespace std;
using namespace boost;
using namespace boost::multi_index;
class QTable; //forward declaration
typedef QTable Eligibility;
//观测类型
enum Observation{present,absent,idle};
//1)图模型的定义
enum vertex_BatteryLevel_t {vertex_BatteryLevel};
enum vertex_ObservationHistory_t {vertex_ObservationHistory};
enum edge_QFunction_t {edge_QFunction};
enum edge_Eligibility_t {edge_Eligibility};
namespace boost {
BOOST_INSTALL_PROPERTY(vertex,BatteryLevel);
BOOST_INSTALL_PROPERTY(vertex,ObservationHistory);
BOOST_INSTALL_PROPERTY(edge,QFunction);
BOOST_INSTALL_PROPERTY(edge,Eligibility);
}
typedef property<vertex_BatteryLevel_t,int,
property<vertex_ObservationHistory_t,deque<Observation>,
property<vertex_index_t,int>
>
> vertex_state;
typedef property<edge_QFunction_t,QTable,
property<edge_Eligibility_t,Eligibility>
> edge_qfunction;
typedef adjacency_list<
vecS,setS,directedS, //结点用vecS因为无需动态改变结点个数,用setS表示边为了强调是简单图(两个结点之间一个方向的边只能有一条)
vertex_state, //节点的电量和观测历史
edge_qfunction //每个有向边对应一个ublas::matrix<double>对象属性
> Graph;
//2)Q函数的定义
//行为类型
enum NotSensing{off=-2,recharge=-1};
typedef variant<int,NotSensing> Action; //action={各个方向,off,recharge}
//state=<历史观测,电池电量>
struct Status {
friend class boost::serialization::access;
template<class Archive> void serialize(Archive & ar,const unsigned int version);
//从结点id->观测历史的映射
//每一个时刻的历史观测顺序是传感器本身,按照迭代器顺序的其他传感器观测
typedef map<int,deque<Observation> > HistoryType;
HistoryType history;
int batteryLevel; //电池电量
Status() {}
Status(const HistoryType & h,const int & bl);
Status(const Status & s);
~Status() {}
friend bool operator<(const Status & idx1,const Status & idx2);
friend bool operator==(const Status & idx1,const Status & idx2);
};
template<class Archive>
inline void Status::serialize(Archive & ar,const unsigned int)
{
ar & history & batteryLevel;
}
struct QTableElem {
friend class boost::serialization::access;
template<class Archive> void serialize(Archive &,const unsigned int) {}
Status status;
Action myaction, youraction;
double value;
QTableElem(const Status & s,const Action & ma,const Action & ya,double v)
: status(s),myaction(ma),youraction(ya),value(v) {}
};
typedef QTableElem EligibilityElem;
//因为typedef不能circular dependent所以需要定义个类继承其中一个typedef。
class QTable : public multi_index_container <
QTableElem,
indexed_by <
ordered_unique<
composite_key<
QTableElem,
member<QTableElem,Status,&QTableElem::status>,
member<QTableElem,Action,&QTableElem::myaction>,
member<QTableElem,Action,&QTableElem::youraction>
>
>,
ordered_non_unique<member<QTableElem,Status,&QTableElem::status> >
>
> {};
typedef QTable::nth_index<1>::type::iterator ActionIterator;
//3)过滤器定义
class CutGraphFilter {
map<int,int> u2c; //vertex id->cluster id
reference_wrapper<Graph> g;
public:
CutGraphFilter(map<int,int> u,Graph & gg):u2c(u),g(ref(gg)){}
bool operator()(const graph_traits<Graph>::edge_descriptor & e) const {
graph_traits<Graph>::vertex_descriptor t = target(e,unwrap_ref(g));
graph_traits<Graph>::vertex_descriptor s = source(e,unwrap_ref(g));
map<int,int>::const_iterator tit = u2c.find(get(get(vertex_index,unwrap_ref(g)),t));
map<int,int>::const_iterator sit = u2c.find(get(get(vertex_index,unwrap_ref(g)),s));
#ifndef NDEBUG
assert(u2c.end() != tit);
assert(u2c.end() != sit);
#endif
return tit->second == sit->second;
}
};
namespace boost {
namespace serialization {
template<class Archive> inline void save_construct_data(Archive & ar,const QTableElem * e,const unsigned int) {
ar << e->status << e->myaction << e->youraction << e->value;
}
template<class Archive> void load_construct_data(Archive & ar,QTableElem * e,const unsigned int) {
Status s;
Action ma,ya;
double v;
ar >> s >> ma >> ya >> v;
::new(e) QTableElem(s,ma,ya,v);
}
}
}
#endif