Finish course 3 week 2 assignment

This commit is contained in:
2021-02-14 21:00:47 -05:00
parent f6102bd409
commit cc8a0443cb
3 changed files with 31 additions and 74 deletions

View File

@@ -1,47 +1,24 @@
use std::collections::HashMap;
pub type ImpliciteGraph = Vec<u32>;
#[allow(dead_code)]
fn distance(a: &u32, b: &u32) -> u32 {
let mut r = 0;
for i in 0..24 {
let m = 0x1 << i;
if a & m != b & m {
r += 1;
}
fn neighbors(a: u32, n: usize) -> Vec<u32> {
let mut r = vec![a];
for _ in 0..n {
let mut r_new = r.clone();
for a in r {
for i in 0..24 {
let m = 0x1 << i;
let neighbor = a ^ m;
r_new.push(neighbor);
}
}
r_new.sort();
r_new.dedup();
r = r_new;
}
r
}
#[allow(dead_code)]
fn neighbors_distance_1(a: u32) -> Vec<u32> {
let mut r = Vec::new();
for i in 0..24 {
let m = 0x1 << i;
let neighbor = a ^ m;
r.push(neighbor);
}
r
}
#[allow(dead_code)]
fn neighbors_distance_2(a: u32) -> Vec<u32> {
let mut r = Vec::new();
for i in 0..24 {
let m = 0x1 << i;
let n1 = a ^ m;
for j in 0..24 {
let m = 0x1 << j;
let n2 = n1 ^ m;
if n2 != a {
r.push(n2);
}
}
}
r.sort();
r.dedup();
r
}
pub fn k_clustering_big(g: &ImpliciteGraph) -> usize {
let mut node_id_to_cluster_id: Vec<usize> = (0..g.len()).collect();
@@ -58,35 +35,19 @@ pub fn k_clustering_big(g: &ImpliciteGraph) -> usize {
}
for node_a_id in 0..g.len() {
for node_b_value in neighbors_distance_1(g[node_a_id]) {
// Iterate over all nodes in the graph. Then, for each node compute all
// neighbors that are two or less bits away.
for node_b_value in neighbors(g[node_a_id], 2) {
// See if there exist nodes that match the neighbor. If such nodes
// exist iterate over them and merge the clusters if they are not
// already the same. The key insight is that we have to cluster all
// nodes that are two or less (that includes zero) bits apart.
if let Some(node_b_ids) = node_map.get(&node_b_value) {
// These node IDs have distance one meaning we want to merge them into
// the same cluster.
for node_b_id in node_b_ids {
let cluster_id_a = node_id_to_cluster_id[node_a_id];
let cluster_id_b = node_id_to_cluster_id[*node_b_id];
if cluster_id_a != cluster_id_b {
// Merge b into a because nodes have distance 1.
let mut cluster_b = std::mem::take(&mut clusters[cluster_id_b]);
for node_id in &cluster_b {
node_id_to_cluster_id[*node_id] = cluster_id_a;
}
clusters[cluster_id_a].append(&mut cluster_b);
cluster_count -= 1;
}
}
}
}
for node_b_value in neighbors_distance_2(g[node_a_id]) {
if let Some(node_b_ids) = node_map.get(&node_b_value) {
// These node IDs have distance one meaning we want to merge them into
// the same cluster.
for node_b_id in node_b_ids {
let cluster_id_a = node_id_to_cluster_id[node_a_id];
let cluster_id_b = node_id_to_cluster_id[*node_b_id];
if cluster_id_a != cluster_id_b {
// Merge b into a because nodes have distance 2.
// Merge b into a. The code is the same as for k_clustering.
let mut cluster_b = std::mem::take(&mut clusters[cluster_id_b]);
for node_id in &cluster_b {
node_id_to_cluster_id[*node_id] = cluster_id_a;