GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: tmp_project/PhoenixGraph/src/Graph_impl.h Lines: 210 217 96.8 %
Date: 2024-12-09 15:41:43 Branches: 186 228 81.6 %

Line Branch Exec Source
1
/***************************************
2
	Auteur : Pierre Aubert
3
	Mail : pierre.aubert@lapp.in2p3.fr
4
	Licence : CeCILL-C
5
****************************************/
6
7
#ifndef __GRAPH_H_IMPL__
8
#define __GRAPH_H_IMPL__
9
10
#include <stdlib.h>
11
#include <iostream>
12
13
#include "Graph.h"
14
15
///Default constructeur of Graph
16
template<typename T, typename UIdx>
17
5
Graph<T, UIdx>::Graph(){
18
5
	initialisationGraph();
19
5
}
20
21
///Copy constructor of Graph
22
/**	@param other : class to copy
23
*/
24
template<typename T, typename UIdx>
25
1
Graph<T, UIdx>::Graph(const Graph<T, UIdx> & other){
26
1
	copyGraph(other);
27
1
}
28
29
///Destructeur of Graph
30
template<typename T, typename UIdx>
31
12
Graph<T, UIdx>::~Graph(){
32
33
}
34
35
///Definition of equal operator of Graph
36
/**	@param other : class to copy
37
 * 	@return copied class
38
*/
39
template<typename T, typename UIdx>
40
Graph<T, UIdx> & Graph<T, UIdx>::operator = (const Graph<T, UIdx> & other){
41
	copyGraph(other);
42
	return *this;
43
}
44
45
///Save a png file of the graph
46
/**	@param fileNamePng : name of the png file
47
 * 	@return true on success, false otherwise
48
*/
49
template<typename T, typename UIdx>
50
9
bool Graph<T, UIdx>::savePng(const std::string & fileNamePng) const{
51
9
	if(fileNamePng == "") return false;
52
16
	std::string fileTxt("output.dot");
53
8
	if(!saveDot(fileTxt)){
54
		std::cerr << "Graph<T, UIdx>::savePng : can't create file '" << fileTxt << "'" << std::endl;
55
		return false;
56
	}
57

24
	std::string commande("dot -Tpng -o " + fileNamePng + " " + fileTxt + " && rm " + fileTxt);
58
8
	if(system(commande.c_str()) != 0){
59


1
		std::cerr << "Graph<T, UIdx>::savePng : can't create png file '" << fileNamePng << "'" << std::endl;
60
1
		return false;
61
	}
62
7
	return true;
63
}
64
65
///Save the Graph in a dot file
66
/**	@param fileName : name of the file to be created
67
*/
68
template<typename T, typename UIdx>
69
10
bool Graph<T, UIdx>::saveDot(const std::string & fileName) const{
70
10
	if(fileName == ""){return false;}
71
18
	std::ofstream fs;
72
9
	fs.open(fileName.c_str());
73
9
	if(!fs.is_open()){
74


1
		std::cerr << "Graph<T, UIdx>::saveDot : can't open file '" << fileName << "'" << std::endl;
75
1
		return false;
76
	}
77
8
	bool b(saveDot(fs));
78
8
	fs.close();
79
8
	return b;
80
}
81
82
///Save the Graph in a dot file
83
/**	@param[out] fs : file stream to be modified
84
*/
85
template<typename T, typename UIdx>
86
8
bool Graph<T, UIdx>::saveDot(std::ofstream & fs) const{
87
8
	fs << toDot();
88
8
	return true;
89
}
90
91
///Convert the graph to dot language
92
/**	@return dot
93
*/
94
template<typename T, typename UIdx>
95
8
std::string Graph<T, UIdx>::toDot() const{
96
8
	std::string body("");
97
8
	body += "digraph G{\n";
98
	//save the node definition
99
49
	for(typename std::map<UIdx, Node<T, UIdx> >::const_iterator it(p_mapNode.begin()); it != p_mapNode.end(); ++it){
100
41
		body += it->second.getDotDefinition();
101
	}
102
	//save the connections between nodes
103
49
	for(typename std::map<UIdx, Node<T, UIdx> >::const_iterator itNode(p_mapNode.begin()); itNode != p_mapNode.end(); ++itNode){
104
82
		const std::string & parentNodeName(itNode->second.getDotName());
105
41
		const std::list<UIdx> & listChild = itNode->second.getListChild();
106
78
		for(typename std::list<UIdx>::const_iterator it(listChild.begin()); it != listChild.end(); ++it){
107
37
			const Node<T, UIdx> * childNode = getNode(*it);
108
37
			if(childNode == NULL){continue;}
109
37
			const std::string & childNodeName(childNode->getDotName());
110

37
			body += "\t" + parentNodeName + " -> " + childNodeName + "[color=\"red\"];\n";
111
		}
112
	}
113
8
	body += "}\n\n";
114
8
	return body;
115
}
116
117
///Create a node and get its index
118
/**	@param data : data of the Node
119
 * 	@param name : name of the Node
120
 * 	@return index of the Node
121
*/
122
template<typename T, typename UIdx>
123
21
UIdx Graph<T, UIdx>::createNode(const T & data, const std::string & name){
124
21
	UIdx nodeIndex(p_mapNode.size());
125
21
	while(getNode(nodeIndex) != NULL){
126
		++nodeIndex;
127
	}
128
21
	Node<T, UIdx> node(data, name);
129
21
	node.setIndex(nodeIndex);
130
21
	p_mapNode[nodeIndex] = node;
131
42
	return nodeIndex;
132
}
133
134
///Create a node and get its pointer
135
/**	@param data : data of the Node
136
 * 	@param name : name of the Node
137
 * 	@return pointer of the Node
138
*/
139
template<typename T, typename UIdx>
140
Node<T, UIdx> * Graph<T, UIdx>::createNodePtr(const T & data, const std::string & name){
141
	UIdx node = createNode(data, name);
142
	return getNode(node);
143
}
144
145
///Create a node and get its index
146
/**	@param data : data of the Node
147
 * 	@param index : index of the Node
148
 * 	@param name : name of the Node
149
 * 	@return true if the node can be created, false if the index is already taken by an other Node
150
*/
151
template<typename T, typename UIdx>
152
5
bool Graph<T, UIdx>::createNode(const T & data, const UIdx & index, const std::string & name){
153

5
	if(getNode(index) != NULL){	//Check if the Node already exists
154
		return false;
155
	}
156
5
	Node<T, UIdx> node(data, name);
157
5
	node.setIndex(index);
158
5
	p_mapNode[index] = node;
159
5
	return true;
160
}
161
162
///Create a node and get its pointer
163
/**	@param data : data of the Node
164
 * 	@param index : index of the Node
165
 * 	@param name : name of the Node
166
 * 	@return pointer of the Node
167
*/
168
template<typename T, typename UIdx>
169
Node<T, UIdx> * Graph<T, UIdx>::createNodePtr(const T & data, const UIdx & index, const std::string & name){
170
	if(createNode(data, index, name)){
171
		return getNode(index);
172
	}else{
173
		return NULL;
174
	}
175
}
176
177
///Clear the isUpdated attriburte of the Node
178
template<typename T, typename UIdx>
179
2
void Graph<T, UIdx>::clearIsUpdated(){
180
12
	for(typename std::map<UIdx, Node<T, UIdx> >::iterator it(p_mapNode.begin()); it != p_mapNode.end(); ++it){
181
10
		it->second.setIsUpdated(false);
182
	}
183
2
}
184
185
///Clear the map of Node
186
template<typename T, typename UIdx>
187
void Graph<T, UIdx>::clearMapNode(){p_mapNode.clear();}
188
189
///Clear the list of first Node
190
template<typename T, typename UIdx>
191
1
void Graph<T, UIdx>::clearFirstNode(){p_listFirstNode.clear();}
192
193
///Clear the list of last Node
194
template<typename T, typename UIdx>
195
1
void Graph<T, UIdx>::clearLastNode(){p_listLastNode.clear();}
196
197
//Clear all Node
198
template<typename T, typename UIdx>
199
void Graph<T, UIdx>::clearAll(){
200
	clearFirstNode();
201
	clearLastNode();
202
	clearMapNode();
203
}
204
205
///Remove a Node from the Graph
206
/**	@param index : index of the Node to be removed
207
 * 	@param reconnectParentToChildren : true to reconnect parents of the node to be removed to its children
208
*/
209
template<typename T, typename UIdx>
210
2
void Graph<T, UIdx>::removeNode(UIdx index, bool reconnectParentToChildren){
211
2
	Node<T, UIdx> * indexNode = getNode(index);
212
2
	if(indexNode == NULL){return;}	//If the Node does not exist, we stop
213
	//Get the parents of the current Node
214
2
	std::list<UIdx> & listParent = indexNode->getListParent();
215
2
	if(listParent.size() != 0lu){
216
		//Tell them they do not have child anymore
217
4
		for(typename std::list<UIdx>::iterator it(listParent.begin()); it != listParent.end(); ++it){
218
2
			Node<T, UIdx> * parentNode = getNode(*it);
219
2
			if(parentNode == NULL){continue;}
220
2
			parentNode->removeChild(index);
221
		}
222
	}else{
223
		//Let's remove the current Node from first Node
224
		listindex_remove(p_listFirstNode, index);
225
	}
226
	//Get the children of the current Node
227
2
	std::list<UIdx> & listChild = indexNode->getListChild();
228
2
	if(listChild.size() != 0lu){
229
		//Tell them they do not have parent anymore
230
4
		for(typename std::list<UIdx>::iterator it(listChild.begin()); it != listChild.end(); ++it){
231
2
			Node<T, UIdx> * childNode = getNode(*it);
232
2
			if(childNode == NULL){continue;}
233
2
			childNode->removeParent(index);
234
		}
235
	}else{
236
		//Let's remove the current Node from last Node
237
		listindex_remove(p_listLastNode, index);
238
	}
239


2
	if(reconnectParentToChildren && listParent.size() != 0lu && listChild.size() != 0lu){
240
2
		for(typename std::list<UIdx>::iterator it(listParent.begin()); it != listParent.end(); ++it){
241
1
			connectNode(*it, listChild);
242
		}
243
	}
244
	//Now, let's remove the current Node
245
2
	p_mapNode.erase(index);
246
}
247
248
///Update the first and last Node of the Graph
249
template<typename T, typename UIdx>
250
1
void Graph<T, UIdx>::updateFirstLastNode(){
251
1
	clearFirstNode();
252
1
	clearLastNode();
253
6
	for(typename std::map<UIdx, Node<T, UIdx> >::iterator itNode(p_mapNode.begin()); itNode != p_mapNode.end(); ++itNode){
254
5
		if(itNode->second.isStart()){	//If the Node does not have any parent, it is a first Node
255
3
			p_listFirstNode.push_back(itNode->first);
256
		}
257
5
		if(itNode->second.isEnd()){	//If the Node does not have any child, it is a last Node
258
1
			p_listLastNode.push_back(itNode->first);
259
		}
260
	}
261
1
}
262
263
///Connect a parent to its child
264
/**	@param parent : index of the parent Node
265
 * 	@param child : index of the child Node
266
*/
267
template<typename T, typename UIdx>
268
24
void Graph<T, UIdx>::connectNode(UIdx parent, UIdx child){
269
24
	Node<T, UIdx> * parentNode = getNode(parent);
270
24
	if(parentNode == NULL){return;}
271
24
	Node<T, UIdx> * childNode = getNode(child);
272
24
	if(childNode == NULL){return;}
273
24
	parentNode->addChild(child);
274
24
	childNode->addParent(parent);
275
}
276
277
///Connect a parent to its children
278
/**	@param parent : index of the parent Node
279
 * 	@param listChildren : list of the children index
280
*/
281
template<typename T, typename UIdx>
282
1
void Graph<T, UIdx>::connectNode(UIdx parent, const std::list<UIdx> & listChildren){
283
1
	Node<T, UIdx> * parentNode = getNode(parent);
284
1
	if(parentNode == NULL){return;}
285
2
	for(typename std::list<UIdx>::const_iterator it(listChildren.begin()); it != listChildren.end(); ++it){
286
1
		UIdx child = *it;
287
1
		Node<T, UIdx> * childNode = getNode(child);
288
1
		if(childNode == NULL){continue;}
289
1
		parentNode->addChild(child);
290
1
		childNode->addParent(parent);
291
	}
292
}
293
294
///Connect a parent to its children
295
/**	@param parent : index of the parent Node
296
 * 	@param vecChildren : vector of the children index
297
*/
298
template<typename T, typename UIdx>
299
void Graph<T, UIdx>::connectNode(UIdx parent, const std::vector<UIdx> & vecChildren){
300
	Node<T, UIdx> * parentNode = getNode(parent);
301
	if(parentNode == NULL){return;}
302
	for(typename std::vector<UIdx>::const_iterator it(vecChildren.begin()); it != vecChildren.end(); ++it){
303
		UIdx child = *it;
304
		Node<T, UIdx> * childNode = getNode(child);
305
		if(childNode == NULL){continue;}
306
		parentNode->addChild(child);
307
		childNode->addParent(parent);
308
	}
309
}
310
311
///Get a Node by pointer
312
/**	@param index : index of the node to be used
313
 * 	@return pointer to this Node or NULL if the Node does not exist
314
*/
315
template<typename T, typename UIdx>
316
58
const Node<T, UIdx> * Graph<T, UIdx>::getNode(UIdx index) const{
317
58
	typename std::map<UIdx, Node<T, UIdx> >::const_iterator it(p_mapNode.find(index));
318
58
	if(it != p_mapNode.end()){
319
58
		return &(it->second);
320
	}else{
321
		return NULL;
322
	}
323
}
324
325
///Get a Node by pointer
326
/**	@param index : index of the node to be used
327
 * 	@return pointer to this Node or NULL if the Node does not exist
328
*/
329
template<typename T, typename UIdx>
330
100
Node<T, UIdx> * Graph<T, UIdx>::getNode(UIdx index){
331
100
	typename std::map<UIdx, Node<T, UIdx> >::iterator it(p_mapNode.find(index));
332
100
	if(it != p_mapNode.end()){
333
74
		return &(it->second);
334
	}else{
335
26
		return NULL;
336
	}
337
}
338
339
///Get the first node which is not udpated (getIsUpdated() == false)
340
/**	@return pointer to the first node which is not udpated or NULL if there is no
341
*/
342
template<typename T, typename UIdx>
343
const Node<T, UIdx> * Graph<T, UIdx>::getFirstNotUpdatedNode() const{
344
	for(typename std::map<UIdx, Node<T, UIdx> >::const_iterator itNode(p_mapNode.begin()); itNode != p_mapNode.end(); ++itNode){
345
		if(!itNode->second.getIsUpdated()){
346
			return &(itNode->second);
347
		}
348
	}
349
	return NULL;
350
}
351
352
///Get the first node which is not udpated (getIsUpdated() == false)
353
/**	@return pointer to the first node which is not udpated or NULL if there is no
354
*/
355
template<typename T, typename UIdx>
356
Node<T, UIdx> * Graph<T, UIdx>::getFirstNotUpdatedNode(){
357
	for(typename std::map<UIdx, Node<T, UIdx> >::iterator itNode(p_mapNode.begin()); itNode != p_mapNode.end(); ++itNode){
358
		if(!itNode->second.getIsUpdated()){
359
			return &(itNode->second);
360
		}
361
	}
362
	return NULL;
363
}
364
365
///Say if the node at index does exit
366
/**	@param index : index of the node to be searched
367
 * 	@return true if the Node does exist, false otheriwse
368
*/
369
template<typename T, typename UIdx>
370
bool Graph<T, UIdx>::isNodeExist(UIdx index) const{
371
	typename std::map<UIdx, Node<T, UIdx> >::iterator it(p_mapNode.find(index));
372
	return it != p_mapNode.end();
373
}
374
375
///Get the number of nodes inside the graph
376
/**	@return number of nodes inside the graph
377
*/
378
template<typename T, typename UIdx>
379
1
size_t Graph<T, UIdx>::size() const{
380
1
	return p_mapNode.size();
381
}
382
383
///Get the list of the first nodes (without parent)
384
/**	@return list of the first nodes (without parent)
385
*/
386
template<typename T, typename UIdx>
387
2
const std::list<UIdx> & Graph<T, UIdx>::getListFirstNode() const{
388
2
	return p_listFirstNode;
389
}
390
391
///Get the list of the last nodes (without child)
392
/**	@return list of the last nodes (without child)
393
*/
394
template<typename T, typename UIdx>
395
2
const std::list<UIdx> & Graph<T, UIdx>::getListLastNode() const{
396
2
	return p_listLastNode;
397
}
398
399
///Iterate from parents to chidren
400
/**	@param[out] listNode : list node which can be treated simultaneously
401
 * 	@return true if the returned list of nodes is not empty, false if the bottom of the Graph has been reached
402
*/
403
template<typename T, typename UIdx>
404
4
bool Graph<T, UIdx>::iterateChildren(std::list<UIdx> & listNode) const{
405
4
	if(listNode.size() == 0lu){
406
1
		listNode = getListFirstNode();
407
	}else{
408
6
		std::map<UIdx, bool> mapListChildren;
409
9
		for(typename std::list<UIdx>::iterator itNode(listNode.begin()); itNode != listNode.end(); ++itNode){
410
6
			const Node<T, UIdx> * node = getNode(*itNode);
411
6
			if(node != NULL){
412
6
				const std::list<UIdx> & listChildren = node->getListChild();
413
10
				for(typename std::list<UIdx>::const_iterator it(listChildren.begin()); it != listChildren.end(); ++it){
414
4
					mapListChildren[*it] = true;
415
				}
416
			}
417
		}
418
6
		std::list<UIdx> listNodeOut;
419
6
		for(typename std::map<UIdx, bool>::iterator it(mapListChildren.begin()); it != mapListChildren.end(); ++it){
420
3
			listNodeOut.push_back(it->first);
421
		}
422
3
		listNode = listNodeOut;
423
	}
424
4
	return listNode.size() != 0lu;
425
}
426
427
///Iterate from children to parents
428
/**	@param[out] listNode : list node which can be treated simultaneously
429
 * 	@return true if the returned list of nodes is not empty, false if the top of the Graph has been reached
430
*/
431
template<typename T, typename UIdx>
432
4
bool Graph<T, UIdx>::iterateParent(std::list<UIdx> & listNode) const{
433
4
	if(listNode.size() == 0lu){
434
1
		listNode = getListLastNode();
435
	}else{
436
6
		std::map<UIdx, bool> mapListParent;
437
8
		for(typename std::list<UIdx>::iterator itNode(listNode.begin()); itNode != listNode.end(); ++itNode){
438
5
			const Node<T, UIdx> * node = getNode(*itNode);
439
5
			if(node != NULL){
440
5
				const std::list<UIdx> & listParent = node->getListParent();
441
9
				for(typename std::list<UIdx>::const_iterator it(listParent.begin()); it != listParent.end(); ++it){
442
4
					mapListParent[*it] = true;
443
				}
444
			}
445
		}
446
6
		std::list<UIdx> listNodeOut;
447
7
		for(typename std::map<UIdx, bool>::iterator it(mapListParent.begin()); it != mapListParent.end(); ++it){
448
4
			listNodeOut.push_back(it->first);
449
		}
450
3
		listNode = listNodeOut;
451
	}
452
4
	return listNode.size() != 0lu;
453
}
454
455
///Check if the list of given nodes are all updated or not
456
/**	@param listNode : list of nodes to be checked
457
 * 	@return true fi all nodes are updated, false otherwise
458
*/
459
template<typename T, typename UIdx>
460
7
bool Graph<T, UIdx>::isListNodeUdpated(const std::list<UIdx> & listNode) const{
461
7
	bool b(true);
462

17
	for(typename std::list<UIdx>::const_iterator itNode(listNode.begin()); itNode != listNode.end() && b; ++itNode){
463
10
		const Node<T, UIdx> * node = getNode(*itNode);
464
10
		if(node != NULL){
465
10
			b &= node->getIsUpdated();
466
		}
467
	}
468
7
	return b;
469
}
470
471
///Iterate from parents to chidren (all node are iterated only once)
472
/**	@param[out] listNode : list node which can be treated simultaneously
473
 * 	@return true if the returned list of nodes is not empty, false if the bottom of the Graph has been reached
474
*/
475
template<typename T, typename UIdx>
476
3
bool Graph<T, UIdx>::iterateChildrenCheckUpdate(std::list<UIdx> & listNode){
477
3
	if(listNode.size() == 0lu){
478
1
		clearIsUpdated();
479
1
		listNode = getListFirstNode();
480
	}else{
481
4
		std::map<UIdx, bool> mapListChildren;
482
7
		for(typename std::list<UIdx>::iterator itNode(listNode.begin()); itNode != listNode.end(); ++itNode){
483
5
			Node<T, UIdx> * node = getNode(*itNode);
484
5
			if(node != NULL){
485
5
				node->setIsUpdated(true);	//This node has been iterated, so we do not want to pick it as a child
486
5
				std::list<UIdx> & listChildren = node->getListChild();
487
9
				for(typename std::list<UIdx>::iterator it(listChildren.begin()); it != listChildren.end(); ++it){
488
4
					Node<T, UIdx> * nodeChild = getNode(*it);
489
4
					if(nodeChild != NULL){
490
4
						if(!nodeChild->getIsUpdated()){
491
							//The child node is added only if its parents are updated
492
3
							if(isListNodeUdpated(nodeChild->getListParent())){
493
2
								mapListChildren[*it] = true;
494
2
								nodeChild->setIsUpdated(true);
495
							}
496
						}
497
					}
498
				}
499
			}
500
		}
501
4
		std::list<UIdx> listNodeOut;
502
4
		for(typename std::map<UIdx, bool>::iterator it(mapListChildren.begin()); it != mapListChildren.end(); ++it){
503
2
			listNodeOut.push_back(it->first);
504
		}
505
2
		listNode = listNodeOut;
506
	}
507
3
	return listNode.size() != 0lu;
508
}
509
510
///Iterate from children to parents (all node are iterated only once)
511
/**	@param[out] listNode : list node which can be treated simultaneously
512
 * 	@return true if the returned list of nodes is not empty, false if the top of the Graph has been reached
513
*/
514
template<typename T, typename UIdx>
515
4
bool Graph<T, UIdx>::iterateParentCheckUpdate(std::list<UIdx> & listNode){
516
4
	if(listNode.size() == 0lu){
517
1
		clearIsUpdated();
518
1
		listNode = getListLastNode();
519
	}else{
520
6
		std::map<UIdx, bool> mapListParent;
521
8
		for(typename std::list<UIdx>::iterator itNode(listNode.begin()); itNode != listNode.end(); ++itNode){
522
5
			Node<T, UIdx> * node = getNode(*itNode);
523
5
			if(node != NULL){
524
5
				node->setIsUpdated(true);	//This node has been iterated, so we do not want to pick it as a parent
525
5
				std::list<UIdx> & listParent = node->getListParent();
526
9
				for(typename std::list<UIdx>::iterator it(listParent.begin()); it != listParent.end(); ++it){
527
4
					Node<T, UIdx> * nodeParent = getNode(*it);
528
4
					if(nodeParent != NULL){
529
4
						if(!nodeParent->getIsUpdated()){
530
							//The parent node is added only if its children are updated
531
4
							if(isListNodeUdpated(nodeParent->getListChild())){
532
4
								mapListParent[*it] = true;
533
4
								nodeParent->setIsUpdated(true);
534
							}
535
						}
536
					}
537
				}
538
			}
539
		}
540
6
		std::list<UIdx> listNodeOut;
541
7
		for(typename std::map<UIdx, bool>::iterator it(mapListParent.begin()); it != mapListParent.end(); ++it){
542
4
			listNodeOut.push_back(it->first);
543
		}
544
3
		listNode = listNodeOut;
545
	}
546
4
	return listNode.size() != 0lu;
547
}
548
549
///Copy function of Graph
550
/**	@param other : class to copy
551
*/
552
template<typename T, typename UIdx>
553
1
void Graph<T, UIdx>::copyGraph(const Graph<T, UIdx> & other){
554
1
	p_mapNode = other.p_mapNode;
555
1
	p_listFirstNode = other.p_listFirstNode;
556
1
	p_listLastNode = other.p_listLastNode;
557
1
}
558
559
///Initialisation function of the class Graph
560
template<typename T, typename UIdx>
561
5
void Graph<T, UIdx>::initialisationGraph(){
562
563
5
}
564
565
566
567
568
569
#endif
570
571
572