Skip to content

Commit

Permalink
Merge pull request #63 from jpursell/from-points
Browse files Browse the repository at this point in the history
Add from_points method to NAMatrix
  • Loading branch information
johann-cm authored Jun 28, 2024
2 parents 6cdd285 + 85676ea commit 4520a87
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 0 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,14 @@ Options:
Print version
```

### As a library call

```
let points = vec![[0.0, 0.0], [0.0, 1.0], [2.0, 3.0]];
let graph = NAMatrix::from_points(&points);
let solution = christofides::<{ computation_mode::PAR_COMPUTATION }>(&graph);
```

## Algorithms

The algorithms can be found in the technical report (which will be uploaded soon)
Expand Down
67 changes: 67 additions & 0 deletions src/datastructures/nalgebra.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::datastructures::Graph;
use nalgebra::{DMatrix, DVector};
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
use std::ops::{Deref, DerefMut};

use super::{AdjacencyMatrix, Edge};
Expand All @@ -8,6 +9,44 @@ use super::{AdjacencyMatrix, Edge};
#[derive(Debug, PartialEq)]
pub struct NAMatrix(pub DMatrix<f64>);

impl NAMatrix {
/// Create from set of x/y points, using the euclidean distance
pub fn from_points(points: &[[f64; 2]]) -> Self {
let mut matrix = NAMatrix::from_dim(points.len());
points.iter().enumerate().for_each(|(i, from)| {
points.iter().skip(i + 1).enumerate().for_each(|(j, to)| {
let j = i + j + 1;
let weight = ((from[0] - to[0]).powi(2) + (from[1] - to[1]).powi(2)).sqrt();
// uses the fact, that the euclidean distance is symmetric
matrix[(i, j)] = weight;
matrix[(j, i)] = weight;
});
});
matrix
}
/// Create from set of x/y points, using the euclidean distance.
/// Computation is parallelized via rayon.
pub fn par_from_points(points: &[[f64; 2]]) -> Self {
let mut matrix = NAMatrix::from_dim(points.len());
points
.par_iter()
.zip(matrix.par_column_iter_mut())
.for_each(|(from, mut matrix_col_j)| {
//let from = &points[i];
points
.iter()
.zip(matrix_col_j.iter_mut())
.for_each(|(to, matrix_ij)| {
let weight = ((from[0] - to[0]).powi(2) + (from[1] - to[1]).powi(2)).sqrt();
// cannot use the fact, that the euclidean distance is symmetric,
// due to borrowing rules for parallel iterators
*matrix_ij = weight;
});
});
matrix
}
}

impl Deref for NAMatrix {
type Target = DMatrix<f64>;
fn deref(&self) -> &Self::Target {
Expand Down Expand Up @@ -92,4 +131,32 @@ mod test {

assert_eq!(expected, (&graph).into());
}

#[test]
fn test_from_points() {
let points = vec![[0.0, 0.0], [0.0, 1.0], [2.0, 3.0]];
let matrix = NAMatrix::from_points(&points);
for i in 0..points.len() {
for j in 0..points.len() {
let dist = ((points[i][0] - points[j][0]).powi(2)
+ (points[i][1] - points[j][1]).powi(2))
.sqrt();
assert_eq!(dist, matrix[(i, j)]);
}
}
}

#[test]
fn test_par_from_points() {
let points = vec![[0.0, 0.0], [0.0, 1.0], [2.0, 3.0]];
let matrix = NAMatrix::par_from_points(&points);
for i in 0..points.len() {
for j in 0..points.len() {
let dist = ((points[i][0] - points[j][0]).powi(2)
+ (points[i][1] - points[j][1]).powi(2))
.sqrt();
assert_eq!(dist, matrix[(i, j)]);
}
}
}
}

0 comments on commit 4520a87

Please sign in to comment.