utils.cpp 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454
  1. /**
  2. * @file tests/boost_graph/partitioning/utils.cpp
  3. * @author The PARADEVS Development Team
  4. * See the AUTHORS or Authors.txt file
  5. */
  6. /*
  7. * PARADEVS - the multimodeling and simulation environment
  8. * This file is a part of the PARADEVS environment
  9. *
  10. * Copyright (C) 2013 ULCO http://www.univ-litoral.fr
  11. *
  12. * This program is free software: you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License as published by
  14. * the Free Software Foundation, either version 3 of the License, or
  15. * (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  24. */
  25. #include <tests/boost_graph/partitioning/utils.hpp>
  26. #include <algorithm>
  27. #include <iostream>
  28. namespace paradevs { namespace tests { namespace boost_graph {
  29. UnorientedGraph::vertex_iterator vertexIt, vertexEnd;
  30. UnorientedGraph::adjacency_iterator neighbourIt, neighbourEnd;
  31. OrientedGraph::vertex_iterator vertexIto, vertexEndo;
  32. OrientedGraph::adjacency_iterator neighbourIto, neighbourEndo;
  33. struct myclass
  34. {
  35. bool operator() (Entiers *i, Entiers *j)
  36. { return i->at(0) < j->at(0); }
  37. } myobject;
  38. struct myclass2
  39. {
  40. bool operator() (Entiers *i, Entiers *j, UnorientedGraph *g)
  41. { return Calcul_poids(i,g) < Calcul_poids(j,g); }
  42. } mon_tri;
  43. /**
  44. * Fonction de verification de la connexité d'un graphe
  45. * @param *g : adresse d'un graphe de type boost graphe undirected
  46. * @param Partition : vecteur contenant des vecteurs d'entiers [tableau contenant les parties de la partition]
  47. * @param part : vecteur d'entier (une partie de la partition)
  48. * @return un booleen
  49. */
  50. bool Est_connexe(UnorientedGraph *g, EntiersEntiers Partition, Entiers &part)
  51. {
  52. /*
  53. * Copie du graphe contenu par l'adresse *g
  54. */
  55. UnorientedGraph copie_g;
  56. copie_g = *g;
  57. /*
  58. * Modification du graphe copié afin de générer des sous graphes liés aux différentes parties
  59. */
  60. for (uint i=0; i<Partition.size()-1;i++)
  61. {
  62. for (uint j=1+i; j<Partition.size();j++)
  63. {
  64. for (uint k=0; k<Partition.at(i)->size();k++)
  65. {
  66. for (uint y=0; y<Partition.at(j)->size();y++)
  67. {
  68. remove_edge(Partition.at(i)->at(k),Partition.at(j)->at(y),copie_g); //suppression de certains arcs
  69. }
  70. }
  71. }
  72. }
  73. /*
  74. * Objectif : déterminer s'il existe un chemin reliant tous les noeuds d'une même partie
  75. * Méthode : partir d'un sommet de départ tiré aléatoirement dans la partie "part" et parcourir l'ensemble de ces voisins.
  76. * Si le voisin recontré n'est pas contenu dans le vecteur "sommets" il est ajouté. Le processus est répété pour chaque
  77. * nouveau sommet ajouté au vecteur.
  78. * Résultat : si le nombre de sommets contenu dans le vecteur "part" est égale au nombre de sommets du vecteur "sommets"
  79. * alors le graphe est connexe
  80. */
  81. int val;
  82. Entiers sommets;
  83. if(part.size()==1)
  84. val = 0;
  85. else
  86. val=rand_fini(0,part.size()-1); //tirage aléatoire d'un sommets
  87. int vertex = part.at(val);
  88. sommets.push_back(vertex); //ajout du sommets à la lsite des sommets parcouru
  89. /*
  90. * Recherche de voisins n'appartenant pas à la liste des sommets parcourus
  91. */
  92. for(uint i = 0;i<sommets.size();i++){
  93. tie(neighbourIt, neighbourEnd) = adjacent_vertices(sommets.at(i),copie_g);
  94. for (; neighbourIt != neighbourEnd; ++neighbourIt){
  95. if(In_tab(sommets,*neighbourIt)!=1)
  96. sommets.push_back(*neighbourIt);
  97. }
  98. }
  99. /*
  100. * Retour de la réponse vrai ou faux
  101. */
  102. if(part.size()!=sommets.size())
  103. return false;
  104. else
  105. return true;
  106. }
  107. /**
  108. * Fonction de projection
  109. * @param Partition : vecteur contenant des vecteurs d'entiers [tableau contenant les parties de la partition]
  110. * @param lit : itérateur sur une liste contenant une vecteur de vecteur d'entier
  111. * @return
  112. */
  113. /*
  114. * Objectif : obtenir la correspondance entre les sommets d'un graphe Gn et celui de Gn-1
  115. * Méthode : modification des sommets contenus dans "Partition" à l'aide de la liste de correspondance *lit
  116. */
  117. void projection(EntiersEntiers &Partition,ListEntiersEntiers::iterator lit)
  118. {
  119. /*
  120. * Création d'un nouveau vecteur contenant les adresses d'autres vecteur d'entiers.
  121. * Celui-ci est conçu pour recevoir les sommets contenus dans la liste de correspondance,
  122. * correspondant à la projection des sommets du graphe Gn à celui de Gn-1
  123. */
  124. EntiersEntiers new_partition;
  125. for(uint i = 0; i< Partition.size() ; i++)
  126. {
  127. Entiers *new_part = new Entiers();
  128. for(uint j = 0 ; j<Partition.at(i)->size() ; j++)
  129. {
  130. for(uint k = 0; k<((*lit)->at(Partition.at(i)->at(j)))->size();k++){
  131. new_part->push_back((*lit)->at(Partition.at(i)->at(j))->at(k));
  132. }
  133. }
  134. new_partition.push_back(new_part);
  135. }
  136. /*
  137. * Désalocation mémoire des pointeurs que contient "Partition"
  138. */
  139. for(EntiersEntiers::iterator it = Partition.begin(); it != Partition.end(); it++)
  140. {
  141. delete *it;
  142. *it = NULL;
  143. }
  144. Partition = new_partition; // copie de new_partition dans Partition
  145. for(uint i =0; i<Partition.size(); i++) {
  146. // permet de trier chaque sous vecteur de "Partition"
  147. std::sort(Partition[i]->begin(),Partition[i]->end());
  148. }
  149. new_partition.clear();
  150. }
  151. /**
  152. * Fonction qui calcul le poids d'une partie
  153. * @param * part : adresse d'un vecteur d'entier, ici une partie de la partition
  154. * @param *g : adresse d'un graphe de type boost graphe undirected
  155. * @return un type double contenant le poids associé à la partie
  156. */
  157. double Calcul_poids(Entiers *partie, UnorientedGraph *g)
  158. {
  159. double poids=0; // initialisation du poids à 0
  160. /*
  161. * Pour chaque sommet de la partie concerné on ajoute son poids au poids total
  162. */
  163. for(uint j = 0; j<partie->size();j++){
  164. poids+=(*g)[partie->at(j)]._weight;
  165. }
  166. return poids;
  167. }
  168. /**
  169. * Fonction d'affinage suivant un critère de poids
  170. * @param *g : adresse d'un graphe de type boost graphe undirected
  171. * @param Partition : vecteur contenant des vecteurs d'entiers [tableau contenant les parties de la partition]
  172. * @return modification de la partition
  173. */
  174. void Affinage_equilibrage_charge(UnorientedGraph *g, EntiersEntiers &Partition)
  175. {
  176. /*
  177. * Calcule de la somme des poids du graphe et le poids moyen à atteindre
  178. */
  179. double poids_moyen = 0.;
  180. for(uint i = 0; i < num_vertices(*g); i++) {
  181. poids_moyen += (*g)[i]._weight;
  182. }
  183. // détermination du poids moyen à atteindre pour chaque partie
  184. poids_moyen /= Partition.size();
  185. std::vector < double > poids_parties;
  186. /*
  187. * Calcul du poids de chaque partie de la partition
  188. */
  189. for (uint i = 0; i < Partition.size(); i++) {
  190. double tmp = Calcul_poids(Partition.at(i),g);
  191. poids_parties.push_back(tmp);
  192. }
  193. std::clog << "Poids initial des parties : " << std::endl;
  194. for (uint i = 0; i < poids_parties.size(); i++){
  195. std::cout << poids_parties.at(i) << " ";
  196. }
  197. std::cout << "\n" << std::endl;
  198. /*
  199. * Le critère d'amélioration consiste à faire tendre vers 0 la somme
  200. * des écarts entre le poids des parties et le poids moyen
  201. * le "critere" est la somme pour chaque partie de la différence
  202. * en valeurs absolues du poids
  203. * d'une partie moins le poids moyen divisé par le nombre de parties
  204. */
  205. double critere = 0.;
  206. for (uint i = 0; i < poids_parties.size(); i++){
  207. critere += abs(poids_parties.at(i) - poids_moyen);
  208. }
  209. critere /= Partition.size();
  210. // on conserve le poids maximum
  211. double p_max = *max_element(poids_parties.begin(), poids_parties.end());
  212. std::cout << "Valeurs du criètre de départ : " << critere << std::endl;
  213. // création d'un second critère légérement plsu faible que le premier
  214. double best_critere = critere - 1e-7;
  215. uint nbr_passage = 1; // initialisation du nombre de passages à 1
  216. /*
  217. * Tant que le critère n'est pas amélioré etque le nombre de
  218. * passage est inférieur au nombre de parties on réalise
  219. * des modifications sur la partition
  220. */
  221. while (best_critere < critere or nbr_passage < Partition.size()) {
  222. critere = best_critere; //critere devient best_critere
  223. // recherche la partie associé au poids maximum
  224. int cpt = recherche_val_double(poids_parties,p_max);
  225. bool decision = false; //initialisatio d'un booleen a false
  226. int nbr_pass_interne = 0;
  227. /*
  228. * tirage aléatoire des sommets de la partie de poids maximum
  229. */
  230. Entiers random_orders(Partition.at(cpt)->size());
  231. for (uint i=0 ; i<Partition.at(cpt)->size() ; i++)
  232. random_orders.at(i)=Partition.at(cpt)->at(i);
  233. for (uint j=0 ; j<Partition.at(cpt)->size()-1 ; j++) {
  234. int rand_pos = (rand() % Partition.at(cpt)->size()-j)+j;
  235. int tmp = random_orders[j];
  236. random_orders[j] = random_orders[rand_pos];
  237. random_orders[rand_pos] = tmp;
  238. }
  239. /*
  240. * Si le nombre de sommets d'une partie excéde les 400, on tire au hasar 400 sommets sans remise
  241. * et on effectue les modifications (ceci permet d'eviter une explosion des temps de calcul)
  242. */
  243. int size;
  244. if(Partition.at(cpt)->size()>400)
  245. size = 400;
  246. else
  247. size = Partition.at(cpt)->size();
  248. /*
  249. * Seconde boucle Tant que sur les sommets d'une partie.
  250. * Tant que le critere booleen est vrai et que le nombre de passe interne est inférieur au seuil size faire
  251. */
  252. while(decision!=true && nbr_pass_interne < size){
  253. int vertex = random_orders.at(nbr_pass_interne); //tirage d'un sommets dans la parite de poids maximum
  254. Entiers community = Neigh_community(g,Partition,vertex,cpt); // recherche des communautés voisines à ce sommet (s'il est au bord)
  255. if(community.size()!=0) // s'il existe au moins une communauté voisine
  256. {
  257. std::vector<double> new_poids_parties; // initialisation d'un nouveau vecteur contenant des doubles
  258. std::vector<double> tmp_critere; // initialisation d'un nouveau vecteur contenant des doubles
  259. /*
  260. * Pour chacune des parties (communauté) voisine au sommet vertexs faire
  261. */
  262. for(uint k = 0; k < community.size();k++)
  263. {
  264. new_poids_parties = poids_parties; //copie du tableau de poids des parties dans new_poids_parties
  265. /*
  266. * Modification des poids des parties :
  267. * on ajoute le poids du sommets à la partie voisine
  268. * et on soustrait son poids à sa partie d'origine
  269. */
  270. new_poids_parties.at(community.at(k))+=(*g)[vertex]._weight;
  271. new_poids_parties.at(cpt)-=(*g)[vertex]._weight;
  272. /*
  273. * Calcul ldu nouveau critère associé à cette modification
  274. */
  275. double new_critere = 0.;
  276. for(uint i = 0; i<poids_parties.size();i++){
  277. new_critere += abs(new_poids_parties.at(i)-poids_moyen);
  278. }
  279. new_critere/=Partition.size();
  280. tmp_critere.push_back(new_critere); // enregistrement du résutlat dans le tableau tmp_critere
  281. }
  282. double val_min = *min_element(tmp_critere.begin(),tmp_critere.end()); // enregistrement de la valeur minimale du tableau tmp_critere
  283. int val = recherche_val_double(tmp_critere,val_min); // recherche de la communauté correspondant à cette valeur
  284. /*
  285. * Si la valeur associé est plus petite et que la partie selectionné n'est pas vérouillée faire
  286. */
  287. if(val_min<critere && poids_parties.at(val)!=-1)
  288. {
  289. /*
  290. * On change le sommet vertex de partie, il est déplacé vers la partie
  291. * qui permet la meilleure amélioration du critère
  292. */
  293. Partition.at(community.at(val))->push_back(vertex);
  294. suprim_val(*Partition.at(cpt),vertex);
  295. std::sort(Partition.at(community.at(val))->begin(), Partition.at(community.at(val))->end());
  296. /*
  297. * Vérification de la sauvegarde de la connexsité,
  298. * si se n'est pas le cas retour à l'état précédent
  299. */
  300. if(Est_connexe(g,Partition,*Partition.at(cpt))!=1)
  301. {
  302. suprim_val(*Partition.at(community.at(val)),vertex);
  303. Partition.at(cpt)->push_back(vertex);
  304. std::sort(Partition.at(cpt)->begin(), Partition.at(cpt)->end());
  305. std::cout<<" C'EST MORT RETOUR EN ARRIERE ! "<<std::endl;
  306. }
  307. else
  308. {
  309. poids_parties = new_poids_parties;
  310. decision = true;
  311. std::cout<<" Modification reussi ! "<<std::endl;
  312. }
  313. }
  314. }
  315. nbr_pass_interne++;
  316. }
  317. /*
  318. * Si aucune modification n'a été réalisé pour cett partie de poids maximum
  319. */
  320. if(decision==false)
  321. {
  322. nbr_passage++; // augmentation du nombre de passage
  323. poids_parties.at(cpt)=-1; // vérrouillage de la partie
  324. std::clog<<"nouveau passag ! "<<std::endl;
  325. }
  326. else
  327. {
  328. best_critere = 0.;
  329. for(uint i = 0; i<poids_parties.size();i++){
  330. best_critere += abs(poids_parties.at(i)-poids_moyen);
  331. }
  332. best_critere/=Partition.size();
  333. nbr_passage = 0;
  334. }
  335. std::clog<<"Poids des parties modifié : "<<std::endl;
  336. for(uint i = 0; i<poids_parties.size(); i++){
  337. std::cout<<poids_parties.at(i)<<" ";
  338. }
  339. std::cout<<"\n"<<std::endl;
  340. p_max = *max_element(poids_parties.begin(),poids_parties.end());
  341. std::cout<<"Valeurs du criètre : "<<critere<<std::endl;
  342. std::cout<<"Valeurs du best_criètre : "<<best_critere<<std::endl;
  343. std::cout<<"Nombre de passage : "<<nbr_passage<<std::endl;
  344. std::cout<<"\n"<<std::endl;
  345. }
  346. }
  347. Entiers Neigh_community(UnorientedGraph *g, EntiersEntiers &Partition, int vertex, int comm_in)
  348. {
  349. Entiers community;
  350. int comm;
  351. tie(neighbourIt, neighbourEnd) = adjacent_vertices(vertex,*g);
  352. for (; neighbourIt != neighbourEnd; ++neighbourIt){
  353. comm = In_community_dichotomie(Partition,*neighbourIt);
  354. if(In_tab(community,comm)!=1 && comm!=comm_in)
  355. community.push_back(comm);
  356. }
  357. return community;
  358. }
  359. void Affinage_recherche_locale(UnorientedGraph *g, EntiersEntiers &Partition, double &cut, std::string name)
  360. {
  361. Entiers random_orders(num_vertices(*g)); //gestion d'un tableau contenant tout les sommets et ranger de façon aléatoire
  362. for (uint i=0 ; i<num_vertices(*g) ; i++)
  363. random_orders.at(i)=i;
  364. for (uint j=0 ; j<num_vertices(*g)-1 ; j++) {
  365. int rand_pos = (rand() % num_vertices(*g)-j)+j;
  366. int tmp = random_orders[j];
  367. random_orders[j] = random_orders[rand_pos];
  368. random_orders[rand_pos] = tmp;
  369. }
  370. uint size = random_orders.size();
  371. if(num_vertices(*g)>500)
  372. size=500;
  373. std::vector<std::vector<double> > tabe_cut;
  374. //std::cout<<"Passage : "<<Partition.size()<<std::endl;
  375. for(uint k = 0; k < Partition.size();k++){
  376. std::vector<double> tmp;
  377. double vol = 0.;
  378. double cut = Modif_Cut_one_cluster(*Partition.at(k), *g, vol);
  379. tmp.push_back(cut);
  380. tmp.push_back(vol);
  381. tabe_cut.push_back(tmp);
  382. }
  383. for(uint i = 0; i < size; i++){
  384. if(random_orders.at(i)!=-1){
  385. int vertex = random_orders.at(i);
  386. //std::cout<<vertex<<std::endl;
  387. int comm = In_community_dichotomie(Partition, vertex);
  388. Entiers community = Neigh_community(g,Partition,vertex,comm);
  389. std::vector<double> tmp_cut;
  390. if(community.size()!=0 && Partition.at(comm)->size()!=1){
  391. tmp_cut = modif_cut_tmp(g,Partition,tabe_cut,vertex,comm,community,cut,name);
  392. /*for(uint z = 0; z<tmp_cut.size(); z++){
  393. std::cout<<tmp_cut.at(z)<<std::endl;
  394. }
  395. std::cout<<"\n"<<std::endl;*/
  396. double cut_min = *min_element(tmp_cut.begin(),tmp_cut.end());
  397. std::cout<<"cout de coupe minimum de la liste : "<<cut_min<<std::endl;
  398. if(cut_min<cut){
  399. std::clog<<"Changement ! "<<std::endl;
  400. int tmp = recherche_val_double(tmp_cut,cut_min);
  401. cut=cut_min;
  402. Partition.at(community.at(tmp))->push_back(vertex);
  403. suprim_val(*Partition.at(comm),vertex);
  404. std::sort(Partition.at(community.at(tmp))->begin(), Partition.at(community.at(tmp))->end());
  405. tabe_cut.clear();
  406. for(uint k = 0; k < Partition.size();k++){
  407. std::vector<double> tmp;
  408. double vol = 0.;
  409. double cut = Modif_Cut_one_cluster(*Partition.at(k), *g, vol);
  410. tmp.push_back(cut);
  411. tmp.push_back(vol);
  412. tabe_cut.push_back(tmp);
  413. }
  414. }
  415. }
  416. //Modif_fonction_Gain_Cut(Partition,g,community,vertex,cut,name);
  417. /*if(Est_connexe(g,Partition,*Partition.at(comm))!=1)
  418. {
  419. suprim_val(*Partition.at(community.at(tmp)),vertex);
  420. Partition.at(comm)->push_back(vertex);
  421. std::sort(*Partition.at(comm));
  422. std::cout<<" C'EST MORT RETOUR EN ARRIERE ! "<<std::endl;
  423. }*/
  424. }
  425. }
  426. }
  427. double Modif_Cut_one_cluster(Entiers &cluster, UnorientedGraph &g, double &vol)
  428. {
  429. edge_t e1;
  430. bool found;
  431. double cpt=0.;
  432. for(uint i=0;i<cluster.size();i++){
  433. tie(neighbourIt, neighbourEnd) = adjacent_vertices(cluster.at(i), g);
  434. for (; neighbourIt != neighbourEnd; ++neighbourIt){
  435. tie(e1,found)=edge(vertex(cluster[i],g),vertex(*neighbourIt,g),g);
  436. if(In_tab(cluster,*neighbourIt)!=1){
  437. cpt+=g[e1]._weight;
  438. }
  439. }
  440. }
  441. vol = Cluster_Degree(g,cluster);
  442. return cpt/2.;
  443. }
  444. std::vector<double> modif_cut_tmp(UnorientedGraph *g, EntiersEntiers &Partition, std::vector<std::vector<double> > tabe_cut, int vertexs, int comm_in, Entiers community, double cut,std::string name){
  445. edge_t e1;
  446. bool found;
  447. //std::cout<<"le sommet tiré est : "<<vertexs<<std::endl;
  448. if(name!="norm")
  449. {
  450. std::vector<double> modif_cut(community.size());
  451. double cpt_comm_in;
  452. double cpt_comm_out;
  453. for(uint i =0; i<community.size(); i++){
  454. double tmp_cut = cut;
  455. cpt_comm_in=0;
  456. cpt_comm_out=0;
  457. tie(neighbourIt, neighbourEnd) = adjacent_vertices(vertexs,*g);
  458. for (; neighbourIt != neighbourEnd; ++neighbourIt){
  459. tie(e1,found)=edge(vertex(vertexs,*g),vertex(*neighbourIt,*g),*g);
  460. if(In_tab(*Partition.at(comm_in),*neighbourIt)==1)
  461. cpt_comm_in+=(*g)[e1]._weight;
  462. else if(In_tab(*Partition.at(community.at(i)),*neighbourIt)==1)
  463. cpt_comm_out+=(*g)[e1]._weight;
  464. }
  465. tmp_cut+=cpt_comm_in;
  466. tmp_cut-=cpt_comm_out;
  467. modif_cut.at(i)=tmp_cut;
  468. }
  469. return modif_cut;
  470. }
  471. else{
  472. std::vector<double> modif_cut(community.size());
  473. double cpt_comm_in;
  474. double cpt_comm_out;
  475. double tmp_cut;
  476. for(uint i =0; i<community.size(); i++){
  477. std::vector<std::vector<double> > tab_cut = tabe_cut;
  478. tmp_cut =0.;
  479. cpt_comm_in=0.;
  480. cpt_comm_out=0.;
  481. tie(neighbourIt, neighbourEnd) = adjacent_vertices(vertexs,*g);
  482. for (; neighbourIt != neighbourEnd; ++neighbourIt){
  483. tie(e1,found)=edge(vertex(vertexs,*g),vertex(*neighbourIt,*g),*g);
  484. if(In_tab(*Partition.at(comm_in),*neighbourIt)==1)
  485. cpt_comm_in+=(*g)[e1]._weight;
  486. else if(In_tab(*Partition.at(community.at(i)),*neighbourIt)==1)
  487. cpt_comm_out+=(*g)[e1]._weight;
  488. }
  489. cpt_comm_in/=2.;
  490. cpt_comm_out/=2.;
  491. tab_cut.at(comm_in).at(0)+=cpt_comm_in;
  492. tab_cut.at(comm_in).at(0)-=cpt_comm_out;
  493. tab_cut.at(comm_in).at(1)-= Degree(*g ,vertexs);
  494. tab_cut.at(community.at(i)).at(0)+=cpt_comm_in;
  495. tab_cut.at(community.at(i)).at(0)-=cpt_comm_out;
  496. tab_cut.at(community.at(i)).at(1)+= Degree(*g ,vertexs);
  497. for(uint j = 0; j < tab_cut.size();j++){
  498. tmp_cut+=((tab_cut.at(j).at(0))/(tab_cut.at(j).at(1)));
  499. }
  500. modif_cut.at(i)=tmp_cut;
  501. }
  502. return modif_cut;
  503. }
  504. }
  505. void Modif_fonction_Gain_Cut(EntiersEntiers &Partition,UnorientedGraph *g, Entiers &community, int val, double &cut,std::string name)
  506. {
  507. /*std::cout<<"Nombre de communauté voisine : "<<community.size()<<std::endl;
  508. std::cout<<"\n"<<std::endl;*/
  509. for(uint i = 0; i<community.size();i++){
  510. EntiersEntiers new_partition;
  511. for(uint k = 0; k < Partition.size();k++){
  512. Entiers * tmp = new Entiers();
  513. for(uint j = 0;j<Partition.at(k)->size();j++){
  514. tmp->push_back(Partition.at(k)->at(j));
  515. }
  516. new_partition.push_back(tmp);
  517. }
  518. /*std::cout<<"Avant Modification partition"<<std::endl;
  519. std::cout<<"************"<<std::endl;
  520. for(uint t = 0; t< new_partition.size() ; t++)
  521. {
  522. for(uint j = 0 ; j<new_partition.at(t)->size() ; j++)
  523. {
  524. std::cout<<new_partition.at(t)->at(j)<<std::endl;
  525. }
  526. std::cout<<"\n"<<std::endl;
  527. }
  528. std::cout<<"************"<<std::endl;*/
  529. new_partition.at(community.at(i))->push_back(val);
  530. suprim_val(*new_partition.at(In_community_dichotomie(Partition,val)),val);
  531. std::sort(new_partition.at(community.at(i))->begin(),
  532. new_partition.at(community.at(i))->end());
  533. /*std::cout<<"Modification partition"<<std::endl;
  534. std::cout<<"************"<<std::endl;
  535. for(uint t= 0; t< new_partition.size() ; t++)
  536. {
  537. for(uint j = 0 ; j<new_partition.at(t)->size() ; j++)
  538. {
  539. std::cout<<new_partition.at(t)->at(j)<<std::endl;
  540. }
  541. std::cout<<"\n"<<std::endl;
  542. }
  543. std::cout<<"************"<<std::endl;*/
  544. double coupe = Cut_cluster(new_partition,*g,name);
  545. //std::cout<<"cout de coupe : "<<coupe<<std::endl;
  546. if(coupe<cut)
  547. {
  548. for(EntiersEntiers::iterator it = Partition.begin(); it != Partition.end(); it++)
  549. {
  550. delete *it;
  551. *it = NULL;
  552. }
  553. Partition = new_partition;
  554. cut = coupe;
  555. }
  556. else
  557. {
  558. for(EntiersEntiers::iterator it = new_partition.begin(); it != new_partition.end(); it++)
  559. {
  560. delete *it;
  561. *it = NULL;
  562. }
  563. }
  564. }
  565. }
  566. void contraction_HEM(UnorientedGraph *g, Base_Graph &baseg, ListEntiersEntiers &liste_corr){
  567. UnorientedGraph *gtmp = new UnorientedGraph();
  568. *gtmp=*g;
  569. Entiers Random_list_vertices; // Initialisation du tableau de sommets rangés aléatoirements
  570. EntiersEntiers *tableau_de_correspondance = new EntiersEntiers();
  571. edge_t e1,e2; // Iterateurs sur les arcs
  572. bool found;
  573. uint nbr_vertex = num_vertices(*gtmp);
  574. Entiers sommets_a_detruire; // Initialisation d'un tableau pret à recevoir les "sommets à détruire"
  575. /*
  576. * Création d'un vecteur contenant l'ensemble des sommets du graphe. Ces sommets sont rangés
  577. * aléatoirement afin de simuler un tirage aléatoire
  578. */
  579. for (uint i=0 ; i<nbr_vertex ; i++)
  580. Random_list_vertices.push_back(i);
  581. for (uint j=0 ; j<nbr_vertex-1 ; j++) {
  582. int rand_pos = rand()%(nbr_vertex-j)+j;
  583. int tmp = Random_list_vertices[j];
  584. Random_list_vertices[j] = Random_list_vertices[rand_pos];
  585. Random_list_vertices[rand_pos] = tmp;
  586. }
  587. /*
  588. * Pour chaque sommet non verrouiller faire ....
  589. */
  590. for(uint i=0; i<nbr_vertex; i++){
  591. int vertexs = Random_list_vertices[i];
  592. if(vertexs!=-1){
  593. Entiers liste_voisin = Liste_adjacence(*gtmp,vertexs,Random_list_vertices); // Recherche des sommets adjacents au sommets tiré
  594. if(liste_voisin.size()!=0){
  595. /*
  596. * S'il en existe au mois un sommet adjacent au sommet tiré qui n'est pas verrouillé, on
  597. * choisi celui dont l'arc les reliants est le plus fort. Dans le cas où les arcs ont tous
  598. * le même poids, on selectionne le sommet d'identifiant le plus petit
  599. */
  600. double poids_a = 0.;
  601. int best_vertexs = -1;
  602. for(uint j=0;j<liste_voisin.size();j++){
  603. tie(e1,found)=edge(vertex(vertexs,*gtmp),vertex(liste_voisin[j],*gtmp),*gtmp);
  604. if((*gtmp)[e1]._weight>poids_a){
  605. best_vertexs = liste_voisin[j];
  606. poids_a = (*gtmp)[e1]._weight;
  607. }
  608. }
  609. Entiers * couple = new Entiers(); // Initialisation du vecteur contenant le couple de sommet fusionné
  610. int vertex_delete = std::max(vertexs, best_vertexs); // Sommet d'indentifiant le plus grand (qui sera détruit)
  611. //std::cout<<"sommet détruit : "<<vertex_delete<<std::endl;
  612. int vertex_save = std::min(vertexs,best_vertexs); // Sommet d'identifiant le plus petit (qui sera conservé)
  613. //std::cout<<"sommet sauvé : "<<vertex_save<<std::endl;
  614. sommets_a_detruire.push_back(vertex_delete); // On ajoute le sommet détruit au tableau des sommets à détruire
  615. /*
  616. * On ajoute au tableau "couple" le couple de sommet à fusionner
  617. */
  618. couple->push_back(vertex_save);
  619. couple->push_back(vertex_delete);
  620. tableau_de_correspondance->push_back(couple); // Ajout du "couple" à la liste de correspondance
  621. remove_edge(vertex_save,vertex_delete,*gtmp); // Suppression de l'arc reliant le couple de sommets
  622. Entiers neigh_vertex_save; // Initialisation du vecteur contenant les somemts adjacents au "sommet sauvegardé"
  623. Entiers neigh_vertex_delete; // Initialisation du vecteur contenant les somemts adjacents au "sommet à détruire"
  624. tie(neighbourIt, neighbourEnd) = adjacent_vertices(vertex_save,*gtmp);
  625. /*
  626. * Remplissage de ces deux tableaux à l'aide de la fonction adjacent_vertices de boost graph
  627. * [La création de ces tableaux est nécéssaire du fait que certains arcs sont détruit au cours
  628. * du processus]
  629. */
  630. for (; neighbourIt != neighbourEnd; ++neighbourIt){
  631. neigh_vertex_save.push_back(*neighbourIt);
  632. }
  633. tie(neighbourIt, neighbourEnd) = adjacent_vertices(vertex_delete,*gtmp);
  634. for (; neighbourIt != neighbourEnd; ++neighbourIt){
  635. neigh_vertex_delete.push_back(*neighbourIt);
  636. }
  637. /*
  638. * Recherche de sommets communs entre le "sommet sauvegardé" et le "sommet à détruire"
  639. * S'il existe un tel sommet "v" alors on ajoute le poids de l'arcs (vertex_delet,v)
  640. * à celui de l'arcs (vertex_save,v) et on détruit l'arcs reliant "v" au "sommet à détruire"
  641. */
  642. for(uint j=0;j<neigh_vertex_delete.size();j++){
  643. if(In_tab(neigh_vertex_save,neigh_vertex_delete[j])==1){
  644. tie(e2,found)=edge(vertex(vertex_save,*gtmp),vertex(neigh_vertex_delete[j],*gtmp),*gtmp);
  645. tie(e1,found)=edge(vertex(vertex_delete,*gtmp),vertex(neigh_vertex_delete[j],*gtmp),*gtmp);
  646. (*gtmp)[e2]._weight+=(*gtmp)[e1]._weight;
  647. remove_edge(vertex_delete,neigh_vertex_delete[j],*gtmp);
  648. }
  649. else
  650. {
  651. tie(e1,found)=edge(vertex(vertex_delete,*gtmp),vertex(neigh_vertex_delete[j],*gtmp),*gtmp);
  652. add_edge(vertex_save,neigh_vertex_delete[j],EdgeProperties((*gtmp)[e1]._weight),*gtmp);
  653. remove_edge(vertex_delete,neigh_vertex_delete[j],*gtmp);
  654. }
  655. }
  656. (*gtmp)[vertex_save]._weight+=(*gtmp)[vertex_delete]._weight; // ajout du poids du sommet détruit au sommet conservé
  657. /*
  658. * Vérouillage du "sommet sauvegardé" et du "sommet à détruire"
  659. */
  660. Random_list_vertices[i]=-1;
  661. Random_list_vertices[recherche_val(Random_list_vertices,best_vertexs)]=-1;
  662. }
  663. else{
  664. /*
  665. * Et si le sommet tiré ne possède pas de sommet adjacent non verrouillé
  666. * alors on l'ajoute à la liste de correspondance des sommets et on
  667. * le verrouille
  668. */
  669. Entiers *couple = new Entiers();
  670. couple->push_back(Random_list_vertices.at(i));
  671. tableau_de_correspondance->push_back(couple);
  672. Random_list_vertices[i]=-1;
  673. }
  674. }
  675. }
  676. std::sort(sommets_a_detruire.begin(), sommets_a_detruire.end()); // Trie dans l'ordre croissant des "sommets à détruire"
  677. //std::cout<<"\n"<<std::endl;
  678. /*
  679. * Suppression des sommets de la liste "sommets à détruire". Cette suppression est
  680. * effectuée dans l'ordre décroissant afin à maintenir à jour la renumérotation
  681. * des sommets
  682. */
  683. for(int j=(sommets_a_detruire.size()-1);j>-1;j--){
  684. //std::cout<<"Noeuds a supprimer : "<<sommets_a_detruire.at(j)<<std::endl;
  685. remove_vertex(sommets_a_detruire[j],*gtmp);
  686. }
  687. /**std::clog<<"Affichage avant tri "<<std::endl;
  688. for(uint k = 0;k<tableau_de_correspondance->size();k++){
  689. for(uint v = 0; v<tableau_de_correspondance->at(k)->size();v++){
  690. std::cout<<tableau_de_correspondance->at(k)->at(v)<<" ";
  691. }
  692. std::cout<<"\n"<<std::endl;
  693. }*/
  694. std::sort(tableau_de_correspondance->begin(),tableau_de_correspondance->end(),myobject); // Trie dans l'ordre croissant des couples de sommets de la liste de correspondance
  695. std::clog<<"Tableau de correspondance "<<std::endl;
  696. for(uint k = 0;k<tableau_de_correspondance->size();k++){
  697. for(uint v = 0; v<tableau_de_correspondance->at(k)->size();v++){
  698. std::cout<<tableau_de_correspondance->at(k)->at(v)<<" ";
  699. }
  700. std::cout<<"\n"<<std::endl;
  701. }
  702. liste_corr.push_back(tableau_de_correspondance);
  703. std::cout<<"\n"<<std::endl;
  704. baseg.push_back(gtmp); // Ajout du graphe modifié à la "base des graphe"
  705. }
  706. void contraction_Random_Maching(UnorientedGraph *g, Base_Graph &baseg, ListEntiersEntiers &liste_corr){
  707. UnorientedGraph *gtmp = new UnorientedGraph();
  708. *gtmp=*g;
  709. Entiers Random_list_vertices; // Initialisation du tableau de sommets rangés aléatoirements
  710. EntiersEntiers *tableau_de_correspondance = new EntiersEntiers();
  711. edge_t e1,e2; // Iterateurs sur les arcs
  712. bool found;
  713. uint nbr_vertex = num_vertices(*gtmp);
  714. Entiers sommets_a_detruire; // Initialisation d'un tableau pret à recevoir les "sommets à détruire"
  715. /*
  716. * Création d'un vecteur contenant l'ensemble des sommets du graphe. Ces sommets sont rangés
  717. * aléatoirement afin de simuler un tirage aléatoire
  718. */
  719. for (uint i=0 ; i<nbr_vertex ; i++)
  720. Random_list_vertices.push_back(i);
  721. for (uint j=0 ; j<nbr_vertex-1 ; j++) {
  722. int rand_pos = rand()%(nbr_vertex-j)+j;
  723. int tmp = Random_list_vertices[j];
  724. Random_list_vertices[j] = Random_list_vertices[rand_pos];
  725. Random_list_vertices[rand_pos] = tmp;
  726. }
  727. /*
  728. * Pour chaque sommet non verrouiller faire ....
  729. */
  730. for(uint i=0; i<nbr_vertex; i++){
  731. int vertexs = Random_list_vertices[i];
  732. if(vertexs!=-1){
  733. Entiers liste_voisin = Liste_adjacence(*gtmp,vertexs,Random_list_vertices); // Recherche des sommets adjacents au sommets tiré
  734. if(liste_voisin.size()!=0){
  735. /*
  736. * S'il en existe au mois un sommet adjacent au sommet tiré qui n'est pas verrouillé, on
  737. * choisi celui dont l'arc les reliants est le plus fort. Dans le cas où les arcs ont tous
  738. * le même poids, on selectionne le sommet d'identifiant le plus petit
  739. */
  740. int tmp;
  741. if(liste_voisin.size()==1)
  742. tmp = 0;
  743. else
  744. tmp = rand_fini(0,liste_voisin.size()-1);
  745. int best_vertexs = liste_voisin.at(tmp);
  746. Entiers * couple = new Entiers(); // Initialisation du vecteur contenant le couple de sommet fusionné
  747. int vertex_delete = std::max(vertexs, best_vertexs); // Sommet d'indentifiant le plus grand (qui sera détruit)
  748. //std::cout<<"sommet détruit : "<<vertex_delete<<std::endl;
  749. int vertex_save = std::min(vertexs,best_vertexs); // Sommet d'identifiant le plus petit (qui sera conservé)
  750. //std::cout<<"sommet sauvé : "<<vertex_save<<std::endl;
  751. sommets_a_detruire.push_back(vertex_delete); // On ajoute le sommet détruit au tableau des sommets à détruire
  752. /*
  753. * On ajoute au tableau "couple" le couple de sommet à fusionner
  754. */
  755. couple->push_back(vertex_save);
  756. couple->push_back(vertex_delete);
  757. tableau_de_correspondance->push_back(couple); // Ajout du "couple" à la liste de correspondance
  758. remove_edge(vertex_save,vertex_delete,*gtmp); // Suppression de l'arc reliant le couple de sommets
  759. Entiers neigh_vertex_save; // Initialisation du vecteur contenant les somemts adjacents au "sommet sauvegardé"
  760. Entiers neigh_vertex_delete; // Initialisation du vecteur contenant les somemts adjacents au "sommet à détruire"
  761. tie(neighbourIt, neighbourEnd) = adjacent_vertices(vertex_save,*gtmp);
  762. /*
  763. * Remplissage de ces deux tableaux à l'aide de la fonction adjacent_vertices de boost graph
  764. * [La création de ces tableaux est nécéssaire du fait que certains arcs sont détruit au cours
  765. * du processus]
  766. */
  767. for (; neighbourIt != neighbourEnd; ++neighbourIt){
  768. neigh_vertex_save.push_back(*neighbourIt);
  769. }
  770. tie(neighbourIt, neighbourEnd) = adjacent_vertices(vertex_delete,*gtmp);
  771. for (; neighbourIt != neighbourEnd; ++neighbourIt){
  772. neigh_vertex_delete.push_back(*neighbourIt);
  773. }
  774. /*
  775. * Recherche de sommets communs entre le "sommet sauvegardé" et le "sommet à détruire"
  776. * S'il existe un tel sommet "v" alors on ajoute le poids de l'arcs (vertex_delet,v)
  777. * à celui de l'arcs (vertex_save,v) et on détruit l'arcs reliant "v" au "sommet à détruire"
  778. */
  779. for(uint j=0;j<neigh_vertex_delete.size();j++){
  780. if(In_tab(neigh_vertex_save,neigh_vertex_delete[j])==1){
  781. tie(e2,found)=edge(vertex(vertex_save,*gtmp),vertex(neigh_vertex_delete[j],*gtmp),*gtmp);
  782. tie(e1,found)=edge(vertex(vertex_delete,*gtmp),vertex(neigh_vertex_delete[j],*gtmp),*gtmp);
  783. (*gtmp)[e2]._weight+=(*gtmp)[e1]._weight;
  784. remove_edge(vertex_delete,neigh_vertex_delete[j],*gtmp);
  785. }
  786. else
  787. {
  788. tie(e1,found)=edge(vertex(vertex_delete,*gtmp),vertex(neigh_vertex_delete[j],*gtmp),*gtmp);
  789. add_edge(vertex_save,neigh_vertex_delete[j],EdgeProperties((*gtmp)[e1]._weight),*gtmp);
  790. remove_edge(vertex_delete,neigh_vertex_delete[j],*gtmp);
  791. }
  792. }
  793. (*gtmp)[vertex_save]._weight+=(*gtmp)[vertex_delete]._weight; // ajout du poids du sommet détruit au sommet conservé
  794. /*
  795. * Vérouillage du "sommet sauvegardé" et du "sommet à détruire"
  796. */
  797. Random_list_vertices[i]=-1;
  798. Random_list_vertices[recherche_val(Random_list_vertices,best_vertexs)]=-1;
  799. }
  800. else{
  801. /*
  802. * Et si le sommet tiré ne possède pas de sommet adjacent non verrouillé
  803. * alors on l'ajoute à la liste de correspondance des sommets et on
  804. * le verrouille
  805. */
  806. Entiers *couple = new Entiers();
  807. couple->push_back(Random_list_vertices.at(i));
  808. tableau_de_correspondance->push_back(couple);
  809. Random_list_vertices[i]=-1;
  810. }
  811. }
  812. }
  813. std::sort(sommets_a_detruire.begin(), sommets_a_detruire.end()); // Trie dans l'ordre croissant des "sommets à détruire"
  814. //std::cout<<"\n"<<std::endl;
  815. /*
  816. * Suppression des sommets de la liste "sommets à détruire". Cette suppression est
  817. * effectuée dans l'ordre décroissant afin à maintenir à jour la renumérotation
  818. * des sommets
  819. */
  820. for(int j=(sommets_a_detruire.size()-1);j>-1;j--){
  821. //std::cout<<"Noeuds a supprimer : "<<sommets_a_detruire.at(j)<<std::endl;
  822. remove_vertex(sommets_a_detruire[j],*gtmp);
  823. }
  824. /**std::clog<<"Affichage avant tri "<<std::endl;
  825. for(uint k = 0;k<tableau_de_correspondance->size();k++){
  826. for(uint v = 0; v<tableau_de_correspondance->at(k)->size();v++){
  827. std::cout<<tableau_de_correspondance->at(k)->at(v)<<" ";
  828. }
  829. std::cout<<"\n"<<std::endl;
  830. }*/
  831. std::sort(tableau_de_correspondance->begin(),tableau_de_correspondance->end(),myobject); // Trie dans l'ordre croissant des couples de sommets de la liste de correspondance
  832. std::clog<<"Tableau de correspondance "<<std::endl;
  833. for(uint k = 0;k<tableau_de_correspondance->size();k++){
  834. for(uint v = 0; v<tableau_de_correspondance->at(k)->size();v++){
  835. std::cout<<tableau_de_correspondance->at(k)->at(v)<<" ";
  836. }
  837. std::cout<<"\n"<<std::endl;
  838. }
  839. liste_corr.push_back(tableau_de_correspondance);
  840. std::cout<<"\n"<<std::endl;
  841. baseg.push_back(gtmp); // Ajout du graphe modifié à la "base des graphe"
  842. }
  843. Entiers Liste_adjacence(UnorientedGraph &g, int vertexs,const Entiers &random_vertices){ // a revoir !!!!
  844. Entiers liste_voisin;
  845. tie(neighbourIt, neighbourEnd) = adjacent_vertices(vertexs, g);
  846. for (; neighbourIt != neighbourEnd; ++neighbourIt){
  847. if(In_tab(random_vertices,*neighbourIt)==1)
  848. liste_voisin.push_back(*neighbourIt);
  849. }
  850. return liste_voisin;
  851. }
  852. int rand_fini(int a, int b){
  853. return rand()%(b-a)+a;
  854. }
  855. /**
  856. * Fonction de recherche d'une valeur dans un tableau.
  857. * @param tab
  858. * @param val
  859. * @return
  860. */
  861. int recherche_val2(const std::vector<float> &tab,float val){
  862. int cpt=0;
  863. while(tab[cpt]!=val)
  864. cpt++;
  865. return cpt;
  866. }
  867. int recherche_val_double(const std::vector<double> &tab,double val){
  868. int cpt=0;
  869. while(tab[cpt]!=val)
  870. cpt++;
  871. return cpt;
  872. }
  873. int recherche_val(const Entiers &tab,int val){
  874. int cpt=0;
  875. while(tab[cpt]!=val)
  876. cpt++;
  877. return cpt;
  878. }
  879. /**
  880. * @param tab
  881. * @param i
  882. * @return
  883. */
  884. int dichotomie(const Entiers &tab, int i){
  885. /* déclaration des variables locales à la fonction */
  886. int id; //indice de début
  887. int ifin; //indice de fin
  888. int im; //indice de "milieu"
  889. /* initialisation de ces variables avant la boucle de recherche */
  890. id = 0; //intervalle de recherche compris entre 0...
  891. ifin = tab.size(); //...et nbVal
  892. /* boucle de recherche */
  893. while ((ifin - id) > 1){
  894. im = (id + ifin)/2; //on détermine l'indice de milieu
  895. if(tab[im] > i) ifin = im; //si la valeur qui est à la case "im" est supérieure à la valeur recherchée, l'indice de fin "ifin" << devient >> l'indice de milieu, ainsi l'intervalle de recherche est restreint lors du prochain tour de boucle
  896. else id = im; //sinon l'indice de début << devient >> l'indice de milieu et l'intervalle est de la même façon restreint
  897. }
  898. /* test conditionnant la valeur que la fonction va renvoyer */
  899. if (tab[id] == i) return id; //si on a trouvé la bonne valeur, on retourne l'indice
  900. else return -1; //sinon on retourne -1
  901. }
  902. /**
  903. * Fonction permettant de supprimer une case d'un tableau.
  904. * @param tab une référence sur un tableau d'entiers
  905. * @param i un indice dans tab
  906. */
  907. void suprim_val(Entiers &tab,int i) {
  908. tab.erase(tab.begin() + dichotomie(tab,i));
  909. }
  910. /**
  911. * Détermine si une valeur se trouve dans un tableau.
  912. * @param tab une référence sur un tableau d'entiers
  913. * @param val une valeur
  914. * @return true si la valeur a été trouvée, false sinon
  915. */
  916. bool In_tab(const Entiers &tab, int val)
  917. {
  918. for (uint i=0; i < tab.size(); i++)
  919. if(tab[i]==val)
  920. return true;
  921. return false;
  922. }
  923. bool In_tab_dichotomie(const Entiers &tab, int val)
  924. {
  925. if(dichotomie(tab,val)!=-1)
  926. return true;
  927. else
  928. return false;
  929. }
  930. void Liste_Voisin(const Entiers &P,Entiers &tab,const UnorientedGraph &g)
  931. {
  932. tie(neighbourIt, neighbourEnd) = adjacent_vertices(P.at(P.size()-1), g);
  933. for (; neighbourIt != neighbourEnd; ++neighbourIt)
  934. {
  935. if((In_tab(tab,*neighbourIt) == false ) && (In_tab(P,*neighbourIt) == false ))
  936. tab.push_back(*neighbourIt);
  937. }
  938. }
  939. int Cout_coupe(Entiers P,int val, UnorientedGraph &g)
  940. {
  941. int cpt=0;
  942. P.push_back(val);
  943. for(uint i=0;i<P.size();i++){
  944. tie(neighbourIt, neighbourEnd) = adjacent_vertices(P[i], g);
  945. for (; neighbourIt != neighbourEnd; ++neighbourIt){
  946. if(In_tab(P,*neighbourIt)!=1){
  947. cpt++;
  948. }
  949. }
  950. }
  951. return cpt;
  952. }
  953. double Cut_one_cluster(const Entiers &cluster, UnorientedGraph &g, std::string name)
  954. {
  955. if(name=="norm"){
  956. edge_t e1;
  957. bool found;
  958. double cpt=0.;
  959. for(uint i=0;i<cluster.size();i++){
  960. tie(neighbourIt, neighbourEnd) = adjacent_vertices(cluster[i], g);
  961. for (; neighbourIt != neighbourEnd; ++neighbourIt){
  962. tie(e1,found)=edge(vertex(cluster[i],g),vertex(*neighbourIt,g),g);
  963. if(In_tab(cluster,*neighbourIt)!=1){
  964. cpt+=g[e1]._weight;
  965. }
  966. }
  967. }
  968. double vol = Cluster_Degree(g,cluster);
  969. return (cpt/2.)/vol;
  970. }
  971. else{
  972. edge_t e1;
  973. bool found;
  974. double cpt=0.;
  975. for(uint i=0;i<cluster.size();i++){
  976. tie(neighbourIt, neighbourEnd) = adjacent_vertices(cluster.at(i), g);
  977. for (; neighbourIt != neighbourEnd; ++neighbourIt){
  978. tie(e1,found)=edge(vertex(cluster.at(i),g),vertex(*neighbourIt,g),g);
  979. if(In_tab(cluster,*neighbourIt)!=1){
  980. cpt+=g[e1]._weight;
  981. }
  982. }
  983. }
  984. return cpt/2.;
  985. }
  986. }
  987. double Cut_cluster(const EntiersEntiers &tab_cluster,UnorientedGraph &g,std::string name)
  988. {
  989. double cpt=0.;
  990. for(uint i=0;i<tab_cluster.size();i++){
  991. cpt+=Cut_one_cluster(*tab_cluster[i],g,name);
  992. }
  993. return cpt;
  994. }
  995. double Cout_coupe_pond(Entiers P, int val, UnorientedGraph &g)
  996. {
  997. edge_t e1;
  998. bool found;
  999. double cpt=0;
  1000. P.push_back(val);
  1001. for(uint i=0;i<P.size();i++){
  1002. tie(neighbourIt, neighbourEnd) = adjacent_vertices(P[i], g);
  1003. for (; neighbourIt != neighbourEnd; ++neighbourIt){
  1004. tie(e1,found)=edge(vertex(P[i],g),vertex(*neighbourIt,g),g);
  1005. if(In_tab(P,*neighbourIt)!=1){
  1006. cpt+=g[e1]._weight;
  1007. }
  1008. }
  1009. }
  1010. return cpt;
  1011. }
  1012. int In_community_dichotomie(const EntiersEntiers &part, int val)
  1013. {
  1014. for (uint i = 0; i < part.size() ; i++) {
  1015. if (In_tab_dichotomie(*part[i], val)) {
  1016. return i;
  1017. }
  1018. }
  1019. return -1;
  1020. }
  1021. double Degree(UnorientedGraph& g, int node)
  1022. {
  1023. edge_t e1;
  1024. bool found;
  1025. double val = 0.;
  1026. tie(neighbourIt, neighbourEnd) = adjacent_vertices(node, g);
  1027. for (; neighbourIt != neighbourEnd; ++neighbourIt) {
  1028. tie(e1, found) = edge(vertex(node, g), vertex(*neighbourIt, g), g);
  1029. val += g[e1]._weight;
  1030. }
  1031. return val;
  1032. }
  1033. double Cluster_Degree(UnorientedGraph &g , const Entiers &cluster)
  1034. {
  1035. double val = 0.;
  1036. for(uint i = 0; i < cluster.size(); i++){
  1037. val += Degree(g, cluster.at(i));
  1038. }
  1039. return val;
  1040. }
  1041. void List_edge_partie(Entiers *Partie, OrientedGraph *go, Edges &edge_partie,
  1042. OutputEdges &outputedgespartie){
  1043. edge_to e1;
  1044. //bool found;
  1045. for(uint i = 0; i < Partie->size(); i++) {
  1046. tie(neighbourIto, neighbourEndo) = adjacent_vertices(Partie->at(i),
  1047. *go);
  1048. for (; neighbourIto != neighbourEndo; ++neighbourIto) {
  1049. if(In_tab_dichotomie(*Partie,*neighbourIto)) {
  1050. Edge new_edge;
  1051. new_edge.first = Partie->at(i);
  1052. new_edge.second = *neighbourIto;
  1053. edge_partie.push_back(new_edge);
  1054. } else {
  1055. Edge new_edge;
  1056. new_edge.first = Partie->at(i);
  1057. new_edge.second = *neighbourIto;
  1058. outputedgespartie.push_back(new_edge);
  1059. }
  1060. }
  1061. }
  1062. }
  1063. void Global_Neigh_community(UnorientedGraph *g,
  1064. const EntiersEntiers &Partition,
  1065. Entiers *community, int vertex, int comm_in)
  1066. {
  1067. int comm;
  1068. tie(neighbourIt, neighbourEnd) = adjacent_vertices(vertex, *g);
  1069. for (; neighbourIt != neighbourEnd; ++neighbourIt){
  1070. comm = In_community_dichotomie(Partition, *neighbourIt);
  1071. if (In_tab(*community,comm) != 1 and comm != comm_in)
  1072. community->push_back(comm);
  1073. }
  1074. }
  1075. OrientedGraphs Graph_Partition(const EntiersEntiers& Partition,
  1076. OrientedGraph *go,
  1077. UnorientedGraph *g,
  1078. OutputEdgeList &outputedgelist,
  1079. InputEdgeList &inputedgelist,
  1080. Connections &connections)
  1081. {
  1082. OrientedGraphs graph_partie;
  1083. EntiersEntiers neigh_community;
  1084. for (uint i = 0; i < Partition.size();i++){
  1085. Edges edge_partie;
  1086. List_edge_partie(Partition.at(i),go,edge_partie,outputedgelist.at(i));
  1087. OrientedGraph graph;
  1088. std::vector<vertex_to> tab_vertex_to;
  1089. Entiers *community = new Entiers();
  1090. for (uint j = 0; j < Partition.at(i)->size(); j++) {
  1091. Global_Neigh_community(g, Partition, community,
  1092. Partition.at(i)->at(j),i);
  1093. vertex_to v = add_vertex(graph);
  1094. tab_vertex_to.push_back(v);
  1095. graph[v] = VertexProperties((*go)[Partition.at(i)->at(j)]._index,
  1096. (*go)[Partition.at(i)->at(j)]._weight,
  1097. (*go)[Partition.at(i)->at(j)]._type);
  1098. }
  1099. neigh_community.push_back(community);
  1100. for(uint k = 0; k < edge_partie.size(); k++) {
  1101. add_edge(tab_vertex_to.at(recherche_val(*Partition.at(i),
  1102. edge_partie.at(k).first)),
  1103. tab_vertex_to.at(recherche_val(*Partition.at(i),
  1104. edge_partie.at(k).second)),
  1105. graph);
  1106. }
  1107. graph_partie.push_back(graph);
  1108. }
  1109. for (uint i = 0; i < neigh_community.size(); i++) {
  1110. InputEdges inputedges;
  1111. for (uint j = 0; j < neigh_community.at(i)->size(); j++) {
  1112. for (uint k = 0;
  1113. k < outputedgelist.at(neigh_community.at(i)->at(j)).size();
  1114. k++) {
  1115. if (In_tab_dichotomie(
  1116. *Partition.at(i),
  1117. outputedgelist.at(
  1118. neigh_community.at(i)->at(j)).at(k).second))
  1119. inputedges.push_back(
  1120. outputedgelist.at(
  1121. neigh_community.at(i)->at(j)).at(k));
  1122. }
  1123. }
  1124. inputedgelist.push_back(inputedges);
  1125. }
  1126. for (uint i = 0; i < outputedgelist.size(); i++){
  1127. Connection connec;
  1128. for(uint j = 0; j < outputedgelist.at(i).size(); j++){
  1129. Port port1;
  1130. port1.first = i + 1;
  1131. port1.second = outputedgelist.at(i).at(j).first;
  1132. Port port2;
  1133. port2.first = In_community_dichotomie(
  1134. Partition,outputedgelist.at(i).at(j).second) + 1;
  1135. port2.second = outputedgelist.at(i).at(j).second;
  1136. connec.first = port1;
  1137. connec.second = port2;
  1138. connections.push_back(connec);
  1139. }
  1140. }
  1141. for (EntiersEntiers::iterator it = neigh_community.begin();
  1142. it != neigh_community.end(); it++) {
  1143. delete *it;
  1144. *it = NULL;
  1145. }
  1146. return graph_partie;
  1147. }
  1148. /*double In_modularity(UnorientedGraph &g , const Entiers &cluster){
  1149. property_map<UnorientedGraph,edge_weight_t>::type poids_arc=get(edge_weight_t(),g);
  1150. edge_t e1;
  1151. bool found;
  1152. int val=0;
  1153. for(uint i=0;i<cluster.size();i++){
  1154. tie(neighbourIt, neighbourEnd) = adjacent_vertices(cluster[i],g);
  1155. for (; neighbourIt != neighbourEnd; ++neighbourIt){
  1156. tie(e1,found)=edge(vertex(cluster[i],g),vertex(*neighbourIt,g),g);
  1157. if(In_tab(cluster,*neighbourIt)==1)
  1158. val+=get(poids_arc,e1);
  1159. }
  1160. }
  1161. return val/2.;
  1162. }*/
  1163. /**
  1164. *
  1165. * @param g
  1166. * @param cluster
  1167. * @return
  1168. */
  1169. /**
  1170. *
  1171. * @param g
  1172. * @param part
  1173. * @return
  1174. */
  1175. /*double Modularity(UnorientedGraph &g,const EntiersEntiers &part) {
  1176. double q = 0.;
  1177. int tmp=num_edges(g);
  1178. for(uint i=0;i<part.size();i++){
  1179. q+=In_modularity(g,*part[i])/tmp-(Cluster_Degree(g,*part[i])/(2*tmp))*(Cluster_Degree(g,*part[i])/(2*tmp));
  1180. }
  1181. return q;
  1182. }*/
  1183. /**
  1184. *
  1185. * @param part
  1186. * @param val
  1187. * @return
  1188. */
  1189. /**
  1190. * Fonction de calcul du gain de modularité de déplacement d'un sommet d'une communoté à une autre !!!!!
  1191. * ajoute le sommet à part[val] et on calcul la nouvelle modularité
  1192. * on prend la différence entre la modularité et la nouvouvelle !
  1193. * @param cur_mod
  1194. * @param val
  1195. * @param neight
  1196. * @param node_comm
  1197. * @param part
  1198. * @param g
  1199. */
  1200. /*double Modularity_gain(double cur_mod , int val , int neight , int node_comm , EntiersEntiers part , UnorientedGraph &g) {
  1201. double q;
  1202. part[neight]->push_back(val);
  1203. std::sort(*part[neight]);
  1204. q=Modularity(g,part);
  1205. return q-cur_mod;
  1206. }*/
  1207. /**
  1208. * Fonction de calcul du gain de modularité de déplacement d'un sommet d'une communoté à une autre !!!!!
  1209. * ajoute le sommet à part[val] et on calcul la nouvelle modularité
  1210. * on prend la différence entre la modularité et la nouvouvelle !
  1211. * @param cur_mod
  1212. * @param tmp_community
  1213. * @param neight
  1214. * @param node_comm
  1215. * @param part
  1216. * @param g
  1217. */
  1218. /*double Modularity_gain_phase_2(double cur_mod, Entiers tmp_community, int neight, int node_comm, EntiersEntiers part, UnorientedGraph &g) {
  1219. double q;
  1220. for (uint i=0;i<tmp_community.size();i++)
  1221. part[neight]->push_back(tmp_community[i]);
  1222. std::sort(*part[neight]);
  1223. q = Modularity(g,part);
  1224. return q - cur_mod;
  1225. }*/
  1226. /**
  1227. * Donne la liste des communautés voisines à celle contenant le sommet val.
  1228. * @param part
  1229. * @param val
  1230. * @param g
  1231. * @return
  1232. */
  1233. /*Entiers Neight_community(const EntiersEntiers &part, int val , UnorientedGraph &g){
  1234. Entiers Neight;
  1235. tie(neighbourIt, neighbourEnd) = adjacent_vertices(val, g);
  1236. for (; neighbourIt != neighbourEnd; ++neighbourIt){
  1237. int tmp=In_community(part,*neighbourIt);
  1238. if(In_tab(Neight,tmp)!=1 && In_tab(*part[In_community(part,val)],*neighbourIt)!=1)
  1239. Neight.push_back(tmp);
  1240. }
  1241. std::sort(Neight);
  1242. return Neight;
  1243. }*/
  1244. /**
  1245. *
  1246. * @param part
  1247. * @param community
  1248. * @param g
  1249. * @return
  1250. */
  1251. /*Entiers Part_Neight_community(const EntiersEntiers &part,int community, UnorientedGraph &g){
  1252. Entiers Neight;
  1253. for(uint i =0;i<part[community]->size();i++){
  1254. tie(neighbourIt, neighbourEnd) = adjacent_vertices(part[community]->at(i), g);
  1255. for (; neighbourIt != neighbourEnd; ++neighbourIt){
  1256. int tmp=In_community(part,*neighbourIt);
  1257. if(In_tab(Neight,tmp)!=1 && tmp!=community)
  1258. Neight.push_back(tmp);
  1259. }
  1260. }
  1261. std::sort(Neight);
  1262. return Neight;
  1263. }*/
  1264. } } } // namespace paradevs tests boost_graph