Skip to main content

sample/
sample.rs

1// An example that uses FLAME to analyze multi-dimensional data.
2//
3// To run the example, execute the following from the project root:
4//   cargo run --example sample examples/matrix.txt
5
6extern crate flame_clustering;
7
8use flame_clustering::{distance, DistanceGraph};
9use std::env;
10use std::fs::File;
11use std::io::{self, Write};
12use std::process::exit;
13
14fn read_data(reader: impl io::BufRead) -> io::Result<Vec<Vec<f64>>> {
15    let mut lines = reader
16        .lines()
17        .map(|x| x.unwrap().trim().to_string())
18        .filter(|x| !x.is_empty());
19
20    let header = lines
21        .next()
22        .unwrap()
23        .split_whitespace()
24        .map(|n| n.parse::<usize>().unwrap())
25        .collect::<Vec<usize>>();
26    let n = header[0];
27    let m = header[1];
28    println!("Reading dataset with {} rows and {} columns", n, m);
29
30    let mut out = Vec::with_capacity(n);
31    for line in lines {
32        let v = line
33            .split_whitespace()
34            .map(|n| n.parse::<f64>().unwrap())
35            .collect::<Vec<f64>>();
36        assert_eq!(v.len(), m);
37        out.push(v);
38    }
39    Ok(out)
40}
41
42fn print_cluster(cluster: &[usize]) {
43    for (j, v) in cluster.iter().enumerate() {
44        if j > 0 {
45            print!(",");
46            if j % 10 == 0 {
47                println!();
48            }
49        }
50        print!("{:5}", v);
51    }
52    println!();
53}
54
55fn main() -> io::Result<()> {
56    let filename = env::args().nth(1);
57    if filename.is_none() {
58        eprintln!("No input file");
59        exit(1);
60    }
61    let data = read_data(io::BufReader::new(File::open(filename.unwrap())?))?;
62    let flame = DistanceGraph::build(&data, distance::euclidean);
63
64    print!("Detecting Cluster Supporting Objects ...");
65    io::stdout().flush()?;
66    let supports = flame.find_supporting_objects(10, -2.0);
67    println!("done, found {}", supports.count());
68
69    print!("Propagating fuzzy memberships ... ");
70    io::stdout().flush()?;
71    let fuzzyships = supports
72        .approximate_fuzzy_memberships(500, 1e-6)
73        .assign_outliers();
74    println!("done");
75
76    print!("Defining clusters from fuzzy memberships ... ");
77    io::stdout().flush()?;
78    let (clusters, outliers) = fuzzyships.make_clusters(-1.0);
79    println!("done");
80
81    for (i, cluster) in clusters.iter().enumerate() {
82        print!("\nCluster {:3}, with {:6} members:\n", i + 1, cluster.len());
83        print_cluster(cluster);
84    }
85    print!("\nCluster outliers, with {:6} members:\n", outliers.len());
86    print_cluster(&outliers);
87
88    Ok(())
89}