-
-
Notifications
You must be signed in to change notification settings - Fork 53
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
Random distribution sampling #416
Random distribution sampling #416
Conversation
Thank you! I'd be very glad to accept more functions like these, especially if they can be implemented in Numbat. Before we do so, let's maybe discuss a minimum standard:
Please feel free to add more of these in a single PR if that is easier for you. |
Thanks a lot for your feedback!
Yes, that might be better. I will bundle them into a single PR. |
Since you are already reviewing, here are a few more notes on the implementations that might be relevant which I had not written up yet because I have not yet had time to look into the testing question:
|
# name: Normal distribution sampling | ||
# url: https://en.wikipedia.org/wiki/Normal_distribution | ||
# description: Samples a normal distribution with mean μ and standard deviation σ using the Box-Muller transform. | ||
fn rand_norm<T>(μ: T, σ: T) -> T = | ||
μ + sqrt(-2 σ² × ln(random())) × sin(2π × random()) |
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.
😍
numbat/modules/core/random.nbt
Outdated
fn rand_pareto<T>(α: Scalar, min: T) -> T = | ||
if value_of(min) > 0 && α > 0 | ||
then min / ((1-random())^(1/α)) | ||
else NaN * unit_of(min) |
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.
We should really make 0, NaN and inf polymorphic (#37).
Thank you very much — this looks fantastic! I wrote a small example program (in Rust... we really need a list data type in Numbat!) to sample large amounts of numbers from those distributions and compared the normalized histograms with the PDFs of those distributions. Everything looked correct 👍 use numbat::{
module_importer::FileSystemImporter, resolver::CodeSource, Context, InterpreterResult,
};
use std::path::Path;
fn get_value(ctx: &mut Context, code: &str) -> f64 {
match ctx.interpret(code, CodeSource::Internal).unwrap().1 {
InterpreterResult::Value(v) => v.unsafe_as_quantity().unsafe_value().0,
_ => todo!(),
}
}
fn main() {
let module_path = Path::new(&std::env::var_os("CARGO_MANIFEST_DIR").unwrap()).join("modules");
let mut importer = FileSystemImporter::default();
importer.add_path(module_path);
let mut ctx = Context::new(importer);
let _result = ctx.interpret("use all", CodeSource::Internal).unwrap();
let code = std::env::args().nth(1).unwrap();
let results = (0..10000)
.map(|_| get_value(&mut ctx, code.as_str()))
.collect::<Vec<_>>();
for r in results {
println!("{}", r);
}
} And a Python script to plot a histogram: import matplotlib.pyplot as plt
import numpy as np
import sys
data = np.loadtxt(sys.argv[1])
weights = np.ones_like(data) / len(data)
plt.hist(data, bins=50, weights=weights)
plt.show()
👍
I think that is completely acceptable. Changing that would require us to keep state somewhere (like in a static variable), right?
👍
👍 |
Co-authored-by: David Peter <sharkdp@users.noreply.github.com>
I just implemented a proper version of |
Thanks a lot for all your comments and catching my mistakes!
Thanks, this is really helpful! I think if we wanted to integrate this in the normal testing one should be able to do a Kolmogorov-Smirnov test to automatically judge whether the expected pdf fits the sampled data. I will have a look if there is a rust library that would let us do this easily.
Yes, the Box-Muller transform provides two independent random numbers at a time and we only use one of them. |
Oh perfect, thanks a lot, this will make it a lot more user friendly! |
I'd be okay with merging this without any additional tests. If you want to work on that, please feel free to go ahead. ~~But let's also keep test execution time in mind. Drawing 10000 samples in debug mode (which is what we usually have for Edit: nevermind. if you want to implement this, let's just do it. Worst case, we can deactivate those tests locally and only run them in CI, if they take too long. |
1136774
to
f5c1475
Compare
Well, I am not totally sure it is worth the effort then. Implementation would not be straight forward for me as I am not familiar with any of the rust libraries that can do K-S tests and these functions are not likely going to be modified a lot or rely on parts that are likely change a lot so it may be good enough to manually compare the histograms instead of doing it automatically. |
numbat/modules/core/random.nbt
Outdated
fn rand_expon<T>(λ: T) -> 1/T = | ||
if value_of(λ) > 0 | ||
then - ln(1-random()) / λ | ||
else error("Argument λ must not be positive.") |
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.
else error("Argument λ must not be positive.") | |
else error("Argument λ must be positive.") |
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.
Thanks for catching this, that was a silly mistake.
…andom sampling functions.
f5c1475
to
d373f78
Compare
Thank you! |
Welcome, thanks a lot for your help! |
This PR adds the function
rand_uniform(a, b)
which samples the continuous uniform distribution using inversion sampling. The function takes care of argument reversal.Partially addresses #413.