Showing
8 changed files
with
318 additions
and
68 deletions
1 | #include "stdafx.h" | 1 | #include "stdafx.h" |
2 | #include "GraphItem.h" | 2 | #include "GraphItem.h" |
3 | 3 | ||
4 | -GraphItem::GraphItem(ifstream& fin, int numOfLines) | 4 | +GraphItem::GraphItem(const char *filename) |
5 | { | 5 | { |
6 | - //numOfLines == ifstream에서 읽을 라인의 수 | 6 | + fin.open(filename); |
7 | - | ||
8 | if (!fin) | 7 | if (!fin) |
9 | - throw std::exception("graph file input is invalid"); | 8 | + throw std::exception("graph file is not available"); |
10 | - else if (numOfLines < 1) | 9 | + |
11 | - throw std::exception("invalid numOfLines"); | 10 | + graph = new Graph(); |
11 | + read_more(); | ||
12 | +} | ||
12 | 13 | ||
14 | +GraphItem::~GraphItem() | ||
15 | +{ | ||
16 | + fin.close(); | ||
17 | +} | ||
18 | + | ||
19 | +void GraphItem::read_more() | ||
20 | +{ | ||
13 | /** | 21 | /** |
14 | - * Parse Paper dataset | 22 | + * Parse Paper dataset |
15 | - * - paper_key, [author_list], publish_year | 23 | + * - paper_key, [author_list], publish_year |
16 | - * Column Delimiter: || | 24 | + * Column Delimiter: || |
17 | - * Author list Delimiter: && | 25 | + * Author list Delimiter: && |
18 | - */ | 26 | + */ |
19 | std::string line; | 27 | std::string line; |
20 | vector<std::string> tokens; | 28 | vector<std::string> tokens; |
21 | vector<std::string> authors; | 29 | vector<std::string> authors; |
22 | - vector<pair<string, string>> edges; | 30 | + /*vector<pair<string, string>> edges;*/ |
23 | - | 31 | + |
24 | - //String <--> int 양방향 변환을 위해 bidirectional map 상숑 | 32 | + //vector<simple_edge> edges_indexes; |
25 | - //map<string, int> -> <vertex label, vertex index> | 33 | + |
26 | - /*typedef boost::bimap<string, int> bm_type;*/ | ||
27 | - /*bm_type node_ids; | ||
28 | - vector<simple_edge> edges_indexes*/; //int로 변환된 edge | ||
29 | - | ||
30 | - int node_cnt = 0; | ||
31 | int line_cnt = 0; | 34 | int line_cnt = 0; |
32 | qDebug() << "* graph reading start"; | 35 | qDebug() << "* graph reading start"; |
33 | - | 36 | + |
34 | //한 줄씩 읽어서 Parse | 37 | //한 줄씩 읽어서 Parse |
38 | + int node_cnt = 0; | ||
35 | while (std::getline(fin, line) && !line.empty()) { | 39 | while (std::getline(fin, line) && !line.empty()) { |
36 | //boost::split 이용해 문자열 분리 | 40 | //boost::split 이용해 문자열 분리 |
37 | //tokens[0]: Paper-key. ex) conf/iastedCSN/KeimS06 | 41 | //tokens[0]: Paper-key. ex) conf/iastedCSN/KeimS06 |
... | @@ -39,53 +43,72 @@ GraphItem::GraphItem(ifstream& fin, int numOfLines) | ... | @@ -39,53 +43,72 @@ GraphItem::GraphItem(ifstream& fin, int numOfLines) |
39 | //tokens[2]: Published year. | 43 | //tokens[2]: Published year. |
40 | boost::split(tokens, line, boost::is_any_of("||"), boost::token_compress_on); | 44 | boost::split(tokens, line, boost::is_any_of("||"), boost::token_compress_on); |
41 | boost::split(authors, tokens[1], boost::is_any_of("&&"), boost::token_compress_on); | 45 | boost::split(authors, tokens[1], boost::is_any_of("&&"), boost::token_compress_on); |
42 | - | 46 | + |
43 | const string& paper_key = tokens[0]; | 47 | const string& paper_key = tokens[0]; |
44 | if (node_ids.left.find(paper_key) == node_ids.left.end()) { | 48 | if (node_ids.left.find(paper_key) == node_ids.left.end()) { |
45 | - node_ids.insert(bm_type::value_type(paper_key, node_cnt++)); | 49 | + node_ids.insert(bm_type::value_type(paper_key, node_cnt + whole_node_cnt)); |
50 | + ++node_cnt; | ||
46 | } | 51 | } |
47 | - | 52 | + |
48 | for (auto author : authors) { | 53 | for (auto author : authors) { |
49 | edges.push_back(pair<string, string>(paper_key, author)); | 54 | edges.push_back(pair<string, string>(paper_key, author)); |
50 | if (node_ids.left.find(author) == node_ids.left.end()) { | 55 | if (node_ids.left.find(author) == node_ids.left.end()) { |
51 | - node_ids.insert(bm_type::value_type(author, node_cnt++)); | 56 | + node_ids.insert(bm_type::value_type(author, node_cnt + whole_node_cnt)); |
57 | + ++node_cnt; | ||
52 | } | 58 | } |
53 | } | 59 | } |
54 | - | 60 | + |
55 | //debug | 61 | //debug |
56 | ++line_cnt; | 62 | ++line_cnt; |
57 | - if (line_cnt >= numOfLines) break; | 63 | + if (line_cnt >= READ_LINE_UNIT) break; |
58 | } | 64 | } |
59 | qDebug() << "* graph reading complete"; | 65 | qDebug() << "* graph reading complete"; |
60 | qDebug() << "* # of read line: " << line_cnt; | 66 | qDebug() << "* # of read line: " << line_cnt; |
61 | qDebug() << "* # of nodes: " << node_cnt; | 67 | qDebug() << "* # of nodes: " << node_cnt; |
62 | - qDebug() << "* # of edges: " << edges.size(); | 68 | + //qDebug() << "* # of edges: " << edges.size(); |
69 | + | ||
63 | 70 | ||
71 | + | ||
64 | //edge conversion | 72 | //edge conversion |
65 | //<string, string> to <int, int> | 73 | //<string, string> to <int, int> |
66 | //using boost::bimap (bidirectional map) | 74 | //using boost::bimap (bidirectional map) |
75 | + edges_indexes.clear(); | ||
67 | for (auto edge : edges) { | 76 | for (auto edge : edges) { |
68 | edges_indexes.push_back({ | 77 | edges_indexes.push_back({ |
69 | node_ids.left.find(edge.first)->get_right(), | 78 | node_ids.left.find(edge.first)->get_right(), |
70 | node_ids.left.find(edge.second)->get_right() | 79 | node_ids.left.find(edge.second)->get_right() |
71 | }); | 80 | }); |
72 | } | 81 | } |
73 | - //Graph --> defined in "PaperGraphWidget.h" | 82 | + |
74 | //Graph graph(edges_indexes.begin(), edges_indexes.end(), node_ids.size()); | 83 | //Graph graph(edges_indexes.begin(), edges_indexes.end(), node_ids.size()); |
84 | + //graph = new Graph(edges_indexes.begin(), edges_indexes.end(), node_ids.size()); | ||
85 | + //for (auto& e: edges_indexes) { | ||
86 | + // boost::add_edge(e.first, e.second, graph); | ||
87 | + //} | ||
88 | + | ||
89 | + if (graph) { | ||
90 | + delete graph; | ||
91 | + graph = nullptr; | ||
92 | + } | ||
75 | graph = new Graph(edges_indexes.begin(), edges_indexes.end(), node_ids.size()); | 93 | graph = new Graph(edges_indexes.begin(), edges_indexes.end(), node_ids.size()); |
94 | + | ||
76 | 95 | ||
96 | + | ||
77 | //set index property | 97 | //set index property |
78 | qDebug() << "* set vertex property start"; | 98 | qDebug() << "* set vertex property start"; |
79 | vertex_iterator vi, vi_end; | 99 | vertex_iterator vi, vi_end; |
80 | int i = 0; | 100 | int i = 0; |
81 | - for (boost::tie(vi, vi_end)=vertices(*graph); vi!=vi_end; ++vi) { | 101 | + for (boost::tie(vi, vi_end) = vertices(*graph); vi != vi_end; ++vi) { |
82 | //Vertex Property 설정 | 102 | //Vertex Property 설정 |
83 | - //index: 0 ~ ... | 103 | + //index: n ~ ... |
84 | //name : map의 value(i) 기준으로 찾은 Key | 104 | //name : map의 value(i) 기준으로 찾은 Key |
85 | - // map --> map<string, int> (boost bidirectional map) | 105 | + // map --> map<string, int> (boost bidirectional map) |
86 | std::string node_label = node_ids.right.find(i)->get_left(); | 106 | std::string node_label = node_ids.right.find(i)->get_left(); |
87 | boost::put(vertex_index, *graph, *vi, i); | 107 | boost::put(vertex_index, *graph, *vi, i); |
88 | boost::put(vertex_name, *graph, *vi, node_label); | 108 | boost::put(vertex_name, *graph, *vi, node_label); |
109 | + boost::put(vertex_record, *graph, *vi, 0); | ||
110 | + | ||
111 | + qDebug() << "** index: " << i << ", name: " << node_label.c_str(); | ||
89 | 112 | ||
90 | //node type 설정 | 113 | //node type 설정 |
91 | if (boost::regex_match(node_label, paper_reg)) { | 114 | if (boost::regex_match(node_label, paper_reg)) { |
... | @@ -99,7 +122,7 @@ GraphItem::GraphItem(ifstream& fin, int numOfLines) | ... | @@ -99,7 +122,7 @@ GraphItem::GraphItem(ifstream& fin, int numOfLines) |
99 | ++i; | 122 | ++i; |
100 | } | 123 | } |
101 | qDebug() << "* set vertex property end"; | 124 | qDebug() << "* set vertex property end"; |
102 | - | 125 | + whole_node_cnt += node_cnt; |
103 | 126 | ||
104 | //qDebug("* set edges weight start"); | 127 | //qDebug("* set edges weight start"); |
105 | ////모든 edge의 weight를 1로 설정 | 128 | ////모든 edge의 weight를 1로 설정 |
... | @@ -133,7 +156,7 @@ GraphItem::GraphItem(ifstream& fin, int numOfLines) | ... | @@ -133,7 +156,7 @@ GraphItem::GraphItem(ifstream& fin, int numOfLines) |
133 | //while (current != boost::vertex(start_idx, *graph)) { | 156 | //while (current != boost::vertex(start_idx, *graph)) { |
134 | //} | 157 | //} |
135 | //qDebug("* path highlighting end"); | 158 | //qDebug("* path highlighting end"); |
136 | - | 159 | + |
137 | 160 | ||
138 | //graph layout calculation | 161 | //graph layout calculation |
139 | //using boost::random_graph_layout and boost::kamada_kawai_spring_layout | 162 | //using boost::random_graph_layout and boost::kamada_kawai_spring_layout |
... | @@ -148,18 +171,18 @@ GraphItem::GraphItem(ifstream& fin, int numOfLines) | ... | @@ -148,18 +171,18 @@ GraphItem::GraphItem(ifstream& fin, int numOfLines) |
148 | Topology::point_difference_type extent; | 171 | Topology::point_difference_type extent; |
149 | extent[0] = extent[1] = (double)SCREEN_SIZE; | 172 | extent[0] = extent[1] = (double)SCREEN_SIZE; |
150 | rectangle_topology<> rect_top(gen, | 173 | rectangle_topology<> rect_top(gen, |
151 | - -SCREEN_SIZE/2, -SCREEN_SIZE/2, | 174 | + -SCREEN_SIZE / 2, -SCREEN_SIZE / 2, |
152 | - SCREEN_SIZE/2, SCREEN_SIZE/2); | 175 | + SCREEN_SIZE / 2, SCREEN_SIZE / 2); |
153 | - | 176 | + |
154 | switch (LAYOUT_MODE) { | 177 | switch (LAYOUT_MODE) { |
155 | case GRAPH_LAYOUT::RANDOM_LAYOUT: | 178 | case GRAPH_LAYOUT::RANDOM_LAYOUT: |
156 | random_graph_layout(*graph, get(vertex_position, *graph), rect_top); | 179 | random_graph_layout(*graph, get(vertex_position, *graph), rect_top); |
157 | break; | 180 | break; |
158 | - | 181 | + |
159 | case GRAPH_LAYOUT::CIRCLE_LAYOUT: | 182 | case GRAPH_LAYOUT::CIRCLE_LAYOUT: |
160 | - circle_graph_layout(*graph, get(vertex_position, *graph), SCREEN_SIZE/2); | 183 | + circle_graph_layout(*graph, get(vertex_position, *graph), SCREEN_SIZE / 2); |
161 | break; | 184 | break; |
162 | - | 185 | + |
163 | case GRAPH_LAYOUT::FRUCHTERMAN_REINGOLD_LAYOUT: | 186 | case GRAPH_LAYOUT::FRUCHTERMAN_REINGOLD_LAYOUT: |
164 | fruchterman_reingold_force_directed_layout(*graph, | 187 | fruchterman_reingold_force_directed_layout(*graph, |
165 | get(vertex_position, *graph), | 188 | get(vertex_position, *graph), |
... | @@ -172,14 +195,18 @@ GraphItem::GraphItem(ifstream& fin, int numOfLines) | ... | @@ -172,14 +195,18 @@ GraphItem::GraphItem(ifstream& fin, int numOfLines) |
172 | qDebug() << "* make graph layout end"; | 195 | qDebug() << "* make graph layout end"; |
173 | 196 | ||
174 | 197 | ||
198 | + //clear lists | ||
199 | + nodeList.clear(); | ||
200 | + edgeList.clear(); | ||
201 | + | ||
175 | //add edges | 202 | //add edges |
176 | - auto position = get(vertex_position, *graph); | 203 | + auto position = boost::get(vertex_position, *graph); |
177 | - auto label = get(vertex_name, *graph); | 204 | + auto label = boost::get(vertex_name, *graph); |
178 | - auto nodeType = get(vertex_type, *graph); | 205 | + auto nodeType = boost::get(vertex_type, *graph); |
179 | 206 | ||
180 | edge_iterator ei, ei_end; | 207 | edge_iterator ei, ei_end; |
181 | vertex_descriptor u, v; | 208 | vertex_descriptor u, v; |
182 | - for (boost::tie(ei, ei_end)=boost::edges(*graph); ei!=ei_end; ++ei) { | 209 | + for (boost::tie(ei, ei_end) = boost::edges(*graph); ei != ei_end; ++ei) { |
183 | u = source(*ei, *graph); | 210 | u = source(*ei, *graph); |
184 | v = target(*ei, *graph); | 211 | v = target(*ei, *graph); |
185 | Point p1 = position[u]; | 212 | Point p1 = position[u]; |
... | @@ -187,14 +214,14 @@ GraphItem::GraphItem(ifstream& fin, int numOfLines) | ... | @@ -187,14 +214,14 @@ GraphItem::GraphItem(ifstream& fin, int numOfLines) |
187 | 214 | ||
188 | //make edge item and push it to list | 215 | //make edge item and push it to list |
189 | EdgeItem *edge; | 216 | EdgeItem *edge; |
190 | - | 217 | + |
191 | edge = new EdgeItem(p1[0], p1[1], p2[0], p2[1], QColor(Qt::black), 0); | 218 | edge = new EdgeItem(p1[0], p1[1], p2[0], p2[1], QColor(Qt::black), 0); |
192 | edge->setPos(p1[0], p1[1]); | 219 | edge->setPos(p1[0], p1[1]); |
193 | edgeList << edge; | 220 | edgeList << edge; |
194 | } | 221 | } |
195 | 222 | ||
196 | //add nodes | 223 | //add nodes |
197 | - for (boost::tie(vi, vi_end)=vertices(*graph); vi!=vi_end; ++vi) { | 224 | + for (boost::tie(vi, vi_end) = vertices(*graph); vi != vi_end; ++vi) { |
198 | Point p = position[*vi]; | 225 | Point p = position[*vi]; |
199 | auto nt = nodeType[*vi]; | 226 | auto nt = nodeType[*vi]; |
200 | std::string name = label[*vi]; | 227 | std::string name = label[*vi]; |
... | @@ -203,7 +230,8 @@ GraphItem::GraphItem(ifstream& fin, int numOfLines) | ... | @@ -203,7 +230,8 @@ GraphItem::GraphItem(ifstream& fin, int numOfLines) |
203 | NodeItem *node; | 230 | NodeItem *node; |
204 | if (nt == NODE_TYPE::NODE_PAPER) { | 231 | if (nt == NODE_TYPE::NODE_PAPER) { |
205 | node = new NodeItem(p[0], p[1], QColor(Qt::darkGreen), QString(name.c_str()), nt); | 232 | node = new NodeItem(p[0], p[1], QColor(Qt::darkGreen), QString(name.c_str()), nt); |
206 | - } else { | 233 | + } |
234 | + else { | ||
207 | node = new NodeItem(p[0], p[1], QColor(Qt::green), QString(name.c_str()), nt); | 235 | node = new NodeItem(p[0], p[1], QColor(Qt::green), QString(name.c_str()), nt); |
208 | } | 236 | } |
209 | node->setPos(QPointF(p[0], p[1])); | 237 | node->setPos(QPointF(p[0], p[1])); |
... | @@ -262,6 +290,63 @@ void GraphItem::reset_color() | ... | @@ -262,6 +290,63 @@ void GraphItem::reset_color() |
262 | } | 290 | } |
263 | } | 291 | } |
264 | 292 | ||
293 | +void GraphItem::topK_highlight() | ||
294 | +{ | ||
295 | + // 저자 노드별 실적 계산 | ||
296 | + vertex_iterator vi, vi_end; | ||
297 | + Graph::adjacency_iterator ai, ai_end; | ||
298 | + | ||
299 | + auto nodeLabel = boost::get(vertex_name, *graph); | ||
300 | + auto nodeType = boost::get(vertex_type, *graph); | ||
301 | + auto numOfRecords = boost::get(vertex_record, *graph); | ||
302 | + | ||
303 | + //실적 count 초기화 | ||
304 | + //for (boost::tie(vi, vi_end) = boost::vertices(*graph); vi != vi_end; ++vi) { | ||
305 | + // if (nodeType[*vi] != NODE_TYPE::NODE_AUTHOR) { | ||
306 | + // continue; | ||
307 | + // } | ||
308 | + // boost::put(vertex_record, *graph, *vi, 0); | ||
309 | + //} | ||
310 | + | ||
311 | + // <record, label> | ||
312 | + TopKHeap<pair<int, string>> heap(TOP_K); | ||
313 | + for (boost::tie(vi, vi_end) = boost::vertices(*graph); vi != vi_end; ++vi) { | ||
314 | + if (nodeType[*vi] != NODE_TYPE::NODE_AUTHOR) { | ||
315 | + continue; | ||
316 | + } | ||
317 | + | ||
318 | + int record_cnt = 0; | ||
319 | + for (boost::tie(ai, ai_end) = boost::adjacent_vertices(*vi, *graph); | ||
320 | + ai != ai_end; ++ai) { | ||
321 | + if (nodeType[*vi] == NODE_TYPE::NODE_PAPER) { | ||
322 | + ++record_cnt; | ||
323 | + } | ||
324 | + } | ||
325 | + | ||
326 | + boost::put(vertex_record, *graph, *vi, record_cnt); | ||
327 | + heap.push(make_pair(record_cnt, nodeLabel[*vi])); | ||
328 | + } | ||
329 | + | ||
330 | + //get top K records | ||
331 | + pair<int, string> topk_arr[TOP_K]; | ||
332 | + for (int i = 0; i < TOP_K; ++i) { | ||
333 | + topk_arr[i] = heap.pop(); | ||
334 | + } | ||
335 | + | ||
336 | + for (auto& n: nodeList) { | ||
337 | + auto label = n->getLabel(); | ||
338 | + n->setColor(QColor(Qt::lightGray)); | ||
339 | + for (auto& p: topk_arr) { | ||
340 | + if (label.toStdString() == p.second) { | ||
341 | + n->setColor(QColor(Qt::red)); | ||
342 | + break; | ||
343 | + } | ||
344 | + } | ||
345 | + } | ||
346 | + | ||
347 | + //delete[] topk_arr; | ||
348 | +} | ||
349 | + | ||
265 | //event handler | 350 | //event handler |
266 | void GraphItem::mousePressEvent(QGraphicsSceneMouseEvent *event) | 351 | void GraphItem::mousePressEvent(QGraphicsSceneMouseEvent *event) |
267 | { | 352 | { | ... | ... |
... | @@ -13,7 +13,12 @@ class GraphItem | ... | @@ -13,7 +13,12 @@ class GraphItem |
13 | : public QGraphicsItem | 13 | : public QGraphicsItem |
14 | { | 14 | { |
15 | public: | 15 | public: |
16 | - GraphItem(ifstream& fin, int numOfLines); | 16 | + //GraphItem(ifstream* pFin); |
17 | + GraphItem(const char* filename); | ||
18 | + virtual ~GraphItem(); | ||
19 | + | ||
20 | + //io | ||
21 | + void read_more(); | ||
17 | 22 | ||
18 | //overrides | 23 | //overrides |
19 | QRectF boundingRect() const override; | 24 | QRectF boundingRect() const override; |
... | @@ -23,6 +28,7 @@ public: | ... | @@ -23,6 +28,7 @@ public: |
23 | //methods | 28 | //methods |
24 | void path_highlighting(std::string start, std::string end); | 29 | void path_highlighting(std::string start, std::string end); |
25 | void reset_color(); | 30 | void reset_color(); |
31 | + void topK_highlight(); | ||
26 | 32 | ||
27 | protected: | 33 | protected: |
28 | void mousePressEvent(QGraphicsSceneMouseEvent *event) override; | 34 | void mousePressEvent(QGraphicsSceneMouseEvent *event) override; |
... | @@ -30,8 +36,12 @@ protected: | ... | @@ -30,8 +36,12 @@ protected: |
30 | void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; | 36 | void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; |
31 | 37 | ||
32 | private: | 38 | private: |
39 | + ifstream fin; | ||
33 | bm_type node_ids; | 40 | bm_type node_ids; |
41 | + vector<pair<string, string>> edges; | ||
34 | vector<simple_edge> edges_indexes; | 42 | vector<simple_edge> edges_indexes; |
43 | + int whole_node_cnt = 0; | ||
44 | + | ||
35 | Graph *graph = nullptr; | 45 | Graph *graph = nullptr; |
36 | QList<NodeItem *> nodeList; | 46 | QList<NodeItem *> nodeList; |
37 | QList<EdgeItem *> edgeList; | 47 | QList<EdgeItem *> edgeList; | ... | ... |
... | @@ -25,35 +25,56 @@ MainWindow::~MainWindow() | ... | @@ -25,35 +25,56 @@ MainWindow::~MainWindow() |
25 | 25 | ||
26 | } | 26 | } |
27 | 27 | ||
28 | -void MainWindow::print_graph(std::ifstream& fin) | 28 | +void MainWindow::print_graph(const char * filename) |
29 | { | 29 | { |
30 | - graphWidget->print_graph(fin); | 30 | + graphWidget->print_graph(filename); |
31 | } | 31 | } |
32 | 32 | ||
33 | +//void MainWindow::print_graph(std::ifstream *pFin) | ||
34 | +//{ | ||
35 | +// graphWidget->print_graph(pFin); | ||
36 | +//} | ||
37 | + | ||
33 | ////////////////////////////////////////////////////////////////// | 38 | ////////////////////////////////////////////////////////////////// |
34 | // private methods | 39 | // private methods |
35 | ////////////////////////////////////////////////////////////////// | 40 | ////////////////////////////////////////////////////////////////// |
36 | void MainWindow::createActions() | 41 | void MainWindow::createActions() |
37 | { | 42 | { |
38 | - testHighlightAct = new QAction(tr("&Highlight"), this); | 43 | + readMoreAct = new QAction(tr("Read more"), this); |
44 | + readMoreAct->setStatusTip(tr("read more lines from file")); | ||
45 | + connect(readMoreAct, &QAction::triggered, this, &MainWindow::read_more); | ||
46 | + | ||
47 | + testHighlightAct = new QAction(tr("Highlight"), this); | ||
39 | testHighlightAct->setStatusTip(tr("Highlighting node")); | 48 | testHighlightAct->setStatusTip(tr("Highlighting node")); |
40 | connect(testHighlightAct, &QAction::triggered, this, &MainWindow::test_highlighting); | 49 | connect(testHighlightAct, &QAction::triggered, this, &MainWindow::test_highlighting); |
41 | - | 50 | + topkAct = new QAction(tr("topK"), this); |
42 | - resetColorAct = new QAction(tr("&Reset colors"), this); | 51 | + topkAct->setStatusTip(tr("highlight who was top k papers")); |
52 | + connect(topkAct, &QAction::triggered, this, &MainWindow::topk); | ||
53 | + resetColorAct = new QAction(tr("Reset colors"), this); | ||
43 | resetColorAct->setStatusTip(tr("Reset all node's color")); | 54 | resetColorAct->setStatusTip(tr("Reset all node's color")); |
44 | connect(resetColorAct, &QAction::triggered, this, &MainWindow::reset_color); | 55 | connect(resetColorAct, &QAction::triggered, this, &MainWindow::reset_color); |
45 | } | 56 | } |
46 | 57 | ||
47 | void MainWindow::createMenus() | 58 | void MainWindow::createMenus() |
48 | { | 59 | { |
60 | + fileMenu = menuBar()->addMenu(tr("&File")); | ||
61 | + fileMenu->addAction(readMoreAct); | ||
62 | + | ||
49 | actionMenu = menuBar()->addMenu(tr("&Actions")); | 63 | actionMenu = menuBar()->addMenu(tr("&Actions")); |
50 | actionMenu->addAction(testHighlightAct); | 64 | actionMenu->addAction(testHighlightAct); |
65 | + actionMenu->addAction(topkAct); | ||
51 | actionMenu->addAction(resetColorAct); | 66 | actionMenu->addAction(resetColorAct); |
52 | } | 67 | } |
53 | 68 | ||
54 | ////////////////////////////////////////////////////////////////// | 69 | ////////////////////////////////////////////////////////////////// |
55 | // slots | 70 | // slots |
56 | ////////////////////////////////////////////////////////////////// | 71 | ////////////////////////////////////////////////////////////////// |
72 | +void MainWindow::read_more() | ||
73 | +{ | ||
74 | + qDebug("* MainWindow::read_more"); | ||
75 | + graphWidget->read_more(); | ||
76 | +} | ||
77 | + | ||
57 | void MainWindow::test_highlighting() | 78 | void MainWindow::test_highlighting() |
58 | { | 79 | { |
59 | /*QMessageBox::information(this, "test", | 80 | /*QMessageBox::information(this, "test", |
... | @@ -62,7 +83,12 @@ void MainWindow::test_highlighting() | ... | @@ -62,7 +83,12 @@ void MainWindow::test_highlighting() |
62 | //graphWidget->update(); | 83 | //graphWidget->update(); |
63 | } | 84 | } |
64 | 85 | ||
86 | +void MainWindow::topk() | ||
87 | +{ | ||
88 | + graphWidget->topk(); | ||
89 | +} | ||
90 | + | ||
65 | void MainWindow::reset_color() | 91 | void MainWindow::reset_color() |
66 | { | 92 | { |
67 | graphWidget->reset_color(); | 93 | graphWidget->reset_color(); |
68 | -} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
94 | +} | ... | ... |
... | @@ -12,14 +12,18 @@ public: | ... | @@ -12,14 +12,18 @@ public: |
12 | MainWindow(QWidget *parent = 0); | 12 | MainWindow(QWidget *parent = 0); |
13 | ~MainWindow(); | 13 | ~MainWindow(); |
14 | 14 | ||
15 | - void print_graph(std::ifstream& fin); | 15 | + //void print_graph(std::ifstream *pFin); |
16 | - /*void test_highlighting();*/ | 16 | + void print_graph(const char* filename); |
17 | + | ||
17 | 18 | ||
18 | private: | 19 | private: |
19 | PaperGraphWidget *graphWidget; | 20 | PaperGraphWidget *graphWidget; |
20 | 21 | ||
22 | + QMenu *fileMenu; | ||
23 | + QAction *readMoreAct; | ||
21 | QMenu *actionMenu; | 24 | QMenu *actionMenu; |
22 | QAction *testHighlightAct; | 25 | QAction *testHighlightAct; |
26 | + QAction *topkAct; | ||
23 | QAction *resetColorAct; | 27 | QAction *resetColorAct; |
24 | 28 | ||
25 | private: | 29 | private: |
... | @@ -27,7 +31,9 @@ private: | ... | @@ -27,7 +31,9 @@ private: |
27 | void createMenus(); | 31 | void createMenus(); |
28 | 32 | ||
29 | private slots: | 33 | private slots: |
34 | + void read_more(); | ||
30 | void test_highlighting(); | 35 | void test_highlighting(); |
36 | + void topk(); | ||
31 | void reset_color(); | 37 | void reset_color(); |
32 | }; | 38 | }; |
33 | 39 | ... | ... |
... | @@ -25,23 +25,47 @@ PaperGraphWidget::PaperGraphWidget(QWidget *parent) | ... | @@ -25,23 +25,47 @@ PaperGraphWidget::PaperGraphWidget(QWidget *parent) |
25 | setWindowTitle(tr("dblp paper graph visualization")); | 25 | setWindowTitle(tr("dblp paper graph visualization")); |
26 | } | 26 | } |
27 | 27 | ||
28 | -void PaperGraphWidget::print_graph(ifstream& fin) | 28 | +//void PaperGraphWidget::print_graph(ifstream* pFin) |
29 | +//{ | ||
30 | +// qDebug("* PaperGraphWidget::print_graph"); | ||
31 | +// //QGraphicsItem *graph_item = new GraphItem(fin); | ||
32 | +// if (graphItem) | ||
33 | +// throw std::exception("already have graph item"); | ||
34 | +// | ||
35 | +// graphItem = new GraphItem(pFin); | ||
36 | +// graphItem->setPos(0, 0); | ||
37 | +// scene->addItem(graphItem); | ||
38 | +//} | ||
39 | + | ||
40 | +void PaperGraphWidget::print_graph(const char * filename) | ||
29 | { | 41 | { |
30 | - //QGraphicsItem *graph_item = new GraphItem(fin); | ||
31 | if (graphItem) | 42 | if (graphItem) |
32 | throw std::exception("already have graph item"); | 43 | throw std::exception("already have graph item"); |
33 | 44 | ||
34 | - graphItem = new GraphItem(fin, READ_LINE_UNIT); | 45 | + graphItem = new GraphItem(filename); |
35 | graphItem->setPos(0, 0); | 46 | graphItem->setPos(0, 0); |
36 | scene->addItem(graphItem); | 47 | scene->addItem(graphItem); |
37 | } | 48 | } |
38 | 49 | ||
50 | +void PaperGraphWidget::read_more() | ||
51 | +{ | ||
52 | + qDebug("* PaperGraphWidget::read_more"); | ||
53 | + graphItem->read_more(); | ||
54 | + scene->update(); | ||
55 | +} | ||
56 | + | ||
39 | void PaperGraphWidget::path_highlight() | 57 | void PaperGraphWidget::path_highlight() |
40 | { | 58 | { |
41 | graphItem->path_highlighting(std::string(""), std::string("")); | 59 | graphItem->path_highlighting(std::string(""), std::string("")); |
42 | scene->update(); | 60 | scene->update(); |
43 | } | 61 | } |
44 | 62 | ||
63 | +void PaperGraphWidget::topk() | ||
64 | +{ | ||
65 | + graphItem->topK_highlight(); | ||
66 | + scene->update(); | ||
67 | +} | ||
68 | + | ||
45 | void PaperGraphWidget::reset_color() | 69 | void PaperGraphWidget::reset_color() |
46 | { | 70 | { |
47 | graphItem->reset_color(); | 71 | graphItem->reset_color(); | ... | ... |
... | @@ -11,9 +11,13 @@ class PaperGraphWidget : public QWidget | ... | @@ -11,9 +11,13 @@ class PaperGraphWidget : public QWidget |
11 | 11 | ||
12 | public: | 12 | public: |
13 | PaperGraphWidget(QWidget *parent = 0); | 13 | PaperGraphWidget(QWidget *parent = 0); |
14 | - void print_graph(ifstream& fin); | 14 | + //void print_graph(ifstream* pFin); |
15 | + void print_graph(const char* filename); | ||
15 | 16 | ||
17 | +//main window slots | ||
18 | + void read_more(); | ||
16 | void path_highlight(); | 19 | void path_highlight(); |
20 | + void topk(); | ||
17 | void reset_color(); | 21 | void reset_color(); |
18 | 22 | ||
19 | private slots: | 23 | private slots: | ... | ... |
... | @@ -9,9 +9,9 @@ int main(int argc, char *argv[]) | ... | @@ -9,9 +9,9 @@ int main(int argc, char *argv[]) |
9 | MainWindow m; | 9 | MainWindow m; |
10 | 10 | ||
11 | try { | 11 | try { |
12 | - ifstream fin(PAPER_FILENAME); | 12 | + //ifstream fin(PAPER_FILENAME); |
13 | - m.print_graph(fin); | 13 | + m.print_graph(PAPER_FILENAME); |
14 | - fin.close(); | 14 | + //fin.close(); |
15 | } catch (const std::exception& e) { | 15 | } catch (const std::exception& e) { |
16 | qDebug() << "Error: " << e.what(); | 16 | qDebug() << "Error: " << e.what(); |
17 | return EXIT_FAILURE; | 17 | return EXIT_FAILURE; | ... | ... |
... | @@ -28,13 +28,20 @@ | ... | @@ -28,13 +28,20 @@ |
28 | #include <boost/graph/topology.hpp> | 28 | #include <boost/graph/topology.hpp> |
29 | #include <boost/regex.hpp> | 29 | #include <boost/regex.hpp> |
30 | 30 | ||
31 | +#include <cstdio> | ||
32 | +#include <cstdlib> | ||
33 | +#include <cstring> | ||
34 | + | ||
31 | #include <algorithm> | 35 | #include <algorithm> |
32 | #include <exception> | 36 | #include <exception> |
33 | #include <fstream> | 37 | #include <fstream> |
34 | #include <iostream> | 38 | #include <iostream> |
35 | #include <iterator> | 39 | #include <iterator> |
40 | +#include <limits> | ||
36 | #include <map> | 41 | #include <map> |
42 | +#include <queue> | ||
37 | #include <string> | 43 | #include <string> |
44 | +#include <utility> | ||
38 | #include <vector> | 45 | #include <vector> |
39 | 46 | ||
40 | using namespace boost; | 47 | using namespace boost; |
... | @@ -43,9 +50,11 @@ using namespace std; | ... | @@ -43,9 +50,11 @@ using namespace std; |
43 | /* enums */ | 50 | /* enums */ |
44 | enum vertex_position_t { vertex_position }; | 51 | enum vertex_position_t { vertex_position }; |
45 | enum vertex_type_t { vertex_type }; | 52 | enum vertex_type_t { vertex_type }; |
53 | +enum vertex_record_t { vertex_record }; | ||
46 | namespace boost { | 54 | namespace boost { |
47 | BOOST_INSTALL_PROPERTY(vertex, position); | 55 | BOOST_INSTALL_PROPERTY(vertex, position); |
48 | BOOST_INSTALL_PROPERTY(vertex, type); | 56 | BOOST_INSTALL_PROPERTY(vertex, type); |
57 | + BOOST_INSTALL_PROPERTY(vertex, record); | ||
49 | } | 58 | } |
50 | enum NODE_TYPE { | 59 | enum NODE_TYPE { |
51 | NODE_PAPER, | 60 | NODE_PAPER, |
... | @@ -64,7 +73,8 @@ typedef square_topology<>::point_type point; | ... | @@ -64,7 +73,8 @@ typedef square_topology<>::point_type point; |
64 | typedef boost::property<vertex_index_t, int, | 73 | typedef boost::property<vertex_index_t, int, |
65 | boost::property<vertex_name_t, std::string, | 74 | boost::property<vertex_name_t, std::string, |
66 | boost::property<vertex_position_t, point, | 75 | boost::property<vertex_position_t, point, |
67 | - boost::property<vertex_type_t, int>>> | 76 | + boost::property<vertex_type_t, int, |
77 | + boost::property<vertex_record_t, int>>>> | ||
68 | > VertexProperties; | 78 | > VertexProperties; |
69 | typedef boost::adjacency_list< | 79 | typedef boost::adjacency_list< |
70 | listS, //outEdgeList | 80 | listS, //outEdgeList |
... | @@ -77,6 +87,7 @@ typedef boost::adjacency_list< | ... | @@ -77,6 +87,7 @@ typedef boost::adjacency_list< |
77 | > Graph; | 87 | > Graph; |
78 | typedef typename graph_traits<Graph>::edge_iterator edge_iterator; | 88 | typedef typename graph_traits<Graph>::edge_iterator edge_iterator; |
79 | typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator; | 89 | typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator; |
90 | +//typedef boost::graph_traits<Graph>::adjacency_iterator adjacency_iterator; | ||
80 | typedef boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor; | 91 | typedef boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor; |
81 | typedef square_topology<> Topology; | 92 | typedef square_topology<> Topology; |
82 | typedef typename Topology::point_type Point; | 93 | typedef typename Topology::point_type Point; |
... | @@ -95,14 +106,98 @@ namespace { | ... | @@ -95,14 +106,98 @@ namespace { |
95 | const int NODE_SIZE = 4; | 106 | const int NODE_SIZE = 4; |
96 | const int LAYOUT_MODE = GRAPH_LAYOUT::RANDOM_LAYOUT; | 107 | const int LAYOUT_MODE = GRAPH_LAYOUT::RANDOM_LAYOUT; |
97 | const int SCREEN_SIZE = 1000; | 108 | const int SCREEN_SIZE = 1000; |
98 | - const int READ_LINE_UNIT = 100; //한 번에 몇 라인을 읽을지 | 109 | + const int READ_LINE_UNIT = 5; //한 번에 몇 라인을 읽을지 |
99 | 110 | ||
100 | /* topK */ | 111 | /* topK */ |
101 | - const int TOP_K = 10; //상위 몇 개 아이템에 대해 할 지 | 112 | + const int TOP_K = 10; //상위 몇 개 아이템에 대해 highlight 할 지 |
102 | 113 | ||
103 | } | 114 | } |
104 | 115 | ||
105 | - | 116 | +/* boost */ |
106 | namespace boost { | 117 | namespace boost { |
107 | const boost::regex paper_reg("(conf|journals).*"); | 118 | const boost::regex paper_reg("(conf|journals).*"); |
108 | -} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
119 | +} | ||
120 | + | ||
121 | +/* topK heap */ | ||
122 | +template <typename T> | ||
123 | +class TopKHeap { | ||
124 | +private: | ||
125 | + int k; //max size | ||
126 | + int size; //current size | ||
127 | + T *heap; | ||
128 | + | ||
129 | +private: | ||
130 | + void reHeapDown(int root) { | ||
131 | + //after pop | ||
132 | + int minIdx, left, right; | ||
133 | + | ||
134 | + left = root * 2 + 1; | ||
135 | + right = root * 2 + 2; | ||
136 | + | ||
137 | + if (left <= (size - 1)) { | ||
138 | + if (left == (size - 1)) | ||
139 | + minIdx = left; | ||
140 | + else { | ||
141 | + minIdx = ((heap[left] <= heap[right]) ? left : right); | ||
142 | + } | ||
143 | + | ||
144 | + if (heap[root] > heap[minIdx]) { | ||
145 | + swap(heap[root], heap[minIdx]); | ||
146 | + reHeapDown(minIdx); | ||
147 | + } | ||
148 | + } | ||
149 | + } | ||
150 | + void reHeapUp(int root, int bottom) { | ||
151 | + //bottom: 위로 올릴 노드 idx | ||
152 | + //after push | ||
153 | + if (root > bottom) { | ||
154 | + int parent = (bottom - 1) / 2; | ||
155 | + if (heap[parent] < heap[bottom]) { | ||
156 | + swap(heap[parent], heap[bottom]); | ||
157 | + reHeapUp(root, parent); | ||
158 | + } | ||
159 | + } | ||
160 | + } | ||
161 | + | ||
162 | +public: | ||
163 | + TopKHeap(int _k) : k(_k), size(0) { | ||
164 | + if (_k <= 0) abort(); | ||
165 | + heap = new T[_k]; | ||
166 | + memset(heap, 0, sizeof(heap)); | ||
167 | + } | ||
168 | + ~TopKHeap() { | ||
169 | + if (heap) delete[] heap; | ||
170 | + } | ||
171 | + | ||
172 | +public: | ||
173 | + void push(T elem) { | ||
174 | + if (size < k) { | ||
175 | + heap[size++] = elem; | ||
176 | + } | ||
177 | + else { | ||
178 | + if (elem < heap[0]) { | ||
179 | + //less than minimum | ||
180 | + } | ||
181 | + else { | ||
182 | + pop(); | ||
183 | + heap[size++] = elem; | ||
184 | + } | ||
185 | + } | ||
186 | + | ||
187 | + reHeapUp(0, size - 1); | ||
188 | + } | ||
189 | + T pop() { | ||
190 | + if (size <= 0) | ||
191 | + abort(); | ||
192 | + else if (size == 1) { | ||
193 | + T ret = heap[--size]; | ||
194 | + return ret; | ||
195 | + } | ||
196 | + else { | ||
197 | + T ret = heap[0]; | ||
198 | + heap[0] = heap[--size]; | ||
199 | + reHeapDown(0); | ||
200 | + return ret; | ||
201 | + } | ||
202 | + } | ||
203 | +}; | ||
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
-
Please register or login to post a comment