#![feature(duration)] #![feature(duration_span)] #![feature(append)] use std::ops::*; use std::borrow::Borrow; use std::f32; use std::cell::RefCell; use std::fs::File; use std::io::BufReader; use std::io::BufRead; use std::time::Duration; use std::env; #[derive(Clone,Copy)] struct Measure { x : f32, y : f32 } impl Measure{ #[allow(non_snake_case)] pub fn new(X:f32,Y:f32) -> Measure{ Measure{ x:X, y:Y } } } impl Add for Measure{ type Output = Measure; fn add(self, rhs:Measure) -> Measure { Measure{ x: self.x + rhs.x, y: self.y + rhs.y, } } } impl Sub for Measure{ type Output = Measure; fn sub(self, rhs: Measure) -> Measure { Measure{ x: self.x - rhs.x, y: self.y - rhs.y } } } impl Div<f32> for Measure { type Output = Measure; fn div(self, rhs: f32) -> Measure { Measure{ x: self.x / rhs, y: self.y / rhs } } } impl Mul<f32> for Measure { type Output = Measure; fn mul(self, rhs: f32) -> Measure { Measure{ x: self.x * rhs, y: self.y * rhs } } } #[inline] fn sqr(v:f32)->f32 { v * v } fn dist (a: & Measure, b: & Measure) -> f32 { (sqr(ax - bx) + sqr(ay - by)).sqrt() } #[derive(Clone)] struct Class { mean: Measure, count: usize, #[cfg(collect_measures)] measures: Vec<Measure> } impl Class{ #[cfg(collect_measures)] pub fn new( m: Measure ) -> Class { Class{ mean: m, count: 1, measures: vec![m.clone()] } } #[cfg(not(collect_measures))] pub fn new( m: Measure ) -> Class { Class{ mean: m, count: 1, } } #[cfg(collect_measures)] pub fn append(&mut self, m: Measure){ self.mean = ( self.mean * self.count as f32 + m ) /( self.count + 1)as f32; self.measures.push(m.clone()); self.count += 1; } #[cfg(not(collect_measures))] pub fn append(&mut self, m: Measure){ self.mean = ( self.mean * self.count as f32 + m ) /( self.count + 1)as f32; self.count += 1; } #[cfg(collect_measures)] pub fn merge(&mut self, m: &mut Class) { self.mean = ( self.mean * self.count as f32 + ((m.mean) * m.count as f32 )) / ( self.count + m.count) as f32; self.count += m.count; self.measures.append(&mut m.measures); } #[cfg(not(collect_measures))] pub fn merge(&mut self, m: &mut Class) { self.mean = ( self.mean * self.count as f32 + ((m.mean) * m.count as f32 )) / ( self.count + m.count) as f32; self.count += m.count; } } #[test] fn test_Measure() { let a = Measure::new(1f32,3f32); let b = Measure::new(4f32,5f32); let add = a + b; assert!( add.x == 5f32 && add.y == 8f32 ); let dif = a - b; assert!( dif.x == -3f32 && dif.y == -2f32 ); let mlt = &a * 3f32; assert!( mlt.x == 3f32 && mlt.y == 9f32 ); let div = &b / 2f32; assert!( div.x == 2f32 && div.y == 2.5f32 ); } #[test] fn test_Class() { let mut cls = Class::new( Measure::new(1f32,2f32) ); assert!( cls.mean.x == 1f32 && cls.mean.y == 2f32 ); assert!( cls.count == 1 ); cls.append( Measure::new(3f32,4f32) ); assert!( cls.mean.x == 2f32 && cls.mean.y == 3f32 ); assert!( cls.count == 2 ); } struct Classifier { list:Vec<RefCell<Class>>, ncls_dist:f32 } impl Classifier{ pub fn new(mdist:f32) -> Classifier{ Classifier{ list:Vec::new(), ncls_dist:mdist } } pub fn classificate(&mut self, m: Measure){ let mut min_dist:f32 = f32::MAX; let mut near_cls = 0; let mut index:usize = 0; for i in self.list.iter() { let d = dist( &m, & i.borrow().mean); if d < min_dist { min_dist = d; near_cls = index; } index+=1; } if min_dist < self.ncls_dist{ self.list[near_cls].borrow_mut().append(m); } else { self.list.push(RefCell::new( Class::new(m))); } } #[allow(dead_code)] pub fn merge_classes(&mut self) { let mut uniq: Vec<RefCell<Class>>= Vec::new(); for cls in self.list.iter(){ let mut is_uniq = true; for trg in uniq.iter(){ if dist( &cls.borrow().mean, &trg.borrow().mean) < self.ncls_dist { trg.borrow_mut().merge(&mut *cls.borrow_mut()); is_uniq = false; break; } } if is_uniq { uniq.push(RefCell::new(cls.borrow_mut().clone())); } } self.list = uniq; } } fn read_measures_from_file( name: String ) -> Vec<Measure> { let mut list:Vec<Measure> = Vec::new(); let f = File::open(name).unwrap(); let mut reader = BufReader::new(&f); let mut ret_string = String::new(); while let Ok(size ) = reader.read_line( &mut ret_string){ if size > 0 { let len = ret_string.len() - 1; ret_string.truncate(len); let buffer:Vec<&str> = ret_string.split(' ').collect(); let var:f32 = (buffer[0]).parse::<f32>().unwrap(); let var2:f32 = (buffer[1]).parse::<f32>().unwrap(); list.push(Measure::new(var,var2)); } else{ break; } ret_string.clear(); } return list; } fn main() { let measures = read_measures_from_file(env::args().skip(1).next().unwrap()); let mut clsf = Classifier::new(3f32); let d = Duration::span(||{ for i in measures{ clsf. classificate(i); } if cfg!(merge_classes){ clsf.merge_classes(); } }); println!("work time: {}", d.secs() as f64 + d.extra_nanos()as f64 / 1000000000.0f64); for i in clsf.list{ let i = i.borrow(); println!("[{}, {}]: {}",i.mean.x,i.mean.y, i.count); } }