Guest User

Untitled

a guest
May 26th, 2018
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.27 KB | None | 0 0
  1. extern crate rand;
  2.  
  3. use rand::Rng;
  4.  
  5. use std::cmp::Ordering;
  6. use std::fmt;
  7. use std::ops::Bound::Included;
  8. use std::cmp::Ordering::Less;
  9.  
  10. use std::collections::BTreeSet;
  11. use std::time::{Duration, Instant};
  12.  
  13. static mut cnt: u64 = 0;
  14.  
  15. fn main() {
  16. for dimension in 2..=6 {
  17. let mut v = makerandompoints(1600, dimension);
  18. get_closest_pair(&mut v);
  19. }
  20.  
  21. }
  22.  
  23. #[derive(Debug, Clone)]
  24. pub struct Point {
  25. pub coordinates: Vec<f64>,
  26. }
  27.  
  28. impl Point {
  29. pub fn new(coordinates: Vec<f64>) -> Point {
  30. Point { coordinates }
  31. }
  32. pub fn distance(point1: &Point, point2: &Point) -> f64 {
  33. point1
  34. .coordinates
  35. .iter()
  36. .zip(point2.coordinates.iter())
  37. .map(|(x1, x2)| (x1 - x2).powi(2))
  38. .sum::<f64>()
  39. .sqrt()
  40. }
  41.  
  42. }
  43.  
  44. pub fn get_closest_pair<'a>(points: &'a mut Vec<Point>) -> (&'a Point, &'a Point) {
  45. let mut total_time = Duration::from_secs(0);
  46. let mut total_cmp = 0;
  47.  
  48. let firstco = |p: &Point| p.coordinates[0];
  49. let secondco = |p: &Point| p.coordinates[1];
  50. points.sort_unstable_by(|p1, p2| firstco(p1).partial_cmp(&firstco(p2)).unwrap_or(Less));
  51.  
  52. let mut closest_pair = (&points[0], &points[1]);
  53. let mut min_distance = Point::distance(closest_pair.0, closest_pair.1);
  54.  
  55. let mut set = BTreeSet::new();
  56. set.insert(&points[0]);
  57. if !set.insert(&points[1]) {
  58. return (&points[0], &points[1]);
  59. }
  60.  
  61. let mut points = points.iter();
  62. points.nth(1);
  63.  
  64. let mut rangepoints = make_zero_points(closest_pair.0.coordinates.len());
  65.  
  66. let mut removalvec: Vec<&Point> = Vec::new();
  67.  
  68. for firstpoint in points {
  69. remove_left_points(&mut removalvec, &mut set);
  70. set_range(
  71. secondco(firstpoint),
  72. min_distance,
  73. &mut rangepoints.0,
  74. &mut rangepoints.1,
  75. );
  76.  
  77. {
  78. //timing occurs here!
  79. let startcnt = unsafe { cnt };
  80. let starttime = Instant::now();
  81. let range = set.range::<Point, _>((Included(&rangepoints.0), Included(&rangepoints.1)));
  82. //let foo = set.contains(&rangepoints.0);
  83. total_time += starttime.elapsed();
  84. total_cmp += unsafe { cnt } - startcnt;
  85. //println!("{}", unsafe { cnt } - startcnt);
  86.  
  87. for secondpoint in
  88. set.range::<Point, _>((Included(&rangepoints.0), Included(&rangepoints.1)))
  89. {
  90. if firstco(secondpoint) <= firstco(firstpoint) - min_distance {
  91. removalvec.push(secondpoint);
  92. continue;
  93. }
  94.  
  95. let distance = Point::distance(firstpoint, secondpoint);
  96. if distance < min_distance {
  97. min_distance = distance;
  98. closest_pair = (secondpoint, firstpoint);
  99. }
  100. }
  101. }
  102.  
  103. if !set.insert(firstpoint) {
  104. //if we want references to two seperate points, we can do
  105. //a search in the points vector, which takes O(n) time
  106. return (firstpoint, firstpoint);
  107. }
  108. }
  109. println!("partialtiming: {}", time_to_string(total_time));
  110. println!("total_cmp: {}", total_cmp);
  111. closest_pair
  112. }
  113.  
  114. fn remove_left_points(removalvec: &mut Vec<&Point>, set: &mut BTreeSet<&Point>) {
  115. for point in removalvec.drain(..) {
  116. if !set.remove(point) {
  117. panic!("tried to remove nonexistant item");
  118. }
  119. }
  120. }
  121.  
  122. fn set_range(coordinate: f64, distance: f64, point1: &mut Point, point2: &mut Point) {
  123. point1.coordinates[1] = coordinate - distance;
  124. point2.coordinates[1] = coordinate + distance;
  125. }
  126.  
  127. fn make_zero_points(length: usize) -> (Point, Point) {
  128. let zero_vec1 = vec![0.0; length];
  129. let zero_vec2 = vec![0.0; length];
  130. (Point::new(zero_vec1), Point::new(zero_vec2))
  131. }
  132.  
  133.  
  134. impl fmt::Display for Point {
  135. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  136. write!(
  137. f,
  138. "{}",
  139. self.coordinates
  140. .iter()
  141. .map(ToString::to_string)
  142. .collect::<Vec<String>>()
  143. .join(" ")
  144. )
  145. }
  146. }
  147.  
  148. impl PartialEq for Point {
  149. fn eq(&self, other: &Point) -> bool {
  150. self.coordinates.eq(&other.coordinates)
  151. }
  152. }
  153.  
  154. impl Eq for Point {}
  155.  
  156. impl PartialOrd for Point {
  157. fn partial_cmp(&self, other: &Point) -> Option<Ordering> {
  158.  
  159. // cutsom cmp:
  160. (&self.coordinates[1..], &self.coordinates[0])
  161. .partial_cmp(&(&other.coordinates[1..], &other.coordinates[0]))
  162.  
  163. // vec cmp:
  164. // self.coordinates.partial_cmp(&other.coordinates)
  165.  
  166. }
  167. }
  168.  
  169. impl Ord for Point {
  170. fn cmp(&self, other: &Point) -> Ordering {
  171. unsafe { cnt += 1;}
  172. match Point::partial_cmp(self, other) {
  173. Some(ordering) => ordering,
  174. None => unreachable!(),
  175. }
  176. }
  177. }
  178.  
  179. pub fn makerandompoints(amount: usize, dimension: usize) -> Vec<Point> {
  180. let mut rng = rand::thread_rng();
  181. (0..amount)
  182. .map(|_| Point::new((0..dimension).map(|_| rng.gen_range(0.0, 10.0)).collect()))
  183. .collect()
  184. }
  185.  
  186. pub fn time_to_string(time: Duration) -> String {
  187. let time = time.as_secs() as f64 * 1e9 + time.subsec_nanos() as f64;
  188. format!("{}", time)
  189. }
  190.  
  191. pub fn time_to_string_ms(time: Duration) -> String {
  192. let time = time.as_secs() as f64 * 1e3 + time.subsec_nanos() as f64 / 1e6;
  193. format!("{}", time)
  194. }
Add Comment
Please, Sign In to add comment