Skip to content

Commit

Permalink
Refactor constructors for covariance matrix.
Browse files Browse the repository at this point in the history
  • Loading branch information
n3vu0r committed Jan 12, 2025
1 parent 113cf6f commit b8e8a8a
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 105 deletions.
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "oefpil"
version = "0.1.1"
version = "0.2.0"
rust-version = "1.82.0"
edition = "2021"
description = """Optimum Estimate of Function Parameters by Iterated Linearization (OEFPIL):
Expand Down Expand Up @@ -42,14 +42,14 @@ rustdoc-args = ["--cfg", "docsrs", "--html-in-header", "katex.html"]
members = ["oefpil-sys"]

[dependencies]
oefpil-sys = { version = "0.1.1", path = "oefpil-sys" }
oefpil-sys = { version = "0.2.0", path = "oefpil-sys" }
derive_more = { version = "1.0.0", features = ["display", "error", "from"] }
rand = { version = "0.8.5", default-features = false, optional = true }
rand_distr = { version = "0.4.3", default-features = false, optional = true }

[dev-dependencies]
rand_chacha = "0.3.1"
const-hex = "1.13.1"
const-hex = "1.14.0"

[lints.rust]
missing-docs = "forbid"
Expand Down
7 changes: 7 additions & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# Version 0.2.0 (2025-01-12)

* Refactor constructors for sample covariance matrix introducing `with_unknown_scale()`.
* Redefine model of `sine.rs` example in degrees rather than radians.
* Improve documentation (e.g., add troubleshooting section, fix index in formula).
* Update KaTeX.

# Version 0.1.1 (2024-12-15)

* Clean up documentation (e.g., links).
Expand Down
32 changes: 16 additions & 16 deletions examples/sine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ use rand_chacha::{rand_core::SeedableRng, ChaChaRng};
#[allow(clippy::float_cmp)]
fn main() -> Result<(), OefpilError> {
// Define explicit model of one independent variable and two parameters.
let model = Model {
fx: |x, p| p[1] * (x[0] + p[0]).sin(),
dfdx: &[|x, p| p[1] * (x[0] + p[0]).cos()],
const MODEL: Model = Model {
fx: |x, p| p[1] * (x[0] + p[0]).to_radians().sin(),
dfdx: &[|x, p| p[1] * (x[0] + p[0]).to_radians().cos().to_radians()],
dfdp: &[
|x, p| p[1] * (x[0] + p[0]).cos(),
|x, p| (x[0] + p[0]).sin(),
|x, p| p[1] * (x[0] + p[0]).to_radians().cos().to_radians(),
|x, p| (x[0] + p[0]).to_radians().sin(),
],
implicit: false,
};
// Define true values.
let p_mean = [8f64.to_radians(), 10.0];
let x_mean = [-60.0, -40.0, -20.0, -10.0, 10.0, 20.0, 40.0, 60.0].map(f64::to_radians);
let y_mean = x_mean.map(|x_mean| (model.fx)(&[x_mean], &p_mean));
let p_mean = [8f64, 10.0];
let x_mean = [-60.0, -40.0, -20.0, -10.0, 10.0, 20.0, 40.0, 60.0];
let y_mean = x_mean.map(|x_mean| (MODEL.fx)(&[x_mean], &p_mean));
// Define covariance matrix with constant Pearson `correlation` `coefficient` (PCC).
let x_deviation = x_mean.map(|x| x.abs() * 2e-2);
let y_deviation = y_mean.map(|y| y.abs() * 8e-2);
Expand All @@ -30,7 +30,7 @@ fn main() -> Result<(), OefpilError> {
.zip(&y_deviation)
.map(|(x, y)| x * y * coefficient)
.collect::<Vec<f64>>();
let covariance = &Covariance::new_diagonals(8, 2, true)
let covariance = &Covariance::new_diagonals(8, 2)
.with_tile(0, 0, &x_deviation.map(|x| x * x))?
.with_tile(1, 1, &y_deviation.map(|y| y * y))?
.with_tile(0, 1, &correlation)?
Expand All @@ -54,7 +54,7 @@ fn main() -> Result<(), OefpilError> {
covariance,
};
// Pretend mediocre estimates of parameter means and assign output slices.
let p_mean_initial = [9.5f64.to_radians(), 12.0];
let p_mean_initial = [9.5f64, 12.0];
let mut parameter = Parameter {
mean: &mut p_mean_initial.clone(),
deviation: &mut [0f64; 2],
Expand All @@ -63,14 +63,14 @@ fn main() -> Result<(), OefpilError> {
};
// Perform fitting with default settings.
let oefpil = Algorithm::default();
let report = oefpil.fit(model, &mut variable, &mut parameter, Logfile::default())?;
let report = oefpil.fit(MODEL, &mut variable, &mut parameter, Logfile::default())?;
// Assert expected results.
let round = |value: f64| (value * 1e2).round() / 1e2;
assert_eq!(7, report.iterations);
assert_eq!(0.73, report.chi_squared_p_value().map(round)?);
// `parameter.mean` deviates from `p_mean` in agreement with `parameter.deviation`.
assert_eq!(8.16, round(parameter.mean[0].to_degrees()));
assert_eq!(0.19, round(parameter.deviation[0].to_degrees()));
assert_eq!(8.16, round(parameter.mean[0]));
assert_eq!(0.19, round(parameter.deviation[0]));
assert_eq!(9.95, round(parameter.mean[1]));
assert_eq!(0.28, round(parameter.deviation[1]));
assert_eq!(0.30, round(parameter.correlation[1]));
Expand All @@ -91,7 +91,7 @@ fn main() -> Result<(), OefpilError> {
deviation: &mut [0f64; 2],
correlation: &mut [0f64; 4],
};
oefpil.fit(model, &mut variable, &mut parameter, Logfile::default())?;
oefpil.fit(MODEL, &mut variable, &mut parameter, Logfile::default())?;
p_sample[sample] = parameter.mean[0];
p_sample[sample + samples] = parameter.mean[1];
p_correlation[sample] = parameter.correlation[1];
Expand All @@ -106,8 +106,8 @@ fn main() -> Result<(), OefpilError> {
let [p_mean_1, p_deviation_1] = mean_deviation(&p_sample[samples..]);
let [p_correlation_mean, p_correlation_deviation] = mean_deviation(&p_correlation);
// Simulation agrees well with `p_mean` and `parameter.deviation`.
assert_eq!(8.00, round(p_mean_0.to_degrees()));
assert_eq!(0.19, round(p_deviation_0.to_degrees()));
assert_eq!(8.00, round(p_mean_0));
assert_eq!(0.19, round(p_deviation_0));
assert_eq!(10.0, round(p_mean_1));
assert_eq!(0.28, round(p_deviation_1));
assert_eq!(0.30, round(p_correlation_mean));
Expand Down
10 changes: 5 additions & 5 deletions oefpil-sys/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "oefpil-sys"
version = "0.1.1"
version = "0.2.0"
rust-version = "1.82.0"
edition = "2021"
links = "oefpil"
Expand Down Expand Up @@ -32,15 +32,15 @@ include = [
]

[dependencies]
libc = "0.2.159"
special = "0.11.2"
libc = "0.2.169"
special = "0.11.3"

[features]
built-in = []

[build-dependencies]
cc = "1.1.13"
bindgen = { version = "0.71.0", optional = true }
cc = "1.2.9"
bindgen = { version = "0.71.1", optional = true }

[lints.rust]
missing-docs = "forbid"
Expand Down
4 changes: 4 additions & 0 deletions oefpil-sys/RELEASES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Version 0.2.0 (2025-01-12)

* Improve documentation (i.e., use table for system requirements).

# Version 0.1.1 (2024-12-15)

* Clean up documentation (e.g., license files, copyright notices, system requirements).
Expand Down
Loading

0 comments on commit b8e8a8a

Please sign in to comment.