From dc545e4063f4be1b915d60447074f86ff81a0452 Mon Sep 17 00:00:00 2001 From: Anders Olsson Date: Thu, 6 Feb 2020 10:01:43 +0100 Subject: [PATCH] Initial commit. Basic structure in place, need to implement logic. --- .gitignore | 3 +++ Cargo.toml | 8 ++++++ examples/basic.rs | 56 +++++++++++++++++++++++++++++++++++++++ src/kernel.rs | 11 ++++++++ src/kernel/constant.rs | 13 +++++++++ src/kernel/exponential.rs | 14 ++++++++++ src/kernel/matern52.rs | 14 ++++++++++ src/lib.rs | 6 +++++ src/model.rs | 23 ++++++++++++++++ 9 files changed, 148 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 examples/basic.rs create mode 100644 src/kernel.rs create mode 100644 src/kernel/constant.rs create mode 100644 src/kernel/exponential.rs create mode 100644 src/kernel/matern52.rs create mode 100644 src/lib.rs create mode 100644 src/model.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6936990 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target +**/*.rs.bk +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..37bd60c --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "kickscore" +version = "0.1.0" +authors = ["Anders Olsson "] +edition = "2018" + +[dependencies] +ndarray = "0.13" \ No newline at end of file diff --git a/examples/basic.rs b/examples/basic.rs new file mode 100644 index 0000000..86df4f5 --- /dev/null +++ b/examples/basic.rs @@ -0,0 +1,56 @@ +use kickscore as ks; + +fn main() { + let mut model = ks::BinaryModel {}; + + // Spike's skill does not change over time. + let k_spike = ks::kernel::Constant::new(0.5); + + // Tom's skill changes over time, with "jagged" (non-smooth) dynamics. + let k_tom = ks::kernel::Exponential::new(1.0, 1.0); + + // Jerry's skill has a constant offset and smooth dynamics. + let k_jerry: Vec> = vec![ + Box::new(ks::kernel::Constant::new(1.0)), + Box::new(ks::kernel::Matern52::new(0.5, 1.0)), + ]; + + // Now we are ready to add the items in the model. + model.add_item("Spike", k_spike); + model.add_item("Tom", k_tom); + model.add_item("Jerry", k_jerry); + + // At first, Jerry beats Tom a couple of times. + model.observe(&["Jerry"], &["Tom"], 0.0); + model.observe(&["Jerry"], &["Tom"], 0.9); + + // Then, Tom beats Spike, and then Jerry. + model.observe(&["Tom"], &["Spike"], 1.7); + model.observe(&["Tom"], &["Jerry"], 2.1); + + // Finally, Jerry beats Tom, and then Tom + Spike. + model.observe(&["Jerry"], &["Tom"], 3.0); + model.observe(&["Jerry"], &["Tom", "Spike"], 3.5); + + model.fit(true); + + // We can predict a future outcome... + let (p_win, p_los) = model.probabilities(&[&"Jerry"], &[&"Tom"], 4.0); + println!( + "Chances that Jerry beats Tom at t = 4.0: {:.1}%", + 100.0 * p_win + ); + + // ... or simulate what could have happened in the past. + let (p_win, p_los) = model.probabilities(&[&"Jerry"], &[&"Tom"], 2.0); + println!( + "Chances that Jerry beats Tom at t = 2.0: {:.1}%", + 100.0 * p_win + ); + + let (p_win, p_los) = model.probabilities(&[&"Jerry"], &[&"Tom"], -1.0); + println!( + "Chances that Jerry beats Tom at t = -1.0: {:.1}%", + 100.0 * p_win + ); +} diff --git a/src/kernel.rs b/src/kernel.rs new file mode 100644 index 0000000..89ee905 --- /dev/null +++ b/src/kernel.rs @@ -0,0 +1,11 @@ +mod constant; +mod exponential; +mod matern52; + +pub use constant::Constant; +pub use exponential::Exponential; +pub use matern52::Matern52; + +pub trait Kernel {} + +impl Kernel for Vec> {} diff --git a/src/kernel/constant.rs b/src/kernel/constant.rs new file mode 100644 index 0000000..3b67ae7 --- /dev/null +++ b/src/kernel/constant.rs @@ -0,0 +1,13 @@ +use super::Kernel; + +pub struct Constant { + var: f64, +} + +impl Constant { + pub fn new(var: f64) -> Self { + Constant { var } + } +} + +impl Kernel for Constant {} diff --git a/src/kernel/exponential.rs b/src/kernel/exponential.rs new file mode 100644 index 0000000..2a602c6 --- /dev/null +++ b/src/kernel/exponential.rs @@ -0,0 +1,14 @@ +use super::Kernel; + +pub struct Exponential { + var: f64, + l_scale: f64, +} + +impl Exponential { + pub fn new(var: f64, l_scale: f64) -> Self { + Exponential { var, l_scale } + } +} + +impl Kernel for Exponential {} diff --git a/src/kernel/matern52.rs b/src/kernel/matern52.rs new file mode 100644 index 0000000..7501220 --- /dev/null +++ b/src/kernel/matern52.rs @@ -0,0 +1,14 @@ +use super::Kernel; + +pub struct Matern52 { + var: f64, + l_scale: f64, +} + +impl Matern52 { + pub fn new(var: f64, l_scale: f64) -> Self { + Matern52 { var, l_scale } + } +} + +impl Kernel for Matern52 {} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..5ea3605 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,6 @@ +// https://github.com/lucasmaystre/kickscore/tree/master/kickscore +pub mod kernel; +mod model; + +pub use kernel::Kernel; +pub use model::*; diff --git a/src/model.rs b/src/model.rs new file mode 100644 index 0000000..ec81ec3 --- /dev/null +++ b/src/model.rs @@ -0,0 +1,23 @@ +use crate::kernel::Kernel; + +pub struct BinaryModel { + // +} + +impl BinaryModel { + pub fn add_item(&mut self, name: &str, kernel: impl Kernel) { + // + } + + pub fn observe(&mut self, winners: &[&str], losers: &[&str], t: f64) { + // + } + + pub fn fit(&mut self, verbose: bool) { + // + } + + pub fn probabilities(&mut self, team1: &[&str], team2: &[&str], t: f64) -> (f64, f64) { + (0.0, 0.0) + } +}