You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MissingNodes_Sparse2c.m 41KB

5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. function [ rand_score, purity, p_triads, missing_nodes_mapping, removed_nodes] = MissingNodes_Sparse2c( dataFilePath, dataFileName, affinityType, ...
  2. num_missing_nodes_arr, percentKnownPlaceholdersVec, dumpSmallFlag, dumpSmallDataPath, iter, missingNodes)
  3. %UNTITLED2 Summary of this function goes here
  4. % Detailed explanation goes here
  5. %[SUCCESS,MESSAGE,MESSAGEID] = mkdir('C:\\MissingNodes\\Code\\Results\\',dataFileName);
  6. global g_threshold;
  7. % addpath 'Spectral Clustering' % sigal 13.8.12
  8. % addpath 'mex'% sigal 13.8.12
  9. p_triads = [];
  10. %create a log file for this run
  11. %date_now = clock;
  12. %date_now = strcat(num2str(date_now(1)),'_',num2str(date_now(2)),'_', num2str(date_now(3)),'_', num2str(date_now(4)), num2str(date_now(5)),'_', num2str(date_now(6)));
  13. %diary(strcat('C:\missingnodes\Code\Log\log', date_now,'.log'));
  14. %affinity calculation types
  15. global affinity_calculation_shortest_path;
  16. global affinity_calculation_euclid;
  17. global affinity_calculation_common_friends;
  18. global affinity_calculation_random_clustering;
  19. global affinity_calculation_adamic_adar;
  20. global affinity_calculation_katz_beta_0_5;
  21. global affinity_calculation_katz_beta_0_05;
  22. global affinity_calculation_katz_beta_0_005;
  23. affinity_calculation_shortest_path = 0;
  24. affinity_calculation_euclid = 1;
  25. affinity_calculation_common_friends = 2;
  26. affinity_calculation_random_clustering = 3;
  27. affinity_calculation_adamic_adar = 4;
  28. affinity_calculation_katz_beta_0_5 = 5;
  29. affinity_calculation_katz_beta_0_05 = 6;
  30. affinity_calculation_katz_beta_0_005 = 7;
  31. percent_known_placeholders_vec = percentKnownPlaceholdersVec;
  32. if nargin >= 9
  33. select_random_missing_nodes = 0;
  34. else
  35. select_random_missing_nodes = 1;
  36. end
  37. compensate_for_unknown_placeholers = 1;
  38. compensate_vec = [0 0.3 0.65 1 1.5];
  39. %configuration parameters
  40. %num_values = 100000; %number of values to read from the raw data
  41. %graph_sizes = [400 600 800 1000 1200 1400]; %size of the graph matrix
  42. %graph_sizes = [400 1000]; %size of the graph matrix
  43. % num_missing_nodes_arr = 5 : 5 : 30; %number of missing nodes from the network
  44. % num_missing_nodes_arr = [11,21,31,41,50]; % 20;
  45. %%num_missing_nodes_arr = 1;
  46. unite_common_friends = 0; %should UNK nodes be united in accordance with the "friend of my friend principle"
  47. cluster_only_missing_nodes = 1;
  48. % if affinity_calculation_type == affinity_calculation_shortest_path || affinity_calculation_type == affinity_calculation_euclid
  49. % non_neighbors_distance = Inf;
  50. % elseif affinity_calculation_type == affinity_calculation_common_friends
  51. % non_neighbors_distance = 0;
  52. % end
  53. non_neighbors_distance = 0;
  54. withAttr = 0;
  55. %read the full network, up to num_values links
  56. %disp('reading network information from file...');
  57. fprintf('reading network information from file %s%s ...\n', dataFilePath, dataFileName);
  58. load(strcat(dataFilePath, dataFileName), 'data');
  59. data = sparse(data);
  60. clear('graph');
  61. %rand_score = zeros(2, 2, size(num_missing_nodes_arr,2), 6, 2); %(normalized or not, unite common friends, num missing nodes, affinity calculation, cluster only missing)
  62. %rand_score_sq = rand_score;
  63. %purity = zeros(2, size(num_missing_nodes_arr,2), 6, 2);%(unite common friends, num missing nodes, affinity calculation, cluster only missing)
  64. %purity_sq = purity;
  65. rand_score = [];
  66. purity = [];
  67. graph_size = size(data,1);
  68. graph_edges = nnz(data)/2; % number of edges
  69. %initialize the data matrix (binary adjacency)
  70. disp('generating network graph...');
  71. actual_graph_size = size(data,1);
  72. original_data = data;
  73. missing_nodes_mapping = [];
  74. for num_missing_nodes_idx = 1 : size(num_missing_nodes_arr,2)
  75. if select_random_missing_nodes
  76. num_missing_nodes = num_missing_nodes_arr(1, num_missing_nodes_idx);
  77. else
  78. num_missing_nodes = length(missingNodes);
  79. end
  80. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  81. %remove random nodes %
  82. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  83. %randomize the missing nodes indexes and sort in descending order
  84. %disp('selecting random missing nodes...');
  85. fprintf('selecting %d random missing nodes...\n',num_missing_nodes);
  86. if select_random_missing_nodes
  87. [data, missing_nodes_mapping] = RemoveRandomNodes( original_data, num_missing_nodes, missing_nodes_mapping, non_neighbors_distance );
  88. else
  89. [data, missing_nodes_mapping] = RemoveRandomNodes( original_data, num_missing_nodes, missing_nodes_mapping, non_neighbors_distance, missingNodes);
  90. end
  91. data_untouched = data;
  92. for percent_known_placeholders = percent_known_placeholders_vec
  93. data = data_untouched;
  94. S = zeros(1, size(data,2));
  95. num_placeholders_to_remove = 0;
  96. placeholders_to_remove = [];
  97. num_placeholders = size(data,1) - actual_graph_size + num_missing_nodes ;
  98. last_known_node = size(data,1) - num_placeholders;
  99. if percent_known_placeholders < 1
  100. num_placeholders_to_remove = round(num_placeholders * (1 - percent_known_placeholders));
  101. while size(placeholders_to_remove, 2) < num_placeholders_to_remove
  102. %randomly selecting unique placeholder indexes
  103. placeholders_to_remove = unique([placeholders_to_remove, randi(num_placeholders, 1, num_placeholders_to_remove - size(placeholders_to_remove, 2))]);
  104. end
  105. %rand_vec = rand(1, num_placeholders);
  106. %placeholders_to_remove = find(rand_vec > percent_known_placeholders) + last_known_node;
  107. placeholders_to_remove = placeholders_to_remove + last_known_node;
  108. %S is the group of neighbors of the unknown placeholders
  109. S = data(placeholders_to_remove(1), :);
  110. for i = placeholders_to_remove
  111. S = S | data(i,:);
  112. end
  113. %switch from binary vector to list of indexes
  114. % S = find(S);
  115. data_all_placeholders = data;
  116. data(placeholders_to_remove,:) = [];
  117. data(:,placeholders_to_remove) = [];
  118. num_placeholders = num_placeholders - num_placeholders_to_remove;
  119. end
  120. removed_nodes{num_missing_nodes_idx} = missing_nodes_mapping(1,:); %save the removed nodes in each iteration
  121. %disp('finding all pairs shortest paths...');
  122. %if we got an argument for the affinity calculation type then use
  123. %it. otherwise loop over all the types
  124. if nargin >= 3
  125. affinity_types = affinityType;
  126. else
  127. affinity_types = affinity_calculation_shortest_path: affinity_calculation_katz_beta_0_005;
  128. end
  129. orig_S = S;
  130. for affinity_calculation_type = affinity_types
  131. fprintf('affinity_calculation_type = %d\n', affinity_calculation_type);
  132. %data = data_untouched;
  133. first_unk_node = actual_graph_size - num_missing_nodes + 1;
  134. num_added_nodes = size(data,1) - first_unk_node + 1;
  135. % calculate the affinity / similarity matrix
  136. fprintf('calculating affinity matrix, type %d...\n', affinity_calculation_type);
  137. tic %affinity_calc_time
  138. affinity = CalcAffinity( data, affinity_calculation_type, actual_graph_size, num_missing_nodes);
  139. affinity_calc_time = toc;%affinity_calc_time
  140. %TODO: extend the dimension reduction to adding missing
  141. %links / reclustering
  142. for reduce_dimensions = 1 %[0 1] %0 must be first because it does not change the affinity matrix
  143. reduce_dim_time = 0;
  144. if reduce_dimensions == 1
  145. tic %ReduceDimensions
  146. [affinity, num_placeholders, first_unk_node] = ReduceDimensions(affinity, first_unk_node);
  147. reduce_dim_time = toc; %ReduceDimensions
  148. end
  149. fprintf('calculating true clustering\n');
  150. true_clustering = BuildTrueClustering(missing_nodes_mapping, actual_graph_size, num_missing_nodes, percent_known_placeholders, placeholders_to_remove, last_known_node);
  151. %figure,imshow(affinity,[]), title('Affinity Matrix')
  152. for num_clusters_known = 1 %%[1 4]
  153. k = DetermineNumberOfClusters(num_clusters_known, data_untouched, actual_graph_size, num_missing_nodes, num_added_nodes);
  154. debugEstimateK = 1;
  155. if debugEstimateK == 1 && affinity_calculation_type == 2
  156. for type=[0,3,4,8]
  157. estK = DetermineNumberOfClusters(type, data_untouched, actual_graph_size, num_missing_nodes, num_added_nodes);
  158. end
  159. end
  160. last_known_node = first_unk_node - 1;
  161. fprintf('calculating PredictGraph with k=%d and reduce_dimensions=%d ...\n',k,reduce_dimensions);
  162. tic %graph_predict_time
  163. [newData, test_clustering] = PredictGraph(affinity, k, data, num_placeholders, affinity_calculation_type, cluster_only_missing_nodes);
  164. graph_predict_time = toc; %graph_predict_time
  165. if compensate_for_unknown_placeholers == 1
  166. fprintf('*** running with compensate_for_unknown_placeholers mode ...\n');
  167. S = orig_S;
  168. if size(newData,1) > size(S,2)
  169. %for breakpoint
  170. tttt = 98;
  171. end
  172. sigma = 1/4;
  173. S = S(1:size(newData,1));
  174. S = S + randn(size(S)) * sigma;
  175. sorted_S = sort(S, 'descend');
  176. %sum over the columns and find the columns which
  177. %indicate at least one neighbor
  178. %neighbors_of_new_nodes = find(sum(newData(first_unk_node:size(newData,1), :)));
  179. first_united_node = size(newData,1) - k +1;
  180. if affinity_calculation_type == affinity_calculation_katz_beta_0_05
  181. newAffinity = CalcAffinityByKatzBeta_Sparse( newData, 0.05, 4 );
  182. elseif affinity_calculation_type == affinity_calculation_adamic_adar
  183. newAffinity = CalculateAffinityByAdamicAdar_Sparse(newData, size(newData,1), 0, 0);
  184. elseif affinity_calculation_type == affinity_calculation_common_friends
  185. newAffinity = CalcAffinityByCommonNeighbors_Sparse(newData, size(newData,1), 0);
  186. end
  187. newNodesAffinity = newAffinity(first_united_node:size(newAffinity,1), :);
  188. newNodesAffinity(newNodesAffinity>=1) = 0;
  189. newNodesAffinity = newNodesAffinity / max(max(newNodesAffinity));
  190. %newNodesAffinity = newNodesAffinity / 2;
  191. newNodesAffinity(newData(first_united_node:size(newAffinity,1), :) >= 1) = 0;
  192. newNodesAffinity = (newNodesAffinity / max(max(newNodesAffinity)));
  193. %%%%trying to take only the
  194. %%%%k highest affinities
  195. sortedNewNodesAffinity = sort(newNodesAffinity(:), 'descend');
  196. %affinityThreshold = sortedNewNodesAffinity(k + size(neighbors_of_new_nodes, 2));
  197. newNodesAffinity_orig = newNodesAffinity;
  198. end
  199. if percent_known_placeholders < 1 && compensate_for_unknown_placeholers == 1
  200. %calculating as a function of number of links added
  201. meanNumLinks = mean(sum(data(1:last_known_node, 1:last_known_node)));
  202. maxNumLinksToAdd = meanNumLinks * num_placeholders;
  203. maxNumLinksToAdd = min(maxNumLinksToAdd, 25);
  204. %sigal 27.6.13
  205. linksToAdd = round(compensate_vec*num_missing_nodes);
  206. else
  207. maxNumLinksToAdd = 0;
  208. %sigal 27.6.13
  209. linksToAdd = 0;
  210. end
  211. %%%%% for distance as
  212. %%%%% function of num
  213. %%%%% placeholders %%%%
  214. %max_neighbors = S >= sorted_S(maxNumLinksToAdd);
  215. %sigal 27.6.13
  216. %for numLinksToAdd = 0 : maxNumLinksToAdd
  217. for linksInx = 1:size(linksToAdd,2)
  218. numLinksToAdd = linksToAdd(linksInx);
  219. withAttr = compensate_vec(linksInx)*100; % numLinksToAdd
  220. if compensate_for_unknown_placeholers == 1
  221. newNodesAffinity = newNodesAffinity_orig;
  222. neighbors = [];
  223. if numLinksToAdd > 0
  224. % get the indexes of the #numLinksToAdd neighbors that have the
  225. % top (higher) S value
  226. neighbors = find(S >= sorted_S(numLinksToAdd), numLinksToAdd);
  227. end
  228. newDataWithMissingLinks = newData; % partial graph with the clustered nodes
  229. newDataForClustering = data; % partial graph with partial PHs
  230. for neighbor = neighbors
  231. % missing links - add links to clustered nodes
  232. [value, closest_new_node] = max(newNodesAffinity(:,neighbor));
  233. closest_new_node = closest_new_node(1);
  234. newDataWithMissingLinks(first_united_node + closest_new_node - 1, neighbor) = 1;
  235. newDataWithMissingLinks(neighbor, first_united_node + closest_new_node - 1) = 1;
  236. % Speculative MISC - add PH to the partial data
  237. newPlaceholder = zeros(1, size(newDataForClustering,2));
  238. newPlaceholder(neighbor) = 1;
  239. newDataForClustering = [newDataForClustering, newPlaceholder'; newPlaceholder, 0];
  240. end
  241. affinityWithS = CalcAffinity( newDataForClustering, affinity_calculation_type, actual_graph_size, num_missing_nodes);
  242. if reduce_dimensions == 1
  243. [affinityWithS, num_placeholdersWithS, first_unk_node_with_s] = ReduceDimensions(affinityWithS, first_united_node);
  244. else
  245. num_placeholdersWithS = num_placeholders + length(neighbors);
  246. first_unk_node_with_s = first_united_node;
  247. end
  248. [newPredictedGraph, newClustering] = PredictGraph(affinityWithS, k, newDataForClustering, num_placeholdersWithS, affinity_calculation_type, cluster_only_missing_nodes);
  249. %remap the original data so that
  250. %the known nodes match the
  251. %predicted data and the missing
  252. %nodes match the predicted nodes
  253. %created from each cluster
  254. perm_vector = 1:size(original_data,1);
  255. perm_vector(missing_nodes_mapping(1,:)) = [];
  256. perm_vector = [perm_vector, missing_nodes_mapping(1,:)];
  257. remapped_data = original_data(perm_vector,perm_vector);
  258. [small_data, indices_to_remove] = DecreaseGraphSize(remapped_data, first_united_node : size(remapped_data,1), neighbors); %changed from neighbors to perm(max_neighbors) - to be fair when there are more nieghbors
  259. %small_data2 = DecreaseGraphSize(newData, last_known_node+1 : size(newData,1));
  260. %new_nodes_affinity_sum = sum(sum(newNodesAffinity));
  261. %in case there is an empty cluster, the unrelated nodes may contain node index that does not exist
  262. %in the predicted graph (which may contain less nodes)
  263. indices_to_remove(indices_to_remove > size(newPredictedGraph,2)) = [];
  264. small_data2 = newData;
  265. small_data2(indices_to_remove,:) = [];
  266. small_data2(:,indices_to_remove) = [];
  267. %small_data3 = DecreaseGraphSize(newDataWithMissingLinks, last_known_node+1 : size(newDataWithMissingLinks,1));
  268. small_data3 = newDataWithMissingLinks;
  269. small_data3(indices_to_remove,:) = [];
  270. small_data3(:,indices_to_remove) = [];
  271. small_data4 = newPredictedGraph;
  272. small_data4(indices_to_remove,:) = [];
  273. small_data4(:,indices_to_remove) = [];
  274. %%% Sigal 23.6.13 - save reduce graphs for GED
  275. if dumpSmallFlag == 1
  276. saveSmallData(dumpSmallDataPath, dataFileName, iter, affinity_calculation_type, withAttr, num_missing_nodes, small_data, 1);
  277. saveSmallData(dumpSmallDataPath, dataFileName, iter, affinity_calculation_type, withAttr, num_missing_nodes, small_data2, 2);
  278. end
  279. %only calculate on the first iteration to save time
  280. if numLinksToAdd == 0
  281. edit_distance = 99; %GraphEditDistance( small_data, small_data2, num_missing_nodes );
  282. edit_distance2 = edit_distance;
  283. edit_distance3 = edit_distance;
  284. else
  285. edit_distance2 = 99; %GraphEditDistance( small_data, small_data3, num_missing_nodes );
  286. edit_distance3 = 99; %GraphEditDistance( small_data, small_data4, num_missing_nodes );
  287. if dumpSmallFlag == 1
  288. saveSmallData(dumpSmallDataPath, dataFileName, iter, affinity_calculation_type, withAttr, num_missing_nodes, small_data3, 3);
  289. saveSmallData(dumpSmallDataPath, dataFileName, iter, affinity_calculation_type, withAttr, num_missing_nodes, small_data4, 4);
  290. end
  291. end
  292. else
  293. perm_vector = 1:size(original_data,1);
  294. perm_vector(missing_nodes_mapping(1,:)) = [];
  295. perm_vector = [perm_vector, missing_nodes_mapping(1,:)];
  296. remapped_data = original_data(perm_vector,perm_vector);
  297. [small_data, indices_to_remove] = DecreaseGraphSize(remapped_data, (size(remapped_data,1) - num_missing_nodes + 1) : size(remapped_data,1), []); %changed from neighbors to perm(max_neighbors) - to be fair when there are more nieghbors
  298. indices_to_remove(indices_to_remove > size(newData,2)) = [];
  299. small_data2 = newData;
  300. small_data2(indices_to_remove,:) = [];
  301. small_data2(:,indices_to_remove) = [];
  302. % Sigal 23.6.13 - save reduce graphs for GED
  303. withAttr = (1 - percent_known_placeholders)*10;
  304. if dumpSmallFlag == 1
  305. saveSmallData(dumpSmallDataPath, dataFileName, iter, affinity_calculation_type, withAttr, num_missing_nodes, small_data, 1);
  306. saveSmallData(dumpSmallDataPath, dataFileName, iter, affinity_calculation_type, withAttr, num_missing_nodes, small_data2, 2);
  307. end
  308. %sigal 6.12.12 - *** TODO *** temporary for test only TODO
  309. %edit_distance = GraphEditDistance( small_data, small_data2, num_missing_nodes );
  310. edit_distance = 99;
  311. end
  312. %fprintf('num_links_to_add = %d; missing links distance = %d, new clustering dist = %d\n', numLinksToAdd, full(edit_distance2), full(edit_distance3));
  313. fprintf('calculating purity\n');
  314. curr_index = size(purity,2) + 1;
  315. %purity for actual clustering
  316. try
  317. temp_purity = ClusteringPurity(true_clustering, test_clustering);
  318. catch ME1
  319. temp_purity = 99; % Sigal 12.8.12 - tmp %
  320. ddddd = 1;
  321. end
  322. purity(curr_index).score = temp_purity;
  323. purity(curr_index).score_sq = temp_purity^2;
  324. purity(curr_index).unite_common_friends = unite_common_friends;
  325. purity(curr_index).num_missing_nodes_idx = num_missing_nodes_idx;
  326. purity(curr_index).num_missing_nodes = num_missing_nodes_arr(num_missing_nodes_idx);
  327. purity(curr_index).affinity_calculation_type = affinity_calculation_type;
  328. purity(curr_index).withAttr = withAttr; %sigal - 10.7.13
  329. purity(curr_index).cluster_only_missing_nodes = cluster_only_missing_nodes;
  330. purity(curr_index).num_clusters_known = num_clusters_known;
  331. purity(curr_index).k = k; % sigal 26.6.13 - the predict # of clusters
  332. purity(curr_index).num_placeholders = num_placeholders;
  333. purity(curr_index).num_placeholders_to_remove = num_placeholders_to_remove;
  334. purity(curr_index).iteration = 1;
  335. purity(curr_index).test_clustering = test_clustering;
  336. purity(curr_index).true_clustering = true_clustering;
  337. purity(curr_index).graph_size = graph_size;
  338. purity(curr_index).graph_edges = graph_edges; % sigal - number of edges
  339. purity(curr_index).inverse_purity = 1; % Sigal 12.8.12 - tmp % CalculateInversePurity(true_clustering, test_clustering);
  340. purity(curr_index).NMI = 0; %CalcNormalizedMutualInformation(true_clustering, test_clustering);
  341. purity(curr_index).removed_nodes = removed_nodes;
  342. purity(curr_index).percent_known_placeholders = percent_known_placeholders;
  343. purity(curr_index).reduce_dimensions = reduce_dimensions;
  344. purity(curr_index).missing_nodes_mapping = missing_nodes_mapping;
  345. purity(curr_index).compensate_for_unknown_placeholers = compensate_for_unknown_placeholers;
  346. purity(curr_index).edit_distance = edit_distance;
  347. if compensate_for_unknown_placeholers == 1
  348. purity(curr_index).numLinksToAdd = numLinksToAdd;
  349. purity(curr_index).edit_distance_missing_links = edit_distance2;
  350. purity(curr_index).edit_distance_new_clustering = edit_distance3;
  351. fprintf('numLinksToAdd - %d\nedit_distance - %d\nedit_distance_missing_links - %d\nedit_distance_new_clustering - %d\n', numLinksToAdd, full(edit_distance), full(edit_distance2), full(edit_distance3));
  352. end
  353. purity(curr_index).affinity_calc_time = affinity_calc_time;
  354. purity(curr_index).reduce_dim_time = reduce_dim_time;
  355. purity(curr_index).graph_predict_time = graph_predict_time;
  356. if compensate_for_unknown_placeholers == 0
  357. break
  358. end
  359. end
  360. %
  361. % purity(unite_common_friends+1, num_missing_nodes_idx, affinity_calculation_type+1, cluster_only_missing_nodes+1) = ...
  362. % purity(unite_common_friends+1, num_missing_nodes_idx, affinity_calculation_type+1, cluster_only_missing_nodes+1) + temp_purity;
  363. %
  364. % purity_sq(unite_common_friends+1, num_missing_nodes_idx, affinity_calculation_type+1, cluster_only_missing_nodes+1) = ...
  365. % purity_sq(unite_common_friends+1, num_missing_nodes_idx, affinity_calculation_type+1, cluster_only_missing_nodes+1) + temp_purity^2;
  366. %
  367. LogMsg(sprintf('Sparse2c: Size=%d,Miss=%d,PHs=%d,Affinity=%d,Att=%d,Purity=%.3f', ...
  368. graph_size,purity(curr_index).num_missing_nodes,num_placeholders,affinity_calculation_type,withAttr,temp_purity));
  369. %fprintf('affinity_calculation_type = %d, unite_common_friends = %d\n', affinity_calculation_type, unite_common_friends);
  370. %fprintf('Graph size: %d, Number of missing nodes: %d, Purity: %f \n' ,graph_size, num_missing_nodes, temp_purity);
  371. %fprintf('============================================\n\n\n');
  372. %clear U;
  373. clear eigValues;
  374. clear eigVectors;
  375. end
  376. end
  377. clear('affinity');
  378. end
  379. end
  380. end
  381. end
  382. function [affinity] = CalcAffinity( data, affinity_calculation_type, actual_graph_size, num_missing_nodes)
  383. global affinity_calculation_shortest_path;
  384. global affinity_calculation_euclid;
  385. global affinity_calculation_common_friends;
  386. global affinity_calculation_random_clustering;
  387. global affinity_calculation_adamic_adar;
  388. global affinity_calculation_katz_beta_0_5;
  389. global affinity_calculation_katz_beta_0_05;
  390. global affinity_calculation_katz_beta_0_005;
  391. if affinity_calculation_type == affinity_calculation_euclid
  392. sp_mat = graphallshortestpaths(data);
  393. %remove INF values
  394. max_value = max(sp_mat(sp_mat ~= Inf)) + 1;
  395. sp_mat_euclid = sp_mat;
  396. sp_mat_euclid(sp_mat == Inf) = max_value;
  397. affinity = CalculateAffinity(sp_mat_euclid);
  398. %affinity = exp(-(sp_mat.^2))/(2 * 0.3^2);
  399. elseif affinity_calculation_type == affinity_calculation_shortest_path
  400. % max_value = max(sp_mat(sp_mat ~= Inf)) + 1;
  401. % sp_mat_euclid = sp_mat;
  402. % sp_mat_euclid(sp_mat == Inf) = max_value;
  403. % affinity = (sp_mat_euclid + 1).^(-affinity_exp_factor);
  404. %affinity = spfun(affinityFunc, data);
  405. affinity = graphallshortestpaths(data);
  406. affinity = affinity .^ -2;
  407. affinity(affinity == Inf) = 1; %added on 05/11/11
  408. elseif affinity_calculation_type == affinity_calculation_common_friends
  409. affinity = CalcAffinityByCommonNeighbors_Sparse(data, actual_graph_size, num_missing_nodes);
  410. %affinity = CalcAffinityByCommonNeighbors(data, actual_graph_size, num_missing_nodes);
  411. elseif affinity_calculation_type == affinity_calculation_random_clustering
  412. affinity = data; %just a placeholder...
  413. elseif affinity_calculation_type == affinity_calculation_adamic_adar
  414. affinity = CalculateAffinityByAdamicAdar_Sparse( data, actual_graph_size, num_missing_nodes, 1 );
  415. if nnz(affinity) < 5
  416. x = 8;
  417. end
  418. elseif affinity_calculation_type == affinity_calculation_katz_beta_0_5
  419. affinity = CalcAffinityByKatzBeta_Sparse( data, 0.5, 3 );
  420. elseif affinity_calculation_type == affinity_calculation_katz_beta_0_05
  421. affinity = CalcAffinityByKatzBeta_Sparse( data, 0.05, 4 );
  422. elseif affinity_calculation_type == affinity_calculation_katz_beta_0_005
  423. affinity = CalcAffinityByKatzBeta_Sparse( data, 0.005, 4 );
  424. end
  425. end
  426. function [test_clustering] = SpectralClustering(affinity, k, num_placeholders, affinity_calculation_type, cluster_only_missing_nodes)
  427. global affinity_calculation_shortest_path;
  428. global affinity_calculation_euclid;
  429. global affinity_calculation_common_friends;
  430. global affinity_calculation_random_clustering;
  431. global affinity_calculation_adamic_adar;
  432. global affinity_calculation_katz_beta_0_5;
  433. global affinity_calculation_katz_beta_0_05;
  434. global affinity_calculation_katz_beta_0_005;
  435. first_unk_node = size(affinity,1) - num_placeholders + 1;
  436. diagonal = sum(affinity, 2); %sum the rows
  437. D = sparse(diag(diagonal)); %D is the matrix whose diagonal is the sum of the rows of A
  438. clear('diagonal');
  439. fprintf('Calculating NL\n');
  440. D = sqrt(D);
  441. NL1 = D * affinity * D;
  442. clear('D');
  443. fprintf('calculating U\n');
  444. fail = 0;
  445. try
  446. [nEigVec,eigValues] = eigs(NL1,k);
  447. catch ME1
  448. opts.tol = 1e-1;
  449. try
  450. [nEigVec,eigValues] = eigs(NL1,k, 'LM', opts);
  451. catch ME2
  452. fail = 1;
  453. end
  454. end
  455. % select k largest eigen vectors
  456. if fail == 0
  457. U = [];
  458. % construct the normalized matrix U from the obtained eigen vectors
  459. for i=1:size(nEigVec,1)
  460. n = sqrt(sum(nEigVec(i,:).^2));
  461. U(i,:) = nEigVec(i,:) ./ n;
  462. end
  463. num_samples = size(affinity,1) - first_unk_node + 1;
  464. if cluster_only_missing_nodes == 1
  465. U(1:first_unk_node - 1 ,:) = []; %cluster only the missing nodes
  466. end
  467. fprintf('kmeans clustering\n');
  468. % perform kmeans clustering on the matrix U
  469. fail = 1;
  470. while fail > 0
  471. try
  472. currK = k;
  473. [IDX,C, SUMD, D] = kmeans(U,currK, 'EmptyAction', 'singleton'); %in case of an empty cluster just drop it
  474. fail = 0;
  475. catch ME1
  476. fail = fail + 1;
  477. if fail < 100
  478. disp('error in kmeans clustering. trying again...');
  479. else
  480. %give up on clustering and select random clusters...
  481. IDX = randi(currK, size(U));
  482. fail = 0;
  483. end
  484. end
  485. end
  486. test_clustering = IDX(size(IDX,1) - num_samples + 1 : size(IDX,1));
  487. %if it's random just replace everything...
  488. if affinity_calculation_type == affinity_calculation_random_clustering
  489. test_clustering = randi(k, size(test_clustering,1), size(test_clustering,2));
  490. end
  491. else
  492. disp('Failed in finding eigenvectors - using random!');
  493. if cluster_only_missing_nodes == 0
  494. num_samples = size(affinity,1);
  495. else
  496. num_samples = num_placeholders;
  497. end
  498. test_clustering = randi(k, num_samples, 1);
  499. end
  500. end
  501. function [newData, test_clustering] = PredictGraph(affinity, k, data, num_placeholders, affinity_calculation_type, cluster_only_missing_nodes)
  502. last_known_node = size(data,1) - num_placeholders;
  503. first_unk_node = last_known_node + 1;
  504. [test_clustering] = SpectralClustering(affinity, k, num_placeholders, affinity_calculation_type, cluster_only_missing_nodes);
  505. newNodes = CreateNewNodesFromClusters(data, test_clustering);
  506. newData = [data(1:last_known_node,1:last_known_node), newNodes(:, 1:last_known_node)';...
  507. newNodes(:,1:last_known_node), zeros(size(newNodes,1))];
  508. end
  509. function [k] = DetermineNumberOfClusters(num_clusters_known, data_untouched, actual_graph_size, num_missing_nodes, num_added_nodes)
  510. %determine k - the number of clusters
  511. if num_clusters_known == 1
  512. k = num_missing_nodes;
  513. else
  514. numKnownNodes = actual_graph_size - num_missing_nodes;
  515. sumKnownEdges = sum(sum(data_untouched(1 : numKnownNodes, 1 : numKnownNodes)));
  516. meanKnownEdges = sumKnownEdges/numKnownNodes;
  517. addedEdges = num_added_nodes*2; % undirect graph
  518. fprintf('EstimatedK: numKnownN=%d, meanKnownE=%.3f, addedE=%d, missN=%d, meanMissE=%.3f\n', ...
  519. numKnownNodes,full(meanKnownEdges),num_added_nodes,num_missing_nodes,addedEdges/num_missing_nodes);
  520. if num_clusters_known == 0
  521. %k = round(num_added_nodes / meanKnownEdges);
  522. k = round(num_added_nodes / floor(meanKnownEdges));
  523. %fprintf('EstimatedK: type=%d, actual=%d, rounding k to %d\n',num_clusters_known, num_missing_nodes, k);
  524. elseif num_clusters_known == 2 %guessing upper limit
  525. k = 2*round(num_added_nodes / meanKnownEdges);
  526. %fprintf('EstimatedK: type=%d, actual=%d, guessing upper limit %d\n',num_clusters_known, num_missing_nodes, k);
  527. elseif num_clusters_known == 3 % e=a*n
  528. a = meanKnownEdges;
  529. e = sumKnownEdges+num_added_nodes;
  530. k = round(e/a-numKnownNodes);
  531. %fprintf('EstimatedK: type=%d, actual=%d, rounding k to %d\n',num_clusters_known, num_missing_nodes, k);
  532. elseif num_clusters_known == 4 % e=a*n^2
  533. a = meanKnownEdges/numKnownNodes;
  534. e = sumKnownEdges+addedEdges;
  535. k = round(sqrt(e/a)-numKnownNodes);
  536. %fprintf('EstimatedK: type=%d, actual=%d, rounding k to %d\n',num_clusters_known, num_missing_nodes, k);
  537. elseif num_clusters_known == 5 % e=a*n^2
  538. a = meanKnownEdges/numKnownNodes;
  539. e = sumKnownEdges+addedEdges;
  540. k = ceil(sqrt(e/a)-numKnownNodes);
  541. %fprintf('EstimatedK: type=%d, actual=%d, rounding k to %d\n',num_clusters_known, num_missing_nodes, k);
  542. elseif num_clusters_known == 6 % e=a*n
  543. a = meanKnownEdges;
  544. e = sumKnownEdges+num_added_nodes;
  545. k = ceil(e/a-numKnownNodes);
  546. elseif num_clusters_known == 7
  547. k = ceil(num_added_nodes / meanKnownEdges);
  548. elseif num_clusters_known == 8
  549. k = round(num_added_nodes / meanKnownEdges);
  550. end
  551. LogMsg(sprintf('EstimatedK(size,PHs,type,actual,k):\t%d\t%d\t%d\t%d\t%d', ...
  552. actual_graph_size,num_added_nodes,num_clusters_known, num_missing_nodes, k),'EstimateK_Log2.txt');
  553. end
  554. end %function
  555. function [affinity, num_placeholders, first_unk_node] = ReduceDimensions(affinity, first_unk_node)
  556. size_before = size(affinity,1);
  557. num_placeholders = size(affinity,1) - first_unk_node + 1;
  558. affinity_sum = sum(affinity(first_unk_node:size(affinity,1),:)); %the sum of the affinity of placeholders to all other nodes
  559. nodes_to_keep = (affinity_sum > 0); %keep only nodes which have some affinity to the placeholders
  560. nodes_to_keep(first_unk_node:size(affinity,1)) = 1; %keep all the placeholders even if for some reason they have a sum of zero...
  561. affinity = affinity(nodes_to_keep, nodes_to_keep);
  562. size_after = size(affinity,1);
  563. first_unk_node = size(affinity,1) - num_placeholders + 1;
  564. LogMsg(sprintf('ReduceDimensions from %d to %d',size_before,size_after),'ReduceDimensions_Log.txt');
  565. end
  566. function [true_clustering] = BuildTrueClustering(missing_nodes_mapping, actual_graph_size, num_missing_nodes, percent_known_placeholders, placeholders_to_remove, last_known_node)
  567. true_clustering = []; %zeros(size(test_clustering, 1), 1);
  568. for i = 2 : size(missing_nodes_mapping, 1)
  569. for j = 1 : size(missing_nodes_mapping,2)
  570. if missing_nodes_mapping(i,j) ~= 0
  571. true_clustering(missing_nodes_mapping(i,j) - actual_graph_size + num_missing_nodes, 1) = j; % missing_nodes_mapping(1, j);
  572. end
  573. end
  574. end
  575. if percent_known_placeholders < 1
  576. true_clustering(placeholders_to_remove - last_known_node) = [];
  577. end
  578. end
  579. function saveSmallData(dumpSmallDataPath, dataFileName, iter, affinity_type, withAttr, missNodes, small_data, i)
  580. %%% Sigal 24.1.13 - TODO
  581. outFile = sprintf('%s_%d_%d_%d_%d_small_data_%d', dataFileName, iter, missNodes, affinity_type, withAttr, i);
  582. if affinity_type == 9 % save instead a dummy size (1) and the best_alg
  583. SaveIntMatrixToFile(strcat(dumpSmallDataPath, outFile,'_edges.txt'), small_data, 1);
  584. else
  585. SaveAsciiGraph(dumpSmallDataPath, outFile, small_data, 1); %% also save graph size
  586. end
  587. end