Skip to content

Commit

Permalink
M src/list/raxos/evolution/src/contour.rs
Browse files Browse the repository at this point in the history
  • Loading branch information
drmingdrmer committed Sep 7, 2024
1 parent c61f629 commit d180d30
Show file tree
Hide file tree
Showing 5 changed files with 286 additions and 123 deletions.
130 changes: 94 additions & 36 deletions src/list/raxos/evolution/src/contour.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,35 @@
use std::fmt;

use crate::point::Point;

pub struct CC<'a>(pub &'a Contour, pub usize);

impl<'a> fmt::Display for CC<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}:{}", self.1, self.0)
}
}

/// The Contour line of all the points that have the same value
///
/// This is not an accurate line.
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct Contour {
pub points: Vec<Point>,
}

impl fmt::Display for Contour {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for (i, p) in self.points.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", p)?;
}
Ok(())
}
}

impl Contour {
pub fn new(points: impl IntoIterator<Item = Point>) -> Self {
Self {
Expand All @@ -20,8 +42,15 @@ impl Contour {
/// `prob_move` is the chance of moving a point.
/// `1 - prob_move` is the chance of adding a new point.
pub fn rand_update(&self, prob_move: f64) -> Self {
let l = self.points.len();

// Generate a rand number between 0 and 1
let rand = rand::random::<f64>();
let mut rand = rand::random::<f64>();

if l <= 3 {
// always move
rand = 0.0;
}

if rand < prob_move {
// move a point
Expand All @@ -31,20 +60,22 @@ impl Contour {
return self.clone();
}

let p0 = self.points[i];

let (x_left, x_right) = if i == 0 {
let right_sibling = self.points[i + 1].x;
(0.0, right_sibling)
} else if i == self.points.len() - 1 {
} else if i == l - 1 {
let left_sibling = self.points[i - 1].x;
(left_sibling, (left_sibling * 1.5f64))
(left_sibling, (self.points[i].x * 1.5f64))
} else {
(self.points[i - 1].x, self.points[i + 1].x)
};

let (y_low, y_high) = if i == 0 {
let right_sibling = self.points[i + 1].y;
(right_sibling, (right_sibling * 1.5f64))
} else if i == self.points.len() - 1 {
(right_sibling, (self.points[i].y * 1.5f64))
} else if i == l - 1 {
let last = self.points[i - 1].y;
(0.0, last)
} else {
Expand All @@ -53,46 +84,73 @@ impl Contour {

let mut points = self.points.clone();

points[i] = Point::new(
let p = Point::new(
rand::random::<f64>() * (x_right - x_left) + x_left,
rand::random::<f64>() * (y_high - y_low) + y_low,
);
// println!("Move point {}/{l} {} to {}", i, p0, p);
if i == l - 1 {
println!("Move point {}/{l} {} to {}", i, p0, p);
}
points[i] = p;
Self { points }
} else {
// Add a new point
let add_remove = rand::random::<f64>();
if add_remove > 0.5 {
// Add a new point

// The index of point before which to add new point
let i = (rand::random::<u64>() as usize) % (self.points.len() + 1);
// The index of point before which to add new point
let i = (rand::random::<u64>() as usize) % (self.points.len() + 1);

let (x_left, x_right) = if i == 0 {
let right_sibling = self.points[i].x;
(0.0, right_sibling)
} else if i == self.points.len() {
let left_sibling = self.points[i - 1].x;
(left_sibling, (left_sibling * 1.5f64))
} else {
(self.points[i - 1].x, self.points[i].x)
};
let (x_left, x_right) = if i == 0 {
let right_sibling = self.points[i].x;
(0.0, right_sibling)
} else if i == self.points.len() {
let left_sibling = self.points[i - 1].x;
(left_sibling, (left_sibling * 1.5f64))
} else {
(self.points[i - 1].x, self.points[i].x)
};

let (y_low, y_high) = if i == 0 {
let right_sibling = self.points[i].y;
(right_sibling, (right_sibling * 1.5f64))
} else if i == self.points.len() {
let last = self.points[i - 1].y;
(0.0, last)
} else {
(self.points[i].y, self.points[i - 1].y)
};
let (y_low, y_high) = if i == 0 {
let right_sibling = self.points[i].y;
(right_sibling, (right_sibling * 1.5f64))
} else if i == self.points.len() {
let last = self.points[i - 1].y;
(0.0, last)
} else {
(self.points[i].y, self.points[i - 1].y)
};

let mut points = self.points.clone();
points.insert(
i,
Point::new(
let mut points = self.points.clone();
let p = Point::new(
rand::random::<f64>() * (x_right - x_left) + x_left,
rand::random::<f64>() * (y_high - y_low) + y_low,
),
);
Self { points }
);
// println!("Add point {}/{l} at {}", i, p);
if i == l {
println!("Add point {}/{l} at {}", i, p);
}
points.insert(i, p);
Self { points }
} else {
// remove a point
let i = (rand::random::<u64>() as usize) % self.points.len();
if self.points[i] == Point::new(1f64, 1f64) {
// The unit point should not be removed
return self.clone();
}

let mut points = self.points.clone();
// println!("Remove point at {}/{l} {}", i, points[i]);

if i == l - 1 {
println!("Remove point at {}/{l} {}", i, points[i]);
}

points.remove(i);
Self { points }
}
}
}

Expand Down Expand Up @@ -140,7 +198,7 @@ impl Contour {
assert!(self
.points
.iter()
.position(|p| *p == Point::new(0.0, 0.0))
.position(|p| *p == Point::new(1.0, 1.0))
.is_some());

for i in 1..self.points.len() {
Expand Down
82 changes: 82 additions & 0 deletions src/list/raxos/evolution/src/display_slice.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
use std::fmt;

/// Implement `Display` for `&[T]` if T is `Display`.
///
/// It outputs at most `MAX` elements, excluding those from the 5th to the second-to-last one:
/// - `DisplaySlice(&[1,2,3,4,5,6])` outputs: `"[1,2,3,4,...,6]"`.
pub(crate) struct DisplaySlice<'a, T: fmt::Display, const MAX: usize = 5>(pub &'a [T]);

impl<'a, T: fmt::Display, const MAX: usize> fmt::Display for DisplaySlice<'a, T, MAX> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let slice = self.0;
let len = slice.len();

write!(f, "[")?;

if len > MAX {
for (i, t) in slice[..(MAX - 1)].iter().enumerate() {
if i > 0 {
write!(f, ",")?;
}

write!(f, "{}", t)?;
}

write!(f, ",..,")?;
write!(f, "{}", slice.last().unwrap())?;
} else {
for (i, t) in slice.iter().enumerate() {
if i > 0 {
write!(f, ",")?;
}

write!(f, "{}", t)?;
}
}

write!(f, "]")
}
}

pub(crate) trait DisplaySliceExt<'a, T: fmt::Display> {
fn display(&'a self) -> DisplaySlice<'a, T>;

/// Display at most `MAX` elements.
fn display_n<const MAX: usize>(&'a self) -> DisplaySlice<'a, T, MAX>;
}

impl<T> DisplaySliceExt<'_, T> for [T]
where
T: fmt::Display,
{
fn display(&self) -> DisplaySlice<T> {
DisplaySlice(self)
}

fn display_n<const MAX: usize>(&'_ self) -> DisplaySlice<'_, T, MAX> {
DisplaySlice(self)
}
}

#[cfg(test)]
mod tests {
use crate::display_slice::DisplaySlice;

#[test]
fn test_display_slice() {
let a = vec![1, 2, 3, 4];
assert_eq!("[1,2,3,4]", DisplaySlice::<_>(&a).to_string());

let a = vec![1, 2, 3, 4, 5];
assert_eq!("[1,2,3,4,5]", DisplaySlice::<_>(&a).to_string());

let a = vec![1, 2, 3, 4, 5, 6];
assert_eq!("[1,2,3,4,..,6]", DisplaySlice::<_>(&a).to_string());

let a = vec![1, 2, 3, 4, 5, 6, 7];
assert_eq!("[1,2,3,4,..,7]", DisplaySlice::<_>(&a).to_string());

let a = vec![1, 2, 3, 4, 5, 6, 7];
assert_eq!("[1,..,7]", DisplaySlice::<_, 2>(&a).to_string());
}
}
Loading

0 comments on commit d180d30

Please sign in to comment.