Change time to use i64 instead of u64
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,2 +1,4 @@
|
|||||||
/target
|
/target
|
||||||
/Cargo.lock
|
/Cargo.lock
|
||||||
|
|
||||||
|
*.svg
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ edition = "2021"
|
|||||||
approx = { version = "0.5.1", optional = true }
|
approx = { version = "0.5.1", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
plotters = { version = "0.3.1", default-features = false, features = ["svg_backend", "all_elements", "all_series"] }
|
||||||
time = { version = "0.3.9", features = ["parsing"] }
|
time = { version = "0.3.9", features = ["parsing"] }
|
||||||
trueskill-tt = { path = ".", features = ["approx"] }
|
trueskill-tt = { path = ".", features = ["approx"] }
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use plotters::prelude::*;
|
||||||
use time::Date;
|
use time::Date;
|
||||||
use trueskill_tt::{History, IndexMap};
|
use trueskill_tt::{History, IndexMap};
|
||||||
|
|
||||||
@@ -37,13 +38,104 @@ fn main() {
|
|||||||
.assume_utc()
|
.assume_utc()
|
||||||
.unix_timestamp();
|
.unix_timestamp();
|
||||||
|
|
||||||
times.push(time as u64 / (60 * 60 * 24));
|
times.push(time / (60 * 60 * 24));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut hist = History::builder().sigma(1.6).gamma(0.036).build();
|
let mut hist = History::builder().sigma(1.6).gamma(0.036).build();
|
||||||
|
|
||||||
hist.add_events(composition, results, times, vec![]);
|
hist.add_events(composition, results, times, vec![]);
|
||||||
hist.convergence(10, 0.01, true);
|
hist.convergence(10, 0.01, true);
|
||||||
|
|
||||||
|
let players = [
|
||||||
|
("djokovic", "d643"),
|
||||||
|
("federer", "f324"),
|
||||||
|
("sampras", "s402"),
|
||||||
|
("lendl", "l018"),
|
||||||
|
("connors", "c044"),
|
||||||
|
("nadal", "n409"),
|
||||||
|
("john_mcenroe", "m047"),
|
||||||
|
("bjorn_borg", "b058"),
|
||||||
|
("aggasi", "a092"),
|
||||||
|
("hewitt", "h432"),
|
||||||
|
("edberg", "e004"),
|
||||||
|
("vilas", "v028"),
|
||||||
|
("nastase", "n008"),
|
||||||
|
("courier", "c243"),
|
||||||
|
("kuerten", "k293"),
|
||||||
|
("murray", "mc10"),
|
||||||
|
("wilander", "w023"),
|
||||||
|
("roddick", "r485"),
|
||||||
|
];
|
||||||
|
|
||||||
|
let curves = hist.learning_curves();
|
||||||
|
|
||||||
|
let mut x_spec = (f64::MAX, f64::MIN);
|
||||||
|
let mut y_spec = (f64::MAX, f64::MIN);
|
||||||
|
|
||||||
|
for id in players.iter().map(|&(_, id)| index_map.get_or_create(id)) {
|
||||||
|
for (ts, gs) in &curves[&id] {
|
||||||
|
let ts = *ts as f64;
|
||||||
|
|
||||||
|
if ts < x_spec.0 {
|
||||||
|
x_spec.0 = ts;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ts > x_spec.1 {
|
||||||
|
x_spec.1 = ts;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mu = gs.mu as f64;
|
||||||
|
|
||||||
|
if mu < y_spec.0 {
|
||||||
|
y_spec.0 = mu;
|
||||||
|
}
|
||||||
|
|
||||||
|
if mu > y_spec.1 {
|
||||||
|
y_spec.1 = mu;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let root = SVGBackend::new("plot.svg", (1024, 1024)).into_drawing_area();
|
||||||
|
|
||||||
|
root.fill(&WHITE).unwrap();
|
||||||
|
|
||||||
|
let mut chart = ChartBuilder::on(&root)
|
||||||
|
.caption("Hello world", ("sans-serif", 50).into_font())
|
||||||
|
.margin(5)
|
||||||
|
.x_label_area_size(30)
|
||||||
|
.y_label_area_size(30)
|
||||||
|
.build_cartesian_2d(x_spec.0..x_spec.1, y_spec.0..y_spec.1)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
chart.configure_mesh().draw().unwrap();
|
||||||
|
|
||||||
|
for (idx, (player, id)) in players
|
||||||
|
.iter()
|
||||||
|
.map(|&(player, id)| (player, index_map.get_or_create(id)))
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
|
let mut data = Vec::new();
|
||||||
|
|
||||||
|
for (ts, gs) in &curves[&id] {
|
||||||
|
data.push((*ts as f64, gs.mu));
|
||||||
|
}
|
||||||
|
|
||||||
|
let color = Palette99::pick(idx);
|
||||||
|
|
||||||
|
chart
|
||||||
|
.draw_series(LineSeries::new(data, &color))
|
||||||
|
.unwrap()
|
||||||
|
.label(format!("{}", player))
|
||||||
|
.legend(move |(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &color));
|
||||||
|
}
|
||||||
|
|
||||||
|
chart
|
||||||
|
.configure_series_labels()
|
||||||
|
.background_style(&WHITE.mix(0.8))
|
||||||
|
.border_style(&BLACK)
|
||||||
|
.draw()
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
mod csv {
|
mod csv {
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ use crate::{gaussian::Gaussian, player::Player, N_INF};
|
|||||||
pub(crate) struct Agent {
|
pub(crate) struct Agent {
|
||||||
pub(crate) player: Player,
|
pub(crate) player: Player,
|
||||||
pub(crate) message: Gaussian,
|
pub(crate) message: Gaussian,
|
||||||
pub(crate) last_time: u64,
|
pub(crate) last_time: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Agent {
|
impl Agent {
|
||||||
pub(crate) fn receive(&self, elapsed: u64) -> Gaussian {
|
pub(crate) fn receive(&self, elapsed: i64) -> Gaussian {
|
||||||
if self.message != N_INF {
|
if self.message != N_INF {
|
||||||
self.message.forget(self.player.gamma, elapsed)
|
self.message.forget(self.player.gamma, elapsed)
|
||||||
} else {
|
} else {
|
||||||
@@ -22,7 +22,7 @@ impl Default for Agent {
|
|||||||
Self {
|
Self {
|
||||||
player: Player::default(),
|
player: Player::default(),
|
||||||
message: N_INF,
|
message: N_INF,
|
||||||
last_time: u64::MIN,
|
last_time: i64::MIN,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -32,7 +32,7 @@ pub(crate) fn clean<'a, A: Iterator<Item = &'a mut Agent>>(agents: A, last_time:
|
|||||||
a.message = N_INF;
|
a.message = N_INF;
|
||||||
|
|
||||||
if last_time {
|
if last_time {
|
||||||
a.last_time = 0;
|
a.last_time = i64::MIN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/batch.rs
12
src/batch.rs
@@ -9,7 +9,7 @@ pub(crate) struct Skill {
|
|||||||
pub(crate) forward: Gaussian,
|
pub(crate) forward: Gaussian,
|
||||||
backward: Gaussian,
|
backward: Gaussian,
|
||||||
likelihood: Gaussian,
|
likelihood: Gaussian,
|
||||||
pub(crate) elapsed: u64,
|
pub(crate) elapsed: i64,
|
||||||
pub(crate) online: Gaussian,
|
pub(crate) online: Gaussian,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ impl Event {
|
|||||||
pub struct Batch {
|
pub struct Batch {
|
||||||
pub(crate) events: Vec<Event>,
|
pub(crate) events: Vec<Event>,
|
||||||
pub(crate) skills: HashMap<Index, Skill>,
|
pub(crate) skills: HashMap<Index, Skill>,
|
||||||
pub(crate) time: u64,
|
pub(crate) time: i64,
|
||||||
p_draw: f64,
|
p_draw: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ impl Batch {
|
|||||||
composition: Vec<Vec<Vec<Index>>>,
|
composition: Vec<Vec<Vec<Index>>>,
|
||||||
results: Vec<Vec<f64>>,
|
results: Vec<Vec<f64>>,
|
||||||
weights: Vec<Vec<Vec<f64>>>,
|
weights: Vec<Vec<Vec<f64>>>,
|
||||||
time: u64,
|
time: i64,
|
||||||
p_draw: f64,
|
p_draw: f64,
|
||||||
agents: &mut HashMap<Index, Agent>,
|
agents: &mut HashMap<Index, Agent>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@@ -444,10 +444,10 @@ impl Batch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn compute_elapsed(last_time: u64, actual_time: u64) -> u64 {
|
pub(crate) fn compute_elapsed(last_time: i64, actual_time: i64) -> i64 {
|
||||||
if last_time == u64::MIN {
|
if last_time == i64::MIN {
|
||||||
0
|
0
|
||||||
} else if last_time == u64::MAX {
|
} else if last_time == i64::MAX {
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
actual_time - last_time
|
actual_time - last_time
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ impl Gaussian {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn forget(&self, gamma: f64, t: u64) -> Self {
|
pub(crate) fn forget(&self, gamma: f64, t: i64) -> Self {
|
||||||
Self {
|
Self {
|
||||||
mu: self.mu,
|
mu: self.mu,
|
||||||
sigma: (self.sigma.powi(2) + t as f64 * gamma.powi(2)).sqrt(),
|
sigma: (self.sigma.powi(2) + t as f64 * gamma.powi(2)).sqrt(),
|
||||||
|
|||||||
@@ -206,8 +206,8 @@ impl History {
|
|||||||
(step, i)
|
(step, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn learning_curves(&self) -> HashMap<Index, Vec<(u64, Gaussian)>> {
|
pub fn learning_curves(&self) -> HashMap<Index, Vec<(i64, Gaussian)>> {
|
||||||
let mut data: HashMap<Index, Vec<(u64, Gaussian)>> = HashMap::new();
|
let mut data: HashMap<Index, Vec<(i64, Gaussian)>> = HashMap::new();
|
||||||
|
|
||||||
for b in &self.batches {
|
for b in &self.batches {
|
||||||
for agent in b.skills.keys() {
|
for agent in b.skills.keys() {
|
||||||
@@ -235,7 +235,7 @@ impl History {
|
|||||||
&mut self,
|
&mut self,
|
||||||
composition: Vec<Vec<Vec<Index>>>,
|
composition: Vec<Vec<Vec<Index>>>,
|
||||||
results: Vec<Vec<f64>>,
|
results: Vec<Vec<f64>>,
|
||||||
times: Vec<u64>,
|
times: Vec<i64>,
|
||||||
weights: Vec<Vec<Vec<f64>>>,
|
weights: Vec<Vec<Vec<f64>>>,
|
||||||
) {
|
) {
|
||||||
self.add_events_with_prior(composition, results, times, weights, HashMap::new())
|
self.add_events_with_prior(composition, results, times, weights, HashMap::new())
|
||||||
@@ -245,7 +245,7 @@ impl History {
|
|||||||
&mut self,
|
&mut self,
|
||||||
composition: Vec<Vec<Vec<Index>>>,
|
composition: Vec<Vec<Vec<Index>>>,
|
||||||
results: Vec<Vec<f64>>,
|
results: Vec<Vec<f64>>,
|
||||||
times: Vec<u64>,
|
times: Vec<i64>,
|
||||||
weights: Vec<Vec<Vec<f64>>>,
|
weights: Vec<Vec<Vec<f64>>>,
|
||||||
priors: HashMap<Index, Player>,
|
priors: HashMap<Index, Player>,
|
||||||
) {
|
) {
|
||||||
@@ -302,7 +302,7 @@ impl History {
|
|||||||
|
|
||||||
while i < n {
|
while i < n {
|
||||||
let mut j = i + 1;
|
let mut j = i + 1;
|
||||||
let t = if self.time { times[o[i]] } else { i as u64 + 1 };
|
let t = if self.time { times[o[i]] } else { i as i64 + 1 };
|
||||||
|
|
||||||
while self.time && j < n && times[o[j]] == t {
|
while self.time && j < n && times[o[j]] == t {
|
||||||
j += 1;
|
j += 1;
|
||||||
@@ -329,7 +329,7 @@ impl History {
|
|||||||
|
|
||||||
let a = self.agents.get_mut(agent).unwrap();
|
let a = self.agents.get_mut(agent).unwrap();
|
||||||
|
|
||||||
a.last_time = if self.time { b.time } else { u64::MAX };
|
a.last_time = if self.time { b.time } else { i64::MAX };
|
||||||
a.message = b.forward_prior_out(agent);
|
a.message = b.forward_prior_out(agent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,7 +359,7 @@ impl History {
|
|||||||
for a in b.skills.keys() {
|
for a in b.skills.keys() {
|
||||||
let agent = self.agents.get_mut(a).unwrap();
|
let agent = self.agents.get_mut(a).unwrap();
|
||||||
|
|
||||||
agent.last_time = if self.time { t } else { u64::MAX };
|
agent.last_time = if self.time { t } else { i64::MAX };
|
||||||
agent.message = b.forward_prior_out(a);
|
agent.message = b.forward_prior_out(a);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -379,7 +379,7 @@ impl History {
|
|||||||
for a in b.skills.keys() {
|
for a in b.skills.keys() {
|
||||||
let agent = self.agents.get_mut(a).unwrap();
|
let agent = self.agents.get_mut(a).unwrap();
|
||||||
|
|
||||||
agent.last_time = if self.time { t } else { u64::MAX };
|
agent.last_time = if self.time { t } else { i64::MAX };
|
||||||
agent.message = b.forward_prior_out(a);
|
agent.message = b.forward_prior_out(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,7 +406,7 @@ impl History {
|
|||||||
|
|
||||||
let a = self.agents.get_mut(agent).unwrap();
|
let a = self.agents.get_mut(agent).unwrap();
|
||||||
|
|
||||||
a.last_time = if self.time { b.time } else { u64::MAX };
|
a.last_time = if self.time { b.time } else { i64::MAX };
|
||||||
a.message = b.forward_prior_out(agent);
|
a.message = b.forward_prior_out(agent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ pub(crate) fn sort_perm(x: &[f64], reverse: bool) -> Vec<usize> {
|
|||||||
v.into_iter().map(|(i, _)| i).collect()
|
v.into_iter().map(|(i, _)| i).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn sort_time(xs: &[u64], reverse: bool) -> Vec<usize> {
|
pub(crate) fn sort_time(xs: &[i64], reverse: bool) -> Vec<usize> {
|
||||||
let mut x = xs.iter().enumerate().collect::<Vec<_>>();
|
let mut x = xs.iter().enumerate().collect::<Vec<_>>();
|
||||||
|
|
||||||
if reverse {
|
if reverse {
|
||||||
|
|||||||
Reference in New Issue
Block a user