-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
seq WASM compatibility #33
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,8 +27,10 @@ use super::*; | |
use super::select::*; | ||
use super::iterlimit::*; | ||
use super::earlystopper::*; | ||
use std::time::Instant; | ||
use std::boxed::Box; | ||
use std::marker::PhantomData; | ||
use rand::prng::XorShiftRng; | ||
|
||
|
||
/// A sequential implementation of `::sim::Simulation`. | ||
/// The genetic algorithm is run in a single thread. | ||
|
@@ -42,7 +44,6 @@ where | |
iter_limit: IterLimit, | ||
selector: Box<Selector<T, F>>, | ||
earlystopper: Option<EarlyStopper<F>>, | ||
duration: Option<NanoSecond>, | ||
error: Option<String>, | ||
phantom: PhantomData<&'a T>, | ||
} | ||
|
@@ -63,15 +64,13 @@ where | |
iter_limit: IterLimit::new(100), | ||
selector: Box::new(MaximizeSelector::new(3)), | ||
earlystopper: None, | ||
duration: Some(0), | ||
error: None, | ||
phantom: PhantomData::default(), | ||
}, | ||
} | ||
} | ||
|
||
fn step(&mut self) -> StepResult { | ||
let time_start; | ||
|
||
if self.population.is_empty() { | ||
self.error = Some( | ||
|
@@ -88,8 +87,7 @@ where | |
}; | ||
|
||
if !should_stop { | ||
time_start = Instant::now(); | ||
|
||
|
||
let mut children: Vec<T>; | ||
{ | ||
// Perform selection | ||
|
@@ -120,15 +118,6 @@ where | |
} | ||
|
||
self.iter_limit.inc(); | ||
self.duration = match self.duration { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rather than remove this code, I would refactor it to a free function (not exported) and have that function have a different implementation based on the target. The regular implementation would be this removed code, while the WASM implementation would simply return Could you also tell me how you compiled this project for WASM (I tried building it and got over 90 errors for undefined identifiers, such as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll get something up soon that demonstrates that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. about the Instant stuff, it could be as easy as an if/else Option each time, I just thought that there might be a better idea 😆 I guess we can improve later on as well though There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Thanks 👍. That will allow me to help you better.
I don't really understand what you mean here, but we can take a look at it once I get your PR to compile There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I successfully build it like that:
|
||
Some(x) => { | ||
let elapsed = time_start.elapsed(); | ||
let y = elapsed.as_secs() as NanoSecond * 1_000_000_000 | ||
+ u64::from(elapsed.subsec_nanos()) as NanoSecond; | ||
Some(x + y) | ||
} | ||
None => None, | ||
}; | ||
|
||
StepResult::Success // Not done yet, but successful | ||
} else { | ||
|
@@ -169,7 +158,7 @@ where | |
} | ||
|
||
fn time(&self) -> Option<NanoSecond> { | ||
self.duration | ||
None | ||
} | ||
|
||
fn population(&self) -> Vec<T> { | ||
|
@@ -185,7 +174,7 @@ where | |
/// Kill off phenotypes using stochastic universal sampling. | ||
fn kill_off(&mut self, count: usize) { | ||
let ratio = self.population.len() / count; | ||
let mut i = ::rand::thread_rng().gen_range::<usize>(0, self.population.len()); | ||
let mut i = XorShiftRng::new_unseeded().gen_range::<usize>(0, self.population.len()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I know - fromEntropy won't work with WASM though, I was trying to find something that is sufficiently random and available, but I think it will come back to the user to take care of seeding it properly. This is an architecture issue, I'd say - because PRNGs will repeat after a while which means passing in a RNG is going to different than what it is now (I think). But in any case, passing in a seed will need an interface, the question is where 😄 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would think that passing in the seed would go well in the |
||
for _ in 0..count { | ||
self.population.swap_remove(i); | ||
i += ratio; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure why you need this but it might be needed somewhere. Just make sure to remove unused
use
statements if this isn't needed 😄There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True laziness on my side. will be gone soon 👍