Advertisement
Guest User

Untitled

a guest
Mar 6th, 2017
184
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 4.85 KB | None | 0 0
  1. //--------------------
  2. // TOML /*
  3. [package]
  4. name = "ts"
  5. version = "0.1.0"
  6. authors = ["xxx.xxx <xxx.xxx>"]
  7.  
  8. [dependencies]
  9. csv = "*"
  10. clap = "*"
  11. */
  12. //--------------------
  13.  
  14.  
  15. // Loading external crates
  16. extern crate clap;      // Command line parsing
  17. extern crate csv;       // CSV loading
  18.  
  19. use std::cmp::PartialEq;
  20.  
  21.  
  22. // --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
  23. // Time series trait
  24. // --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
  25.  
  26. struct TimeSerie {
  27.     class:String,
  28.     data:Vec<f64>,
  29.     ptr:*const f64
  30. }
  31.  
  32. impl TimeSerie {
  33.  
  34.     #[inline(always)]
  35.     fn length(&self) -> usize {
  36.         self.data.len()
  37.     }
  38.  
  39.     #[inline(always)]
  40.     fn at(&self, idx:isize) -> f64 { unsafe{*self.ptr.offset(idx)} }
  41.  
  42.     #[inline(always)]
  43.     fn square_dist(&self, self_idx: isize, other_idx:isize, other: &Self) -> f64 {
  44.         let dif = self.at(self_idx) - other.at(other_idx);
  45.         dif*dif
  46.     }
  47.  
  48.     fn compute_dtw(&self, other: &Self, m : *mut f64) -> f64 {
  49.         let dim = self.length() as isize;
  50.         unsafe{
  51.             // --- Init 0,0
  52.             *m = self.square_dist(0, 0, other);
  53.  
  54.             // --- Init the two "axis"
  55.             // --- --- first line, along columns (0, ..): self
  56.             // --- --- first column, along lines (.., 0): other
  57.             for x in 1..dim as isize {
  58.                 *m.offset(x) = *m.offset(x-1) + self.square_dist(0, x, other);               // First line
  59.                 *m.offset(dim*x) = *m.offset(dim*(x-1)) + self.square_dist(x, 0, other);     // First col
  60.             }
  61.  
  62.             // --- Compute DTW
  63.             for idx_col in 1..dim as isize {
  64.                 for idx_line in 1..dim as isize {
  65.                     *m.offset(dim*idx_line+idx_col) = {
  66.                         // Compute ancestors
  67.                         let d11 = *m.offset(dim*(idx_line-1) + idx_col-1);
  68.                         let d01 = *m.offset(dim*(idx_line)   + idx_col-1);
  69.                         let d10 = *m.offset(dim*(idx_line-1) + idx_col);
  70.                         // Take the smallest ancestor and add the current distance
  71.                         (if d11<d01 { if d11<d10 {d11} else {d10} }
  72.                          else { if d01<d10 {d01} else {d10} }) + self.square_dist(idx_line, idx_col, other)
  73.                             // The next line actually call cmath
  74.                             // d11.min(d01).min(d10) + self.square_dist(idx_line, idx_col, other)
  75.                     };
  76.                 }
  77.             }
  78.             let last = dim - 1 as isize;
  79.             (*m.offset(dim*last+last)) //.sqrt()
  80.         }
  81.  
  82.     }
  83.  
  84.     // --- --- --- static functions
  85.     fn new(class:String, data:Vec<f64>) -> TimeSerie { TimeSerie{class: class, ptr: data.as_ptr(), data: data} }
  86. }
  87.  
  88.  
  89.  
  90.  
  91. // --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
  92. // Command line building
  93. // --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
  94. fn check_cli<'a>() -> clap::ArgMatches<'a> {
  95.     let matches = clap::App::new("ts")
  96.         .version("0.0")
  97.         .about("Working with time series")
  98.         .arg(clap::Arg::with_name("INPUT FILE")
  99.              .required(true)
  100.              .index(1)
  101.              .help("Input file, must be a csv")
  102.             ).get_matches();
  103.     return matches;
  104. }
  105.  
  106.  
  107.  
  108. // --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
  109. // Main app
  110. // --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---
  111. fn main() {
  112.  
  113.     // --- 0: Get the command line arguments
  114.     let matches = check_cli();
  115.     let file = matches.value_of("INPUT FILE").unwrap();
  116.  
  117.     // --- 1: Load the CSV
  118.     let mut rdr = csv::Reader::from_file(file).unwrap();
  119.     let rows = rdr.records().map(|r| r.unwrap());
  120.     let mut vec:Vec<TimeSerie> = Vec::new();
  121.     for row in rows {
  122.         let mut iter = row.into_iter();
  123.         let class:String = iter.next().unwrap();
  124.         let data:Vec<f64> = iter.map( |s| s.parse().unwrap() ).collect();
  125.         vec.push( TimeSerie::new(class, data) );
  126.     }
  127.  
  128.     // --- 2: Compute sum of DTW
  129.     let mut total_e:f64 = 0.0;
  130.     let ts_size = vec[0].length();
  131.     let working_area = vec![0 as f64; ts_size * ts_size].as_mut_ptr();
  132.  
  133.     let now = std::time::SystemTime::now();
  134.     for (id, vi) in vec.iter().enumerate() {
  135.         for vj in vec.iter().skip(id) {
  136.             total_e += vi.compute_dtw(vj, working_area);
  137.         }
  138.     }
  139.     match now.elapsed() {
  140.         Ok(elapsed) => { println!("{} s", elapsed.as_secs()); }
  141.         Err(_) => { () }
  142.     }
  143.  
  144.     println!("Total error: {}", total_e);
  145. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement