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_Sparse2.m 43KB

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