00001 /** 00002 * @file ordertree.h 00003 * @author Reshen Amin <reshen@zensrc.com> 00004 * 00005 * @brief Contains the class definition for @ref OrderTree 00006 * 00007 * @license Byzantine Generals Problem Coding Sample.<br> 00008 * Copyright (C) 2010 Reshen Amin.<br> 00009 * See @ref license_sec for details.<br> 00010 */ 00011 00012 #ifndef SRC_ORDERTREE_H_ 00013 #define SRC_ORDERTREE_H_ 00014 00015 #include <boost/graph/graphviz.hpp> 00016 #include <boost/graph/adjacency_list.hpp> 00017 #include <boost/graph/depth_first_search.hpp> 00018 00019 #include <log4cpp/Category.hh> 00020 00021 #include "order.h" 00022 00023 /** 00024 * @brief An N-ary Tree of @ref Order "Orders" 00025 */ 00026 class OrderTree { 00027 public: 00028 /** 00029 * @brief Constructor 00030 * 00031 * @param kLogCategoryName Debugging name for logger endpoint 00032 * @param kSharedMemName Shared memory name (used to find traitor set) 00033 * @param kTraitorSetName Traitor set, located in shared memory 00034 */ 00035 OrderTree(const char* kLogCategoryName, 00036 const char* kSharedMemName, 00037 const char* kTraitorSetName); 00038 00039 /** 00040 * @brief Destructor 00041 */ 00042 ~OrderTree(); 00043 00044 /** 00045 * @brief Serialize the tree to Graphviz DOT file format 00046 * 00047 * @param outfile The name of the file to write 00048 */ 00049 void PrintTree(const char* outfile) const; 00050 00051 /** 00052 * @brief Add an @ref Order to the tree. The Order's 00053 * communication_path is used as the insertion key. 00054 * 00055 * @param kOrderToAdd Order to add to the tree 00056 * 00057 * @return Depth at which the Order was added 00058 */ 00059 int Add(const LocalOrder kOrderToAdd); 00060 00061 /** 00062 * @brief The number of nodes present in the tree 00063 * 00064 * @return Node count 00065 */ 00066 unsigned int NodeCount() const; 00067 00068 /** 00069 * @brief The number of edges present in the tree 00070 * 00071 * @return Edge count 00072 */ 00073 unsigned int EdgeCount() const; 00074 00075 /** 00076 * @brief Roll up output orders for the nodes in the tree. 00077 * This function performs a Depth First Search (DFS) on the tree, and 00078 * for leaf nodes, input orders are copied to output orders. For 00079 * non-lef nodes, the output orders are set to the majority of child 00080 * node output orders. In this way, parent's output orders 00081 * reflect what the majority of their children output orders indicated. 00082 * If a tie occurs during voting, MarchingOrders::kAttack is chosen. 00083 * 00084 * @return The root's output marching order after the output orders 00085 * have rolled up the tree. This represents the final decision for this 00086 * general to attack or retreat. 00087 */ 00088 MarchingOrders::type FinalizeOrders(); 00089 00090 private: 00091 /** 00092 * @brief Graph vertices' definition 00093 */ 00094 struct OrderVertex { 00095 /** 00096 * @brief Reference to the locally owned (non-shared) @ref Order 00097 */ 00098 LocalOrder local_order; 00099 00100 /** 00101 * @brief This field is where the output of the @ref FinalizeOrders 00102 * is stored, the majority of child vertices @ref local_order 00103 * "local_orders'" marching orders. If this vertex is a leaf node, 00104 * the @ref local_order "local_order's" marching orders are copied 00105 * to this field directly. 00106 */ 00107 MarchingOrders::type child_majority_marching_orders; 00108 00109 /** 00110 * @brief Used in vertex coloring when generating output, indicates 00111 * if the path that includes this vertex has passed through a 00112 * Traitor General's hands. 00113 */ 00114 bool comm_path_contains_traitor; 00115 }; 00116 00117 /** 00118 * @brief Graph data structure definition. 00119 * VertexList uses vecS (std::vector) because of the lower per-vertex 00120 * space overhead; the compromise is that add_vertex has often-decent 00121 * performance (except in the case of having to reallocate the whole 00122 * graph). OutEdgeList uses vecS (std::vector) because it has the 00123 * lowest amount of space overhead per edge and the often-fastest 00124 * performance for add_edge(). Directed since we are creating a tree, 00125 * and the vertex type is provided. 00126 * 00127 * For details, see <http://www.boost.org/doc/libs/1_42_0/libs/graph/doc/using_adjacency_list.html#sec:choosing-graph-type> 00128 */ 00129 typedef boost::adjacency_list<boost::vecS, 00130 boost::vecS, 00131 boost::directedS, 00132 OrderVertex> OrderGraphType; 00133 00134 /** 00135 * @brief Another underlying graph related type, this one provides an 00136 * identifier for vertices. 00137 */ 00138 typedef boost::graph_traits<OrderGraphType>::vertex_descriptor 00139 OrderNodeIDType; 00140 00141 /** 00142 * @brief Another underlying graph related type, this one provides an 00143 * iterator for traversing the graph. 00144 */ 00145 typedef boost::graph_traits<OrderGraphType>::adjacency_iterator 00146 OrderNodeIteratorType; 00147 00148 /** 00149 * @brief Recursive function that adds the provided order to the tree 00150 * in the proper position. The function walks down the tree using 00151 * the LocalOrder's embedded communication_path to know which path to 00152 * traverse. 00153 * 00154 * @param kParentNodeID Keeps track of the current vertex's parent in 00155 * the tree 00156 * @param kOrderToAdd Order to add to the tree, since we're passing by 00157 * reference the stack overhead is minimal. 00158 * @param traitor_in_path Once we find a traitor general in the path, we 00159 * can toggle this to TRUE such that we don't have to continue checking 00160 * since all children along that path are suspect. Otherwise, no 00161 * traitors have been found, so this remains FALSE. 00162 * 00163 * @return The depth at which the kOrderToAdd was inserted. 00164 */ 00165 int Add(const OrderNodeIDType kParentNodeID, 00166 const LocalOrder kOrderToAdd, 00167 bool traitor_in_path); 00168 00169 /** 00170 * @brief Check if left_order's entire communication_path is a prefix 00171 * of right_order's communication_path. If it is, return TRUE, FALSE 00172 * otherwise. 00173 * 00174 * @param left_order Order to check entire communication_path 00175 * @param right_order Order to check prefix 00176 * 00177 * @return TRUE if prefix matches, FALSE otherwise 00178 */ 00179 bool PrefixMatches(const LocalOrder left_order, 00180 const LocalOrder right_order) const; 00181 00182 /** 00183 * @brief Check the @ref traitor_set_ for the provided argument 00184 * 00185 * @param kGeneralID General's Unique ID to search @ref traitor_set_ for 00186 * 00187 * @return TRUE if found, FALSE otherwise 00188 */ 00189 bool TraitorSetContains(const unsigned int kGeneralID) const; 00190 00191 /** 00192 * @brief Add a @ref OrderVertex "vertex" to the tree. If the 00193 * parent_node_id is valid, then a directed edge is added between the 00194 * parent and the newly created vertex. The vertex is populated with the 00195 * other provided arugments. 00196 * 00197 * @param parent_node_id Parent node identifier to add as source of 00198 * edge, if valid. Otherwise, an edge is not created between the newly 00199 * created vertex and any other vertex. 00200 * @param kChildOrder Place this value in the newly created vertex's 00201 * local_order field 00202 * @param kMarchingOrders Place this value in the newly created vertex's 00203 * child_majority_marching_orders field 00204 * @param kCommPathContainsTraitor Place this value in the newly 00205 * created vertex's comm_path_contains_traitor field 00206 * 00207 * @return Newly created vertex's unique identifier 00208 */ 00209 OrderNodeIDType AddVertex(const OrderNodeIDType parent_node_id, 00210 const LocalOrder kChildOrder, 00211 const MarchingOrders::type kMarchingOrders, 00212 const bool kCommPathContainsTraitor); 00213 00214 /** 00215 * @brief Debug logger reference 00216 */ 00217 log4cpp::Category& log_; 00218 00219 /** 00220 * @brief Reference to the underlying tree 00221 */ 00222 OrderGraphType* order_tree_; 00223 00224 /** 00225 * @brief Root node's unique identifier 00226 */ 00227 OrderNodeIDType root_node_id_; 00228 00229 /** 00230 * @brief Reference to shared memory's traitor set 00231 */ 00232 SharedMemoryUIntSet* traitor_set_; 00233 00234 /* Forward declare a few nested classes. We define them in the cpp file 00235 * to avoid including the nested class's definition in this enclosing 00236 * class, which make sense in this context since the definition is only 00237 * relevant to our implementation */ 00238 00239 /** 00240 * @brief Traverse the tree and write out each vertex to a DOT output 00241 * file 00242 */ 00243 class OrderVertexWriter; 00244 00245 /** 00246 * @brief Depth First Search visitor of tree where vertex visitations 00247 * populate child_majority_marching_orders 00248 */ 00249 class DFSVotingVisitor; 00250 }; 00251 00252 #endif // SRC_ORDERTREE_H_
1.6.3